calypso_util.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. #include "metroflip_i.h"
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "calypso_util.h"
  5. CalypsoElement make_calypso_final_element(
  6. const char* key,
  7. int size,
  8. const char* label,
  9. CalypsoFinalType final_type) {
  10. CalypsoElement final_element = {};
  11. final_element.type = CALYPSO_ELEMENT_TYPE_FINAL;
  12. final_element.final = malloc(sizeof(CalypsoFinalElement));
  13. final_element.final->size = size;
  14. final_element.final->final_type = final_type;
  15. strncpy(final_element.final->key, key, 36);
  16. strncpy(final_element.final->label, label, 64);
  17. return final_element;
  18. }
  19. CalypsoElement make_calypso_bitmap_element(const char* key, int size, CalypsoElement* elements) {
  20. CalypsoElement bitmap_element = {};
  21. bitmap_element.type = CALYPSO_ELEMENT_TYPE_BITMAP;
  22. bitmap_element.bitmap = malloc(sizeof(CalypsoBitmapElement));
  23. bitmap_element.bitmap->size = size;
  24. bitmap_element.bitmap->elements = malloc(size * sizeof(CalypsoElement));
  25. for(int i = 0; i < size; i++) {
  26. bitmap_element.bitmap->elements[i] = elements[i];
  27. }
  28. strncpy(bitmap_element.bitmap->key, key, 36);
  29. return bitmap_element;
  30. }
  31. CalypsoElement
  32. make_calypso_container_element(const char* key, int size, CalypsoElement* elements) {
  33. CalypsoElement container_element = {};
  34. container_element.type = CALYPSO_ELEMENT_TYPE_CONTAINER;
  35. container_element.container = malloc(sizeof(CalypsoContainerElement));
  36. container_element.container->size = size;
  37. container_element.container->elements = malloc(size * sizeof(CalypsoElement));
  38. for(int i = 0; i < size; i++) {
  39. container_element.container->elements[i] = elements[i];
  40. }
  41. strncpy(container_element.container->key, key, 36);
  42. return container_element;
  43. }
  44. CalypsoElement make_calypso_repeater_element(const char* key, int size, CalypsoElement element) {
  45. CalypsoElement repeater_element = {};
  46. repeater_element.type = CALYPSO_ELEMENT_TYPE_REPEATER;
  47. repeater_element.repeater = malloc(sizeof(CalypsoRepeaterElement));
  48. repeater_element.repeater->size = size;
  49. repeater_element.repeater->element = element;
  50. strncpy(repeater_element.repeater->key, key, 36);
  51. return repeater_element;
  52. }
  53. void free_calypso_element(CalypsoElement* element) {
  54. if(element->type == CALYPSO_ELEMENT_TYPE_FINAL) {
  55. free(element->final);
  56. } else if(element->type == CALYPSO_ELEMENT_TYPE_BITMAP) {
  57. for(int i = 0; i < element->bitmap->size; i++) {
  58. free_calypso_element(&element->bitmap->elements[i]);
  59. }
  60. free(element->bitmap->elements);
  61. free(element->bitmap);
  62. } else if(element->type == CALYPSO_ELEMENT_TYPE_CONTAINER) {
  63. for(int i = 0; i < element->container->size; i++) {
  64. free_calypso_element(&element->container->elements[i]);
  65. }
  66. free(element->container->elements);
  67. free(element->container);
  68. } else if(element->type == CALYPSO_ELEMENT_TYPE_REPEATER) {
  69. free_calypso_element(&element->repeater->element);
  70. free(element->repeater);
  71. }
  72. }
  73. void free_calypso_structure(CalypsoApp* structure) {
  74. for(int i = 0; i < structure->container->size; i++) {
  75. free_calypso_element(&structure->container->elements[i]);
  76. }
  77. free(structure->container->elements);
  78. free(structure->container);
  79. free(structure);
  80. }
  81. int* get_bitmap_positions(const char* binary_string, int* count) {
  82. int length = strlen(binary_string);
  83. int* positions = malloc(length * sizeof(int));
  84. int pos_index = 0;
  85. for(int i = 0; i < length; i++) {
  86. if(binary_string[length - 1 - i] == '1') {
  87. positions[pos_index++] = i;
  88. }
  89. }
  90. *count = pos_index;
  91. return positions;
  92. }
  93. int is_bit_present(int* positions, int count, int bit) {
  94. for(int i = 0; i < count; i++) {
  95. if(positions[i] == bit) {
  96. return 1;
  97. }
  98. }
  99. return 0;
  100. }
  101. bool is_calypso_subnode_present(
  102. const char* binary_string,
  103. const char* key,
  104. CalypsoBitmapElement* bitmap) {
  105. char bit_slice[bitmap->size + 1];
  106. strncpy(bit_slice, binary_string, bitmap->size);
  107. bit_slice[bitmap->size] = '\0';
  108. int count = 0;
  109. int* positions = get_bitmap_positions(bit_slice, &count);
  110. int offset = bitmap->size;
  111. for(int i = 0; i < count; i++) {
  112. CalypsoElement* element = &bitmap->elements[positions[i]];
  113. if(element->type == CALYPSO_ELEMENT_TYPE_FINAL) {
  114. if(strcmp(element->final->key, key) == 0) {
  115. free(positions);
  116. return true;
  117. }
  118. offset += element->final->size;
  119. } else {
  120. if(strcmp(element->bitmap->key, key) == 0) {
  121. free(positions);
  122. return true;
  123. }
  124. int sub_binary_string_size = element->bitmap->size;
  125. char bit_slice[sub_binary_string_size + 1];
  126. strncpy(bit_slice, binary_string, sub_binary_string_size);
  127. bit_slice[sub_binary_string_size] = '\0';
  128. if(is_calypso_subnode_present(binary_string + offset, key, element->bitmap)) {
  129. free(positions);
  130. return true;
  131. }
  132. offset += element->bitmap->size;
  133. }
  134. }
  135. free(positions);
  136. return false;
  137. }
  138. bool is_calypso_node_present(const char* binary_string, const char* key, CalypsoApp* structure) {
  139. int offset = 0;
  140. for(int i = 0; i < structure->container->size; i++) {
  141. if(structure->container->elements[i].type == CALYPSO_ELEMENT_TYPE_FINAL) {
  142. if(strcmp(structure->container->elements[i].final->key, key) == 0) {
  143. return true;
  144. }
  145. offset += structure->container->elements[i].final->size;
  146. } else {
  147. if(strcmp(structure->container->elements[i].bitmap->key, key) == 0) {
  148. return true;
  149. }
  150. int sub_binary_string_size = structure->container->elements[i].bitmap->size;
  151. char bit_slice[sub_binary_string_size + 1];
  152. strncpy(bit_slice, binary_string, sub_binary_string_size);
  153. bit_slice[sub_binary_string_size] = '\0';
  154. if(is_calypso_subnode_present(
  155. binary_string + offset, key, structure->container->elements[i].bitmap)) {
  156. return true;
  157. }
  158. offset += structure->container->elements[i].bitmap->size;
  159. }
  160. }
  161. return false;
  162. }
  163. int get_calypso_subnode_offset(
  164. const char* binary_string,
  165. const char* key,
  166. CalypsoElement* elem,
  167. bool* found) {
  168. // recursive function to get the offset of a subnode in a calypso binary string
  169. if(elem->type == CALYPSO_ELEMENT_TYPE_FINAL) {
  170. if(strcmp(elem->final->key, key) == 0) {
  171. *found = true;
  172. return 0;
  173. }
  174. return elem->final->size;
  175. } else if(elem->type == CALYPSO_ELEMENT_TYPE_BITMAP) {
  176. CalypsoBitmapElement* bitmap = elem->bitmap;
  177. char bit_slice[bitmap->size + 1];
  178. strncpy(bit_slice, binary_string, bitmap->size);
  179. bit_slice[bitmap->size] = '\0';
  180. int count = 0;
  181. int* positions = get_bitmap_positions(bit_slice, &count);
  182. bool f = false;
  183. int count_offset = bitmap->size;
  184. for(int i = 0; i < count; i++) {
  185. CalypsoElement element = bitmap->elements[positions[i]];
  186. count_offset +=
  187. get_calypso_subnode_offset(binary_string + count_offset, key, &element, &f);
  188. if(f) {
  189. *found = true;
  190. free(positions);
  191. return count_offset;
  192. }
  193. }
  194. free(positions);
  195. return count_offset;
  196. } else if(elem->type == CALYPSO_ELEMENT_TYPE_CONTAINER) {
  197. // same as bitmap but without bitmap at the beginning
  198. CalypsoContainerElement* container = elem->container;
  199. int count_offset = 0;
  200. bool f = false;
  201. for(int i = 0; i < container->size; i++) {
  202. CalypsoElement element = container->elements[i];
  203. count_offset +=
  204. get_calypso_subnode_offset(binary_string + count_offset, key, &element, &f);
  205. if(f) {
  206. *found = true;
  207. return count_offset;
  208. }
  209. }
  210. return count_offset;
  211. } else if(elem->type == CALYPSO_ELEMENT_TYPE_REPEATER) {
  212. // same as bitmap but instead of a bitmap, we have the count of how many times to repeat the inner element
  213. CalypsoRepeaterElement* repeater = elem->repeater;
  214. char bit_slice[repeater->size + 1];
  215. strncpy(bit_slice, binary_string, repeater->size);
  216. bit_slice[repeater->size] = '\0';
  217. int C = bit_slice_to_dec(bit_slice, 0, repeater->size - 1);
  218. int count_offset = repeater->size;
  219. bool f = false;
  220. for(int i = 0; i < C; i++) {
  221. count_offset += get_calypso_subnode_offset(
  222. binary_string + count_offset, key, &repeater->element, &f);
  223. if(f) {
  224. *found = true;
  225. return count_offset;
  226. }
  227. }
  228. }
  229. return 0;
  230. }
  231. int get_calypso_node_offset(const char* binary_string, const char* key, CalypsoApp* structure) {
  232. CalypsoElement* element = malloc(sizeof(CalypsoElement));
  233. element->type = CALYPSO_ELEMENT_TYPE_CONTAINER;
  234. element->container = structure->container;
  235. bool found;
  236. int offset = get_calypso_subnode_offset(binary_string, key, element, &found);
  237. if(!found) {
  238. FURI_LOG_E("Metroflip:Scene:Calypso", "Key %s not found in calypso structure", key);
  239. }
  240. free(element);
  241. return offset;
  242. }
  243. int get_calypso_subnode_size(const char* key, CalypsoElement* element) {
  244. if(element->type == CALYPSO_ELEMENT_TYPE_FINAL) {
  245. if(strcmp(element->final->key, key) == 0) {
  246. return element->final->size;
  247. }
  248. } else if(element->type == CALYPSO_ELEMENT_TYPE_BITMAP) {
  249. if(strcmp(element->bitmap->key, key) == 0) {
  250. return element->bitmap->size;
  251. }
  252. for(int i = 0; i < element->bitmap->size; i++) {
  253. int size = get_calypso_subnode_size(key, &element->bitmap->elements[i]);
  254. if(size != 0) {
  255. return size;
  256. }
  257. }
  258. } else if(element->type == CALYPSO_ELEMENT_TYPE_CONTAINER) {
  259. if(strcmp(element->container->key, key) == 0) {
  260. return element->container->size;
  261. }
  262. for(int i = 0; i < element->container->size; i++) {
  263. int size = get_calypso_subnode_size(key, &element->container->elements[i]);
  264. if(size != 0) {
  265. return size;
  266. }
  267. }
  268. } else if(element->type == CALYPSO_ELEMENT_TYPE_REPEATER) {
  269. if(strcmp(element->repeater->key, key) == 0) {
  270. return element->repeater->size;
  271. }
  272. int size = get_calypso_subnode_size(key, &element->repeater->element);
  273. if(size != 0) {
  274. return size;
  275. }
  276. }
  277. return 0;
  278. }
  279. int get_calypso_node_size(const char* key, CalypsoApp* structure) {
  280. CalypsoElement* element = malloc(sizeof(CalypsoElement));
  281. element->type = CALYPSO_ELEMENT_TYPE_CONTAINER;
  282. element->container = structure->container;
  283. int count = get_calypso_subnode_size(key, element);
  284. free(element);
  285. return count;
  286. }
  287. CALYPSO_CARD_TYPE guess_card_type(int country_num, int network_num) {
  288. switch(country_num) {
  289. case 56:
  290. switch(network_num) {
  291. case 1:
  292. return CALYPSO_CARD_MOBIB;
  293. default:
  294. return CALYPSO_CARD_UNKNOWN;
  295. }
  296. case 124:
  297. switch(network_num) {
  298. case 1:
  299. return CALYPSO_CARD_OPUS;
  300. default:
  301. return CALYPSO_CARD_UNKNOWN;
  302. }
  303. case 131:
  304. return CALYPSO_CARD_VIVA;
  305. case 250:
  306. switch(network_num) {
  307. case 0:
  308. return CALYPSO_CARD_PASSPASS;
  309. case 64:
  310. return CALYPSO_CARD_TAM; // Montpellier
  311. case 149:
  312. return CALYPSO_CARD_TRANSPOLE; // Lille
  313. case 502:
  314. return CALYPSO_CARD_OURA;
  315. case 901:
  316. return CALYPSO_CARD_NAVIGO;
  317. case 908:
  318. return CALYPSO_CARD_KORRIGO;
  319. case 916:
  320. return CALYPSO_CARD_TISSEO;
  321. case 920:
  322. return CALYPSO_CARD_ENVIBUS;
  323. case 921:
  324. return CALYPSO_CARD_GIRONDE;
  325. default:
  326. return CALYPSO_CARD_UNKNOWN;
  327. }
  328. case 376:
  329. return CALYPSO_CARD_RAVKAV;
  330. default:
  331. return CALYPSO_CARD_UNKNOWN;
  332. }
  333. }
  334. const char* get_country_string(int country_num) {
  335. switch(country_num) {
  336. case 56:
  337. return "Belgium";
  338. case 124:
  339. return "Canada";
  340. case 131:
  341. return "Portugal";
  342. case 250:
  343. return "France";
  344. case 376:
  345. return "Israel";
  346. default: {
  347. char* country = malloc(4 * sizeof(char));
  348. snprintf(country, 4, "%d", country_num);
  349. return country;
  350. }
  351. }
  352. }
  353. const char* get_network_string(CALYPSO_CARD_TYPE card_type) {
  354. switch(card_type) {
  355. case CALYPSO_CARD_MOBIB:
  356. return "Mobib";
  357. case CALYPSO_CARD_OPUS:
  358. return "Opus";
  359. case CALYPSO_CARD_VIVA:
  360. return "Viva";
  361. case CALYPSO_CARD_PASSPASS:
  362. return "PassPass";
  363. case CALYPSO_CARD_TAM:
  364. return "TAM";
  365. case CALYPSO_CARD_OURA:
  366. return "Oura";
  367. case CALYPSO_CARD_NAVIGO:
  368. return "IDFM";
  369. case CALYPSO_CARD_KORRIGO:
  370. return "KorriGo";
  371. case CALYPSO_CARD_TISSEO:
  372. return "Tisseo";
  373. case CALYPSO_CARD_ENVIBUS:
  374. return "Envibus";
  375. case CALYPSO_CARD_GIRONDE:
  376. return "Gironde";
  377. case CALYPSO_CARD_RAVKAV:
  378. return "Rav-Kav";
  379. default:
  380. return "Unknown";
  381. }
  382. }