#include "httpd.js.h" #include "file.js.h" #include "http.h" #include "mem.h" #include "ssb.db.h" #include "ssb.h" #include "task.h" #include "util.js.h" #include #if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(_WIN32) #include #endif typedef struct _index_t { tf_http_request_t* request; bool found; bool not_modified; bool use_handler; bool use_static; void* data; size_t size; char app_blob_id[k_blob_id_len]; const char* file; tf_httpd_user_app_t* user_app; char etag[256]; } index_t; static bool _has_property(JSContext* context, JSValue object, const char* name) { JSAtom atom = JS_NewAtom(context, name); bool result = JS_HasProperty(context, object, atom) > 0; JS_FreeAtom(context, atom); return result; } static void _httpd_endpoint_app_index_work(tf_ssb_t* ssb, void* user_data) { index_t* data = user_data; data->use_static = true; tf_httpd_user_app_t* user_app = data->user_app; size_t app_path_length = strlen("path:") + strlen(user_app->app) + 1; char* app_path = tf_malloc(app_path_length); snprintf(app_path, app_path_length, "path:%s", user_app->app); const char* app_blob_id = tf_ssb_db_get_property(ssb, user_app->user, app_path); tf_free(app_path); uint8_t* app_blob = NULL; size_t app_blob_size = 0; if (tf_ssb_db_blob_get(ssb, app_blob_id, &app_blob, &app_blob_size)) { JSMallocFunctions funcs = { 0 }; tf_get_js_malloc_functions(&funcs); JSRuntime* runtime = JS_NewRuntime2(&funcs, NULL); JSContext* context = JS_NewContext(runtime); JSValue app = JS_ParseJSON(context, (const char*)app_blob, app_blob_size, NULL); JSValue files = JS_GetPropertyStr(context, app, "files"); if (!_has_property(context, files, "app.js")) { JSValue index = JS_GetPropertyStr(context, files, "index.html"); if (JS_IsString(index)) { const char* index_string = JS_ToCString(context, index); tf_ssb_db_blob_get(ssb, index_string, (uint8_t**)&data->data, &data->size); JS_FreeCString(context, index_string); } JS_FreeValue(context, index); } JS_FreeValue(context, files); JS_FreeValue(context, app); JS_FreeContext(context); JS_FreeRuntime(runtime); tf_free(app_blob); } tf_free((void*)app_blob_id); } static char* _replace(const char* original, size_t size, const char* find, const char* replace, size_t* out_size) { char* pos = strstr(original, find); if (!pos) { return tf_strdup(original); } size_t replace_length = strlen(replace); size_t find_length = strlen(find); size_t new_size = size + replace_length - find_length; char* buffer = tf_malloc(new_size); memcpy(buffer, original, pos - original); memcpy(buffer + (pos - original), replace, replace_length); memcpy(buffer + (pos - original) + replace_length, pos + find_length, size - (pos - original) - find_length); *out_size = new_size; return buffer; } static char* _append_raw(char* document, size_t* current_size, const char* data, size_t size) { document = tf_resize_vec(document, *current_size + size); memcpy(document + *current_size, data, size); document[*current_size + size] = '\0'; *current_size += size; return document; } static char* _append_encoded(char* document, const char* data, size_t size, size_t* out_size) { size_t current_size = strlen(document); int accum = 0; for (int i = 0; (size_t)i < size; i++) { switch (data[i]) { case '"': if (i > accum) { document = _append_raw(document, ¤t_size, data + accum, i - accum); } document = _append_raw(document, ¤t_size, """, strlen(""")); accum = i + 1; break; case '\'': if (i > accum) { document = _append_raw(document, ¤t_size, data + accum, i - accum); } document = _append_raw(document, ¤t_size, "'", strlen("'")); accum = i + 1; break; case '<': if (i > accum) { document = _append_raw(document, ¤t_size, data + accum, i - accum); } document = _append_raw(document, ¤t_size, "<", strlen("<")); accum = i + 1; break; case '>': if (i > accum) { document = _append_raw(document, ¤t_size, data + accum, i - accum); } document = _append_raw(document, ¤t_size, ">", strlen(">")); accum = i + 1; break; case '&': if (i > accum) { document = _append_raw(document, ¤t_size, data + accum, i - accum); } document = _append_raw(document, ¤t_size, "&", strlen("&")); accum = i + 1; break; default: break; } } *out_size = current_size; return document; } static void _httpd_endpoint_app_index_file_read(tf_task_t* task, const char* path, int result, const void* data, void* user_data) { index_t* state = user_data; if (result > 0) { char* replacement = tf_strdup("