Compare commits
4 Commits
d84b06f814
...
9ce08f79fb
| Author | SHA1 | Date | |
|---|---|---|---|
| 9ce08f79fb | |||
| 0fa9c90ab9 | |||
| 2b191a5345 | |||
| 6381ba6785 |
24
core/app.js
24
core/app.js
@@ -79,7 +79,6 @@ App.prototype.send = function (message) {
|
|||||||
*/
|
*/
|
||||||
exports.app_socket = async function socket(request, response) {
|
exports.app_socket = async function socket(request, response) {
|
||||||
let process;
|
let process;
|
||||||
let options = {};
|
|
||||||
let credentials = await httpd.auth_query(request.headers);
|
let credentials = await httpd.auth_query(request.headers);
|
||||||
|
|
||||||
response.onClose = async function () {
|
response.onClose = async function () {
|
||||||
@@ -111,7 +110,6 @@ exports.app_socket = async function socket(request, response) {
|
|||||||
let packageName;
|
let packageName;
|
||||||
let blobId;
|
let blobId;
|
||||||
let match;
|
let match;
|
||||||
let parentApp;
|
|
||||||
if (
|
if (
|
||||||
(match = /^\/([&%][^\.]{44}(?:\.\w+)?)(\/?.*)/.exec(message.path))
|
(match = /^\/([&%][^\.]{44}(?:\.\w+)?)(\/?.*)/.exec(message.path))
|
||||||
) {
|
) {
|
||||||
@@ -132,13 +130,6 @@ exports.app_socket = async function socket(request, response) {
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (packageOwner != 'core') {
|
|
||||||
let coreId = await new Database('core').get('path:' + packageName);
|
|
||||||
parentApp = {
|
|
||||||
path: '/~core/' + packageName + '/',
|
|
||||||
id: coreId,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
response.send(
|
response.send(
|
||||||
JSON.stringify(
|
JSON.stringify(
|
||||||
@@ -146,7 +137,6 @@ exports.app_socket = async function socket(request, response) {
|
|||||||
{
|
{
|
||||||
action: 'session',
|
action: 'session',
|
||||||
credentials: credentials,
|
credentials: credentials,
|
||||||
parentApp: parentApp,
|
|
||||||
id: blobId,
|
id: blobId,
|
||||||
},
|
},
|
||||||
await ssb_internal.getIdentityInfo(
|
await ssb_internal.getIdentityInfo(
|
||||||
@@ -159,12 +149,6 @@ exports.app_socket = async function socket(request, response) {
|
|||||||
0x1
|
0x1
|
||||||
);
|
);
|
||||||
|
|
||||||
options.api = message.api || [];
|
|
||||||
options.credentials = credentials;
|
|
||||||
options.packageOwner = packageOwner;
|
|
||||||
options.packageName = packageName;
|
|
||||||
options.url = message.url;
|
|
||||||
let sessionId = 'session_' + (g_session_index++).toString();
|
|
||||||
if (blobId) {
|
if (blobId) {
|
||||||
if (message.edit_only) {
|
if (message.edit_only) {
|
||||||
response.send(
|
response.send(
|
||||||
@@ -176,6 +160,14 @@ exports.app_socket = async function socket(request, response) {
|
|||||||
0x1
|
0x1
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
let sessionId = 'session_' + (g_session_index++).toString();
|
||||||
|
let options = {
|
||||||
|
api: message.api || [],
|
||||||
|
credentials: credentials,
|
||||||
|
packageOwner: packageOwner,
|
||||||
|
packageName: packageName,
|
||||||
|
url: message.url,
|
||||||
|
};
|
||||||
process = await core.getProcessBlob(blobId, sessionId, options);
|
process = await core.getProcessBlob(blobId, sessionId, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
153
src/httpd.app.c
153
src/httpd.app.c
@@ -220,7 +220,6 @@ typedef struct _app_t
|
|||||||
tf_http_request_t* request;
|
tf_http_request_t* request;
|
||||||
const char* settings;
|
const char* settings;
|
||||||
JSValue credentials;
|
JSValue credentials;
|
||||||
|
|
||||||
tf_taskstub_t* taskstub;
|
tf_taskstub_t* taskstub;
|
||||||
JSValue process;
|
JSValue process;
|
||||||
} app_t;
|
} app_t;
|
||||||
@@ -247,22 +246,158 @@ typedef struct _app_hello_t
|
|||||||
{
|
{
|
||||||
app_t* app;
|
app_t* app;
|
||||||
JSValue message;
|
JSValue message;
|
||||||
|
const char* user;
|
||||||
const char* path;
|
const char* path;
|
||||||
|
char blob_id[k_id_base64_len];
|
||||||
|
tf_ssb_identity_info_t* identity_info;
|
||||||
|
tf_httpd_user_app_t* user_app;
|
||||||
} app_hello_t;
|
} app_hello_t;
|
||||||
|
|
||||||
static void _httpd_app_hello_work(tf_ssb_t* ssb, void* user_data)
|
static void _httpd_app_hello_work(tf_ssb_t* ssb, void* user_data)
|
||||||
{
|
{
|
||||||
app_hello_t* work = user_data;
|
app_hello_t* work = user_data;
|
||||||
tf_printf("%s\n", work->path);
|
|
||||||
|
work->user_app = tf_httpd_parse_user_app_from_path(work->path, NULL);
|
||||||
|
if (work->user_app)
|
||||||
|
{
|
||||||
|
size_t length = strlen("path:") + strlen(work->user_app->app) + 1;
|
||||||
|
char* key = alloca(length);
|
||||||
|
snprintf(key, length, "path:%s", work->user_app->app);
|
||||||
|
const char* value = tf_ssb_db_get_property(ssb, work->user_app->user, key);
|
||||||
|
tf_string_set(work->blob_id, sizeof(work->blob_id), value);
|
||||||
|
tf_free((void*)value);
|
||||||
|
}
|
||||||
|
else if (work->path[0] == '/' && (work->path[1] == '%' || work->path[1] == '&') && strlen(work->path) >= 1 + k_blob_id_len && strstr(work->path, ".sha256"))
|
||||||
|
{
|
||||||
|
memcpy(work->blob_id, work->path + 1, strstr(work->path, ".sha256") - work->path - 1 + strlen(".sha256"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*work->blob_id)
|
||||||
|
{
|
||||||
|
work->identity_info = tf_ssb_db_get_identity_info(ssb, work->user, work->user_app ? work->user_app->user : NULL, work->user_app ? work->user_app->app : NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _http_json_send(tf_http_request_t* request, JSContext* context, JSValue value)
|
||||||
|
{
|
||||||
|
JSValue json = JS_JSONStringify(context, value, JS_NULL, JS_NULL);
|
||||||
|
size_t json_length = 0;
|
||||||
|
const char* payload = JS_ToCStringLen(context, &json_length, json);
|
||||||
|
tf_http_request_websocket_send(request, 0x1, payload, json_length);
|
||||||
|
JS_FreeCString(context, payload);
|
||||||
|
JS_FreeValue(context, json);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _httpd_app_hello_after_work(tf_ssb_t* ssb, int status, void* user_data)
|
static void _httpd_app_hello_after_work(tf_ssb_t* ssb, int status, void* user_data)
|
||||||
{
|
{
|
||||||
app_hello_t* work = user_data;
|
app_hello_t* work = user_data;
|
||||||
JSContext* context = tf_ssb_get_context(ssb);
|
JSContext* context = tf_ssb_get_context(ssb);
|
||||||
|
|
||||||
|
if (!*work->blob_id)
|
||||||
|
{
|
||||||
|
JSValue object = JS_NewObject(context);
|
||||||
|
JS_SetPropertyStr(context, object, "action", JS_NewString(context, "tfrpc"));
|
||||||
|
JS_SetPropertyStr(context, object, "method", JS_NewString(context, "error"));
|
||||||
|
JSValue params = JS_NewArray(context);
|
||||||
|
size_t length = strlen(work->path) + strlen(" not found") + 1;
|
||||||
|
char* message = alloca(length);
|
||||||
|
snprintf(message, length, "%s not found", work->path);
|
||||||
|
JS_SetPropertyUint32(context, params, 0, JS_NewString(context, message));
|
||||||
|
JS_SetPropertyStr(context, object, "params", params);
|
||||||
|
JS_SetPropertyStr(context, object, "id", JS_NewInt32(context, -1));
|
||||||
|
_http_json_send(work->app->request, context, object);
|
||||||
|
JS_FreeValue(context, object);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
JSValue object = JS_NewObject(context);
|
||||||
|
JS_SetPropertyStr(context, object, "action", JS_NewString(context, "session"));
|
||||||
|
JS_SetPropertyStr(context, object, "credentials", JS_DupValue(context, work->app->credentials));
|
||||||
|
JS_SetPropertyStr(context, object, "id", JS_NewString(context, work->blob_id));
|
||||||
|
|
||||||
|
if (work->identity_info)
|
||||||
|
{
|
||||||
|
JSValue identities = JS_NewArray(context);
|
||||||
|
for (int i = 0; i < work->identity_info->count; i++)
|
||||||
|
{
|
||||||
|
JS_SetPropertyUint32(context, identities, i, JS_NewString(context, work->identity_info->identity[i]));
|
||||||
|
}
|
||||||
|
JS_SetPropertyStr(context, object, "identities", identities);
|
||||||
|
|
||||||
|
JSValue names = JS_NewObject(context);
|
||||||
|
for (int i = 0; i < work->identity_info->count; i++)
|
||||||
|
{
|
||||||
|
JS_SetPropertyStr(context, names, work->identity_info->identity[i],
|
||||||
|
JS_NewString(context, work->identity_info->name[i] ? work->identity_info->name[i] : work->identity_info->identity[i]));
|
||||||
|
}
|
||||||
|
JS_SetPropertyStr(context, object, "names", names);
|
||||||
|
JS_SetPropertyStr(context, object, "identity", JS_NewString(context, work->identity_info->active_identity));
|
||||||
|
}
|
||||||
|
_http_json_send(work->app->request, context, object);
|
||||||
|
JS_FreeValue(context, object);
|
||||||
|
|
||||||
|
JSValue edit_only = JS_GetPropertyStr(context, work->message, "edit_only");
|
||||||
|
bool is_edit_only = JS_ToBool(context, edit_only) > 0;
|
||||||
|
JS_FreeValue(context, edit_only);
|
||||||
|
|
||||||
|
if (is_edit_only)
|
||||||
|
{
|
||||||
|
JSValue global = JS_GetGlobalObject(context);
|
||||||
|
JSValue version = JS_GetPropertyStr(context, global, "version");
|
||||||
|
JS_FreeValue(context, global);
|
||||||
|
|
||||||
|
JSValue ready = JS_NewObject(context);
|
||||||
|
JS_SetPropertyStr(context, ready, "action", JS_NewString(context, "ready"));
|
||||||
|
JS_SetPropertyStr(context, ready, "version", JS_Call(context, version, JS_NULL, 0, NULL));
|
||||||
|
JS_SetPropertyStr(context, ready, "edit_only", JS_TRUE);
|
||||||
|
_http_json_send(work->app->request, context, ready);
|
||||||
|
JS_FreeValue(context, ready);
|
||||||
|
JS_FreeValue(context, version);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
JSValue options = JS_NewObject(context);
|
||||||
|
JSValue api = JS_GetPropertyStr(context, work->message, "api");
|
||||||
|
JS_SetPropertyStr(context, options, "api", JS_IsUndefined(api) ? JS_NewArray(context) : api);
|
||||||
|
JS_SetPropertyStr(context, options, "credentials", JS_DupValue(context, work->app->credentials));
|
||||||
|
JS_SetPropertyStr(context, options, "packageOwner", work->user_app ? JS_NewString(context, work->user_app->user) : JS_UNDEFINED);
|
||||||
|
JS_SetPropertyStr(context, options, "packageName", work->user_app ? JS_NewString(context, work->user_app->app) : JS_UNDEFINED);
|
||||||
|
JS_SetPropertyStr(context, options, "url", JS_GetPropertyStr(context, work->message, "url"));
|
||||||
|
|
||||||
|
JSValue global = JS_GetGlobalObject(context);
|
||||||
|
JSValue exports = JS_GetPropertyStr(context, global, "exports");
|
||||||
|
JSValue get_process_blob = JS_GetPropertyStr(context, exports, "getProcessBlob");
|
||||||
|
|
||||||
|
static int64_t s_session_id;
|
||||||
|
char session_id[64];
|
||||||
|
snprintf(session_id, sizeof(session_id), "app_%" PRId64, ++s_session_id);
|
||||||
|
|
||||||
|
JSValue args[] = {
|
||||||
|
JS_NewString(context, work->blob_id),
|
||||||
|
JS_NewString(context, session_id),
|
||||||
|
options,
|
||||||
|
};
|
||||||
|
JSValue result = JS_Call(context, get_process_blob, JS_UNDEFINED, tf_countof(args), args);
|
||||||
|
tf_util_report_error(context, result);
|
||||||
|
JS_FreeValue(context, result);
|
||||||
|
|
||||||
|
JS_FreeValue(context, get_process_blob);
|
||||||
|
JS_FreeValue(context, exports);
|
||||||
|
JS_FreeValue(context, global);
|
||||||
|
|
||||||
|
for (int i = 0; i < tf_countof(args); i++)
|
||||||
|
{
|
||||||
|
JS_FreeValue(context, args[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tf_http_request_unref(work->app->request);
|
tf_http_request_unref(work->app->request);
|
||||||
|
JS_FreeCString(context, work->user);
|
||||||
JS_FreeCString(context, work->path);
|
JS_FreeCString(context, work->path);
|
||||||
JS_FreeValue(context, work->message);
|
JS_FreeValue(context, work->message);
|
||||||
|
tf_free(work->identity_info);
|
||||||
|
tf_free(work->user_app);
|
||||||
tf_free(work);
|
tf_free(work);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,14 +407,18 @@ static void _httpd_app_message_hello(app_t* work, JSValue message)
|
|||||||
tf_task_t* task = tf_task_get(context);
|
tf_task_t* task = tf_task_get(context);
|
||||||
tf_ssb_t* ssb = tf_task_get_ssb(task);
|
tf_ssb_t* ssb = tf_task_get_ssb(task);
|
||||||
tf_http_request_ref(work->request);
|
tf_http_request_ref(work->request);
|
||||||
JSValue path = JS_GetPropertyStr(context, message, "path");
|
|
||||||
|
JSValue session = JS_IsObject(work->credentials) ? JS_GetPropertyStr(context, work->credentials, "session") : JS_UNDEFINED;
|
||||||
|
const char* user = tf_util_get_property_as_string(context, session, "name");
|
||||||
|
JS_FreeValue(context, session);
|
||||||
|
|
||||||
app_hello_t* hello = tf_malloc(sizeof(app_hello_t));
|
app_hello_t* hello = tf_malloc(sizeof(app_hello_t));
|
||||||
*hello = (app_hello_t) {
|
*hello = (app_hello_t) {
|
||||||
.app = work,
|
.app = work,
|
||||||
|
.user = user,
|
||||||
.message = JS_DupValue(context, message),
|
.message = JS_DupValue(context, message),
|
||||||
.path = JS_ToCString(context, path),
|
.path = tf_util_get_property_as_string(context, message, "path"),
|
||||||
};
|
};
|
||||||
JS_FreeValue(context, path);
|
|
||||||
tf_ssb_run_work(ssb, _httpd_app_hello_work, _httpd_app_hello_after_work, hello);
|
tf_ssb_run_work(ssb, _httpd_app_hello_work, _httpd_app_hello_after_work, hello);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,8 +426,8 @@ static bool _httpd_app_message_call_client_api(app_t* work, JSValue message, con
|
|||||||
{
|
{
|
||||||
bool called = false;
|
bool called = false;
|
||||||
JSContext* context = work->request->context;
|
JSContext* context = work->request->context;
|
||||||
JSValue client_api = JS_GetPropertyStr(context, work->process, "client_api");
|
JSValue client_api = JS_IsObject(work->process) ? JS_GetPropertyStr(context, work->process, "client_api") : JS_UNDEFINED;
|
||||||
JSValue callback = JS_GetPropertyStr(context, client_api, action_string);
|
JSValue callback = JS_IsObject(client_api) ? JS_GetPropertyStr(context, client_api, action_string) : JS_UNDEFINED;
|
||||||
if (!JS_IsUndefined(callback))
|
if (!JS_IsUndefined(callback))
|
||||||
{
|
{
|
||||||
JSValue result = JS_Call(context, callback, JS_NULL, 1, &message);
|
JSValue result = JS_Call(context, callback, JS_NULL, 1, &message);
|
||||||
|
|||||||
@@ -587,7 +587,7 @@ tf_httpd_user_app_t* tf_httpd_parse_user_app_from_path(const char* path, const c
|
|||||||
|
|
||||||
size_t length = strlen(path);
|
size_t length = strlen(path);
|
||||||
size_t suffix_length = expected_suffix ? strlen(expected_suffix) : 0;
|
size_t suffix_length = expected_suffix ? strlen(expected_suffix) : 0;
|
||||||
if (length < suffix_length || strcmp(path + length - suffix_length, expected_suffix) != 0)
|
if (expected_suffix && (length < suffix_length || strcmp(path + length - suffix_length, expected_suffix) != 0))
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -602,6 +602,14 @@ tf_httpd_user_app_t* tf_httpd_parse_user_app_from_path(const char* path, const c
|
|||||||
size_t user_length = (size_t)(slash - user);
|
size_t user_length = (size_t)(slash - user);
|
||||||
const char* app = slash + 1;
|
const char* app = slash + 1;
|
||||||
size_t app_length = (size_t)(length - suffix_length - user_length - 3);
|
size_t app_length = (size_t)(length - suffix_length - user_length - 3);
|
||||||
|
if (!expected_suffix)
|
||||||
|
{
|
||||||
|
char* app_slash = strchr(app, '/');
|
||||||
|
if (app_slash)
|
||||||
|
{
|
||||||
|
app_length = tf_min((size_t)(app_slash - app), app_length);
|
||||||
|
}
|
||||||
|
}
|
||||||
tf_httpd_user_app_t* result = tf_malloc(sizeof(tf_httpd_user_app_t) + user_length + 1 + app_length + 1);
|
tf_httpd_user_app_t* result = tf_malloc(sizeof(tf_httpd_user_app_t) + user_length + 1 + app_length + 1);
|
||||||
|
|
||||||
*result = (tf_httpd_user_app_t) {
|
*result = (tf_httpd_user_app_t) {
|
||||||
|
|||||||
Reference in New Issue
Block a user