web_crawler_callback.h 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105
  1. // web_crawler_callback.h
  2. static bool sent_http_request = false;
  3. static bool get_success = false;
  4. static bool already_success = false;
  5. static WebCrawlerApp *app_instance = NULL;
  6. // Forward declaration of callback functions
  7. static void web_crawler_setting_item_path_clicked(void *context, uint32_t index);
  8. static void web_crawler_setting_item_headers_clicked(void *context, uint32_t index);
  9. static void web_crawler_setting_item_payload_clicked(void *context, uint32_t index);
  10. static void web_crawler_setting_item_ssid_clicked(void *context, uint32_t index);
  11. static void web_crawler_setting_item_password_clicked(void *context, uint32_t index);
  12. static void web_crawler_setting_item_file_type_clicked(void *context, uint32_t index);
  13. static void web_crawler_setting_item_file_rename_clicked(void *context, uint32_t index);
  14. static void web_crawler_setting_item_file_delete_clicked(void *context, uint32_t index);
  15. static void web_crawler_setting_item_file_read_clicked(void *context, uint32_t index);
  16. static void web_crawler_http_method_change(VariableItem *item)
  17. {
  18. uint8_t index = variable_item_get_current_value_index(item);
  19. variable_item_set_current_value_text(item, http_method_names[index]);
  20. // save the http method
  21. if (app_instance)
  22. {
  23. strncpy(app_instance->http_method, http_method_names[index], strlen(http_method_names[index]) + 1);
  24. // save the settings
  25. save_settings(
  26. app_instance->path,
  27. app_instance->ssid,
  28. app_instance->password,
  29. app_instance->file_rename,
  30. app_instance->file_type,
  31. app_instance->http_method,
  32. app_instance->headers,
  33. app_instance->payload);
  34. }
  35. }
  36. static void web_crawler_view_draw_callback(Canvas *canvas, void *context)
  37. {
  38. UNUSED(context);
  39. if (!app_instance)
  40. {
  41. FURI_LOG_E(TAG, "WebCrawlerApp is NULL");
  42. return;
  43. }
  44. if (!canvas)
  45. {
  46. FURI_LOG_E(TAG, "Canvas is NULL");
  47. return;
  48. }
  49. canvas_clear(canvas);
  50. canvas_set_font(canvas, FontSecondary);
  51. if (fhttp.state == INACTIVE)
  52. {
  53. canvas_draw_str(canvas, 0, 7, "Wifi Dev Board disconnected.");
  54. canvas_draw_str(canvas, 0, 17, "Please connect to the board.");
  55. canvas_draw_str(canvas, 0, 32, "If your board is connected,");
  56. canvas_draw_str(canvas, 0, 42, "make sure you have flashed");
  57. canvas_draw_str(canvas, 0, 52, "your WiFi Devboard with the");
  58. canvas_draw_str(canvas, 0, 62, "latest FlipperHTTP flash.");
  59. return;
  60. }
  61. if (app_instance->path)
  62. {
  63. if (!sent_http_request)
  64. {
  65. snprintf(
  66. fhttp.file_path,
  67. sizeof(fhttp.file_path),
  68. STORAGE_EXT_PATH_PREFIX "/apps_data/web_crawler/received_data.txt");
  69. fhttp.save_received_data = true;
  70. if (strstr(app_instance->http_method, "GET") != NULL)
  71. {
  72. canvas_draw_str(canvas, 0, 10, "Sending GET request...");
  73. fhttp.is_bytes_request = false;
  74. // Perform GET request and handle the response
  75. if (app_instance->headers == NULL || app_instance->headers[0] == '\0' || strstr(app_instance->headers, " ") == NULL)
  76. {
  77. get_success = flipper_http_get_request(app_instance->path);
  78. }
  79. else
  80. {
  81. get_success = flipper_http_get_request_with_headers(app_instance->path, app_instance->headers);
  82. }
  83. }
  84. else if (strstr(app_instance->http_method, "POST") != NULL)
  85. {
  86. canvas_draw_str(canvas, 0, 10, "Sending POST request...");
  87. fhttp.is_bytes_request = false;
  88. // Perform POST request and handle the response
  89. get_success = flipper_http_post_request_with_headers(app_instance->path, app_instance->headers, app_instance->payload);
  90. }
  91. else if (strstr(app_instance->http_method, "PUT") != NULL)
  92. {
  93. canvas_draw_str(canvas, 0, 10, "Sending PUT request...");
  94. fhttp.is_bytes_request = false;
  95. // Perform PUT request and handle the response
  96. get_success = flipper_http_put_request_with_headers(app_instance->path, app_instance->headers, app_instance->payload);
  97. }
  98. else if (strstr(app_instance->http_method, "DELETE") != NULL)
  99. {
  100. canvas_draw_str(canvas, 0, 10, "Sending DELETE request...");
  101. fhttp.is_bytes_request = false;
  102. // Perform DELETE request and handle the response
  103. get_success = flipper_http_delete_request_with_headers(app_instance->path, app_instance->headers, app_instance->payload);
  104. }
  105. else
  106. {
  107. // download file
  108. canvas_draw_str(canvas, 0, 10, "Downloading file...");
  109. fhttp.is_bytes_request = true;
  110. // Perform GET request and handle the response
  111. get_success = flipper_http_get_request_bytes(app_instance->path, app_instance->headers);
  112. }
  113. canvas_draw_str(canvas, 0, 20, "Sent!");
  114. if (get_success)
  115. {
  116. canvas_draw_str(canvas, 0, 30, "Receiving data...");
  117. // Set the state to RECEIVING to ensure we continue to see the receiving message
  118. fhttp.state = RECEIVING;
  119. }
  120. else
  121. {
  122. canvas_draw_str(canvas, 0, 30, "Failed.");
  123. }
  124. sent_http_request = true;
  125. }
  126. else
  127. {
  128. // print state
  129. if (get_success && fhttp.state == RECEIVING)
  130. {
  131. canvas_draw_str(canvas, 0, 10, "Receiving and parsing data...");
  132. }
  133. else if (get_success && fhttp.state == IDLE)
  134. {
  135. canvas_draw_str(canvas, 0, 10, "Data saved to file.");
  136. canvas_draw_str(canvas, 0, 20, "Press BACK to return.");
  137. }
  138. else
  139. {
  140. if (fhttp.state == ISSUE)
  141. {
  142. if (strstr(fhttp.last_response, "[ERROR] Not connected to Wifi. Failed to reconnect.") != NULL)
  143. {
  144. canvas_draw_str(canvas, 0, 10, "[ERROR] Not connected to Wifi.");
  145. canvas_draw_str(canvas, 0, 50, "Update your WiFi settings.");
  146. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  147. }
  148. else if (strstr(fhttp.last_response, "[ERROR] Failed to connect to Wifi.") != NULL)
  149. {
  150. canvas_draw_str(canvas, 0, 10, "[ERROR] Not connected to Wifi.");
  151. canvas_draw_str(canvas, 0, 50, "Update your WiFi settings.");
  152. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  153. }
  154. else if (strstr(fhttp.last_response, "[ERROR] GET request failed with error: connection refused") != NULL)
  155. {
  156. canvas_draw_str(canvas, 0, 10, "[ERROR] Connection refused.");
  157. canvas_draw_str(canvas, 0, 50, "Choose another URL.");
  158. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  159. }
  160. else
  161. {
  162. canvas_draw_str(canvas, 0, 10, "[ERROR] Failed to sync data.");
  163. canvas_draw_str(canvas, 0, 30, "If this is your third attempt,");
  164. canvas_draw_str(canvas, 0, 40, "it's likely your URL is not");
  165. canvas_draw_str(canvas, 0, 50, "compabilbe or correct.");
  166. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  167. }
  168. }
  169. else
  170. {
  171. canvas_draw_str(canvas, 0, 10, "HTTP request failed.");
  172. canvas_draw_str(canvas, 0, 20, "Press BACK to return.");
  173. }
  174. get_success = false;
  175. }
  176. }
  177. }
  178. else
  179. {
  180. canvas_draw_str(canvas, 0, 10, "URL not set.");
  181. }
  182. }
  183. /**
  184. * @brief Navigation callback to handle exiting from other views to the submenu.
  185. * @param context The context - WebCrawlerApp object.
  186. * @return WebCrawlerViewSubmenu
  187. */
  188. static uint32_t web_crawler_back_to_configure_callback(void *context)
  189. {
  190. UNUSED(context);
  191. // free file read widget if it exists
  192. if (app_instance->widget_file_read)
  193. {
  194. widget_reset(app_instance->widget_file_read);
  195. }
  196. return WebCrawlerViewSubmenuConfig; // Return to the configure screen
  197. }
  198. /**
  199. * @brief Navigation callback to handle returning to the Wifi Settings screen.
  200. * @param context The context - WebCrawlerApp object.
  201. * @return WebCrawlerViewSubmenu
  202. */
  203. static uint32_t web_crawler_back_to_main_callback(void *context)
  204. {
  205. UNUSED(context);
  206. // reset GET request flags
  207. sent_http_request = false;
  208. get_success = false;
  209. already_success = false;
  210. // free file read widget if it exists
  211. if (app_instance->widget_file_read)
  212. {
  213. widget_reset(app_instance->widget_file_read);
  214. }
  215. return WebCrawlerViewSubmenuMain; // Return to the main submenu
  216. }
  217. static uint32_t web_crawler_back_to_file_callback(void *context)
  218. {
  219. UNUSED(context);
  220. return WebCrawlerViewVariableItemListFile; // Return to the file submenu
  221. }
  222. static uint32_t web_crawler_back_to_wifi_callback(void *context)
  223. {
  224. UNUSED(context);
  225. return WebCrawlerViewVariableItemListWifi; // Return to the wifi submenu
  226. }
  227. static uint32_t web_crawler_back_to_request_callback(void *context)
  228. {
  229. UNUSED(context);
  230. return WebCrawlerViewVariableItemListRequest; // Return to the request submenu
  231. }
  232. /**
  233. * @brief Navigation callback to handle exiting the app from the main submenu.
  234. * @param context The context - unused
  235. * @return VIEW_NONE to exit the app
  236. */
  237. static uint32_t web_crawler_exit_app_callback(void *context)
  238. {
  239. UNUSED(context);
  240. return VIEW_NONE;
  241. }
  242. /**
  243. * @brief Handle submenu item selection.
  244. * @param context The context - WebCrawlerApp object.
  245. * @param index The WebCrawlerSubmenuIndex item that was clicked.
  246. */
  247. static void web_crawler_submenu_callback(void *context, uint32_t index)
  248. {
  249. WebCrawlerApp *app = (WebCrawlerApp *)context;
  250. if (app->view_dispatcher)
  251. {
  252. switch (index)
  253. {
  254. case WebCrawlerSubmenuIndexRun:
  255. sent_http_request = false; // Reset the flag
  256. view_dispatcher_switch_to_view(app->view_dispatcher, WebCrawlerViewRun);
  257. break;
  258. case WebCrawlerSubmenuIndexAbout:
  259. view_dispatcher_switch_to_view(app->view_dispatcher, WebCrawlerViewAbout);
  260. break;
  261. case WebCrawlerSubmenuIndexConfig:
  262. view_dispatcher_switch_to_view(app->view_dispatcher, WebCrawlerViewSubmenuConfig);
  263. break;
  264. case WebCrawlerSubmenuIndexWifi:
  265. view_dispatcher_switch_to_view(app->view_dispatcher, WebCrawlerViewVariableItemListWifi);
  266. break;
  267. case WebCrawlerSubmenuIndexRequest:
  268. view_dispatcher_switch_to_view(app->view_dispatcher, WebCrawlerViewVariableItemListRequest);
  269. break;
  270. case WebCrawlerSubmenuIndexFile:
  271. view_dispatcher_switch_to_view(app->view_dispatcher, WebCrawlerViewVariableItemListFile);
  272. break;
  273. default:
  274. FURI_LOG_E(TAG, "Unknown submenu index");
  275. break;
  276. }
  277. }
  278. }
  279. /**
  280. * @brief Configuration enter callback to handle different items.
  281. * @param context The context - WebCrawlerApp object.
  282. * @param index The index of the item that was clicked.
  283. */
  284. static void web_crawler_wifi_enter_callback(void *context, uint32_t index)
  285. {
  286. switch (index)
  287. {
  288. case 0: // SSID
  289. web_crawler_setting_item_ssid_clicked(context, index);
  290. break;
  291. case 1: // Password
  292. web_crawler_setting_item_password_clicked(context, index);
  293. break;
  294. default:
  295. FURI_LOG_E(TAG, "Unknown configuration item index");
  296. break;
  297. }
  298. }
  299. /**
  300. * @brief Configuration enter callback to handle different items.
  301. * @param context The context - WebCrawlerApp object.
  302. * @param index The index of the item that was clicked.
  303. */
  304. static void web_crawler_file_enter_callback(void *context, uint32_t index)
  305. {
  306. switch (index)
  307. {
  308. case 0: // File Read
  309. web_crawler_setting_item_file_read_clicked(context, index);
  310. break;
  311. case 1: // FIle Type
  312. web_crawler_setting_item_file_type_clicked(context, index);
  313. break;
  314. case 2: // File Rename
  315. web_crawler_setting_item_file_rename_clicked(context, index);
  316. break;
  317. case 3: // File Delete
  318. web_crawler_setting_item_file_delete_clicked(context, index);
  319. break;
  320. default:
  321. FURI_LOG_E(TAG, "Unknown configuration item index");
  322. break;
  323. }
  324. }
  325. /**
  326. * @brief Configuration enter callback to handle different items.
  327. * @param context The context - WebCrawlerApp object.
  328. * @param index The index of the item that was clicked.
  329. */
  330. static void web_crawler_request_enter_callback(void *context, uint32_t index)
  331. {
  332. switch (index)
  333. {
  334. case 0: // URL
  335. web_crawler_setting_item_path_clicked(context, index);
  336. break;
  337. case 1:
  338. // HTTP Method
  339. break;
  340. case 2:
  341. // Headers
  342. web_crawler_setting_item_headers_clicked(context, index);
  343. break;
  344. case 3:
  345. // Payload
  346. web_crawler_setting_item_payload_clicked(context, index);
  347. break;
  348. default:
  349. FURI_LOG_E(TAG, "Unknown configuration item index");
  350. break;
  351. }
  352. }
  353. /**
  354. * @brief Callback for when the user finishes entering the URL.
  355. * @param context The context - WebCrawlerApp object.
  356. */
  357. static void web_crawler_set_path_updated(void *context)
  358. {
  359. WebCrawlerApp *app = (WebCrawlerApp *)context;
  360. if (!app)
  361. {
  362. FURI_LOG_E(TAG, "WebCrawlerApp is NULL");
  363. return;
  364. }
  365. if (!app->path || !app->temp_buffer_path || !app->temp_buffer_size_path || !app->path_item)
  366. {
  367. FURI_LOG_E(TAG, "Invalid path buffer");
  368. return;
  369. }
  370. // Store the entered URL from temp_buffer_path to path
  371. strncpy(app->path, app->temp_buffer_path, app->temp_buffer_size_path - 1);
  372. if (app->path_item)
  373. {
  374. variable_item_set_current_value_text(app->path_item, app->path);
  375. // Save the URL to the settings
  376. save_settings(app->path, app->ssid, app->password, app->file_rename, app->file_type, app->http_method, app->headers, app->payload);
  377. }
  378. // Return to the Configure view
  379. view_dispatcher_switch_to_view(app->view_dispatcher, WebCrawlerViewVariableItemListRequest);
  380. }
  381. /**
  382. * @brief Callback for when the user finishes entering the headers
  383. * @param context The context - WebCrawlerApp object.
  384. */
  385. static void web_crawler_set_headers_updated(void *context)
  386. {
  387. WebCrawlerApp *app = (WebCrawlerApp *)context;
  388. if (!app)
  389. {
  390. FURI_LOG_E(TAG, "WebCrawlerApp is NULL");
  391. return;
  392. }
  393. if (!app->temp_buffer_headers || !app->temp_buffer_size_headers || !app->headers_item)
  394. {
  395. FURI_LOG_E(TAG, "Invalid headers buffer");
  396. return;
  397. }
  398. // Store the entered headers from temp_buffer_headers to headers
  399. strncpy(app->headers, app->temp_buffer_headers, app->temp_buffer_size_headers - 1);
  400. if (app->headers_item)
  401. {
  402. variable_item_set_current_value_text(app->headers_item, app->headers);
  403. // Save the headers to the settings
  404. save_settings(app->path, app->ssid, app->password, app->file_rename, app->file_type, app->http_method, app->headers, app->payload);
  405. }
  406. // Return to the Configure view
  407. view_dispatcher_switch_to_view(app->view_dispatcher, WebCrawlerViewVariableItemListRequest);
  408. }
  409. /**
  410. * @brief Callback for when the user finishes entering the payload.
  411. * @param context The context - WebCrawlerApp object.
  412. */
  413. static void web_crawler_set_payload_updated(void *context)
  414. {
  415. WebCrawlerApp *app = (WebCrawlerApp *)context;
  416. if (!app)
  417. {
  418. FURI_LOG_E(TAG, "WebCrawlerApp is NULL");
  419. return;
  420. }
  421. if (!app->temp_buffer_payload || !app->temp_buffer_size_payload || !app->payload_item)
  422. {
  423. FURI_LOG_E(TAG, "Invalid payload buffer");
  424. return;
  425. }
  426. // Store the entered payload from temp_buffer_payload to payload
  427. strncpy(app->payload, app->temp_buffer_payload, app->temp_buffer_size_payload - 1);
  428. if (app->payload_item)
  429. {
  430. variable_item_set_current_value_text(app->payload_item, app->payload);
  431. // Save the payload to the settings
  432. save_settings(app->path, app->ssid, app->password, app->file_rename, app->file_type, app->http_method, app->headers, app->payload);
  433. }
  434. // Return to the Configure view
  435. view_dispatcher_switch_to_view(app->view_dispatcher, WebCrawlerViewVariableItemListRequest);
  436. }
  437. /**
  438. * @brief Callback for when the user finishes entering the SSID.
  439. * @param context The context - WebCrawlerApp object.
  440. */
  441. static void web_crawler_set_ssid_updated(void *context)
  442. {
  443. WebCrawlerApp *app = (WebCrawlerApp *)context;
  444. if (!app)
  445. {
  446. FURI_LOG_E(TAG, "WebCrawlerApp is NULL");
  447. return;
  448. }
  449. if (!app->temp_buffer_ssid || !app->temp_buffer_size_ssid || !app->ssid || !app->ssid_item)
  450. {
  451. FURI_LOG_E(TAG, "Invalid SSID buffer");
  452. return;
  453. }
  454. // Store the entered SSID from temp_buffer_ssid to ssid
  455. strncpy(app->ssid, app->temp_buffer_ssid, app->temp_buffer_size_ssid - 1);
  456. if (app->ssid_item)
  457. {
  458. variable_item_set_current_value_text(app->ssid_item, app->ssid);
  459. // Save the SSID to the settings
  460. save_settings(app->path, app->ssid, app->password, app->file_rename, app->file_type, app->http_method, app->headers, app->payload);
  461. // send to UART
  462. if (!flipper_http_save_wifi(app->ssid, app->password))
  463. {
  464. FURI_LOG_E(TAG, "Failed to save wifi settings via UART");
  465. FURI_LOG_E(TAG, "Make sure the Flipper is connected to the Wifi Dev Board");
  466. }
  467. }
  468. // Return to the Configure view
  469. view_dispatcher_switch_to_view(app->view_dispatcher, WebCrawlerViewVariableItemListWifi);
  470. }
  471. /**
  472. * @brief Callback for when the user finishes entering the Password.
  473. * @param context The context - WebCrawlerApp object.
  474. */
  475. static void web_crawler_set_password_update(void *context)
  476. {
  477. WebCrawlerApp *app = (WebCrawlerApp *)context;
  478. if (!app)
  479. {
  480. FURI_LOG_E(TAG, "WebCrawlerApp is NULL");
  481. return;
  482. }
  483. if (!app->temp_buffer_password || !app->temp_buffer_size_password || !app->password || !app->password_item)
  484. {
  485. FURI_LOG_E(TAG, "Invalid password buffer");
  486. return;
  487. }
  488. // Store the entered Password from temp_buffer_password to password
  489. strncpy(app->password, app->temp_buffer_password, app->temp_buffer_size_password - 1);
  490. if (app->password_item)
  491. {
  492. variable_item_set_current_value_text(app->password_item, app->password);
  493. // Save the Password to the settings
  494. save_settings(app->path, app->ssid, app->password, app->file_rename, app->file_type, app->http_method, app->headers, app->payload);
  495. // send to UART
  496. if (!flipper_http_save_wifi(app->ssid, app->password))
  497. {
  498. FURI_LOG_E(TAG, "Failed to save wifi settings via UART");
  499. FURI_LOG_E(TAG, "Make sure the Flipper is connected to the Wifi Dev Board");
  500. }
  501. }
  502. // Return to the Configure view
  503. view_dispatcher_switch_to_view(app->view_dispatcher, WebCrawlerViewVariableItemListWifi);
  504. }
  505. /**
  506. * @brief Callback for when the user finishes entering the File Type.
  507. * @param context The context - WebCrawlerApp object.
  508. */
  509. static void web_crawler_set_file_type_update(void *context)
  510. {
  511. WebCrawlerApp *app = (WebCrawlerApp *)context;
  512. if (!app)
  513. {
  514. FURI_LOG_E(TAG, "WebCrawlerApp is NULL");
  515. return;
  516. }
  517. if (!app->temp_buffer_file_type || !app->temp_buffer_size_file_type || !app->file_type || !app->file_type_item)
  518. {
  519. FURI_LOG_E(TAG, "Invalid file type buffer");
  520. return;
  521. }
  522. // Temporary buffer to store the old name
  523. char old_file_type[256];
  524. strncpy(old_file_type, app->file_type, sizeof(old_file_type) - 1);
  525. old_file_type[sizeof(old_file_type) - 1] = '\0'; // Null-terminate
  526. strncpy(app->file_type, app->temp_buffer_file_type, app->temp_buffer_size_file_type - 1);
  527. if (app->file_type_item)
  528. {
  529. variable_item_set_current_value_text(app->file_type_item, app->file_type);
  530. // Save the File Type to the settings
  531. save_settings(app->path, app->ssid, app->password, app->file_rename, app->file_type, app->http_method, app->headers, app->payload);
  532. }
  533. rename_received_data(app->file_rename, app->file_rename, app->file_type, old_file_type);
  534. // set the file path for fhttp.file_path
  535. if (app->file_rename && app->file_type)
  536. {
  537. char file_path[256];
  538. snprintf(file_path, sizeof(file_path), "%s%s%s", RECEIVED_DATA_PATH, app->file_rename, app->file_type);
  539. file_path[sizeof(file_path) - 1] = '\0'; // Null-terminate
  540. strncpy(fhttp.file_path, file_path, sizeof(fhttp.file_path) - 1);
  541. fhttp.file_path[sizeof(fhttp.file_path) - 1] = '\0'; // Null-terminate
  542. }
  543. // Return to the Configure view
  544. view_dispatcher_switch_to_view(app->view_dispatcher, WebCrawlerViewVariableItemListFile);
  545. }
  546. /**
  547. * @brief Callback for when the user finishes entering the File Rename.
  548. * @param context The context - WebCrawlerApp object.
  549. */
  550. static void web_crawler_set_file_rename_update(void *context)
  551. {
  552. WebCrawlerApp *app = (WebCrawlerApp *)context;
  553. if (!app)
  554. {
  555. FURI_LOG_E(TAG, "WebCrawlerApp is NULL");
  556. return;
  557. }
  558. if (!app->temp_buffer_file_rename || !app->temp_buffer_size_file_rename || !app->file_rename || !app->file_rename_item)
  559. {
  560. FURI_LOG_E(TAG, "Invalid file rename buffer");
  561. return;
  562. }
  563. // Temporary buffer to store the old name
  564. char old_name[256];
  565. // Ensure that app->file_rename is null-terminated
  566. strncpy(old_name, app->file_rename, sizeof(old_name) - 1);
  567. old_name[sizeof(old_name) - 1] = '\0'; // Null-terminate
  568. // Store the entered File Rename from temp_buffer_file_rename to file_rename
  569. strncpy(app->file_rename, app->temp_buffer_file_rename, app->temp_buffer_size_file_rename - 1);
  570. if (app->file_rename_item)
  571. {
  572. variable_item_set_current_value_text(app->file_rename_item, app->file_rename);
  573. // Save the File Rename to the settings
  574. save_settings(app->path, app->ssid, app->password, app->file_rename, app->file_type, app->http_method, app->headers, app->payload);
  575. }
  576. rename_received_data(old_name, app->file_rename, app->file_type, app->file_type);
  577. // set the file path for fhttp.file_path
  578. if (app->file_rename && app->file_type)
  579. {
  580. char file_path[256];
  581. snprintf(file_path, sizeof(file_path), "%s%s%s", RECEIVED_DATA_PATH, app->file_rename, app->file_type);
  582. file_path[sizeof(file_path) - 1] = '\0'; // Null-terminate
  583. strncpy(fhttp.file_path, file_path, sizeof(fhttp.file_path) - 1);
  584. fhttp.file_path[sizeof(fhttp.file_path) - 1] = '\0'; // Null-terminate
  585. }
  586. // Return to the Configure view
  587. view_dispatcher_switch_to_view(app->view_dispatcher, WebCrawlerViewVariableItemListFile);
  588. }
  589. /**
  590. * @brief Handler for Path configuration item click.
  591. * @param context The context - WebCrawlerApp object.
  592. * @param index The index of the item that was clicked.
  593. */
  594. static void web_crawler_setting_item_path_clicked(void *context, uint32_t index)
  595. {
  596. WebCrawlerApp *app = (WebCrawlerApp *)context;
  597. if (!app)
  598. {
  599. FURI_LOG_E(TAG, "WebCrawlerApp is NULL");
  600. return;
  601. }
  602. if (!app->text_input_path)
  603. {
  604. FURI_LOG_E(TAG, "Text input is NULL");
  605. return;
  606. }
  607. UNUSED(index);
  608. // Initialize temp_buffer with existing path
  609. if (app->path && strlen(app->path) > 0)
  610. {
  611. strncpy(app->temp_buffer_path, app->path, app->temp_buffer_size_path - 1);
  612. }
  613. else
  614. {
  615. strncpy(app->temp_buffer_path, "https://httpbin.org/get", app->temp_buffer_size_path - 1);
  616. }
  617. app->temp_buffer_path[app->temp_buffer_size_path - 1] = '\0';
  618. // Configure the text input
  619. bool clear_previous_text = false;
  620. uart_text_input_set_result_callback(
  621. app->text_input_path,
  622. web_crawler_set_path_updated,
  623. app,
  624. app->temp_buffer_path,
  625. app->temp_buffer_size_path,
  626. clear_previous_text);
  627. // Set the previous callback to return to Configure screen
  628. view_set_previous_callback(
  629. uart_text_input_get_view(app->text_input_path),
  630. web_crawler_back_to_request_callback);
  631. // Show text input dialog
  632. view_dispatcher_switch_to_view(app->view_dispatcher, WebCrawlerViewTextInput);
  633. }
  634. /**
  635. * @brief Handler for headers configuration item click.
  636. * @param context The context - WebCrawlerApp object.
  637. * @param index The index of the item that was clicked.
  638. */
  639. static void web_crawler_setting_item_headers_clicked(void *context, uint32_t index)
  640. {
  641. WebCrawlerApp *app = (WebCrawlerApp *)context;
  642. if (!app)
  643. {
  644. FURI_LOG_E(TAG, "WebCrawlerApp is NULL");
  645. return;
  646. }
  647. UNUSED(index);
  648. if (!app->text_input_headers)
  649. {
  650. FURI_LOG_E(TAG, "Text input is NULL");
  651. return;
  652. }
  653. if (!app->headers)
  654. {
  655. FURI_LOG_E(TAG, "Headers is NULL");
  656. return;
  657. }
  658. if (!app->temp_buffer_headers)
  659. {
  660. FURI_LOG_E(TAG, "Temp buffer headers is NULL");
  661. return;
  662. }
  663. // Initialize temp_buffer with existing headers
  664. if (app->headers && strlen(app->headers) > 0)
  665. {
  666. strncpy(app->temp_buffer_headers, app->headers, app->temp_buffer_size_headers - 1);
  667. }
  668. else
  669. {
  670. strncpy(app->temp_buffer_headers, "{\"Content-Type\":\"application/json\",\"key\":\"value\"}", app->temp_buffer_size_headers - 1);
  671. }
  672. app->temp_buffer_headers[app->temp_buffer_size_headers - 1] = '\0';
  673. // Configure the text input
  674. bool clear_previous_text = false;
  675. uart_text_input_set_result_callback(
  676. app->text_input_headers,
  677. web_crawler_set_headers_updated,
  678. app,
  679. app->temp_buffer_headers,
  680. app->temp_buffer_size_headers,
  681. clear_previous_text);
  682. // Set the previous callback to return to Configure screen
  683. view_set_previous_callback(
  684. uart_text_input_get_view(app->text_input_headers),
  685. web_crawler_back_to_request_callback);
  686. // Show text input dialog
  687. view_dispatcher_switch_to_view(app->view_dispatcher, WebCrawlerViewTextInputHeaders);
  688. }
  689. /**
  690. * @brief Handler for payload configuration item click.
  691. * @param context The context - WebCrawlerApp object.
  692. * @param index The index of the item that was clicked.
  693. */
  694. static void web_crawler_setting_item_payload_clicked(void *context, uint32_t index)
  695. {
  696. WebCrawlerApp *app = (WebCrawlerApp *)context;
  697. if (!app)
  698. {
  699. FURI_LOG_E(TAG, "WebCrawlerApp is NULL");
  700. return;
  701. }
  702. UNUSED(index);
  703. if (!app->text_input_payload)
  704. {
  705. FURI_LOG_E(TAG, "Text input is NULL");
  706. return;
  707. }
  708. // Initialize temp_buffer with existing payload
  709. if (app->payload && strlen(app->payload) > 0)
  710. {
  711. strncpy(app->temp_buffer_payload, app->payload, app->temp_buffer_size_payload - 1);
  712. }
  713. else
  714. {
  715. strncpy(app->temp_buffer_payload, "{\"key\":\"value\"}", app->temp_buffer_size_payload - 1);
  716. }
  717. app->temp_buffer_payload[app->temp_buffer_size_payload - 1] = '\0';
  718. // Configure the text input
  719. bool clear_previous_text = false;
  720. uart_text_input_set_result_callback(
  721. app->text_input_payload,
  722. web_crawler_set_payload_updated,
  723. app,
  724. app->temp_buffer_payload,
  725. app->temp_buffer_size_payload,
  726. clear_previous_text);
  727. // Set the previous callback to return to Configure screen
  728. view_set_previous_callback(
  729. uart_text_input_get_view(app->text_input_payload),
  730. web_crawler_back_to_request_callback);
  731. // Show text input dialog
  732. view_dispatcher_switch_to_view(app->view_dispatcher, WebCrawlerViewTextInputPayload);
  733. }
  734. /**
  735. * @brief Handler for SSID configuration item click.
  736. * @param context The context - WebCrawlerApp object.
  737. * @param index The index of the item that was clicked.
  738. */
  739. static void web_crawler_setting_item_ssid_clicked(void *context, uint32_t index)
  740. {
  741. WebCrawlerApp *app = (WebCrawlerApp *)context;
  742. if (!app)
  743. {
  744. FURI_LOG_E(TAG, "WebCrawlerApp is NULL");
  745. return;
  746. }
  747. UNUSED(index);
  748. if (!app->text_input_ssid)
  749. {
  750. FURI_LOG_E(TAG, "Text input is NULL");
  751. return;
  752. }
  753. // Initialize temp_buffer with existing SSID
  754. if (app->ssid && strlen(app->ssid) > 0)
  755. {
  756. strncpy(app->temp_buffer_ssid, app->ssid, app->temp_buffer_size_ssid - 1);
  757. }
  758. else
  759. {
  760. strncpy(app->temp_buffer_ssid, "", app->temp_buffer_size_ssid - 1);
  761. }
  762. app->temp_buffer_ssid[app->temp_buffer_size_ssid - 1] = '\0';
  763. // Configure the text input
  764. bool clear_previous_text = false;
  765. uart_text_input_set_result_callback(
  766. app->text_input_ssid,
  767. web_crawler_set_ssid_updated,
  768. app,
  769. app->temp_buffer_ssid,
  770. app->temp_buffer_size_ssid,
  771. clear_previous_text);
  772. // Set the previous callback to return to Configure screen
  773. view_set_previous_callback(
  774. uart_text_input_get_view(app->text_input_ssid),
  775. web_crawler_back_to_wifi_callback);
  776. // Show text input dialog
  777. view_dispatcher_switch_to_view(app->view_dispatcher, WebCrawlerViewTextInputSSID);
  778. }
  779. /**
  780. * @brief Handler for Password configuration item click.
  781. * @param context The context - WebCrawlerApp object.
  782. * @param index The index of the item that was clicked.
  783. */
  784. static void web_crawler_setting_item_password_clicked(void *context, uint32_t index)
  785. {
  786. WebCrawlerApp *app = (WebCrawlerApp *)context;
  787. if (!app)
  788. {
  789. FURI_LOG_E(TAG, "WebCrawlerApp is NULL");
  790. return;
  791. }
  792. UNUSED(index);
  793. if (!app->text_input_password)
  794. {
  795. FURI_LOG_E(TAG, "Text input is NULL");
  796. return;
  797. }
  798. // Initialize temp_buffer with existing password
  799. strncpy(app->temp_buffer_password, app->password, app->temp_buffer_size_password - 1);
  800. app->temp_buffer_password[app->temp_buffer_size_password - 1] = '\0';
  801. // Configure the text input
  802. bool clear_previous_text = false;
  803. uart_text_input_set_result_callback(
  804. app->text_input_password,
  805. web_crawler_set_password_update,
  806. app,
  807. app->temp_buffer_password,
  808. app->temp_buffer_size_password,
  809. clear_previous_text);
  810. // Set the previous callback to return to Configure screen
  811. view_set_previous_callback(
  812. uart_text_input_get_view(app->text_input_password),
  813. web_crawler_back_to_wifi_callback);
  814. // Show text input dialog
  815. view_dispatcher_switch_to_view(app->view_dispatcher, WebCrawlerViewTextInputPassword);
  816. }
  817. /**
  818. * @brief Handler for File Type configuration item click.
  819. * @param context The context - WebCrawlerApp object.
  820. * @param index The index of the item that was clicked.
  821. */
  822. static void web_crawler_setting_item_file_type_clicked(void *context, uint32_t index)
  823. {
  824. WebCrawlerApp *app = (WebCrawlerApp *)context;
  825. if (!app)
  826. {
  827. FURI_LOG_E(TAG, "WebCrawlerApp is NULL");
  828. return;
  829. }
  830. UNUSED(index);
  831. if (!app->text_input_file_type)
  832. {
  833. FURI_LOG_E(TAG, "Text input is NULL");
  834. return;
  835. }
  836. // Initialize temp_buffer with existing file_type
  837. if (app->file_type && strlen(app->file_type) > 0)
  838. {
  839. strncpy(app->temp_buffer_file_type, app->file_type, app->temp_buffer_size_file_type - 1);
  840. }
  841. else
  842. {
  843. strncpy(app->temp_buffer_file_type, ".txt", app->temp_buffer_size_file_type - 1);
  844. }
  845. app->temp_buffer_file_type[app->temp_buffer_size_file_type - 1] = '\0';
  846. // Configure the text input
  847. bool clear_previous_text = false;
  848. uart_text_input_set_result_callback(
  849. app->text_input_file_type,
  850. web_crawler_set_file_type_update,
  851. app,
  852. app->temp_buffer_file_type,
  853. app->temp_buffer_size_file_type,
  854. clear_previous_text);
  855. // Set the previous callback to return to Configure screen
  856. view_set_previous_callback(
  857. uart_text_input_get_view(app->text_input_file_type),
  858. web_crawler_back_to_file_callback);
  859. // Show text input dialog
  860. view_dispatcher_switch_to_view(app->view_dispatcher, WebCrawlerViewTextInputFileType);
  861. }
  862. /**
  863. * @brief Handler for File Rename configuration item click.
  864. * @param context The context - WebCrawlerApp object.
  865. * @param index The index of the item that was clicked.
  866. */
  867. static void web_crawler_setting_item_file_rename_clicked(void *context, uint32_t index)
  868. {
  869. WebCrawlerApp *app = (WebCrawlerApp *)context;
  870. if (!app)
  871. {
  872. FURI_LOG_E(TAG, "WebCrawlerApp is NULL");
  873. return;
  874. }
  875. UNUSED(index);
  876. if (!app->text_input_file_rename)
  877. {
  878. FURI_LOG_E(TAG, "Text input is NULL");
  879. return;
  880. }
  881. // Initialize temp_buffer with existing file_rename
  882. if (app->file_rename && strlen(app->file_rename) > 0)
  883. {
  884. strncpy(app->temp_buffer_file_rename, app->file_rename, app->temp_buffer_size_file_rename - 1);
  885. }
  886. else
  887. {
  888. strncpy(app->temp_buffer_file_rename, "received_data", app->temp_buffer_size_file_rename - 1);
  889. }
  890. app->temp_buffer_file_rename[app->temp_buffer_size_file_rename - 1] = '\0';
  891. // Configure the text input
  892. bool clear_previous_text = false;
  893. uart_text_input_set_result_callback(
  894. app->text_input_file_rename,
  895. web_crawler_set_file_rename_update,
  896. app,
  897. app->temp_buffer_file_rename,
  898. app->temp_buffer_size_file_rename,
  899. clear_previous_text);
  900. // Set the previous callback to return to Configure screen
  901. view_set_previous_callback(
  902. uart_text_input_get_view(app->text_input_file_rename),
  903. web_crawler_back_to_file_callback);
  904. // Show text input dialog
  905. view_dispatcher_switch_to_view(app->view_dispatcher, WebCrawlerViewTextInputFileRename);
  906. }
  907. /**
  908. * @brief Handler for File Delete configuration item click.
  909. * @param context The context - WebCrawlerApp object.
  910. * @param index The index of the item that was clicked.
  911. */
  912. static void web_crawler_setting_item_file_delete_clicked(void *context, uint32_t index)
  913. {
  914. WebCrawlerApp *app = (WebCrawlerApp *)context;
  915. if (!app)
  916. {
  917. FURI_LOG_E(TAG, "WebCrawlerApp is NULL");
  918. return;
  919. }
  920. UNUSED(index);
  921. if (!delete_received_data(app))
  922. {
  923. FURI_LOG_E(TAG, "Failed to delete file");
  924. }
  925. // Set the previous callback to return to Configure screen
  926. view_set_previous_callback(
  927. widget_get_view(app->widget_file_delete),
  928. web_crawler_back_to_file_callback);
  929. // Show text input dialog
  930. view_dispatcher_switch_to_view(app->view_dispatcher, WebCrawlerViewFileDelete);
  931. }
  932. static void web_crawler_setting_item_file_read_clicked(void *context, uint32_t index)
  933. {
  934. WebCrawlerApp *app = (WebCrawlerApp *)context;
  935. if (!app)
  936. {
  937. FURI_LOG_E(TAG, "WebCrawlerApp is NULL");
  938. return;
  939. }
  940. UNUSED(index);
  941. widget_reset(app->widget_file_read);
  942. // load the received data from the saved file
  943. FuriString *received_data = flipper_http_load_from_file(fhttp.file_path);
  944. if (received_data == NULL)
  945. {
  946. FURI_LOG_E(TAG, "Failed to load received data from file.");
  947. if (app->widget_file_read)
  948. {
  949. widget_add_text_scroll_element(
  950. app->widget_file_read,
  951. 0,
  952. 0,
  953. 128,
  954. 64, "File is empty.");
  955. view_dispatcher_switch_to_view(app->view_dispatcher, WebCrawlerViewFileRead);
  956. }
  957. return;
  958. }
  959. const char *data_cstr = furi_string_get_cstr(received_data);
  960. if (data_cstr == NULL)
  961. {
  962. FURI_LOG_E(TAG, "Failed to get C-string from FuriString.");
  963. furi_string_free(received_data);
  964. if (app->widget_file_read)
  965. {
  966. widget_add_text_scroll_element(
  967. app->widget_file_read,
  968. 0,
  969. 0,
  970. 128,
  971. 64, "File is empty.");
  972. view_dispatcher_switch_to_view(app->view_dispatcher, WebCrawlerViewFileRead);
  973. }
  974. return;
  975. }
  976. widget_add_text_scroll_element(app_instance->widget_file_read, 0, 0, 128, 64, data_cstr);
  977. furi_string_free(received_data);
  978. // Set the previous callback to return to Configure screen
  979. view_set_previous_callback(
  980. widget_get_view(app->widget_file_read),
  981. web_crawler_back_to_file_callback);
  982. // Show text input dialog
  983. view_dispatcher_switch_to_view(app->view_dispatcher, WebCrawlerViewFileRead);
  984. }