Esenthel Store.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************/
  5. static StrO MD5Text(C Str8 &text)
  6. {
  7. UID id=MD5Mem(text(), text.length()); return TextHexMem(&id, SIZE(id));
  8. }
  9. void EsenthelStore::RegisterAccount()
  10. {
  11. Explore("http://www.esenthel.com/?id=store&mode=register");
  12. }
  13. EsenthelStore::RESULT EsenthelStore::GetAccessKey(Int item_id)
  14. {
  15. if(item_id<=0)return INVALID_ITEM;
  16. return Explore(S+"http://www.esenthel.com/?id=store&get_access_key="+item_id) ? CONNECTING : CANT_CONNECT;
  17. }
  18. EsenthelStore::RESULT EsenthelStore::Buy(C Str &email, Int app_id, PURCHASE_TYPE purchase_type)
  19. {
  20. if(!ValidEmail(email))return INVALID_EMAIL_FORMAT;
  21. if( app_id <=0)return INVALID_ITEM;
  22. Int item_id;
  23. switch(purchase_type)
  24. {
  25. default : return INVALID_ITEM;
  26. case PURCHASE_1 : item_id=140; break;
  27. case PURCHASE_2 : item_id=141; break;
  28. case PURCHASE_3 : item_id=142; break;
  29. case PURCHASE_5 : item_id=143; break;
  30. case PURCHASE_10 : item_id=144; break;
  31. case PURCHASE_20 : item_id=145; break;
  32. case PURCHASE_50 : item_id=146; break;
  33. case PURCHASE_100: item_id=147; break;
  34. }
  35. return Explore(S+"http://www.esenthel.com/store.php?cmd=buy_item&i="+item_id+"&a="+app_id+"&u="+email) ? CONNECTING : CANT_CONNECT;
  36. }
  37. Int EsenthelStore::PurchaseToUSD(PURCHASE_TYPE purchase_type)
  38. {
  39. switch(purchase_type)
  40. {
  41. case PURCHASE_1 : return 1;
  42. case PURCHASE_2 : return 2;
  43. case PURCHASE_3 : return 3;
  44. case PURCHASE_5 : return 5;
  45. case PURCHASE_10 : return 10;
  46. case PURCHASE_20 : return 20;
  47. case PURCHASE_50 : return 50;
  48. case PURCHASE_100: return 100;
  49. }
  50. return 0;
  51. }
  52. /******************************************************************************/
  53. EsenthelStore::EsenthelStore()
  54. {
  55. _device_id=false;
  56. _license_result=_purchase_result=NONE;
  57. _license_item_id=_purchase_item_id=0;
  58. _license_r=_purchase_r=0;
  59. }
  60. /******************************************************************************/
  61. // LICENSE TEST
  62. /******************************************************************************/
  63. void EsenthelStore::licenseClear(Bool params)
  64. {
  65. _license_download.del(); // delete this first in case it would change anything
  66. _device_id=false;
  67. _license_result=NONE;
  68. _license_r=0;
  69. if(params){_license_item_id=0; _license_key.del(); _license_email.del();}
  70. }
  71. void EsenthelStore::licenseTest(Int item_id, C Str &license_key, C Str &email, Bool device_id)
  72. {
  73. licenseClear(false); T._license_key=license_key; T._license_email=email; // don't clear 'license_key' member in case it's the 'license_key' parameter
  74. if(item_id<=0)_license_result=INVALID_ITEM;else
  75. if(license_key.is() && !ValidLicenseKey(license_key))_license_result=INVALID_LICENSE_KEY_FORMAT;else
  76. if(email .is() && !ValidEmail (email ))_license_result=INVALID_EMAIL_FORMAT;else
  77. if(license_key.is() || email.is() || device_id) // if we were actually requested to test anything
  78. {
  79. T._license_item_id=item_id;
  80. T._license_r =Random();
  81. T._device_id =device_id;
  82. Memt<HTTPParam> params;
  83. //Int time=DateTime().getUTC().seconds1970()/(60*5); // 5 mins
  84. params.New().set("i" , S+item_id); // item id
  85. params.New().set("r" , S+_license_r); // request id
  86. if(license_key.is())params.New().set("l" , license_key); // license key
  87. if(email .is())params.New().set("e" , email); // email
  88. if(device_id )params.New().set("c" , DeviceID()); // computer/device id
  89. params.New().set("cmd", "test_license"); // command
  90. _license_download.create("http://www.esenthel.com/test_license.php", params);
  91. _license_result=CONNECTING;
  92. }
  93. }
  94. void EsenthelStore::updateLicense()
  95. {
  96. if(_license_result==CONNECTING)switch(_license_download.state()) // check for progress
  97. {
  98. case DWNL_NONE :
  99. case DWNL_ERROR: _license_download.del(); _license_result=CANT_CONNECT; break;
  100. case DWNL_DONE:
  101. {
  102. RESULT r=INVALID_RESPONSE;
  103. FileText f; f.readMem(_license_download.data(), _license_download.size());
  104. TextData data; if(data.load(f))if(C TextNode *result=data.findNode("Result"))switch(result->asInt())
  105. {
  106. case 1: r=LICENSE_KEY_FAIL; break;
  107. case 2: r= DEVICE_ID_FAIL; break;
  108. case 3: r= EMAIL_NOT_FOUND; break;
  109. case 0: if(C TextNode *confirm=data.findNode("Confirm")) // OK
  110. {
  111. Int time=DateTime().getUTC().seconds1970()/(60*5); // 5 mins
  112. Str8 str=CaseDown(_license_key+_license_email+(_device_id ? DeviceID() : S)+_license_item_id+_license_r),
  113. a=str+(time-1), b=str+time, c=str+(time+1); // time tolerance
  114. UID code_id; code_id.fromHex(confirm->asText());
  115. r=((MD5Mem(a(), a.length())==code_id || MD5Mem(b(), b.length())==code_id || MD5Mem(c(), c.length())==code_id) ? OK : CONFIRM_CODE_FAIL);
  116. }break;
  117. }
  118. _license_download.del(); _license_result=r; // set at the end
  119. }break;
  120. }
  121. }
  122. EsenthelStore::RESULT EsenthelStore::licenseResult() {updateLicense(); return _license_result;}
  123. /******************************************************************************/
  124. // PURCHASES
  125. /******************************************************************************/
  126. void EsenthelStore::updatePurchases()
  127. {
  128. if(_purchase_result==CONNECTING)switch(_purchase_download.state()) // check for progress
  129. {
  130. case DWNL_NONE :
  131. case DWNL_ERROR: _purchase_download.del(); _purchase_result=CANT_CONNECT; break;
  132. case DWNL_DONE:
  133. {
  134. RESULT r=INVALID_RESPONSE;
  135. FileText f; f.readMem(_purchase_download.data(), _purchase_download.size());
  136. TextData data; if(data.load(f))if(TextNode *result=data.findNode("result"))switch(result->asInt())
  137. {
  138. case 1: r=EMAIL_NOT_FOUND ; break;
  139. case 2: r=INVALID_PASSWORD; break;
  140. case 3: r=INVALID_CALL ; break;
  141. case 0: if(C TextNode *confirm=data.findNode("Confirm")) // OK
  142. {
  143. r=((MD5Text(CaseDown(purchasesEmail())+'|'+_purchase_r+'|'+_purchase_item_id)==confirm->asText()) ? OK : CONFIRM_CODE_FAIL);
  144. if(TextNode *purchases=data.findNode("purchases"))FREPA(purchases->nodes) // list in order
  145. {
  146. TextNode &purchase=purchases->nodes[i];
  147. if(TextNode *date =purchase.findNode("Date"))
  148. if(TextNode *license_key=purchase.findNode("LicenseKey"))
  149. if(TextNode *cost =purchase.findNode("Cost"))
  150. {
  151. Int c=cost->asInt(); if(c>=99)
  152. {
  153. Purchase &purchase=_purchases.New();
  154. purchase.date.fromText(date->asText());
  155. purchase.id = license_key->asText() ;
  156. if(c>=9999)purchase.type=PURCHASE_100;else
  157. if(c>=4999)purchase.type=PURCHASE_50 ;else
  158. if(c>=1999)purchase.type=PURCHASE_20 ;else
  159. if(c>= 999)purchase.type=PURCHASE_10 ;else
  160. if(c>= 499)purchase.type=PURCHASE_5 ;else
  161. if(c>= 299)purchase.type=PURCHASE_3 ;else
  162. if(c>= 199)purchase.type=PURCHASE_2 ;else
  163. purchase.type=PURCHASE_1 ;
  164. }
  165. }
  166. }
  167. }break;
  168. }
  169. _purchase_download.del(); _purchase_result=r; // set at the end
  170. }break;
  171. }
  172. REPA(_consume)
  173. {
  174. Download &consume=_consume[i]; switch(consume.state())
  175. {
  176. case DWNL_DONE:
  177. {
  178. FileText f; f.readMem(consume.data(), consume.size());
  179. TextData data; if(data.load(f))if(TextNode *result=data.findNode("result"))switch(result->asInt())
  180. {
  181. case 3: break; // invalid Key
  182. case 2: break; // invalid PurchaseID
  183. case 1: break; // email not found
  184. case 0: // removed OK
  185. {
  186. if(TextNode *purchase_id=data.findNode("Purchase"))
  187. REPA(_purchases)if(_purchases[i].id==purchase_id->value)_purchases.remove(i, true);
  188. }break;
  189. }
  190. } // !! no break on purpose so it can be removed !!
  191. case DWNL_NONE :
  192. case DWNL_ERROR: _consume.removeValid(i); break;
  193. }
  194. }
  195. }
  196. void EsenthelStore::purchasesClear()
  197. {
  198. _purchase_download.del(); // delete this first in case it would change anything
  199. _purchase_item_id=0;
  200. _purchase_r=0;
  201. _purchase_email.clear();
  202. _purchase_result=NONE;
  203. _purchases.clear();
  204. }
  205. EsenthelStore::RESULT EsenthelStore::purchasesResult() {updatePurchases(); return _purchase_result;}
  206. C Memc<EsenthelStore::Purchase>& EsenthelStore::purchases () {updatePurchases(); return _purchases;}
  207. void EsenthelStore::purchasesRefresh(C Str &email, C Str &access_key, Int item_id)
  208. {
  209. purchasesClear(); _purchase_email=email; _purchase_item_id=item_id;
  210. if(!ValidEmail(email) )_purchase_result=INVALID_EMAIL_FORMAT;else
  211. if( access_key.length()!=32)_purchase_result=INVALID_PASSWORD ;else
  212. if( item_id <= 0)_purchase_result=INVALID_ITEM ;else
  213. {
  214. Memt<HTTPParam> params;
  215. _purchase_r=Random(1, INT_MAX);
  216. params.New().set("cmd", "get");
  217. params.New().set("i", S+item_id);
  218. params.New().set("r", S+_purchase_r); // request_id
  219. params.New().set("e", email);
  220. params.New().set("k", MD5Text(CaseDown(access_key)+'|'+_purchase_r+'|'+item_id));
  221. _purchase_download.create("http://www.esenthel.com/purchases.php", params);
  222. _purchase_result=CONNECTING;
  223. }
  224. }
  225. void EsenthelStore::_purchasesRefresh(C Str &email, C Str &password, Int item_id)
  226. {
  227. purchasesClear(); _purchase_email=email; _purchase_item_id=item_id;
  228. if(!ValidEmail(email))_purchase_result=INVALID_EMAIL_FORMAT;else
  229. if(!password.is() )_purchase_result=INVALID_PASSWORD ;else
  230. if( item_id <=0)_purchase_result=INVALID_ITEM ;else
  231. {
  232. Memt<HTTPParam> params;
  233. _purchase_r=Random(1, INT_MAX);
  234. params.New().set("cmd", "get2");
  235. params.New().set("i", S+item_id);
  236. params.New().set("r", S+_purchase_r); // request_id
  237. params.New().set("e", email);
  238. params.New().set("k", MD5Text(CaseDown(password)+'|'+_purchase_r+'|'+item_id));
  239. _purchase_download.create("http://www.esenthel.com/purchases.php", params);
  240. _purchase_result=CONNECTING;
  241. }
  242. }
  243. EsenthelStore::RESULT EsenthelStore::consume(C Str &email, Int item_id, C Str &purchase_id)
  244. {
  245. if(!ValidEmail(email))return INVALID_EMAIL_FORMAT;
  246. if( item_id<=0 )return INVALID_ITEM;
  247. if(!purchase_id.is() )return INVALID_ITEM;
  248. Memt<HTTPParam> params;
  249. Int request_id=Random(1, INT_MAX);
  250. params.New().set("cmd", "consume");
  251. params.New().set("i", S+item_id);
  252. params.New().set("r", S+request_id);
  253. params.New().set("e", email);
  254. params.New().set("p", purchase_id);
  255. params.New().set("k", MD5Text(CaseDown(purchase_id)+'|'+request_id+'|'+item_id));
  256. _consume.New().create("http://www.esenthel.com/purchases.php", params);
  257. return CONNECTING;
  258. }
  259. /******************************************************************************/
  260. }
  261. /******************************************************************************/