utils.ino 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /*
  2. Utilities
  3. */
  4. //Pretty print for easy debug
  5. void prettyPrintRequest(AsyncWebServerRequest * request) {
  6. if (request->method() == HTTP_GET)
  7. Serial.printf("GET");
  8. else if (request->method() == HTTP_POST)
  9. Serial.printf("POST");
  10. else if (request->method() == HTTP_DELETE)
  11. Serial.printf("DELETE");
  12. else if (request->method() == HTTP_PUT)
  13. Serial.printf("PUT");
  14. else if (request->method() == HTTP_PATCH)
  15. Serial.printf("PATCH");
  16. else if (request->method() == HTTP_HEAD)
  17. Serial.printf("HEAD");
  18. else if (request->method() == HTTP_OPTIONS)
  19. Serial.printf("OPTIONS");
  20. else
  21. Serial.printf("UNKNOWN");
  22. Serial.printf(" http://%s%s\n", request->host().c_str(), request->url().c_str());
  23. if (request->contentLength()) {
  24. Serial.printf("_CONTENT_TYPE: %s\n", request->contentType().c_str());
  25. Serial.printf("_CONTENT_LENGTH: %u\n", request->contentLength());
  26. }
  27. int headers = request->headers();
  28. int i;
  29. for (i = 0; i < headers; i++) {
  30. AsyncWebHeader* h = request->getHeader(i);
  31. Serial.printf("_HEADER[%s]: %s\n", h->name().c_str(), h->value().c_str());
  32. }
  33. int params = request->params();
  34. for (i = 0; i < params; i++) {
  35. AsyncWebParameter* p = request->getParam(i);
  36. if (p->isFile()) {
  37. Serial.printf("_FILE[%s]: %s, size: %u\n", p->name().c_str(), p->value().c_str(), p->size());
  38. } else if (p->isPost()) {
  39. Serial.printf("_POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
  40. } else {
  41. Serial.printf("_GET[%s]: %s\n", p->name().c_str(), p->value().c_str());
  42. }
  43. }
  44. }
  45. //Check if a path is dir
  46. bool IsDir(const String& path) {
  47. File file = SD.open(path);
  48. if (file && !file.isDirectory()) {
  49. file.close();
  50. return false;
  51. }
  52. file.close();
  53. return true;
  54. }
  55. //Generate a random 32 bit hex
  56. String GeneratedRandomHex() {
  57. String hexString = "";
  58. for (int i = 0; i < 8; i++) {
  59. byte randomValue = random(256); // Generate a random byte (0 to 255)
  60. hexString += String(randomValue, HEX); // Convert the random byte to its hexadecimal representation
  61. }
  62. return hexString;
  63. }
  64. //Get the current unix timestamp
  65. unsigned long getTime() {
  66. unsigned long now = timeClient.getEpochTime();
  67. return now;
  68. }
  69. //Convert Unix timestamp to UTC string
  70. String getUTCTimeString(time_t unixTimestamp) {
  71. char utcString[30];
  72. const char* weekdayNames[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
  73. const char* monthNames[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
  74. tm* timeInfo = gmtime(&unixTimestamp);
  75. sprintf(utcString, "%s, %02d %s %04d %02d:%02d:%02d GMT",
  76. weekdayNames[timeInfo->tm_wday], timeInfo->tm_mday, monthNames[timeInfo->tm_mon],
  77. timeInfo->tm_year + 1900, timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec);
  78. return String(utcString);
  79. }
  80. //Get a certain cookie value by its key
  81. String GetCookieValueByKey(AsyncWebServerRequest *request, const String& key) {
  82. //Check if the Cookie header exists
  83. if (!request->hasHeader("Cookie")) {
  84. return "";
  85. }
  86. //Load the cookie value as string from header
  87. String targetValue = "";
  88. AsyncWebHeader* h = request->getHeader("Cookie");
  89. String cookieHeader = String(h->value().c_str());
  90. // Find the start and end positions of target cookie key
  91. int startIndex = cookieHeader.indexOf(key + "=");
  92. if (startIndex != -1) {
  93. startIndex += 9; // Length of "web-auth="
  94. int endIndex = cookieHeader.indexOf(';', startIndex);
  95. if (endIndex == -1) {
  96. endIndex = cookieHeader.length();
  97. }
  98. // Extract the value of the "web-auth" cookie
  99. targetValue = cookieHeader.substring(startIndex, endIndex);
  100. }
  101. return targetValue;
  102. }
  103. //Get the filename from filepath
  104. String basename(const String& filePath) {
  105. int lastSlashIndex = filePath.lastIndexOf('/');
  106. // If no slash is found, return the original path
  107. if (lastSlashIndex == -1) {
  108. return filePath;
  109. }
  110. // Return the substring after the last slash
  111. return filePath.substring(lastSlashIndex + 1);
  112. }
  113. bool recursiveDirRemove(const String& path) {
  114. Serial.println(path);
  115. File directory = SD.open(path);
  116. if (!directory) {
  117. Serial.println("Error opening directory!");
  118. return false;
  119. }
  120. // Delete all the files in the directory
  121. directory.rewindDirectory();
  122. while (true) {
  123. File entry = directory.openNextFile();
  124. if (!entry) {
  125. // No more files
  126. break;
  127. }
  128. String filename = String(entry.name());
  129. if (entry.isDirectory()) {
  130. // Recursively delete the subdirectory
  131. recursiveDirRemove(path + filename);
  132. } else {
  133. // Delete the file
  134. entry.close();
  135. Serial.println("Removing " + path + filename);
  136. SD.remove(path + filename);
  137. }
  138. }
  139. // Close the directory
  140. directory.close();
  141. // Delete the directory itself
  142. if (!SD.rmdir(path)) {
  143. Serial.println("Error deleting directory!");
  144. return false;
  145. }
  146. return true;
  147. }
  148. /*
  149. uint32_t totalSize = 0;
  150. uint16_t fileCount = 0;
  151. uint16_t folderCount = 0;
  152. // Call the recursive function to analyze the directory and its contents
  153. analyzeDirectory(directoryPath, totalSize, fileCount, folderCount);
  154. */
  155. void analyzeDirectory(const String& path, uint32_t& totalSize, uint16_t& fileCount, uint16_t& folderCount) {
  156. File directory = SD.open(path);
  157. if (!directory) {
  158. Serial.println("Error opening directory!");
  159. return;
  160. }
  161. // Analyze all files and subdirectories in the directory
  162. directory.rewindDirectory();
  163. while (true) {
  164. File entry = directory.openNextFile();
  165. if (!entry) {
  166. // No more files
  167. break;
  168. }
  169. if (entry.isDirectory()) {
  170. // Recursively analyze the subdirectory
  171. folderCount++;
  172. analyzeDirectory(entry.name(), totalSize, fileCount, folderCount);
  173. } else {
  174. // Update the counters and add file size to total size
  175. fileCount++;
  176. totalSize += entry.size();
  177. }
  178. entry.close();
  179. }
  180. // Close the directory
  181. directory.close();
  182. }
  183. void scanSDCardForKeyword(const String& directoryPath, const String& keyword, int *matchCounter, AsyncResponseStream *response) {
  184. File directory = SD.open(directoryPath);
  185. if (!directory) {
  186. Serial.println("Error opening directory " + directoryPath);
  187. return;
  188. }
  189. // Scan all files and subdirectories in the directory
  190. directory.rewindDirectory();
  191. while (true) {
  192. File entry = directory.openNextFile();
  193. if (!entry) {
  194. // No more files
  195. break;
  196. }
  197. if (entry.isDirectory()) {
  198. // Recursively scan the subdirectory
  199. scanSDCardForKeyword((directoryPath + entry.name() + "/"), keyword, matchCounter, response);
  200. } else {
  201. // Check if the filename contains the keyword
  202. String filename = basename(entry.name());
  203. if (filename.indexOf(keyword) != -1) {
  204. if ((*matchCounter) > 0){
  205. //Append a comma before appending next matching file
  206. response->print(",");
  207. }
  208. //When writing response, trim off the /www root folder name from directoryPath
  209. response->print("\"" + directoryPath.substring(4) + entry.name() + "\"");
  210. (*matchCounter)++;
  211. }
  212. }
  213. entry.close();
  214. }
  215. // Close the directory
  216. directory.close();
  217. }