PhmsResponse.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. #include "PhmsResponse.h"
  2. #include "Poco/Buffer.h"
  3. #include <fstream>
  4. #include <sstream>
  5. #include "ErrorCode.h"
  6. #include "Poco/Exception.h"
  7. #include "Poco/MD5Engine.h"
  8. #include "Poco/Path.h"
  9. #include "Poco/AutoPtr.h"
  10. #include "Poco/Util/IniFileConfiguration.h"
  11. #include "Poco/TextEncoding.h"
  12. #include "Poco/StreamConverter.h"
  13. #include "Poco/StreamCopier.h"
  14. #include "PhmsSession.h"
  15. #include "PhmsLogger.h"
  16. #include "Util.h"
  17. #include "GlobalTerminalLogoString.h"
  18. using Poco::MD5Engine;
  19. using Poco::DigestEngine;
  20. using Poco::Buffer;
  21. using Poco::Exception;
  22. using Poco::TimeoutException;
  23. using Poco::Path;
  24. using Poco::AutoPtr;
  25. using Poco::Util::IniFileConfiguration;
  26. using Poco::TextEncoding;
  27. using Poco::InputStreamConverter;
  28. using Poco::StreamCopier;
  29. CPhmsResponse::CPhmsResponse()
  30. {
  31. }
  32. CPhmsResponse::CPhmsResponse(CPhmsResponse& phmsResponse)
  33. {
  34. this->m_phmsResponseHead = phmsResponse.GetPhmsResponseHead();
  35. this->m_phmsResponseBody = phmsResponse.GetPhmsResponseBody();
  36. }
  37. CPhmsResponse& CPhmsResponse::operator=(CPhmsResponse& phmsResponse)
  38. {
  39. this->m_phmsResponseHead = phmsResponse.GetPhmsResponseHead();
  40. this->m_phmsResponseBody = phmsResponse.GetPhmsResponseBody();
  41. return *this;
  42. }
  43. CPhmsResponse::~CPhmsResponse(void)
  44. {
  45. }
  46. //Getter
  47. CPhmsResponseHead& CPhmsResponse::GetPhmsResponseHead()
  48. {
  49. return m_phmsResponseHead;
  50. }
  51. CPhmsResponseBody& CPhmsResponse::GetPhmsResponseBody()
  52. {
  53. return m_phmsResponseBody;
  54. }
  55. //Setter
  56. void CPhmsResponse::SetPhmsResponseHead(CPhmsResponseHead phmsResponseHead)
  57. {
  58. m_phmsResponseHead = phmsResponseHead;
  59. }
  60. void CPhmsResponse::SetPhmsResponseBody(CPhmsResponseBody phmsResponseBody)
  61. {
  62. m_phmsResponseBody = phmsResponseBody;
  63. }
  64. //pInputStream:用于获得HttpSession中服务器返回的内容
  65. //pPhmsSession:应传入CPhmsSession*,用于在流异常的状态情况下获得Http异常信息,并写入日志;同时也是为将来扩展使用Http长连接
  66. //时,如果发生http流异常调用HttpSession::reset函数使用
  67. int CPhmsResponse::SetPhmsResponse(istream* pInputStream, void* pPhmsSession)
  68. {
  69. int nPhmsResponseHeadTotalLength = CPhmsResponseHead::GetPhmsResposeHeadTotalLength();
  70. Buffer<char> bufPhmsResponseHead(nPhmsResponseHeadTotalLength+1);
  71. memset(bufPhmsResponseHead.begin(), 0, nPhmsResponseHeadTotalLength+1);
  72. pInputStream->exceptions(ios::failbit);
  73. try
  74. {
  75. pInputStream->read(bufPhmsResponseHead.begin(), nPhmsResponseHeadTotalLength);
  76. }
  77. catch(const std::ios::failure& e)
  78. {
  79. CPhmsLogger::GetPhmsLogger()->WriteLog(bufPhmsResponseHead.begin(), __FUNCTION__, __FILE__, __LINE__);
  80. CPhmsLogger::GetPhmsLogger()->WriteLog(e.what(), __FUNCTION__, __FILE__, __LINE__);
  81. CPhmsLogger::GetPhmsLogger()->WriteLog(CUtil::GetErrorMsg(COMMON_RESPONSE_FORMAT_ERROR), __FUNCTION__, __FILE__, __LINE__);
  82. return COMMON_RESPONSE_FORMAT_ERROR;
  83. }
  84. catch(const TimeoutException& e)
  85. {
  86. CPhmsLogger::GetPhmsLogger()->WriteLog(e, __FUNCTION__, __FILE__, __LINE__);
  87. CPhmsLogger::GetPhmsLogger()->WriteLog(CUtil::GetErrorMsg(COMMON_RECV_TIMEOUT), __FUNCTION__, __FILE__, __LINE__);
  88. return COMMON_RECV_TIMEOUT;
  89. }
  90. catch(Exception& e)
  91. {
  92. CPhmsLogger::GetPhmsLogger()->WriteLog(e, __FUNCTION__, __FILE__, __LINE__);
  93. CPhmsLogger::GetPhmsLogger()->WriteLog(CUtil::GetErrorMsg(COMMON_RECV_FAIL), __FUNCTION__, __FILE__, __LINE__);
  94. return COMMON_RECV_FAIL;
  95. }
  96. string stringPhmsResponseHead = bufPhmsResponseHead.begin();
  97. m_phmsResponseHead.SetPhmsResponseHead(stringPhmsResponseHead);
  98. m_phmsResponseBody.SetInputStreamPointer(pInputStream);
  99. m_phmsResponseBody.SetPhmsSessionPointer(pPhmsSession);
  100. return PHMS_SUCCESSFUL_RESULT;
  101. }
  102. //错误信息一定通过stringMsgContent返回
  103. int CPhmsResponse::GetResult(int nSaveType, string& stringMsgContent, string& stringFilePath, bool bFileClearBeforeWrite, bool bNeedConvertEncoding)
  104. {
  105. EnumPhmsResponseReturnCode enumReturnCode = FAIL_RETURN_CODE;
  106. enumReturnCode = m_phmsResponseHead.GetPhmsResponseReturnCode();
  107. int nRet = PHMS_SUCCESSFUL_RESULT;
  108. if(enumReturnCode != SUCCESS_RETURN_CODE)
  109. {
  110. //错误信息一定通过stringMsgContent返回
  111. nRet = m_phmsResponseBody.InputStreamToString(stringMsgContent);
  112. if(nRet != PHMS_SUCCESSFUL_RESULT)
  113. {
  114. CPhmsLogger::GetPhmsLogger()->WriteLog(CUtil::GetErrorMsg(nRet), __FUNCTION__, __FILE__, __LINE__);
  115. return nRet;
  116. }
  117. else
  118. {
  119. //服务器返回错误信息写日志
  120. int nResultErrorCode = atoi(m_phmsResponseHead.GetReturnCode().c_str());
  121. if(nResultErrorCode!=220403 && nResultErrorCode!=220405 && nResultErrorCode!=220303)
  122. {
  123. CPhmsLogger::GetPhmsLogger()->WriteLog(stringMsgContent, __FUNCTION__, __FILE__, __LINE__);
  124. }
  125. nSaveType = 1;//错误信息都用字符串保存,并写入日志,设置nSaveType为1是为了后面正确计算签名
  126. }
  127. }
  128. else
  129. {
  130. switch(nSaveType)
  131. {
  132. case 0:
  133. //残余的响应内容也收回来,防止影响下次接收
  134. nRet = m_phmsResponseBody.InputStreamToString(stringMsgContent);
  135. break;
  136. case 1:
  137. nRet = m_phmsResponseBody.InputStreamToString(stringMsgContent);
  138. if(nRet != PHMS_SUCCESSFUL_RESULT)
  139. {
  140. CPhmsLogger::GetPhmsLogger()->WriteLog(CUtil::GetErrorMsg(nRet), __FUNCTION__, __FILE__, __LINE__);
  141. return nRet;
  142. }
  143. break;
  144. case 2:
  145. nRet = m_phmsResponseBody.InputStreamToFile(stringFilePath, bFileClearBeforeWrite);
  146. if(nRet != PHMS_SUCCESSFUL_RESULT)
  147. {
  148. CPhmsLogger::GetPhmsLogger()->WriteLog(CUtil::GetErrorMsg(nRet), __FUNCTION__, __FILE__, __LINE__);
  149. return nRet;
  150. }
  151. break;
  152. default:
  153. break;
  154. }
  155. }
  156. //在istream读之前获得流长度的话,不知道所得流长度是否正确,所以把签名验证放到最后,已确定md5源串size
  157. //放到这也因为到这里流的内容全部都读出来了。
  158. //但是对于保存到文件并续写文件的情况,暂时不支持签名验证,将来再说(可以在CPhmsResponseBody中加一个成员变量来保存)
  159. if(!(nSaveType==2&&bFileClearBeforeWrite==false))
  160. {
  161. if(this->ValidateSign(nSaveType, stringMsgContent, stringFilePath) == false)
  162. {
  163. CPhmsLogger::GetPhmsLogger()->WriteLog(CUtil::GetErrorMsg(COMMON_RESPONSE_SIGN_VALIDATE_FAIL), __FUNCTION__, __FILE__, __LINE__);
  164. return COMMON_RESPONSE_SIGN_VALIDATE_FAIL;
  165. }
  166. }
  167. if(bNeedConvertEncoding && (nSaveType==1||nSaveType==2) )
  168. {
  169. nRet = ConvertEncodingFromUtf8(nSaveType, stringMsgContent, stringFilePath);
  170. if(nRet != PHMS_SUCCESSFUL_RESULT)
  171. {
  172. CPhmsLogger::GetPhmsLogger()->WriteLog(CUtil::GetErrorMsg(nRet), __FUNCTION__, __FILE__, __LINE__);
  173. return nRet;
  174. }
  175. }
  176. return atoi(m_phmsResponseHead.GetReturnCode().c_str());
  177. }
  178. bool CPhmsResponse::ValidateSign(int nSaveType, string& stringMsgContent, string& stringFilePath)
  179. {
  180. //首先排除无需验证的情况
  181. if(m_phmsResponseHead.GetReturnCode() == "100001" || m_phmsResponseHead.GetReturnCode() == "100002" ||
  182. m_phmsResponseHead.GetReturnCode() == "100005" || m_phmsResponseHead.GetReturnCode() == "100006" ||
  183. m_phmsResponseHead.GetReturnCode() == "100007")
  184. {
  185. return true;
  186. }
  187. if(m_phmsResponseHead.GetSign() == "00000000000000000000000000000000")//只为1068\1099命令而加
  188. {
  189. return true;
  190. }
  191. //生成第一个md5
  192. string username;
  193. string password;
  194. //获得用户名和密码
  195. {
  196. username = CPhmsRequest::GetUsername();
  197. password = CPhmsRequest::GetPassword();
  198. if(username.size()==0 || password.size()==0)
  199. {
  200. username = g_stringUsername;
  201. password = g_stringPassword;
  202. }
  203. }
  204. string stringSrc1 = username+password;
  205. string md5_1;
  206. md5_1= CUtil::GetMd5(stringSrc1.c_str(), stringSrc1.size());
  207. //获得buf总长度
  208. int nLength = 0;
  209. int nHeadLengthExceptSign = 0;
  210. nHeadLengthExceptSign = m_phmsResponseHead.GetPhmsResposeHeadTotalLength()-(int)m_phmsResponseHead.GetSign().size();
  211. int nIStreamLength = 0;
  212. ifstream ifLocalTargetFile;
  213. streampos pos = 0;
  214. switch(nSaveType)
  215. {
  216. case 0:
  217. nIStreamLength = 0;
  218. break;
  219. case 1:
  220. nIStreamLength = (int)stringMsgContent.size();
  221. break;
  222. case 2:
  223. ifLocalTargetFile.exceptions(ios::failbit|ios::badbit);
  224. try
  225. {
  226. ifLocalTargetFile.open(stringFilePath.c_str(), ios::in|ios::binary);
  227. }
  228. catch(const ios::failure& error)
  229. {
  230. //写日志
  231. CPhmsLogger::GetPhmsLogger()->WriteLog(error.what(), __FUNCTION__, __FILE__, __LINE__);
  232. return false;
  233. }
  234. pos = ifLocalTargetFile.tellg();
  235. ifLocalTargetFile.seekg(0,ios::end);
  236. nIStreamLength = ifLocalTargetFile.tellg();
  237. ifLocalTargetFile.seekg(pos);
  238. break;
  239. default:
  240. nIStreamLength = 0;
  241. break;
  242. }
  243. //获得总长度并构造bufSrc
  244. char* bufSrc = NULL;
  245. nLength = (int)md5_1.size()+nHeadLengthExceptSign+nIStreamLength;
  246. bufSrc = new char[nLength+1];
  247. memset(bufSrc, 0, nLength+1);
  248. //md5_1内容
  249. memcpy(bufSrc, md5_1.c_str(), md5_1.size());
  250. //PhmsResponseHead内容
  251. string stringHeadExceptSign;
  252. stringHeadExceptSign = m_phmsResponseHead.GetVersion()+m_phmsResponseHead.GetReturnCode()+m_phmsResponseHead.GetMessageFormat();
  253. memcpy(bufSrc+md5_1.size(), stringHeadExceptSign.c_str(), nHeadLengthExceptSign);
  254. //PhmsResponseBody内容
  255. switch(nSaveType)
  256. {
  257. case 0:
  258. break;
  259. case 1:
  260. memcpy(bufSrc+md5_1.size()+nHeadLengthExceptSign, stringMsgContent.c_str(), stringMsgContent.size());
  261. break;
  262. case 2:
  263. //int nTempLength = 0;
  264. try
  265. {
  266. ifLocalTargetFile.read(bufSrc+md5_1.size()+nHeadLengthExceptSign, nIStreamLength);
  267. ifLocalTargetFile.close();
  268. }
  269. catch (const ios::failure& error)
  270. {
  271. //写日志
  272. ifLocalTargetFile.close();
  273. delete bufSrc;
  274. CPhmsLogger::GetPhmsLogger()->WriteLog(error.what(), __FUNCTION__, __FILE__, __LINE__);
  275. CPhmsLogger::GetPhmsLogger()->WriteLog(CUtil::GetErrorMsg(COMMON_FILE_READ_FAIL), __FUNCTION__, __FILE__, __LINE__);
  276. return false;
  277. }
  278. break;
  279. }
  280. //生成最终的md5,校验
  281. string md5_2 ;
  282. md5_2 = CUtil::GetMd5(bufSrc, nLength);
  283. if(md5_2 != m_phmsResponseHead.GetSign())
  284. {
  285. delete bufSrc;
  286. return false;
  287. }
  288. delete bufSrc;
  289. return true;
  290. }
  291. int CPhmsResponse::ConvertEncodingFromUtf8(int nSaveType, string& stringMsgContent, string& stringFilePath)
  292. {
  293. string stringTempXmlContent;
  294. string stringWorkingDir = CUtil::GetCurrentAppDir();
  295. string stringIniFilePath = stringWorkingDir+"PhmsConfig.ini";
  296. AutoPtr<IniFileConfiguration> iniFile = new IniFileConfiguration(stringIniFilePath, "gbk");
  297. string stringEncoding = iniFile->getString("OTHER.Encoding", "GBK");
  298. TextEncoding* pEnvEncoding = TextEncoding::find(stringEncoding);
  299. TextEncoding* pUtf8Encoding = TextEncoding::find("UTF-8");
  300. ostringstream ostr;
  301. if(nSaveType == 1)
  302. {
  303. istringstream istr(stringMsgContent);
  304. istr.exceptions(ios::badbit);
  305. InputStreamConverter converter(istr, *pUtf8Encoding, *pEnvEncoding);
  306. try
  307. {
  308. StreamCopier::copyStream(converter, ostr);
  309. }
  310. catch(const std::ios::failure& e)
  311. {
  312. CPhmsLogger::GetPhmsLogger()->WriteLog(e.what(), __FUNCTION__, __FILE__, __LINE__);
  313. CPhmsLogger::GetPhmsLogger()->WriteLog(CUtil::GetErrorMsg(COMMON_INPUT_STREAM_FAIL), __FUNCTION__, __FILE__, __LINE__);
  314. return COMMON_INPUT_STREAM_FAIL;
  315. }
  316. stringTempXmlContent = ostr.str();
  317. }
  318. if(nSaveType == 2)
  319. {
  320. ifstream istr;
  321. istr.exceptions(ios::badbit);
  322. try
  323. {
  324. istr.open(stringFilePath.c_str());
  325. }
  326. catch(const ios::failure& error)
  327. {
  328. //写日志
  329. CPhmsLogger::GetPhmsLogger()->WriteLog(error.what(), __FUNCTION__, __FILE__, __LINE__);
  330. CPhmsLogger::GetPhmsLogger()->WriteLog(CUtil::GetErrorMsg(COMMON_FILE_OPEN_FAIL), __FUNCTION__, __FILE__, __LINE__);
  331. return COMMON_FILE_OPEN_FAIL;
  332. }
  333. InputStreamConverter converter(istr, *pUtf8Encoding, *pEnvEncoding);
  334. try
  335. {
  336. StreamCopier::copyStream(converter, ostr);
  337. }
  338. catch(const std::ios::failure& e)
  339. {
  340. istr.close();
  341. CPhmsLogger::GetPhmsLogger()->WriteLog(e.what(), __FUNCTION__, __FILE__, __LINE__);
  342. CPhmsLogger::GetPhmsLogger()->WriteLog(CUtil::GetErrorMsg(COMMON_INPUT_STREAM_FAIL), __FUNCTION__, __FILE__, __LINE__);
  343. return COMMON_INPUT_STREAM_FAIL;
  344. }
  345. istr.close();
  346. stringTempXmlContent = ostr.str();
  347. }
  348. string stringSrc = "encoding=\"UTF-8\"?>";
  349. string stringDst = "encoding=\"";
  350. stringDst += stringEncoding;
  351. stringDst += "\"?>";
  352. CUtil::ReplaceString(stringTempXmlContent, stringSrc, stringDst);
  353. if(nSaveType == 1)
  354. {
  355. stringMsgContent = stringTempXmlContent;
  356. }
  357. if(nSaveType == 2)
  358. {
  359. ofstream ofs;
  360. ofs.exceptions(ios::failbit | ios::badbit);
  361. try
  362. {
  363. ofs.open(stringFilePath.c_str(), ios::out|ios::trunc);
  364. ofs.write(stringTempXmlContent.c_str(), stringTempXmlContent.size());
  365. ofs.close();
  366. }
  367. catch(const std::ios::failure& e)
  368. {
  369. ofs.close();
  370. CPhmsLogger::GetPhmsLogger()->WriteLog(e.what(), __FUNCTION__, __FILE__, __LINE__);
  371. CPhmsLogger::GetPhmsLogger()->WriteLog(CUtil::GetErrorMsg(COMMON_INPUT_STREAM_FAIL), __FUNCTION__, __FILE__, __LINE__);
  372. return COMMON_INPUT_STREAM_FAIL;
  373. }
  374. }
  375. return PHMS_SUCCESSFUL_RESULT;
  376. }