ChannelMenu.cpp
上传用户:liguizhu
上传日期:2015-11-01
资源大小:2422k
文件大小:12k
源码类别:

P2P编程

开发平台:

Visual C++

  1. /*
  2.  *  Openmysee
  3.  *
  4.  *  This program is free software; you can redistribute it and/or modify
  5.  *  it under the terms of the GNU General Public License as published by
  6.  *  the Free Software Foundation; either version 2 of the License, or
  7.  *  (at your option) any later version.
  8.  *
  9.  *  This program is distributed in the hope that it will be useful,
  10.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  *  GNU General Public License for more details.
  13.  *
  14.  *  You should have received a copy of the GNU General Public License
  15.  *  along with this program; if not, write to the Free Software
  16.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  17.  *
  18.  */
  19. #include "stdafx.h"
  20. #include ".channelmenu.h"
  21. #include "httprequest.h"
  22. #include "xml.h"
  23. #include "MultiLanguageMgr.h"
  24. #include "configfile.h"
  25. #include "..layer1externalmd5.h"
  26. static CChannelMenu* pChannelMenu = NULL;
  27. extern TCHAR g_sAppPath[MAX_PATH];
  28. CChannelMenu::CChannelMenu(void) : h_channelmenu(NULL), h_MenuThread(NULL), 
  29. channeldataOK(0), ParseDataOK(FALSE), useChannel(FALSE), channelthreadStop(FALSE), updatechannel(0),channelrunning(FALSE),
  30.     xmlurl(_T("http://www.Openmysee.com/program.php")),
  31.     pointcookieurl(_T("http://www.Openmysee.com/")),
  32.     pointurl(_T("http://www.Openmysee.com/member/userstat.php"))
  33. {
  34. pHttpSession = new HttpRequest;
  35. pHttpSession->Create();
  36. pTrayIconMenu = new CTrayIconMenu;
  37. }
  38. CChannelMenu::~CChannelMenu(void)
  39. {
  40. DestroyMenu(h_channelmenu);
  41. channelthreadStop = TRUE;
  42. pHttpSession->SetStopRequest();
  43. if(h_MenuThread != NULL)
  44. {
  45. WaitForSingleObject(h_MenuThread,INFINITE);
  46. CloseHandle(h_MenuThread);
  47. }
  48. delete pHttpSession;
  49. delete pTrayIconMenu;
  50. }
  51. CChannelMenu* CChannelMenu::CreateInstance(BOOL useChannel)
  52. {
  53. if(pChannelMenu == NULL)
  54. {
  55. pChannelMenu = new CChannelMenu;
  56. pChannelMenu->useChannel = useChannel;
  57. if(useChannel)
  58. {
  59. mystring filestr(g_sAppPath);
  60. filestr.append(_T("\config.ini"));
  61. ConfigFile config(filestr);
  62. mystring tmp = config.Value(_T("localserver"), _T("channellist"));
  63. if(!(config.fileNotFound || config.stringNotFound))
  64. pChannelMenu->xmlurl = tmp;
  65.             tmp = config.Value(_T("localserver"), _T("userdata"));
  66.             if(!(config.fileNotFound || config.stringNotFound))
  67. pChannelMenu->pointcookieurl = tmp;
  68.             tmp = config.Value(_T("localserver"), _T("postpointurl"));
  69.             if(!(config.fileNotFound || config.stringNotFound))
  70. pChannelMenu->pointurl = tmp;
  71. unsigned int threadID;
  72. pChannelMenu->h_MenuThread = (HANDLE) _beginthreadex(NULL, 0, &_GetMenuThreadProc, pChannelMenu, 0, &threadID);
  73. }
  74. }
  75. return pChannelMenu;
  76. }
  77. CChannelMenu* CChannelMenu::GetInstance()
  78. {
  79. return pChannelMenu;
  80. }
  81. void CChannelMenu::ReleaseInstance()
  82. {
  83. delete pChannelMenu;
  84. }
  85. extern volatile HWND g_hMainWnd;
  86. unsigned int CALLBACK CChannelMenu::_GetMenuThreadProc(void* lpParameter)
  87. {
  88. CChannelMenu* pClass = (CChannelMenu*) lpParameter;
  89.     //发生随机数
  90.     srand(GetTickCount());
  91. int idleinterval = 0;
  92. int nextworkingtime = 0;
  93. int getxmlerrcount = 0;
  94. while(!pClass->channelthreadStop)
  95. {
  96. if(idleinterval >= nextworkingtime ) //当定时器被触发时,开始获取XML的行动
  97. {
  98. InterlockedExchange(&pClass->channeldataOK, 0);
  99. if(!pClass->GetChannelXML())
  100. {
  101. if(getxmlerrcount < 3) //根据已经发生的错误次数制定逐步加长的重试间隔
  102. {
  103. nextworkingtime += 1; //隔1s重试一次
  104. getxmlerrcount++;
  105. }
  106. else if(getxmlerrcount < 6)
  107. {
  108. nextworkingtime += 10; //隔10s重试一次
  109. getxmlerrcount++;
  110. }
  111. else //放弃重试,等待下一次定时唤醒
  112. {
  113.                     InterlockedExchange(&pClass->channeldataOK, -1);
  114. nextworkingtime += 1200;
  115. getxmlerrcount = 0;
  116. }
  117. }
  118. else
  119. {
  120. nextworkingtime += 1200; //隔20min重试一次
  121. getxmlerrcount = 0;
  122. InterlockedExchange(&pClass->channeldataOK, 1);
  123. }
  124. }
  125. else if(pClass->updatechannel == 1)
  126. {
  127. nextworkingtime = idleinterval;
  128. InterlockedExchange(&pClass->updatechannel, 0);
  129. }
  130.         if(idleinterval%300 == 0)
  131.         {
  132.             pClass->PostAddPoint();
  133.         }
  134. Sleep(1000);
  135. idleinterval++;
  136. }
  137. // PostMessage(g_hMainWnd, WM_COMMAND, WM_APP + 1, 0);
  138. return 0;
  139. }
  140. void CChannelMenu::UpdateChannelNow()
  141. {
  142.     InterlockedExchange(&channeldataOK, 0);
  143. InterlockedExchange(&updatechannel, 1);
  144. }
  145. BOOL    CChannelMenu::PostAddPoint()
  146. {
  147.     if(channelrunning == FALSE)
  148.         return FALSE;
  149.     mystring deststr(pointurl);
  150.     mystring formatstr;
  151.     deststr.append(_T("?u="));    //userstat?
  152.     TCHAR datastr[36];
  153.     DWORD len = 36;
  154.     if(!HttpRequest::GetCookieEx(pointcookieurl.c_str(), "MYSE_UID", datastr, &len))
  155.         return FALSE;
  156.     deststr.append(datastr);    //userstat?<userid>
  157.     formatstr.append(datastr);
  158.     formatstr.append(_T("06My&SEe#211")/*约定的密钥*/);
  159.     int _rand = rand();
  160.     _stprintf(datastr, _T("&r=%d&h="), _rand); 
  161.     deststr.append(datastr);    //userstat?<userid>&<random num>&
  162.     _stprintf(datastr, _T("%d"), _rand);
  163.     formatstr.append(datastr);
  164.     char* srcstr = new char[formatstr.size() + 20];
  165.     wsprintfA(srcstr, "%s", formatstr.c_str());
  166.     MD5 md5((unsigned char*) srcstr, strlen(srcstr));
  167.     
  168.     char* result = md5.hex_digest();
  169.     delete[] srcstr;
  170.     wsprintf(datastr, "%hs", result);
  171.     delete[] result;
  172.     deststr.append(datastr);    //userstat?<userid>&<random num>&<md5>
  173. return pHttpSession->OpenRequest(deststr.c_str());
  174. }
  175. BOOL CChannelMenu::GetChannelXML()
  176. {
  177.     LANGID langid = pTrayIconMenu->GetCurLanguage();
  178.     mystring appendxmlurl(xmlurl);
  179.     if(appendxmlurl.find(_T(".php")) != mystring::npos)     //对于非PHP的URL,应该不应用参数
  180.     {
  181.         switch(langid)
  182.         {
  183.         case MAINLAND_LANG_ID:  //简体中文
  184.             appendxmlurl.append(_T("?lang=zh"));
  185.             break;
  186.         case TAIWAN_LANG_ID:
  187.         case HONGKONG_LANG_ID:  //繁体中文
  188.             appendxmlurl.append(_T("?lang=big5"));
  189.             break;
  190.         case DEFAULT_LANG_ID:   //英文
  191.         default:
  192.             appendxmlurl.append(_T("?lang=en"));
  193.         }
  194.     }
  195. if(!pHttpSession->OpenRequest(appendxmlurl.c_str()))
  196. return FALSE;
  197.  //   MessageBox(NULL, "get xml!", "", MB_OK);
  198. BYTE* tempstr = new BYTE[pHttpSession->getBufLen() + 30];
  199. memset(tempstr, 0, pHttpSession->getBufLen() + 30);
  200. pHttpSession->TransBuf(tempstr);
  201. m_critsec_XMLFile.Lock();
  202. strXMLFile = (LPCSTR) tempstr;
  203. m_critsec_XMLFile.Unlock();
  204. delete[] tempstr;
  205. return TRUE;
  206. }
  207. #ifdef _UNICODE
  208. static const std::wstring groupname[] = 
  209. {
  210. _T("GROUP"),
  211. _T("SUBGROUP"),
  212. _T("Channel"),
  213. };
  214. #else
  215. static const std::string groupname[] = 
  216. {
  217. _T("GROUP"),
  218. _T("SUBGROUP"),
  219. _T("Channel"),
  220. };
  221. #endif
  222. #define ChannelPos 2
  223. BOOL CChannelMenu::ParseChannelXML(HMENU hmenu)
  224. {
  225. CXML* p_xml = new CXML;
  226. p_xml->InitXml();
  227. m_critsec_XMLFile.Lock();
  228. if(!p_xml->OpenXml(strXMLFile))
  229. {
  230. m_critsec_XMLFile.Unlock();
  231. p_xml->unInitXml();
  232. delete p_xml;
  233. return FALSE;
  234. }
  235. m_critsec_XMLFile.Unlock();
  236. if(p_xml->SetNodelist(groupname[0].c_str()) != 0)
  237. MakePopupItem(p_xml, hmenu, 0);
  238. if(p_xml->SetNodelist(groupname[ChannelPos].c_str()) != 0)
  239. MakePopupItem(p_xml, hmenu, ChannelPos);
  240. p_xml->unInitXml();
  241. delete p_xml;
  242. return TRUE;
  243. }
  244. void CChannelMenu::MakePopupItem(CXML* p_xml, HMENU hmenu, int isubgroup)
  245. {
  246. BOOL ischannel = (groupname[isubgroup] == _T("Channel"));
  247. while(p_xml->ToNextNode())
  248. {
  249. if(!ischannel)
  250. {
  251. HMENU h_appendmenu = CreatePopupMenu();
  252.             if(p_xml->ToSubNodeList(groupname[isubgroup + 1].c_str()) != 0)  //将组名设定成下一级的组名
  253.             {
  254.     MakePopupItem(p_xml, h_appendmenu, isubgroup + 1);
  255.                 p_xml->BackParentNodeList();
  256.             }
  257.             if((isubgroup + 1 != ChannelPos) && (p_xml->ToSubNodeList(groupname[ChannelPos].c_str()) != 0))   //在本组下面寻找Channel并加入
  258.             {
  259.                 MakePopupItem(p_xml, h_appendmenu, ChannelPos);
  260.                 p_xml->BackParentNodeList();
  261.             }
  262.             if(GetMenuItemCount(h_appendmenu) <= 0)            //如果最后子菜单中一项都没有, 这个node是错误的, 抛弃它
  263.             {
  264.                 assert(0);
  265.                 DestroyMenu(h_appendmenu);
  266.             }
  267.             else
  268.             {
  269.                 mystring str;
  270.     p_xml->GetCurNodeAttrValue(str, _T("Name"));
  271.     AppendMenu(hmenu, MF_STRING | MF_POPUP, (UINT_PTR) h_appendmenu, str.c_str());
  272.             }
  273. }
  274. else//本身已经是Channel,加入菜单中
  275. {
  276. ChannelData data;
  277. p_xml->GetCurNodeAttrValue(data.name, _T("Name"));
  278. p_xml->GetCurNodeAttrValue(data.url, _T("URL"));
  279. channellist.push_back(data);
  280. AppendMenu(hmenu, MF_STRING , TRAYWM_CHANNELSTART + channellist.size() - 1, data.name.c_str());
  281. }
  282. }
  283. }
  284. LPCTSTR CChannelMenu::GetChannelByCmdID(DWORD m_cmdID)
  285. {
  286. if(m_cmdID < TRAYWM_CHANNELSTART || m_cmdID > TRAYWM_CHANNELEND)
  287. return NULL;
  288. size_t index = m_cmdID - TRAYWM_CHANNELSTART;
  289. if(index >= channellist.size())
  290. return NULL;
  291. channellist[index].desc.append(channellist[index].url.c_str());
  292. return channellist[index].url.c_str();
  293. }
  294. namespace{
  295. //一份默认的菜单
  296. UINT_PTR m_traycmd[] = 
  297. {
  298. TRAYWM_HOMEPAGE,
  299. CTrayIconMenu::ID_SEPERATOR,
  300. //CTrayIconMenu::ID_EXTERNAL, 0,
  301. //CTrayIconMenu::ID_SEPERATOR,
  302. CTrayIconMenu::ID_POPUP,
  303.        TRAYWM_UPDATE,
  304.        CTrayIconMenu::ID_LANGUAGE,
  305. CTrayIconMenu::ID_END,
  306. CTrayIconMenu::ID_SEPERATOR,
  307. CTrayIconMenu::ID_POPUP,
  308.        TRAYWM_HELP,
  309.        TRAYWM_NETWORK,
  310.        TRAYWM_EMAIL,
  311.        TRAYWM_ABOUT,
  312. CTrayIconMenu::ID_END,
  313. CTrayIconMenu::ID_SEPERATOR,
  314. TRAYWM_EXIT,
  315. CTrayIconMenu::ID_END};
  316. //不同语言的菜单文本,必须和数据严格对应,每一个数据项在文本里都应该有一个*,包括ID_END, ID_SEPERATOR等
  317. //ID_EXTERNAL除外,其后接一项没有*,而ID_POPUP后应该增加一项*作为标记
  318. /*const TCHAR m_traystrgb[] = 
  319. _T("首页(&P)*-*频道(&C)*-*设置(&S)*SUBSTART*检查更新(&U)*选择语言(&L)*END*-*帮助(&H)*SUBSTART*使用帮助(&H)*判定网络(&N)*电子邮件(&E)*关于(&A)*END*-*退出(&E)*END*");
  320. */
  321. const TCHAR m_traystrgb[] = 
  322. _T("首页(&P)*-*设置(&S)*SUBSTART*检查更新(&U)*选择语言(&L)*END*-*帮助(&H)*SUBSTART*使用帮助(&H)*判定网络(&N)*电子邮件(&E)*关于(&A)*END*-*退出(&E)*END*");
  323. //这里用"-"表示一个分隔符,"SUBSTART"表示开始一个新子菜单,"END"表示一个菜单结束。也可以换成任何方便的字符,程序并不理会它们
  324. const UINT  m_channellisthandlepos = 3;
  325. }
  326. BOOL CChannelMenu::ShowRButtonTIMenu(HWND hparent)
  327. {
  328. h_channelmenu = CreatePopupMenu(); //初始化一个提示的菜单
  329. AppendMenu(h_channelmenu, MF_SEPARATOR, (UINT_PTR) 0, NULL);   //加条分隔线意思一下,以防万一……
  330.     m_traycmd[m_channellisthandlepos] = (UINT_PTR) h_channelmenu;;
  331. pTrayIconMenu->ShowMenu(hparent, m_traycmd, m_traystrgb);
  332. DestroyMenu(h_channelmenu); //放弃生成的菜单
  333. h_channelmenu = NULL;
  334. ParseDataOK = FALSE; //因为生成的菜单已放弃,所以已正确解析的标记变成FALSE
  335. return TRUE;
  336. }
  337. void CChannelMenu::OnPopupMenu(HMENU hmenu, int popuppos)
  338. {
  339. if(pTrayIconMenu->OnMenuPopup(hmenu, popuppos))
  340. return;
  341. if(hmenu != h_channelmenu) //不是频道窗口不需要处理
  342. return;
  343. int count = GetMenuItemCount(hmenu);
  344. if(count == -1) //菜单错误,放弃解析
  345. return;
  346. for(int i = 0; i < count; i++)
  347. DeleteMenu(hmenu, 0, MF_BYPOSITION); //清除掉整个菜单里的内容
  348.     MultiLanguage langDll;
  349. if(channeldataOK == 0) //数据未准备好
  350.     {
  351.     AppendMenu(h_channelmenu, MF_STRING | MF_DISABLED , (UINT_PTR) 0, langDll.GetStringByStr(_T("数据读取中...")));
  352.     }
  353.     else if(channeldataOK == -1)     //获取数据错误
  354.     {
  355.         AppendMenu(h_channelmenu, MF_STRING | MF_DISABLED , (UINT_PTR) 0, langDll.GetStringByStr(_T("数据读取失败!")));
  356.         AppendMenu(hmenu, MF_SEPARATOR, 0, NULL);
  357. AppendMenu(hmenu, MF_STRING, TRAYWM_UPDATECHANNEL, langDll.GetStringByStr(_T("更新频道列表")));
  358.     }
  359.     else
  360.     {
  361.     if(ParseChannelXML(hmenu) == TRUE)
  362.     {
  363.     AppendMenu(hmenu, MF_SEPARATOR, 0, NULL);
  364.     AppendMenu(hmenu, MF_STRING, TRAYWM_UPDATECHANNEL, langDll.GetStringByStr(_T("更新频道列表")));
  365.     }
  366.     else
  367.     {
  368.     AppendMenu(hmenu, MF_STRING | MF_DISABLED, 0, langDll.GetStringByStr(_T("频道文件解析失败")));
  369.     }
  370.     }
  371. }