flip_wifi_storage.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. #include <flip_storage/flip_wifi_storage.h>
  2. char *app_ids[8] = {
  3. "flip_wifi",
  4. "flip_store",
  5. "flip_social",
  6. "flip_trader",
  7. "flip_weather",
  8. "flip_library",
  9. "web_crawler",
  10. "flip_rss"};
  11. // Function to save the playlist
  12. void save_playlist(WiFiPlaylist *playlist)
  13. {
  14. if (!playlist)
  15. {
  16. FURI_LOG_E(TAG, "Playlist is NULL");
  17. return;
  18. }
  19. // Create the directory for saving settings
  20. char directory_path[128];
  21. snprintf(directory_path, sizeof(directory_path), STORAGE_EXT_PATH_PREFIX "/apps_data/flip_wifi");
  22. // Open storage
  23. Storage *storage = furi_record_open(RECORD_STORAGE);
  24. if (!storage)
  25. {
  26. FURI_LOG_E(TAG, "Failed to open storage record");
  27. return;
  28. }
  29. // Create the directory
  30. storage_common_mkdir(storage, directory_path);
  31. // Open the settings file
  32. File *file = storage_file_alloc(storage);
  33. if (!file)
  34. {
  35. FURI_LOG_E(TAG, "Failed to allocate file handle");
  36. furi_record_close(RECORD_STORAGE);
  37. return;
  38. }
  39. if (!storage_file_open(file, WIFI_SSID_LIST_PATH, FSAM_WRITE, FSOM_CREATE_ALWAYS))
  40. {
  41. FURI_LOG_E(TAG, "Failed to open settings file for writing: %s", WIFI_SSID_LIST_PATH);
  42. storage_file_free(file);
  43. furi_record_close(RECORD_STORAGE);
  44. return;
  45. }
  46. for (size_t i = 0; i < playlist->count; i++)
  47. {
  48. if (!playlist->ssids[i] || !playlist->passwords[i])
  49. {
  50. FURI_LOG_E(TAG, "Invalid SSID or password at index %zu", i);
  51. continue;
  52. }
  53. size_t ssid_length = strlen(playlist->ssids[i]);
  54. size_t password_length = strlen(playlist->passwords[i]);
  55. if (storage_file_write(file, playlist->ssids[i], ssid_length) != ssid_length ||
  56. storage_file_write(file, ",", 1) != 1 ||
  57. storage_file_write(file, playlist->passwords[i], password_length) != password_length ||
  58. storage_file_write(file, "\n", 1) != 1)
  59. {
  60. FURI_LOG_E(TAG, "Failed to write playlist");
  61. }
  62. }
  63. storage_file_close(file);
  64. storage_file_free(file);
  65. furi_record_close(RECORD_STORAGE);
  66. }
  67. // Function to load the playlist
  68. bool load_playlist(WiFiPlaylist *playlist)
  69. {
  70. if (!playlist)
  71. {
  72. FURI_LOG_E(TAG, "Playlist is NULL");
  73. return false;
  74. }
  75. // Initialize playlist count
  76. playlist->count = 0;
  77. // Allocate memory for SSIDs and passwords if not already allocated
  78. for (size_t i = 0; i < MAX_WIFI_NETWORKS; i++)
  79. {
  80. if (!playlist->ssids[i])
  81. {
  82. playlist->ssids[i] = malloc(64); // Adjust size as needed
  83. if (!playlist->ssids[i])
  84. {
  85. FURI_LOG_E(TAG, "Memory allocation failed for ssids[%zu]", i);
  86. // Handle memory allocation failure (e.g., clean up and return)
  87. return false;
  88. }
  89. }
  90. if (!playlist->passwords[i])
  91. {
  92. playlist->passwords[i] = malloc(64); // Adjust size as needed
  93. if (!playlist->passwords[i])
  94. {
  95. FURI_LOG_E(TAG, "Memory allocation failed for passwords[%zu]", i);
  96. // Handle memory allocation failure (e.g., clean up and return)
  97. return false;
  98. }
  99. }
  100. }
  101. // Open the settings file
  102. Storage *storage = furi_record_open(RECORD_STORAGE);
  103. if (!storage)
  104. {
  105. FURI_LOG_E(TAG, "Failed to open storage record");
  106. return false;
  107. }
  108. File *file = storage_file_alloc(storage);
  109. if (!file)
  110. {
  111. FURI_LOG_E(TAG, "Failed to allocate file handle");
  112. furi_record_close(RECORD_STORAGE);
  113. return false;
  114. }
  115. if (!storage_file_open(file, WIFI_SSID_LIST_PATH, FSAM_READ, FSOM_OPEN_EXISTING))
  116. {
  117. FURI_LOG_E(TAG, "Failed to open settings file for reading: %s", WIFI_SSID_LIST_PATH);
  118. storage_file_free(file);
  119. furi_record_close(RECORD_STORAGE);
  120. return false; // Return false if the file does not exist
  121. }
  122. // Buffer to hold each line
  123. char line_buffer[128];
  124. size_t line_pos = 0;
  125. char ch;
  126. while (storage_file_read(file, &ch, 1) == 1)
  127. {
  128. if (ch == '\n')
  129. {
  130. // Null-terminate the line
  131. line_buffer[line_pos] = '\0';
  132. // Split the line into SSID and Password
  133. char *comma_pos = strchr(line_buffer, ',');
  134. if (comma_pos)
  135. {
  136. *comma_pos = '\0'; // Replace comma with null character
  137. // Copy SSID
  138. strncpy(playlist->ssids[playlist->count], line_buffer, 63);
  139. playlist->ssids[playlist->count][63] = '\0'; // Ensure null-termination
  140. // Copy Password
  141. strncpy(playlist->passwords[playlist->count], comma_pos + 1, 63);
  142. playlist->passwords[playlist->count][63] = '\0'; // Ensure null-termination
  143. playlist->count++;
  144. if (playlist->count >= MAX_WIFI_NETWORKS)
  145. {
  146. FURI_LOG_W(TAG, "Reached maximum number of WiFi networks: %d", MAX_WIFI_NETWORKS);
  147. break;
  148. }
  149. }
  150. else
  151. {
  152. FURI_LOG_E(TAG, "Invalid line format (no comma found): %s", line_buffer);
  153. }
  154. // Reset line buffer position for the next line
  155. line_pos = 0;
  156. }
  157. else
  158. {
  159. if (line_pos < sizeof(line_buffer) - 1)
  160. {
  161. line_buffer[line_pos++] = ch;
  162. }
  163. else
  164. {
  165. FURI_LOG_E(TAG, "Line buffer overflow");
  166. // Optionally handle line overflow (e.g., skip the rest of the line)
  167. line_pos = 0;
  168. }
  169. }
  170. }
  171. // Handle the last line if it does not end with a newline
  172. if (line_pos > 0)
  173. {
  174. line_buffer[line_pos] = '\0';
  175. char *comma_pos = strchr(line_buffer, ',');
  176. if (comma_pos)
  177. {
  178. *comma_pos = '\0'; // Replace comma with null character
  179. // Copy SSID
  180. strncpy(playlist->ssids[playlist->count], line_buffer, 63);
  181. playlist->ssids[playlist->count][63] = '\0'; // Ensure null-termination
  182. // Copy Password
  183. strncpy(playlist->passwords[playlist->count], comma_pos + 1, 63);
  184. playlist->passwords[playlist->count][63] = '\0'; // Ensure null-termination
  185. playlist->count++;
  186. if (playlist->count >= MAX_WIFI_NETWORKS)
  187. {
  188. FURI_LOG_W(TAG, "Reached maximum number of WiFi networks: %d", MAX_WIFI_NETWORKS);
  189. }
  190. }
  191. else
  192. {
  193. FURI_LOG_E(TAG, "Invalid line format (no comma found): %s", line_buffer);
  194. }
  195. }
  196. // Close and free file resources
  197. storage_file_close(file);
  198. storage_file_free(file);
  199. furi_record_close(RECORD_STORAGE);
  200. return true;
  201. }
  202. void save_settings(const char *ssid, const char *password)
  203. {
  204. char edited_directory_path[128];
  205. char edited_file_path[128];
  206. for (size_t i = 0; i < 8; i++)
  207. {
  208. // Construct the directory and file paths for the current app
  209. snprintf(edited_directory_path, sizeof(edited_directory_path), STORAGE_EXT_PATH_PREFIX "/apps_data/%s", app_ids[i]);
  210. snprintf(edited_file_path, sizeof(edited_file_path), STORAGE_EXT_PATH_PREFIX "/apps_data/%s/settings.bin", app_ids[i]);
  211. // Open the storage record
  212. Storage *storage = furi_record_open(RECORD_STORAGE);
  213. if (!storage)
  214. {
  215. FURI_LOG_E(TAG, "Failed to open storage record for app: %s", app_ids[i]);
  216. continue; // Skip to the next app
  217. }
  218. // Ensure the directory exists
  219. storage_common_mkdir(storage, edited_directory_path);
  220. // Allocate a file handle
  221. File *file = storage_file_alloc(storage);
  222. if (!file)
  223. {
  224. FURI_LOG_E(TAG, "Failed to allocate storage file for app: %s", app_ids[i]);
  225. furi_record_close(RECORD_STORAGE);
  226. continue; // Skip to the next app
  227. }
  228. // Open the file in read mode to read existing data
  229. bool file_opened = storage_file_open(file, edited_file_path, FSAM_READ, FSOM_OPEN_EXISTING);
  230. size_t file_size = 0;
  231. uint8_t *buffer = NULL;
  232. if (file_opened)
  233. {
  234. // Get the file size
  235. file_size = storage_file_size(file);
  236. buffer = malloc(file_size);
  237. if (!buffer)
  238. {
  239. FURI_LOG_E(TAG, "Failed to allocate buffer for app: %s", app_ids[i]);
  240. storage_file_close(file);
  241. storage_file_free(file);
  242. furi_record_close(RECORD_STORAGE);
  243. continue;
  244. }
  245. // Read the existing data
  246. if (storage_file_read(file, buffer, file_size) != file_size)
  247. {
  248. FURI_LOG_E(TAG, "Failed to read settings file for app: %s", app_ids[i]);
  249. free(buffer);
  250. storage_file_close(file);
  251. storage_file_free(file);
  252. furi_record_close(RECORD_STORAGE);
  253. continue;
  254. }
  255. storage_file_close(file);
  256. }
  257. else
  258. {
  259. // If the file doesn't exist, initialize an empty buffer
  260. file_size = 0;
  261. buffer = NULL;
  262. }
  263. storage_file_free(file);
  264. // Prepare new SSID and Password
  265. size_t new_ssid_length = strlen(ssid) + 1; // Including null terminator
  266. size_t new_password_length = strlen(password) + 1; // Including null terminator
  267. // Calculate the new file size
  268. size_t new_file_size = sizeof(size_t) + new_ssid_length + sizeof(size_t) + new_password_length;
  269. // If there is additional data beyond SSID and Password, preserve it
  270. size_t additional_data_size = 0;
  271. uint8_t *additional_data = NULL;
  272. if (buffer)
  273. {
  274. // Parse existing SSID length
  275. if (file_size >= sizeof(size_t))
  276. {
  277. size_t existing_ssid_length;
  278. memcpy(&existing_ssid_length, buffer, sizeof(size_t));
  279. // Parse existing Password length
  280. if (file_size >= sizeof(size_t) + existing_ssid_length + sizeof(size_t))
  281. {
  282. size_t existing_password_length;
  283. memcpy(&existing_password_length, buffer + sizeof(size_t) + existing_ssid_length, sizeof(size_t));
  284. // Calculate the offset where additional data starts
  285. size_t additional_offset = sizeof(size_t) + existing_ssid_length + sizeof(size_t) + existing_password_length;
  286. if (additional_offset < file_size)
  287. {
  288. additional_data_size = file_size - additional_offset;
  289. additional_data = malloc(additional_data_size);
  290. if (additional_data)
  291. {
  292. memcpy(additional_data, buffer + additional_offset, additional_data_size);
  293. }
  294. else
  295. {
  296. FURI_LOG_E(TAG, "Failed to allocate memory for additional data for app: %s", app_ids[i]);
  297. free(buffer);
  298. furi_record_close(RECORD_STORAGE);
  299. continue;
  300. }
  301. }
  302. }
  303. else
  304. {
  305. FURI_LOG_E(TAG, "Settings file format invalid for app: %s", app_ids[i]);
  306. }
  307. }
  308. else
  309. {
  310. FURI_LOG_E(TAG, "Settings file too small for app: %s", app_ids[i]);
  311. }
  312. }
  313. // Allocate a new buffer for updated data
  314. size_t total_new_size = new_file_size + additional_data_size;
  315. uint8_t *new_buffer = malloc(total_new_size);
  316. if (!new_buffer)
  317. {
  318. FURI_LOG_E(TAG, "Failed to allocate new buffer for app: %s", app_ids[i]);
  319. if (buffer)
  320. free(buffer);
  321. if (additional_data)
  322. free(additional_data);
  323. furi_record_close(RECORD_STORAGE);
  324. continue;
  325. }
  326. size_t offset = 0;
  327. // Write new SSID length and SSID
  328. memcpy(new_buffer + offset, &new_ssid_length, sizeof(size_t));
  329. offset += sizeof(size_t);
  330. memcpy(new_buffer + offset, ssid, new_ssid_length);
  331. offset += new_ssid_length;
  332. // Write new Password length and Password
  333. memcpy(new_buffer + offset, &new_password_length, sizeof(size_t));
  334. offset += sizeof(size_t);
  335. memcpy(new_buffer + offset, password, new_password_length);
  336. offset += new_password_length;
  337. // Append any additional data if present
  338. if (additional_data_size > 0 && additional_data)
  339. {
  340. memcpy(new_buffer + offset, additional_data, additional_data_size);
  341. offset += additional_data_size;
  342. }
  343. // Free temporary buffers
  344. if (buffer)
  345. free(buffer);
  346. if (additional_data)
  347. free(additional_data);
  348. // Open the file in write mode with FSOM_CREATE_ALWAYS to overwrite it
  349. file = storage_file_alloc(storage);
  350. if (!file)
  351. {
  352. FURI_LOG_E(TAG, "Failed to allocate storage file for writing: %s", app_ids[i]);
  353. free(new_buffer);
  354. furi_record_close(RECORD_STORAGE);
  355. continue;
  356. }
  357. if (!storage_file_open(file, edited_file_path, FSAM_WRITE, FSOM_CREATE_ALWAYS))
  358. {
  359. FURI_LOG_E(TAG, "Failed to open settings file for writing: %s", edited_file_path);
  360. storage_file_free(file);
  361. free(new_buffer);
  362. furi_record_close(RECORD_STORAGE);
  363. continue;
  364. }
  365. // Write the updated buffer back to the file
  366. if (storage_file_write(file, new_buffer, total_new_size) != total_new_size)
  367. {
  368. FURI_LOG_E(TAG, "Failed to write updated settings for app: %s", app_ids[i]);
  369. }
  370. // Clean up
  371. free(new_buffer);
  372. storage_file_close(file);
  373. storage_file_free(file);
  374. furi_record_close(RECORD_STORAGE);
  375. }
  376. }