コード例 #1
0
ファイル: SLNServer.c プロジェクト: sofian86/stronglink
static int accept_sub(SLNSessionRef const session, strarg_t const knownURI, HTTPConnectionRef const conn, HTTPHeadersRef const headers) {
	strarg_t const type = HTTPHeadersGet(headers, "Content-Type");
	if(!type) return 415; // Unsupported Media Type

	SLNSubmissionRef sub = NULL;
	int rc = SLNSubmissionCreate(session, knownURI, type, &sub);
	if(rc < 0) goto cleanup;
	for(;;) {
		uv_buf_t buf[1] = {};
		rc = HTTPConnectionReadBody(conn, buf);
		if(rc < 0) goto cleanup;
		if(0 == buf->len) break;
		rc = SLNSubmissionWrite(sub, (byte_t const *)buf->base, buf->len);
		if(rc < 0) goto cleanup;
	}
	rc = SLNSubmissionEnd(sub);
	if(rc < 0) goto cleanup;
	rc = SLNSubmissionStoreBatch(&sub, 1);
	if(rc < 0) goto cleanup;
	strarg_t const location = SLNSubmissionGetPrimaryURI(sub);
	if(!location) rc = UV_ENOMEM;
	if(rc < 0) goto cleanup;

	created(location, conn);

cleanup:
	SLNSubmissionFree(&sub);
	if(UV_EACCES == rc) return 403; // Forbidden
	if(UV_UNKNOWN == rc) return 400; // Bad Request
	if(SLN_HASHMISMATCH == rc) return 409; // Conflict
	if(rc < 0) return 500;
	return 0;
}
コード例 #2
0
ファイル: Blog.c プロジェクト: andreydelpozo2/stronglink
static int POST_post(BlogRef const blog,
                     SLNSessionRef const session,
                     HTTPConnectionRef const conn,
                     HTTPMethod const method,
                     strarg_t const URI,
                     HTTPHeadersRef const headers)
{
	if(HTTP_POST != method) return -1;
	if(0 != uripathcmp("/post", URI, NULL)) return -1;

	// TODO: CSRF token
	strarg_t const formtype = HTTPHeadersGet(headers, "content-type"); 
	uv_buf_t boundary[1];
	int rc = MultipartBoundaryFromType(formtype, boundary);
	if(rc < 0) return 400;

	MultipartFormRef form = NULL;
	rc = MultipartFormCreate(conn, boundary, &form);
	if(rc < 0) {
		return 500;
	}

	SLNSubmissionRef sub = NULL;
	SLNSubmissionRef meta = NULL;
	str_t *title = NULL;
	rc = parse_file(blog, session, form, &sub, &meta, &title);
	if(UV_EACCES == rc) {
		MultipartFormFree(&form);
		return 403;
	}
	if(rc < 0) {
		MultipartFormFree(&form);
		return 500;
	}


	SLNSubmissionRef extra = NULL;
	yajl_gen json = NULL;
	str_t *target_QSEscaped = NULL;
	str_t *location = NULL;

	strarg_t const target = SLNSubmissionGetPrimaryURI(sub);
	if(!target) rc = UV_ENOMEM;
	if(rc < 0) goto cleanup;
	target_QSEscaped = QSEscape(target, strlen(target), true);
	if(!target_QSEscaped) rc = UV_ENOMEM;
	if(rc < 0) goto cleanup;

	rc = SLNSubmissionCreate(session, NULL, target, &extra);
	if(rc < 0) goto cleanup;
	rc = SLNSubmissionSetType(extra, SLN_META_TYPE);
	if(rc < 0) goto cleanup;

	SLNSubmissionWrite(extra, (byte_t const *)target, strlen(target));
	SLNSubmissionWrite(extra, (byte_t const *)STR_LEN("\n\n"));

	json = yajl_gen_alloc(NULL);
	if(!json) rc = UV_ENOMEM;
	if(rc < 0) goto cleanup;
	yajl_gen_config(json, yajl_gen_print_callback, (void (*)())SLNSubmissionWrite, extra);
	yajl_gen_config(json, yajl_gen_beautify, (int)true);

	yajl_gen_map_open(json);

	if(title) {
		yajl_gen_string(json, (unsigned char const *)STR_LEN("title"));
		yajl_gen_string(json, (unsigned char const *)title, strlen(title));
	}

	// TODO: Comment or description?

	strarg_t const username = SLNSessionGetUsername(session);
	if(username) {
		yajl_gen_string(json, (unsigned char const *)STR_LEN("submitter-name"));
		yajl_gen_string(json, (unsigned char const *)username, strlen(username));
	}

	strarg_t const reponame = SLNRepoGetName(blog->repo);
	if(reponame) {
		yajl_gen_string(json, (unsigned char const *)STR_LEN("submitter-repo"));
		yajl_gen_string(json, (unsigned char const *)reponame, strlen(reponame));
	}

	time_t const now = time(NULL);
	struct tm t[1];
	gmtime_r(&now, t); // TODO: Error checking?
	str_t tstr[31+1];
	size_t const tlen = strftime(tstr, sizeof(tstr), "%FT%TZ", t); // ISO 8601
	if(tlen) {
		yajl_gen_string(json, (unsigned char const *)STR_LEN("submission-time"));
		yajl_gen_string(json, (unsigned char const *)tstr, tlen);
	}

	yajl_gen_string(json, (unsigned char const *)STR_LEN("submission-software"));
	yajl_gen_string(json, (unsigned char const *)STR_LEN("StrongLink Blog"));

	str_t *fulltext = aasprintf("%s\n%s",
		title ?: "",
		NULL ?: ""); // TODO: Description, GNU-ism
	if(fulltext) {
		yajl_gen_string(json, (unsigned char const *)STR_LEN("fulltext"));
		yajl_gen_string(json, (unsigned char const *)fulltext, strlen(fulltext));
	}
	FREE(&fulltext);

	yajl_gen_map_close(json);

	rc = SLNSubmissionEnd(extra);
	if(rc < 0) goto cleanup;


	SLNSubmissionRef subs[] = { sub, meta, extra };
	rc = SLNSubmissionStoreBatch(subs, numberof(subs));

	location = aasprintf("/?q=%s", target_QSEscaped);
	if(!location) rc = UV_ENOMEM;
	if(rc < 0) goto cleanup;

	HTTPConnectionSendRedirect(conn, 303, location);

cleanup:
	if(json) { yajl_gen_free(json); json = NULL; }
	FREE(&title);
	SLNSubmissionFree(&sub);
	SLNSubmissionFree(&meta);
	SLNSubmissionFree(&extra);
	MultipartFormFree(&form);
	FREE(&target_QSEscaped);
	FREE(&location);

	if(rc < 0) return 500;
	return 0;
}
コード例 #3
0
ファイル: SLNPull.c プロジェクト: Ryezhang/stronglink
static void writer(SLNPullRef const pull) {
	SLNSubmissionRef queue[QUEUE_SIZE];
	size_t count = 0;
	size_t skipped = 0;
	double time = uv_now(async_loop) / 1000.0;
	for(;;) {
		if(pull->stop) goto stop;

		async_mutex_lock(pull->mutex);
		while(0 == count || (count < QUEUE_SIZE && pull->count > 0)) {
			size_t const pos = pull->cur;
			while(!pull->filled[pos]) {
				async_cond_wait(pull->cond, pull->mutex);
				if(pull->stop) {
					async_mutex_unlock(pull->mutex);
					goto stop;
				}
				if(!count) time = uv_now(async_loop) / 1000.0;
			}
			assert(pull->filled[pos]);
			// Skip any bubbles in the queue.
			if(pull->queue[pos]) queue[count++] = pull->queue[pos];
			else skipped++;
			pull->queue[pos] = NULL;
			pull->filled[pos] = false;
			pull->cur = (pull->cur + 1) % QUEUE_SIZE;
			pull->count--;
			async_cond_broadcast(pull->cond);
		}
		async_mutex_unlock(pull->mutex);
		assert(count <= QUEUE_SIZE);

		for(;;) {
			int rc = SLNSubmissionStoreBatch(queue, count);
			if(rc >= 0) break;
			alogf("Submission error: %s (%d)\n", sln_strerror(rc), rc);
			async_sleep(1000 * 5);
		}
		for(size_t i = 0; i < count; ++i) {
			SLNSubmissionFree(&queue[i]);
		}

		double const now = uv_now(async_loop) / 1000.0;
		alogf("Pulled %f files per second\n", count / (now - time));
		time = now;
		count = 0;
		skipped = 0;

	}

stop:
	for(size_t i = 0; i < count; ++i) {
		SLNSubmissionFree(&queue[i]);
	}
	assert_zeroed(queue, count);

	async_mutex_lock(pull->mutex);
	assertf(pull->stop, "Writer ended early");
	assert(pull->tasks > 0);
	pull->tasks--;
	async_cond_broadcast(pull->cond);
	async_mutex_unlock(pull->mutex);
}