flip_store_storage.h 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. #ifndef FLIP_STORE_STORAGE_H
  2. #define FLIP_STORE_STORAGE_H
  3. #include <furi.h>
  4. #include <storage/storage.h>
  5. #define SETTINGS_PATH STORAGE_EXT_PATH_PREFIX "/apps_data/flip_store/settings.bin"
  6. static void save_settings(
  7. const char *ssid,
  8. const char *password)
  9. {
  10. // Create the directory for saving settings
  11. char directory_path[128];
  12. snprintf(directory_path, sizeof(directory_path), STORAGE_EXT_PATH_PREFIX "/apps_data/flip_store");
  13. // Create the directory
  14. Storage *storage = furi_record_open(RECORD_STORAGE);
  15. storage_common_mkdir(storage, directory_path);
  16. // Open the settings file
  17. File *file = storage_file_alloc(storage);
  18. if (!storage_file_open(file, SETTINGS_PATH, FSAM_WRITE, FSOM_CREATE_ALWAYS))
  19. {
  20. FURI_LOG_E(TAG, "Failed to open settings file for writing: %s", SETTINGS_PATH);
  21. storage_file_free(file);
  22. furi_record_close(RECORD_STORAGE);
  23. return;
  24. }
  25. // Save the ssid length and data
  26. size_t ssid_length = strlen(ssid) + 1; // Include null terminator
  27. if (storage_file_write(file, &ssid_length, sizeof(size_t)) != sizeof(size_t) ||
  28. storage_file_write(file, ssid, ssid_length) != ssid_length)
  29. {
  30. FURI_LOG_E(TAG, "Failed to write SSID");
  31. }
  32. // Save the password length and data
  33. size_t password_length = strlen(password) + 1; // Include null terminator
  34. if (storage_file_write(file, &password_length, sizeof(size_t)) != sizeof(size_t) ||
  35. storage_file_write(file, password, password_length) != password_length)
  36. {
  37. FURI_LOG_E(TAG, "Failed to write password");
  38. }
  39. storage_file_close(file);
  40. storage_file_free(file);
  41. furi_record_close(RECORD_STORAGE);
  42. }
  43. static bool load_settings(
  44. char *ssid,
  45. size_t ssid_size,
  46. char *password,
  47. size_t password_size)
  48. {
  49. Storage *storage = furi_record_open(RECORD_STORAGE);
  50. File *file = storage_file_alloc(storage);
  51. if (!storage_file_open(file, SETTINGS_PATH, FSAM_READ, FSOM_OPEN_EXISTING))
  52. {
  53. FURI_LOG_E(TAG, "Failed to open settings file for reading: %s", SETTINGS_PATH);
  54. storage_file_free(file);
  55. furi_record_close(RECORD_STORAGE);
  56. return false; // Return false if the file does not exist
  57. }
  58. // Load the ssid
  59. size_t ssid_length;
  60. if (storage_file_read(file, &ssid_length, sizeof(size_t)) != sizeof(size_t) || ssid_length > ssid_size ||
  61. storage_file_read(file, ssid, ssid_length) != ssid_length)
  62. {
  63. FURI_LOG_E(TAG, "Failed to read SSID");
  64. storage_file_close(file);
  65. storage_file_free(file);
  66. furi_record_close(RECORD_STORAGE);
  67. return false;
  68. }
  69. ssid[ssid_length - 1] = '\0'; // Ensure null-termination
  70. // Load the password
  71. size_t password_length;
  72. if (storage_file_read(file, &password_length, sizeof(size_t)) != sizeof(size_t) || password_length > password_size ||
  73. storage_file_read(file, password, password_length) != password_length)
  74. {
  75. FURI_LOG_E(TAG, "Failed to read password");
  76. storage_file_close(file);
  77. storage_file_free(file);
  78. furi_record_close(RECORD_STORAGE);
  79. return false;
  80. }
  81. password[password_length - 1] = '\0'; // Ensure null-termination
  82. storage_file_close(file);
  83. storage_file_free(file);
  84. furi_record_close(RECORD_STORAGE);
  85. return true;
  86. }
  87. // future implenetation because we need the app category
  88. bool delete_app(const char *app_id, const char *app_category)
  89. {
  90. // Create the directory for saving settings
  91. char directory_path[128];
  92. snprintf(directory_path, sizeof(directory_path), STORAGE_EXT_PATH_PREFIX "/apps/%s/%s", app_category, app_id);
  93. // Create the directory
  94. Storage *storage = furi_record_open(RECORD_STORAGE);
  95. if (!storage_simply_remove_recursive(storage, directory_path))
  96. {
  97. FURI_LOG_E(TAG, "Failed to delete app: %s", app_id);
  98. furi_record_close(RECORD_STORAGE);
  99. return false;
  100. }
  101. furi_record_close(RECORD_STORAGE);
  102. return true;
  103. }
  104. #define BUFFER_SIZE 64
  105. #define MAX_KEY_LENGTH 32
  106. #define MAX_VALUE_LENGTH 64
  107. // Function to parse JSON incrementally from a file
  108. bool parse_json_incrementally(const char *file_path, const char *target_key, char *value_buffer, size_t value_buffer_size)
  109. {
  110. Storage *_storage = NULL;
  111. File *_file = NULL;
  112. char buffer[BUFFER_SIZE];
  113. size_t bytes_read;
  114. bool key_found = false;
  115. bool in_string = false;
  116. bool is_escaped = false;
  117. bool reading_key = false;
  118. bool reading_value = false;
  119. char current_key[MAX_KEY_LENGTH] = {0};
  120. size_t key_index = 0;
  121. size_t value_index = 0;
  122. // Open storage and file
  123. _storage = furi_record_open(RECORD_STORAGE);
  124. if (!_storage)
  125. {
  126. FURI_LOG_E("JSON_PARSE", "Failed to open storage.");
  127. return false;
  128. }
  129. _file = storage_file_alloc(_storage);
  130. if (!_file)
  131. {
  132. FURI_LOG_E("JSON_PARSE", "Failed to allocate file.");
  133. furi_record_close(RECORD_STORAGE);
  134. return false;
  135. }
  136. if (!storage_file_open(_file, file_path, FSAM_READ, FSOM_OPEN_EXISTING))
  137. {
  138. FURI_LOG_E("JSON_PARSE", "Failed to open JSON file for reading.");
  139. goto cleanup;
  140. }
  141. while ((bytes_read = storage_file_read(_file, buffer, BUFFER_SIZE)) > 0)
  142. {
  143. for (size_t i = 0; i < bytes_read; ++i)
  144. {
  145. char c = buffer[i];
  146. if (is_escaped)
  147. {
  148. is_escaped = false;
  149. if (reading_key)
  150. {
  151. if (key_index < MAX_KEY_LENGTH - 1)
  152. {
  153. current_key[key_index++] = c;
  154. }
  155. }
  156. else if (reading_value)
  157. {
  158. if (value_index < value_buffer_size - 1)
  159. {
  160. value_buffer[value_index++] = c;
  161. }
  162. }
  163. continue;
  164. }
  165. if (c == '\\')
  166. {
  167. is_escaped = true;
  168. continue;
  169. }
  170. if (c == '\"')
  171. {
  172. in_string = !in_string;
  173. if (in_string)
  174. {
  175. // Start of a string
  176. if (!reading_key && !reading_value)
  177. {
  178. // Possible start of a key
  179. reading_key = true;
  180. key_index = 0;
  181. current_key[0] = '\0';
  182. }
  183. }
  184. else
  185. {
  186. // End of a string
  187. if (reading_key)
  188. {
  189. reading_key = false;
  190. current_key[key_index] = '\0';
  191. if (strcmp(current_key, target_key) == 0)
  192. {
  193. key_found = true;
  194. }
  195. }
  196. else if (reading_value)
  197. {
  198. reading_value = false;
  199. value_buffer[value_index] = '\0';
  200. if (key_found)
  201. {
  202. // Found the target value
  203. goto success;
  204. }
  205. }
  206. }
  207. continue;
  208. }
  209. if (in_string)
  210. {
  211. if (reading_key)
  212. {
  213. if (key_index < MAX_KEY_LENGTH - 1)
  214. {
  215. current_key[key_index++] = c;
  216. }
  217. }
  218. else if (reading_value)
  219. {
  220. if (value_index < value_buffer_size - 1)
  221. {
  222. value_buffer[value_index++] = c;
  223. }
  224. }
  225. continue;
  226. }
  227. if (c == ':' && key_found && !reading_value)
  228. {
  229. // After colon, start reading the value
  230. // Skip whitespace and possible opening quote
  231. while (i + 1 < bytes_read && (buffer[i + 1] == ' ' || buffer[i + 1] == '\n' || buffer[i + 1] == '\r'))
  232. {
  233. i++;
  234. }
  235. if (i + 1 < bytes_read && buffer[i + 1] == '\"')
  236. {
  237. i++; // Move to the quote
  238. in_string = true;
  239. reading_value = true;
  240. value_index = 0;
  241. }
  242. else
  243. {
  244. // Handle non-string values (e.g., numbers, booleans)
  245. reading_value = true;
  246. value_index = 0;
  247. }
  248. continue;
  249. }
  250. if (reading_value && (c == ',' || c == '}' || c == ']'))
  251. {
  252. // End of the value
  253. reading_value = false;
  254. value_buffer[value_index] = '\0';
  255. if (key_found)
  256. {
  257. // Found the target value
  258. goto success;
  259. }
  260. key_found = false;
  261. }
  262. }
  263. }
  264. success:
  265. storage_file_close(_file);
  266. storage_file_free(_file);
  267. furi_record_close(RECORD_STORAGE);
  268. return key_found;
  269. cleanup:
  270. if (_file)
  271. {
  272. storage_file_free(_file);
  273. }
  274. if (_storage)
  275. {
  276. furi_record_close(RECORD_STORAGE);
  277. }
  278. return false;
  279. }
  280. #endif