Mercurial
comparison mrjunejune/main.c @ 263:ee04e4e69fed
Add functional JRPG frame and tools
Add full-screen background_2 apertures, functional frame chrome, card-driven details, dual-window tools, live conversion workflows, and bounded cleanup for generated downloads.
Co-authored-by: Copilot <[email protected]>
| author | MrJuneJune <mrjunejune@users.noreply.github.com> |
|---|---|
| date | Thu, 06 Aug 2026 11:31:30 -0700 |
| parents | 1f9877b637e9 |
| children | 04fee26ecce0 |
comparison
equal
deleted
inserted
replaced
| 262:0f45474c1b1a | 263:ee04e4e69fed |
|---|---|
| 689 | 689 |
| 690 printf("DEBUG: Video converted, available at /api/download/%s\n", filename); | 690 printf("DEBUG: Video converted, available at /api/download/%s\n", filename); |
| 691 return resp; | 691 return resp; |
| 692 } | 692 } |
| 693 | 693 |
| 694 static boolean Converted_Filename_Is_Valid(const char *filename) | |
| 695 { | |
| 696 if (!filename) | |
| 697 return FALSE; | |
| 698 const char *extension = strrchr(filename, '.'); | |
| 699 if (!extension || (strcmp(extension, ".webp") != 0 && | |
| 700 strcmp(extension, ".mp4") != 0)) | |
| 701 return FALSE; | |
| 702 if ((size_t)(extension - filename) != 36) | |
| 703 return FALSE; | |
| 704 for (size_t i = 0; i < 36; i++) | |
| 705 { | |
| 706 char value = filename[i]; | |
| 707 if (i == 8 || i == 13 || i == 18 || i == 23) | |
| 708 { | |
| 709 if (value != '-') | |
| 710 return FALSE; | |
| 711 continue; | |
| 712 } | |
| 713 if (!((value >= '0' && value <= '9') || | |
| 714 (value >= 'a' && value <= 'f') || | |
| 715 (value >= 'A' && value <= 'F'))) | |
| 716 return FALSE; | |
| 717 } | |
| 718 return TRUE; | |
| 719 } | |
| 720 | |
| 721 static Seobeo_Request_Entry *Converted_File_Error( | |
| 722 Dowa_Arena *arena, | |
| 723 char *status, | |
| 724 char *message) | |
| 725 { | |
| 726 Seobeo_Request_Entry *resp = NULL; | |
| 727 Dowa_HashMap_Push_Arena(resp, "status", status, arena); | |
| 728 Dowa_HashMap_Push_Arena(resp, "content-type", "text/plain", arena); | |
| 729 Dowa_HashMap_Push_Arena(resp, "body", message, arena); | |
| 730 return resp; | |
| 731 } | |
| 732 | |
| 733 Seobeo_Request_Entry *DeleteConvertedFile( | |
| 734 Seobeo_Request_Entry *req, | |
| 735 Dowa_Arena *arena) | |
| 736 { | |
| 737 void *filename_kv = Dowa_HashMap_Get_Ptr(req, ":filename"); | |
| 738 const char *filename = filename_kv | |
| 739 ? ((Seobeo_Request_Entry *)filename_kv)->value | |
| 740 : NULL; | |
| 741 if (!Converted_Filename_Is_Valid(filename)) | |
| 742 return Converted_File_Error(arena, "400", "Invalid converted filename"); | |
| 743 | |
| 744 char filepath[512]; | |
| 745 snprintf(filepath, sizeof(filepath), "/tmp/%s", filename); | |
| 746 if (unlink(filepath) != 0 && errno != ENOENT) | |
| 747 return Converted_File_Error(arena, "500", "Unable to delete converted file"); | |
| 748 | |
| 749 Seobeo_Request_Entry *resp = NULL; | |
| 750 Dowa_HashMap_Push_Arena(resp, "status", "204", arena); | |
| 751 Dowa_HashMap_Push_Arena(resp, "body", "", arena); | |
| 752 return resp; | |
| 753 } | |
| 754 | |
| 694 Seobeo_Request_Entry *DownloadConvertedFile(Seobeo_Request_Entry *req, Dowa_Arena *arena) | 755 Seobeo_Request_Entry *DownloadConvertedFile(Seobeo_Request_Entry *req, Dowa_Arena *arena) |
| 695 { | 756 { |
| 696 Seobeo_Request_Entry *resp = NULL; | 757 Seobeo_Request_Entry *resp = NULL; |
| 697 | 758 |
| 698 void *filename_kv = Dowa_HashMap_Get_Ptr(req, ":filename"); | 759 void *filename_kv = Dowa_HashMap_Get_Ptr(req, ":filename"); |
| 704 Dowa_HashMap_Push_Arena(resp, "body", error_msg, arena); | 765 Dowa_HashMap_Push_Arena(resp, "body", error_msg, arena); |
| 705 return resp; | 766 return resp; |
| 706 } | 767 } |
| 707 | 768 |
| 708 const char *filename = ((Seobeo_Request_Entry*)filename_kv)->value; | 769 const char *filename = ((Seobeo_Request_Entry*)filename_kv)->value; |
| 709 | 770 if (!Converted_Filename_Is_Valid(filename)) |
| 710 // TODO: Maybe check if the uuid is allowed or not? | 771 return Converted_File_Error(arena, "400", "Invalid converted filename"); |
| 711 // if (strlen(filename) != TMP_FILE_LENGTH) | |
| 712 // { | |
| 713 // char *error_msg = "Not Allowed Filename"; | |
| 714 // Dowa_HashMap_Push_Arena(resp, "status", "404", arena); | |
| 715 // Dowa_HashMap_Push_Arena(resp, "content-type", "text/plain", arena); | |
| 716 // Dowa_HashMap_Push_Arena(resp, "body", error_msg, arena); | |
| 717 // return resp; | |
| 718 // } | |
| 719 // boolean allowed = FALSE; | |
| 720 // for (int i = 0; i < Dowa_Array_Length(g_uuid4_array); i++) | |
| 721 // { | |
| 722 // if strcmp(g_uuid4_array, filename) | |
| 723 // { | |
| 724 // allowed = TRUE; | |
| 725 // break; | |
| 726 // } | |
| 727 // g_uuid4_array++; | |
| 728 // } | |
| 729 | 772 |
| 730 char filepath[512]; | 773 char filepath[512]; |
| 731 snprintf(filepath, sizeof(filepath), "/tmp/%s", filename); | 774 snprintf(filepath, sizeof(filepath), "/tmp/%s", filename); |
| 732 | 775 |
| 733 FILE *file = fopen(filepath, "rb"); | 776 FILE *file = fopen(filepath, "rb"); |
| 757 | 800 |
| 758 fread(file_data, 1, file_size, file); | 801 fread(file_data, 1, file_size, file); |
| 759 file_data[file_size] = '\0'; | 802 file_data[file_size] = '\0'; |
| 760 fclose(file); | 803 fclose(file); |
| 761 | 804 |
| 762 const char *content_type = "application/octet-stream"; | 805 char *content_type = "application/octet-stream"; |
| 763 if (strstr(filename, ".webp")) | 806 if (strcmp(strrchr(filename, '.'), ".webp") == 0) |
| 764 content_type = "image/webp"; | 807 content_type = "image/webp"; |
| 765 else if (strstr(filename, ".mp4")) | 808 else if (strstr(filename, ".mp4")) |
| 766 content_type = "video/mp4"; | 809 content_type = "video/mp4"; |
| 767 | 810 |
| 768 char *body = Dowa_Arena_Allocate(arena, file_size + 1); | 811 char *body = Dowa_Arena_Allocate(arena, file_size + 1); |
| 2065 | 2108 |
| 2066 // -- File converter --/ | 2109 // -- File converter --/ |
| 2067 Seobeo_Router_Register("POST", "/api/convert/image-to-webp", ConvertImageToWebP); | 2110 Seobeo_Router_Register("POST", "/api/convert/image-to-webp", ConvertImageToWebP); |
| 2068 Seobeo_Router_Register("POST", "/api/convert/video-to-mp4", ConvertVideoToMP4); | 2111 Seobeo_Router_Register("POST", "/api/convert/video-to-mp4", ConvertVideoToMP4); |
| 2069 Seobeo_Router_Register("GET", "/api/download/:filename", DownloadConvertedFile); | 2112 Seobeo_Router_Register("GET", "/api/download/:filename", DownloadConvertedFile); |
| 2113 Seobeo_Router_Register("DELETE", "/api/download/:filename", DeleteConvertedFile); | |
| 2070 Seobeo_Router_Register("POST", "/api/latex/render", RenderLatexPdf); | 2114 Seobeo_Router_Register("POST", "/api/latex/render", RenderLatexPdf); |
| 2071 | 2115 |
| 2072 // -- S3 Upload --/ | 2116 // -- S3 Upload --/ |
| 2073 Seobeo_Router_Register("POST", "/api/s3/upload-url", GetS3UploadUrl); | 2117 Seobeo_Router_Register("POST", "/api/s3/upload-url", GetS3UploadUrl); |
| 2074 | 2118 |