web_crawler_callback.c 37 KB

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