4 * Copyright (c) 2010-2011 project bchan
6 * This software is provided 'as-is', without any express or implied
7 * warranty. In no event will the authors be held liable for any damages
8 * arising from the use of this software.
10 * Permission is granted to anyone to use this software for any purpose,
11 * including commercial applications, and to alter it and redistribute it
12 * freely, subject to the following restrictions:
14 * 1. The origin of this software must not be misrepresented; you must not
15 * claim that you wrote the original software. If you use this software
16 * in a product, an acknowledgment in the product documentation would be
17 * appreciated but is not required.
19 * 2. Altered source versions must be plainly marked as such, and must not be
20 * misrepresented as being the original software.
22 * 3. This notice may not be removed or altered from any source
32 #include "submitutil.h"
33 #include "sjisstring.h"
36 #include "setcookieheader.h"
38 #define MAKEHEADER_ERR_LEN(dest, dest_len, src, len) \
39 err = sjstring_appendasciistring(dest, dest_len, src, len); \
44 #define MAKEHEADER_ERR(dest, dest_len, src) MAKEHEADER_ERR_LEN(dest, dest_len, (src), strlen((src)))
46 #define MAKEHEADER_NUM_ERR(dest, dest_len, num) \
47 err = sjstring_appendUWstring(dest, dest_len, num); \
52 EXPORT submitutil_poststatus_t submitutil_checkresponse(UB *body, W len)
55 UB *ptr, *title_last, *found;
56 UB title_true[] = {0x82, 0xdc, 0x82, 0xb5, 0x82, 0xbd, '\0'};
57 UB title_error[] = {0x82, 0x64, 0x82, 0x71, 0x82, 0x71, '\0'};
58 UB title_cookie[] = {0x8a, 0x6d, 0x94, 0x46, '\0'};
59 UB title_ocha[] = {0x82, 0xa8, 0x92, 0x83, '\0'};
63 ptr = strstr(ptr, "<!--");
68 for (;ptr < body + len;ptr++) {
73 cmp = strcmp(ptr, "2ch_X:true");
75 return submitutil_poststatus_true;
77 cmp = strcmp(ptr, "2ch_X:false");
79 return submitutil_poststatus_false;
81 cmp = strcmp(ptr, "2ch_X:error");
83 return submitutil_poststatus_error;
85 cmp = strcmp(ptr, "2ch_X:check");
87 return submitutil_poststatus_check;
89 cmp = strcmp(ptr, "2ch_X:cookie");
91 return submitutil_poststatus_cookie;
95 for (ptr = body;ptr < body + len; ptr++) {
97 cmp = strncasecmp(ptr, "<title>", 7);
102 title_last = strstr(ptr, "</");
103 if (title_last == NULL) {
104 return submitutil_poststatus_notfound;
106 found = strstr(ptr, title_true);
107 if ((found != NULL)&&(found < title_last)) {
108 return submitutil_poststatus_true;
110 found = strstr(ptr, title_error);
111 if ((found != NULL)&&(found < title_last)) {
112 return submitutil_poststatus_error;
114 found = strstr(ptr, title_cookie);
115 if ((found != NULL)&&(found < title_last)) {
116 return submitutil_poststatus_cookie;
118 found = strstr(ptr, title_ocha);
119 if ((found != NULL)&&(found < title_last)) {
120 return submitutil_poststatus_error;
125 return submitutil_poststatus_notfound;
128 #ifdef BCHAN_CONFIG_DEBUG
129 EXPORT VOID SUBMITUTIL_POSTSTATUS_DP(submitutil_poststatus_t status)
132 case submitutil_poststatus_notfound:
133 printf("submitutil_poststatus_notfound\n");
135 case submitutil_poststatus_true:
136 printf("submitutil_poststatus_true\n");
138 case submitutil_poststatus_false:
139 printf("submitutil_poststatus_false\n");
141 case submitutil_poststatus_error:
142 printf("submitutil_poststatus_error\n");
144 case submitutil_poststatus_check:
145 printf("submitutil_poststatus_check\n");
147 case submitutil_poststatus_cookie:
148 printf("submitutil_poststatus_cookie\n");
154 LOCAL W submitutil_appendstring_chref_before_urlencode(UB **dest, W *dlen, UB *src, W slen)
156 charreferparser_t parser;
157 charreferparser_result_t result;
159 W i, rem_len, ch_w, err;
165 amp = sjstring_searchchar(rem, rem_len, '&');
167 return sjstring_appendurlencodestring(dest, dlen, rem, rem_len);
169 err = sjstring_appendurlencodestring(dest, dlen, rem, amp - rem);
174 rem_len -= amp - rem;
176 err = charreferparser_initialize(&parser);
180 for (i = 0; i < rem_len; i++) {
181 result = charreferparser_parsechar(&parser, amp[i]);
182 if (result == CHARREFERPARSER_RESULT_DETERMINE) {
183 ch_w = charreferparser_getcharnumber(&parser);
184 if ((ch_w >= 0)&&(ch_w < 256)) {
186 if (ch_b == 0x0a) { /* need more check ? */
188 err = sjstring_appendurlencodestring(dest, dlen, &ch_b2, 1);
193 err = sjstring_appendurlencodestring(dest, dlen, &ch_b, 1);
198 err = sjstring_appendurlencodestring(dest, dlen, amp, i+1);
206 if (result == CHARREFERPARSER_RESULT_INVALID) {
210 charreferparser_finalize(&parser);
223 EXPORT W submitutil_makenextrequestbody(UB *prev_body, W prev_body_len, UB **next_body, W *next_len)
227 UB *name = NULL, *value = NULL;
228 W name_len = 0, value_len = 0;
233 for (ptr = prev_body; ptr < prev_body + prev_body_len;) {
234 ptr = strstr(ptr, "<input ");
242 for (;ptr < prev_body + prev_body_len;) {
243 for (;ptr < prev_body + prev_body_len;ptr++) {
249 if ((name == NULL)||(name_len == 0)) {
253 err = sjstring_appendasciistring(&newbody, &newbody_len, "&", 1);
259 err = sjstring_appendasciistring(&newbody, &newbody_len, name, name_len);
263 sjstring_appendasciistring(&newbody, &newbody_len, "=", 1);
267 err = submitutil_appendstring_chref_before_urlencode(&newbody, &newbody_len, value, value_len);
273 /* check attribute */
274 if (strncasecmp(ptr, "name=\"", 6) == 0) {
277 for (;ptr < prev_body + prev_body_len;ptr++) {
282 name_len = ptr - name;
284 } else if (strncasecmp(ptr, "name=", 5) == 0) {
287 for (;ptr < prev_body + prev_body_len;ptr++) {
288 if ((*ptr == ' ')||(*ptr == '>')) {
292 name_len = ptr - name;
293 } else if (strncasecmp(ptr, "value=\"", 7) == 0) {
296 for (;ptr < prev_body + prev_body_len;ptr++) {
301 value_len = ptr - value;
303 } else if (strncasecmp(ptr, "value=", 6) == 0) {
306 for (;ptr < prev_body + prev_body_len;ptr++) {
307 if ((*ptr == ' ')||(*ptr == '>')) {
311 value_len = ptr - value;
314 for (;ptr < prev_body + prev_body_len;ptr++) {
323 *next_body = newbody;
324 *next_len = newbody_len;
329 LOCAL W submitutil_setcookie_inputparserresult(cookiedb_readheadercontext_t *ctx, setcookieparser_result_t *result)
332 W (*proc)(cookiedb_readheadercontext_t *context, UB ch);
335 switch (result->type) {
336 case SETCOOKIEPARSER_RESULT_TYPE_NAMEATTR:
337 for (i = 0; i < result->val.name.len; i++) {
338 err = cookiedb_readheadercontext_appendchar_attr(ctx, result->val.name.str[i]);
344 case SETCOOKIEPARSER_RESULT_TYPE_VALUE:
345 switch (result->val.value.attr) {
346 case SETCOOKIEPARSER_ATTR_COMMENT:
347 proc = cookiedb_readheadercontext_appendchar_comment;
349 case SETCOOKIEPARSER_ATTR_DOMAIN:
350 proc = cookiedb_readheadercontext_appendchar_domain;
352 case SETCOOKIEPARSER_ATTR_PATH:
353 proc = cookiedb_readheadercontext_appendchar_path;
355 case SETCOOKIEPARSER_ATTR_VERSION:
356 proc = cookiedb_readheadercontext_appendchar_version;
358 case SETCOOKIEPARSER_ATTR_NAME:
359 proc = cookiedb_readheadercontext_appendchar_name;
361 case SETCOOKIEPARSER_ATTR_EXPIRES:
362 case SETCOOKIEPARSER_ATTR_MAX_AGE:
363 case SETCOOKIEPARSER_ATTR_SECURE:
369 for (i = 0; i < result->val.value.len; i++) {
370 err = (*proc)(ctx, result->val.value.str[i]);
377 case SETCOOKIEPARSER_RESULT_TYPE_SECUREATTR:
378 err = cookiedb_readheadercontext_setsecure(ctx);
380 case SETCOOKIEPARSER_RESULT_TYPE_EXPIRESATTR:
381 err = cookiedb_readheadercontext_setexpires(ctx, result->val.expires.time);
388 LOCAL W submitutil_setcookie(setcookieparser_t *parser, cookiedb_t *db, UB *str, W len, UB *host, W host_len, UB *path, W path_len, STIME time)
390 cookiedb_readheadercontext_t *ctx;
391 setcookieparser_result_t *result;
392 W i, j, err, ret, result_len;
394 ctx = cookiedb_startheaderread(db, host, host_len, path, path_len, time);
396 return -1; /* TODO */
400 for (i = 0; i < len; i++) {
401 if (str[i] == '\r') {
404 ret = setcookieparser_inputchar(parser, str[i], &result, &result_len);
405 if (ret != SETCOOKIEPARSER_CONTINUE) {
409 for (j = 0; j < result_len; j++) {
410 err = submitutil_setcookie_inputparserresult(ctx, result + j);
420 ret = setcookieparser_endinput(parser, &result, &result_len);
421 if (ret == SETCOOKIEPARSER_CONTINUE) {
422 for (j = 0; j < result_len; j++) {
423 err = submitutil_setcookie_inputparserresult(ctx, result + j);
428 cookiedb_endheaderread(db, ctx);
433 EXPORT W submitutil_updatecookiedb(cookiedb_t *db, UB *prev_header, W prev_header_len, UB *host, W host_len, STIME time)
437 setcookieparser_t parser;
438 UB *path = "/test/bbs.cgi";
439 W path_len = strlen(path);
441 for (ptr = prev_header; ptr < prev_header + prev_header_len;) {
442 ptr = strstr(ptr, "Set-Cookie:");
447 for (;ptr < prev_header + prev_header_len; ptr++) {
453 for (;ptr < prev_header + prev_header_len; ptr++) {
462 err = setcookieparser_initialize(&parser);
466 err = submitutil_setcookie(&parser, db, start, ptr - start, host, host_len, path, path_len, time);
467 setcookieparser_finalize(&parser);
476 LOCAL W submitutil_setvolatilecookie(cookiedb_t *db, UB *host, W host_len, STIME time, UB *attr, W attr_len, UB *name, W name_len)
478 cookiedb_readheadercontext_t *ctx;
481 ctx = cookiedb_startheaderread(db, host, host_len, "/", 1, time);
483 return -1; /* TODO */
486 for (i = 0; i < attr_len; i++) {
487 err = cookiedb_readheadercontext_appendchar_attr(ctx, attr[i]);
489 cookiedb_endheaderread(db, ctx);
493 err = cookiedb_readheadercontext_appendchar_name(ctx, '"');
495 cookiedb_endheaderread(db, ctx);
498 for (i = 0; i < name_len; i++) {
499 err = cookiedb_readheadercontext_appendchar_name(ctx, name[i]);
501 cookiedb_endheaderread(db, ctx);
505 err = cookiedb_readheadercontext_appendchar_name(ctx, '"');
507 cookiedb_endheaderread(db, ctx);
511 cookiedb_endheaderread(db, ctx);
516 EXPORT W submitutil_setnamemailcookie(cookiedb_t *db, UB *host, W host_len, STIME time, UB *name, W name_len, UB *mail, W mail_len)
520 err = submitutil_setvolatilecookie(db, host, host_len, time, "NAME", 4, name, name_len);
524 err = submitutil_setvolatilecookie(db, host, host_len, time, "MAIL", 4, mail, mail_len);
532 LOCAL W submitutil_makecookieheader(UB **str, W *len, cookiedb_t *cdb, UB *host, W host_len, UB *path, W path_len, STIME time)
534 cookiedb_writeheadercontext_t *ctx;
539 ctx = cookiedb_startheaderwrite(cdb, host, host_len, path, path_len, False, time);
541 return -1; /* TODO */
546 cont = cookiedb_writeheadercontext_makeheader(ctx, &cstr, &cstr_len);
551 err = sjstring_appendasciistring(str, len, cstr, cstr_len);
556 cookiedb_endheaderwrite(cdb, ctx);
561 EXPORT W submitutil_makeheaderstring(UB *host, W host_len, UB *board, W board_len, UB *thread, W thread_len, W content_length, STIME time, cookiedb_t *cdb, UB **header, W *header_len)
567 MAKEHEADER_ERR(&str, &len, "POST /test/bbs.cgi HTTP/1.1\r\n");
568 MAKEHEADER_ERR(&str, &len, "Host: ");
569 MAKEHEADER_ERR_LEN(&str, &len, host, host_len);
570 MAKEHEADER_ERR(&str, &len, "\r\n");
571 MAKEHEADER_ERR(&str, &len, "Accept: */*\r\n");
572 MAKEHEADER_ERR(&str, &len, "Referer: http://");
573 MAKEHEADER_ERR_LEN(&str, &len, host, host_len);
574 MAKEHEADER_ERR(&str, &len, "/test/read.cgi/");
575 MAKEHEADER_ERR_LEN(&str, &len, board, board_len);
576 MAKEHEADER_ERR(&str, &len, "/");
577 MAKEHEADER_ERR_LEN(&str, &len, thread, thread_len);
578 MAKEHEADER_ERR(&str, &len, "/\r\n");
579 MAKEHEADER_ERR(&str, &len, "Content-Length: ");
580 MAKEHEADER_NUM_ERR(&str, &len, content_length);
581 MAKEHEADER_ERR(&str, &len, "\r\n");
582 err = submitutil_makecookieheader(&str, &len, cdb, host, host_len, "/test/bbs.cgi", strlen("/test/bbs.cgi"), time);
586 MAKEHEADER_ERR(&str, &len, "Content-Type: application/x-www-form-urlencoded\r\n");
587 MAKEHEADER_ERR(&str, &len, "Accept-Language: ja\r\nUser-Agent: Monazilla/1.00 (bchan/0.301)\r\nConnection: close\r\n\r\n");
596 LOCAL UB* submitutil_makeerrormessage_search_b_elm(UB *body, W body_len)
601 for (i = 0; i < body_len - 2; i++) {
602 if (body[i] != '<') { /* tmp */
605 if ((body[i+1] == 'b')||(body[i+1] == 'B')) {
606 if (body[i+2] == '>') {
609 if (body[i+2] == ' ') {
610 ptr = sjstring_searchchar(body + i, body_len - i, '>');
622 EXPORT W submitutil_makeerrormessage(UB *body, W body_len, TC **msg, W *msg_len)
624 UB *ptr, *start, *end;
631 ptr = submitutil_makeerrormessage_search_b_elm(body, body_len);
636 rem_len = start - body;
638 end = sjstring_searchchar(start, rem_len, '<');
643 ret_len = sjstring_totcs(start, end - start, NULL);
648 ret = malloc(sizeof(TC)*ret_len);
650 return -1; /* TODO */
652 sjstring_totcs(start, end - start, ret);