Ejemplo n.º 1
0
void CMailMessage::FormatMessage()
{
	start_header();
	prepare_header();
	end_header();
	prepare_body();
}
Ejemplo n.º 2
0
static void
answer_appropriate(struct vmod_fsdirector_file_system *fs)
{
	unsigned available;
	char *url;
	char *url_start;
	char *url_end;
	size_t url_len;
	size_t root_len;
	char *path;
	struct stat stat_buf;

	if (strncmp("GET ", fs->htc.ws->s, 4)) {
		prepare_answer(&fs->htc, 405);
		prepare_body(&fs->htc);
		return;
	}

	url_start = &fs->htc.ws->s[4];
	url_end = strchr(url_start, ' ');
	url_len = (url_end - url_start) + strlen(fs->root) + 1;
	url = WS_Alloc(fs->htc.ws, url_len);
	snprintf(url, url_len, "%s%s", fs->root, url_start);

	path = url;
	if (lstat(path, &stat_buf) < 0) {
		handle_file_error(&fs->htc, errno);
		return;
	}

	answer_file(fs, &stat_buf, path);
}
Ejemplo n.º 3
0
static void
send_response(struct vmod_fsdirector_file_system *fs, struct stat *stat_buf,
    const char *path)
{
	int fd;
	off_t offset = 0;
	ssize_t remaining = stat_buf->st_size;
	ssize_t written;

	fd = open(path, O_RDONLY);

	if(fd < 0) {
		handle_file_error(&fs->htc, errno);
		return;
	}

	prepare_answer(&fs->htc, 200);
	dprintf(fs->htc.fd, "Content-Length: %lu\r\n", stat_buf->st_size);
	add_content_type(fs, path);
	prepare_body(&fs->htc);

	while (remaining > 0) {
		written = sendfile(fs->htc.fd, fd, &offset, remaining);
		if (written < 0) {
			perror("sendfile");
			break;
		}
		remaining -= written;
	}

	// XXX too late for a 500 response...
	close(fd);
}
Ejemplo n.º 4
0
static void
send_redirect(struct vmod_fsdirector_file_system *fs, const char *path)
{
	int link_buf_size;
	char link_buf[4096]; // XXX hardcoded
	const char *absolute_link;
	char const *location;

	link_buf_size = readlink(path, link_buf, 4096);

	if(link_buf_size < 0) {
		handle_file_error(&fs->htc, errno);
		return;
	}

	if (link_buf[0] != '/') {
		absolute_link = absolutize_link(fs->htc.ws, path, link_buf);
		if (absolute_link == NULL) {
			prepare_answer(&fs->htc, 500);
			prepare_body(&fs->htc);
			return;
		}
	}
	else {
		absolute_link = link_buf;
	}

	location = normalize_link(fs, absolute_link);
	if (location == NULL) {
		prepare_answer(&fs->htc, 500);
		prepare_body(&fs->htc);
		return;
	}

	prepare_answer(&fs->htc, 302);
	dprintf(fs->htc.fd, "Location: %s\r\n", location);
	prepare_body(&fs->htc);
}
Ejemplo n.º 5
0
/*
 * macroend_bind
 *
 * Lexical binding for the special MACROEND lexeme type.  No quotelevel/quotemodifier/cond
 * checks here.
 */
static int
macroend_bind (lexctx_t lctx, void *ctx, quotelevel_t ql, quotemodifier_t qm,
               lextype_t lt, condstate_t cs, lexeme_t *lex, lexseq_t *result)
{
    macroctx_t mctx = ctx;
    expansion_t *cur = mctx->curexp;
    expr_ctx_t ectx = mctx->ectx;
    parse_ctx_t pctx = expr_parse_ctx(ectx);
    struct macrodecl_s *curmac;

    lexeme_free(lctx, lex);

    if (cur == 0) {
        expr_signal(mctx->ectx, STC__INTCMPERR, "macroend_bind");
        return 1;
    }

    curmac = name_extraspace(cur->curmacro);

    switch (mctx->state) {
        case EXP_EXITMACRO:
            lexseq_free(lctx, &cur->remaining);
            // FALLTHROUGH
        case EXP_EXITITER:
        case EXP_NORMAL:
            if (curmac->type == MACRO_ITER && lexseq_length(&cur->remaining) > 0) {
                if (cur->sep != 0) {
                    lexseq_instail(result, lexeme_copy(lctx, cur->sep));
                }
                mctx->state = EXP_NORMAL;
                parser_skipmode_set(pctx, 0);
                return prepare_body(mctx, cur, result);
            }
            if (curmac->type == MACRO_ITER && cur->closer != 0) {
                lexseq_instail(result, cur->closer);
            }
            // FALLTHROUGH
        case EXP_ERRORMACRO:
            mctx->curexp = cur->next;
            expansion_free(mctx, cur);
            if (mctx->state != EXP_ERRORMACRO || mctx->curexp == 0) {
                parser_skipmode_set(pctx, 0);
            }
            break;
    }

    mctx->state = EXP_NORMAL;
    return 1;

} /* macroend_bind */
Ejemplo n.º 6
0
static void *
server_bgthread(struct worker *wrk, void *priv)
{
	struct vmod_fsdirector_file_system *fs;
	struct sockaddr_storage addr_s;
	socklen_t len;
	struct http_conn *htc;
	int fd;
	enum htc_status_e htc_status;

	CAST_OBJ_NOTNULL(fs, priv, VMOD_FSDIRECTOR_MAGIC);
	assert(fs->sock >= 0);

	htc = &fs->htc;
	fs->wrk = wrk;
	WS_Init(wrk->aws, fs->ws_name, malloc(WS_LEN), WS_LEN);

	while (1) {
		do {
			fd = accept(fs->sock, (void*)&addr_s, &len);
		} while (fd < 0 && errno == EAGAIN);

		if (fd < 0) {
			continue;
		}

		HTTP1_Init(htc, wrk->aws, fd, NULL, HTTP1_BUF, HTTP1_MAX_HDR);

		htc_status = HTTP1_Rx(htc);
		switch (htc_status) {
			case HTTP1_OVERFLOW:
			case HTTP1_ERROR_EOF:
			case HTTP1_ALL_WHITESPACE:
			case HTTP1_NEED_MORE:
				prepare_answer(htc, 400);
				prepare_body(htc);
				break;
			case HTTP1_COMPLETE:
				answer_appropriate(fs);
				break;
		}

		WS_Reset(wrk->aws, NULL);
		close(fd);
	}

	pthread_exit(0);

	NEEDLESS_RETURN(NULL);
}
Ejemplo n.º 7
0
static void
answer_file(struct vmod_fsdirector_file_system *fs, struct stat *stat_buf,
    const char *path)
{
	mode_t mode = stat_buf->st_mode;

	if (S_ISREG(mode)) {
		if (stat_buf->st_size) {
			send_response(fs, stat_buf, path);
		}
		else {
			prepare_answer(&fs->htc, 204);
			prepare_body(&fs->htc);
		}
	}
	else if (S_ISLNK(mode)) {
		send_redirect(fs, path);
	}
	else {
		prepare_answer(&fs->htc, 404);
		prepare_body(&fs->htc);
	}
}
Ejemplo n.º 8
0
static void
handle_file_error(struct http_conn *htc, int err) {
	int status;

	switch (err) {
		case EACCES:
			status = 403;
			break;
		case ENAMETOOLONG:
		case EFAULT:
			status = 400;
			break;
		case ENOENT:
		case ENOTDIR:
			status = 404;
			break;
		default:
			status = 500;
	}

	prepare_answer(htc, status);
	prepare_body(htc);
}
Ejemplo n.º 9
0
/*
 * macro_expand
 *
 * Expands a macro.
 */
static int
macro_expand (macroctx_t mctx, name_t *macroname, lexseq_t *result)
{
    struct macrodecl_s *macro = name_extraspace(macroname);
    expr_ctx_t ctx = mctx->ectx;
    parse_ctx_t pctx = expr_parse_ctx(ctx);
    lexctx_t lctx = parser_lexmemctx(pctx);
    expansion_t *curexp = expansion_alloc(mctx);
    expansion_t *prev_exp;
    lextype_t lt;
    lexeme_t *lex;
    lexseq_t extras;
    name_t *np;
    scopectx_t expscope;
    int which;
    int nactuals;
    punctclass_t pcl;
    lextype_t psep;
    lextype_t terms[3];
    static strdesc_t comma = STRDEF(",");

    if (macro == 0 || curexp == 0) {
        expr_signal(ctx, STC__INTCMPERR, "macro_expand");
        return 1;
    }
    memset(curexp, 0, sizeof(struct expansion_s));

    // We save the punctuation class here, since it will get
    // munged by the parsing of the macro parameters.
    parser_punctclass_get(pctx, &pcl, &psep);

    prev_exp = 0;
    if (macro->type == MACRO_COND) {
        for (prev_exp = mctx->curexp; prev_exp != 0 && prev_exp->curmacro != macroname;
             prev_exp = prev_exp->next);
    }

    nactuals = 0;
    lexseq_init(&extras);

    // Simple macros with no formal arguments get no processing
    // of parameter lists whatsoever.
    if (macro->type == MACRO_SIMPLE && namereflist_length(&macro->plist) == 0) {
        expscope = 0;
        which = 3;
    } else {
        // For keyword macros, prime the scope with the declared
        // formals, so we can inherit the default values.
        if (macro->type == MACRO_KWD) {
            expscope = scope_copy(macro->ptable, 0);
        } else {
            expscope = scope_begin(scope_namectx(parser_scope_get(pctx)), 0);
        }

        lt = parser_next(pctx, QL_NORMAL, &lex);
        if (macro->type == MACRO_KWD) {
            if (lt != LEXTYPE_DELIM_LPAR) {
                expr_signal(ctx, STC__DELIMEXP, "(");
                parser_insert(pctx, lex);
                return 1;
            }
            which = 0;
            lexeme_free(lctx, lex);
        } else {
            for (which = 0; lt != openers[which] && which < 3; which++);
            if (which >= 3 && namereflist_length(&macro->plist) > 0) {
                expr_signal(ctx, STC__DELIMEXP, "(");
                parser_insert(pctx, lex);
                return 1;
            }
            if (which >= 3) {
                parser_insert(pctx, lex);
            } else {
                lexeme_free(lctx, lex);
            }
        }
    }

    // If we had a match on an opener, process
    // the actual parameters.
    if (which < 3) {

        nameref_t *formal;
        lexseq_t val;

        terms[0] = LEXTYPE_DELIM_COMMA;
        terms[1] = closers[which];

        formal = namereflist_head(&macro->plist);

        while (1) {
            // Keyword macro actuals are of the form name=value
            // For positionals, grab the next formal-parameter name,
            // or set np to NULL to add the actual to %REMAINING.
            if (macro->type == MACRO_KWD) {
                lt = parser_next(pctx, QL_NAME, &lex);
                if (lexeme_boundtype(lex) != LEXTYPE_NAME) {
                    expr_signal(ctx, STC__NAMEEXP);
                    lexeme_free(lctx, lex);
                    break;
                }
                np = name_search(macro->ptable, lex->text.ptr, lex->text.len, 0);
                if (np == 0) {
                    expr_signal(ctx, STC__INTCMPERR, "macro_expand[2]");
                }
                lexeme_free(lctx, lex);
                if (!parser_expect(pctx, QL_NORMAL, LEXTYPE_OP_ASSIGN, 0, 1)) {
                    expr_signal(ctx, STC__OPEREXP, "=");
                    break;
                }
            } else if (nactuals < namereflist_length(&macro->plist)) {
                np = formal->np;
                formal = formal->tq_next;
            } else {
                np = 0;
            }
            lexseq_init(&val);
            // Now parse the actual-parameter, which can be an expression
            if (!parse_lexeme_seq(pctx, 0, QL_NAME, terms, 2, &val, &lt)) {
                lexseq_free(lctx, &val);
                break;
            }

            // If we are recursively expanding a conditional macro and
            // there are no parameters, we're done - no expansion.
            if (prev_exp != 0 && lexseq_length(&val) == 0 && nactuals == 0) {
                scope_end(expscope);
                free(curexp);
                return 1;
            }

            if (np == 0) {
                if (lexseq_length(&extras) > 0) {
                    lexseq_instail(&extras,
                                   lexeme_create(lctx, LEXTYPE_DELIM_COMMA, &comma));
                }
                lexseq_append(&extras, &val);
            } else {
                name_t *actual;
                // Associate the actual with the formal.  For keyword
                // macros, the scope_copy() above sets a special "no check"
                // flag that allows each name to be redeclared once.
                // name_declare() clears this flag, so we can catch genuine
                // redeclarations.
                actual = macparam_special(expscope, name_string(np), &val);
                if (actual == 0) {
                    expr_signal(ctx, STC__INTCMPERR, "macro_expand[3]");
                }
                lexseq_free(lctx, &val);
            }

            nactuals += 1;

            if (lt == closers[which]) {
                break;
            }

            if (lt != LEXTYPE_DELIM_COMMA) {
                expr_signal(ctx, STC__DELIMEXP, ",");
                break;
            }

        } /* while (1) */

        if (lt != closers[which]) {
            expr_signal(ctx, STC__DELIMEXP, "closer");
            lexseq_free(lctx, &extras);
            scope_end(expscope);
            return 1;
        }

        if (nactuals < namereflist_length(&macro->plist)) {
            name_t *anp;
            while (formal != 0) {
                anp = macparam_special(expscope, name_string(formal->np), 0);
                if (anp == 0) {
                    expr_signal(ctx, STC__INTCMPERR, "macro_expand[4]");
                }
                formal = formal->tq_next;
            }
        }

    } /* if which < 3 */

    // The macro actual parameters are now processed; hook
    // the scope into the current hierarchy, restore the punctuation
    // class to what it was before we parsed the actuals, and
    // generate the expansion sequence.

    parser_punctclass_set(pctx, pcl, psep);

    curexp->count = (prev_exp == 0 ? 0 : prev_exp->count);
    curexp->expscope = expscope;
    curexp->curmacro = macroname;
    curexp->next = mctx->curexp;
    curexp->nactuals = nactuals;
    lexseq_append(&curexp->remaining, &extras);
    mctx->curexp = curexp;

    return prepare_body(mctx, curexp, result);

} /* macro_expand */
Ejemplo n.º 10
0
inline size_t request::consume(char const * buf, size_t len) {
    size_t bytes_processed;
    
    if (m_ready) {return 0;}
    
    if (m_body_bytes_needed > 0) {
        bytes_processed = process_body(buf,len);
        if (body_ready()) {
            m_ready = true;
        }
        return bytes_processed;
    }

    // copy new header bytes into buffer
    m_buf->append(buf,len);

    // Search for delimiter in buf. If found read until then. If not read all
    std::string::iterator begin = m_buf->begin();
    std::string::iterator end;

    for (;;) {
        // search for line delimiter
        end = std::search(
            begin,
            m_buf->end(),
            header_delimiter,
            header_delimiter+sizeof(header_delimiter)-1
        );
        
        m_header_bytes += (end-begin+sizeof(header_delimiter));
        
        if (m_header_bytes > max_header_size) {
            // exceeded max header size
            throw exception("Maximum header size exceeded.",
                status_code::request_header_fields_too_large);
        }

        if (end == m_buf->end()) {
            // we are out of bytes. Discard the processed bytes and copy the
            // remaining unprecessed bytes to the beginning of the buffer
            std::copy(begin,end,m_buf->begin());
            m_buf->resize(static_cast<std::string::size_type>(end-begin));
            m_header_bytes -= m_buf->size();

            return len;
        }

        //the range [begin,end) now represents a line to be processed.
        if (end-begin == 0) {
            // we got a blank line
            if (m_method.empty() || get_header("Host") == "") {
                throw exception("Incomplete Request",status_code::bad_request);
            }

            bytes_processed = (
                len - static_cast<std::string::size_type>(m_buf->end()-end)
                    + sizeof(header_delimiter) - 1
            );

            // frees memory used temporarily during request parsing
            m_buf.reset();

            // if this was not an upgrade request and has a content length
            // continue capturing content-length bytes and expose them as a 
            // request body.
            
            if (prepare_body()) {
                bytes_processed += process_body(buf+bytes_processed,len-bytes_processed);
                if (body_ready()) {
                    m_ready = true;
                }
                return bytes_processed;
            } else {
                m_ready = true;

                // return number of bytes processed (starting bytes - bytes left)
                return bytes_processed;
            }
        } else {
            if (m_method.empty()) {
                this->process(begin,end);
            } else {
                this->process_header(begin,end);
            }
        }

        begin = end+(sizeof(header_delimiter)-1);
    }
}