static int GET_upload(BlogRef const blog, SLNSessionRef const session, HTTPConnectionRef const conn, HTTPMethod const method, strarg_t const URI, HTTPHeadersRef const headers) { if(HTTP_GET != method && HTTP_HEAD != method) return -1; if(0 != uripathcmp("/upload", URI, NULL)) return -1; if(!SLNSessionHasPermission(session, SLN_WRONLY)) return 403; str_t *reponame_HTMLSafe = htmlenc(SLNRepoGetName(blog->repo)); if(!reponame_HTMLSafe) return 500; TemplateStaticArg const args[] = { {"reponame", reponame_HTMLSafe}, {"token", "asdf"}, {NULL, NULL}, }; HTTPConnectionWriteResponse(conn, 200, "OK"); HTTPConnectionWriteHeader(conn, "Content-Type", "text/html; charset=utf-8"); HTTPConnectionWriteHeader(conn, "Transfer-Encoding", "chunked"); HTTPConnectionBeginBody(conn); if(HTTP_HEAD != method) { TemplateWriteHTTPChunk(blog->upload, &TemplateStaticCBs, args, conn); HTTPConnectionWriteChunkEnd(conn); } HTTPConnectionEnd(conn); FREE(&reponame_HTMLSafe); return 0; }
int SLNSubmissionCreate(SLNSessionRef const session, strarg_t const knownURI, SLNSubmissionRef *const out) { assert(out); if(!SLNSessionHasPermission(session, SLN_WRONLY)) return UV_EACCES; SLNSubmissionRef sub = calloc(1, sizeof(struct SLNSubmission)); if(!sub) return UV_ENOMEM; int rc = 0; sub->session = session; if(knownURI) { sub->knownURI = strdup(knownURI); if(!sub->knownURI) rc = UV_ENOMEM; if(rc < 0) goto cleanup; } sub->type = NULL; sub->tmppath = SLNRepoCopyTempPath(SLNSessionGetRepo(session)); if(!sub->tmppath) rc = UV_ENOMEM; if(rc < 0) goto cleanup; rc = async_fs_open_mkdirp(sub->tmppath, O_CREAT | O_EXCL | O_RDWR, 0400); if(rc < 0) goto cleanup; sub->tmpfile = rc; sub->hasher = SLNHasherCreate(sub->type); if(!sub->hasher) rc = UV_ENOMEM; if(rc < 0) goto cleanup; sub->metaFileID = 0; *out = sub; sub = NULL; cleanup: SLNSubmissionFree(&sub); return rc; }
int SLNSessionGetFileInfo(SLNSessionRef const session, strarg_t const URI, SLNFileInfo *const info) { if(!SLNSessionHasPermission(session, SLN_RDONLY)) return DB_EACCES; if(!URI) return DB_EINVAL; SLNRepoRef const repo = SLNSessionGetRepo(session); DB_env *db = NULL; SLNRepoDBOpen(repo, &db); DB_txn *txn = NULL; int rc = db_txn_begin(db, NULL, DB_RDONLY, &txn); if(rc < 0) { SLNRepoDBClose(repo, &db); return rc; } DB_cursor *cursor; rc = db_txn_cursor(txn, &cursor); assert(!rc); DB_range fileIDs[1]; SLNURIAndFileIDRange1(fileIDs, txn, URI); DB_val URIAndFileID_key[1]; rc = db_cursor_firstr(cursor, fileIDs, URIAndFileID_key, NULL, +1); DB_val file_val[1]; if(rc >= 0) { strarg_t URI2; uint64_t fileID; SLNURIAndFileIDKeyUnpack(URIAndFileID_key, txn, &URI2, &fileID); assert(0 == strcmp(URI, URI2)); if(info) { DB_val fileID_key[1]; SLNFileByIDKeyPack(fileID_key, txn, fileID); rc = db_get(txn, fileID_key, file_val); } } if(rc < 0) { db_txn_abort(txn); txn = NULL; SLNRepoDBClose(repo, &db); return rc; } if(info) { strarg_t const internalHash = db_read_string(file_val, txn); strarg_t const type = db_read_string(file_val, txn); uint64_t const size = db_read_uint64(file_val); info->hash = strdup(internalHash); info->path = SLNRepoCopyInternalPath(repo, internalHash); info->type = strdup(type); info->size = size; if(!info->hash || !info->path || !info->type) { SLNFileInfoCleanup(info); db_txn_abort(txn); txn = NULL; SLNRepoDBClose(repo, &db); return DB_ENOMEM; } } db_txn_abort(txn); txn = NULL; SLNRepoDBClose(repo, &db); return 0; }
int SLNSessionGetValueForField(SLNSessionRef const session, str_t value[], size_t const max, strarg_t const fileURI, strarg_t const field) { if(!SLNSessionHasPermission(session, SLN_RDONLY)) return DB_EACCES; if(!field) return DB_EINVAL; if(max) value[0] = '\0'; int rc = 0; DB_cursor *metafiles = NULL; DB_cursor *values = NULL; SLNRepoRef const repo = SLNSessionGetRepo(session); DB_env *db = NULL; SLNRepoDBOpen(repo, &db); DB_txn *txn = NULL; rc = db_txn_begin(db, NULL, DB_RDONLY, &txn); if(rc < 0) goto done; rc = db_cursor_open(txn, &metafiles); if(rc < 0) goto done; rc = db_cursor_open(txn, &values); if(rc < 0) goto done; DB_range metaFileIDs[1]; SLNTargetURIAndMetaFileIDRange1(metaFileIDs, txn, fileURI); DB_val metaFileID_key[1]; rc = db_cursor_firstr(metafiles, metaFileIDs, metaFileID_key, NULL, +1); if(rc < 0 && DB_NOTFOUND != rc) goto done; for(; rc >= 0; rc = db_cursor_nextr(metafiles, metaFileIDs, metaFileID_key, NULL, +1)) { strarg_t u; uint64_t metaFileID; SLNTargetURIAndMetaFileIDKeyUnpack(metaFileID_key, txn, &u, &metaFileID); assert(0 == strcmp(fileURI, u)); DB_range vrange[1]; SLNMetaFileIDFieldAndValueRange2(vrange, txn, metaFileID, field); DB_val value_val[1]; rc = db_cursor_firstr(values, vrange, value_val, NULL, +1); if(rc < 0 && DB_NOTFOUND != rc) goto done; for(; rc >= 0; rc = db_cursor_nextr(values, vrange, value_val, NULL, +1)) { uint64_t m; strarg_t f, v; SLNMetaFileIDFieldAndValueKeyUnpack(value_val, txn, &m, &f, &v); assert(metaFileID == m); assert(0 == strcmp(field, f)); if(!v) continue; if(0 == strcmp("", v)) continue; size_t const len = strlen(v); memcpy(value, v, MIN(len, max-1)); value[MIN(len, max-1)] = '\0'; goto done; } } done: db_cursor_close(values); values = NULL; db_cursor_close(metafiles); metafiles = NULL; db_txn_abort(txn); txn = NULL; SLNRepoDBClose(repo, &db); return rc; }
int SLNJSONFilterParserCreate(SLNSessionRef const session, SLNJSONFilterParserRef *const out) { if(!SLNSessionHasPermission(session, SLN_RDONLY)) return DB_EACCES; SLNJSONFilterParserRef parser = calloc(1, sizeof(struct SLNJSONFilterParser)); if(!parser) return DB_ENOMEM; parser->session = session; parser->JSONParser = yajl_alloc(&callbacks, NULL, parser); parser->depth = -1; *out = parser; return 0; }
ssize_t SLNFilterCopyURIs(SLNFilterRef const filter, SLNSessionRef const session, SLNFilterPosition *const pos, int const dir, bool const meta, str_t *URIs[], size_t const max) { assert(URIs); if(!SLNSessionHasPermission(session, SLN_RDONLY)) return DB_EACCES; if(0 == pos->dir) return DB_EINVAL; if(0 == dir) return DB_EINVAL; if(0 == max) return 0; DB_env *db = NULL; DB_txn *txn = NULL; ssize_t rc = 0; SLNRepoRef const repo = SLNSessionGetRepo(session); SLNRepoDBOpen(repo, &db); rc = db_txn_begin(db, NULL, DB_RDONLY, &txn); if(rc < 0) goto cleanup; rc = SLNFilterPrepare(filter, txn); if(rc < 0) goto cleanup; rc = SLNFilterSeekToPosition(filter, pos, txn); if(rc < 0) goto cleanup; int const stepdir = pos->dir * dir; size_t i = 0; for(; i < max; i++) { size_t const x = stepdir > 0 ? i : max-1-i; rc = SLNFilterGetPosition(filter, pos, txn); if(DB_NOTFOUND == rc) { rc = 0; break; } rc = SLNFilterCopyURI(filter, pos->fileID, meta, txn, &URIs[x]); if(rc < 0) goto cleanup; assert(URIs[x]); SLNFilterStep(filter, pos->dir); } // The results should always be in the first `i` slots, even when // filling them in reverse order. if(stepdir < 0) { memmove(URIs+0, URIs+(max-i), sizeof(*URIs) * i); } assert(rc >= 0); rc = i; cleanup: db_txn_abort(txn); txn = NULL; SLNRepoDBClose(repo, &db); return rc; }
int SLNSessionDBOpen(SLNSessionRef const session, SLNMode const mode, DB_env **const dbptr) { if(!SLNSessionHasPermission(session, mode)) return DB_EACCES; assert(session); SLNRepoDBOpenUnsafe(SLNSessionGetRepo(session), dbptr); return 0; }