web_crawler_callback.h 35 KB

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