web_crawler_callback.c 37 KB

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