예제 #1
0
int handle_http_mkcol(http_req * req, http_rsp * rsp)
{
    char * vpath = NULL;

    WEBLOG_API();

#ifdef WEBCFG_SUPPORT_AUTH
    /* Authentication has a very high priority. */
    if (OK != CheckAuthorization(req, rsp))
    {
        return handle_http_error(401, req, rsp);
    }
#endif

    vpath = req->uri;
    ASSERT(vpath && vpath[0]);

    if(0 == strlen(vpath))
    {
        strcat(vpath, "/");
        WEBLOG_VERBOSE("<%s> redirect to root path. [%s].\n", __FUNCTION__, vpath);
    }

    if(OK != Webdav_CheckPath(vpath))
        return handle_http_error(403, req, rsp);

    if(WEBDAVR_OK != Webdav_CreateFolder(vpath))
        return handle_http_error(403, req, rsp);

    rsp->code = 201;
    return http_send_response(rsp);
}
예제 #2
0
int handle_http_post(http_req * req, http_rsp * rsp)
{
    HashElement * e     = NULL;
    int httpbodylen   = 0;
    int readlen       = 0;

    WEBLOG_API();

#ifdef WEBCFG_SUPPORT_AUTH
    /* Authentication has a very high priority. */
    if (OK != CheckAuthorization(req, rsp))
    {
        return handle_http_error(401, req, rsp);
    }
#endif

    e = HashLookup(req->headOptions, "Content-Length");
    if(!e)
    {
        /* RFC2616, 14.23. */
        WEBLOG_ERROR("<%s> Missing \"Content-Length\" in POST/PUT.\n", __FUNCTION__);
        return handle_http_error(400, req, rsp);
    }
    httpbodylen = atoi(e->value.data.string);
    WEBLOG_INFO("<%s> Content-Length:%d.\n", __FUNCTION__, httpbodylen);

    /* Even if we don't care about the data, we should either :
       1. close the socket.
       2. read all data out of the socket.
       This is to enure a keep-alive socket won't fail in next loop.
    */

    if(req->datalen > 0) // data left in head buffer.
        readlen += req->datalen;

    /* if there's more data in socket.... */
    while(readlen < httpbodylen)
    {
        req->datalen = recv(req->sock, req->sockbuf, sizeof(req->sockbuf), 0);
        if(req->datalen < 0)
        {
            print_socket_error();
            break;
        }
        else if(req->datalen == 0)
        {
            WEBLOG_INFO("<%s> client closed. data progress: %d/%d.\n",
                        __FUNCTION__, readlen, httpbodylen);
            break;
        }
        readlen += req->datalen;
        WEBLOG_VERBOSE("<%s> progress: %10d/%d. \n", __FUNCTION__, readlen, httpbodylen);
    }

    rsp->code = 200;
    return http_send_response(rsp);
}
예제 #3
0
int handle_http_delete(http_req * req, http_rsp * rsp)
{
    char * vpath = NULL;
    int ret = 0;

    WEBLOG_API();

#ifdef WEBCFG_SUPPORT_AUTH
    /* Authentication has a very high priority. */
    if (OK != CheckAuthorization(req, rsp))
    {
        return handle_http_error(401, req, rsp);
    }
#endif

    vpath = req->uri;
    ASSERT(vpath && vpath[0]);

    if(0 == strlen(vpath))
    {
        strcat(vpath, "/");
        WEBLOG_VERBOSE("<%s> redirect to root path. [%s].\n", __FUNCTION__, vpath);
    }

    if(OK != Webdav_CheckPath(vpath))
    {
        return handle_http_error(403, req, rsp);
    }

    /* Note that the path can be either a folder, or a file.
    If it is a folder, it can be either empty, or with files.
    */
    if(TRUE == Webdav_isFolder(vpath))
        ret = Webdav_DeleteFolder(vpath);
    else
        ret = Webdav_DeleteFile(vpath);

    if(WEBDAVR_OK == ret)
    {
        rsp->code = 204;
        return http_send_response(rsp);
    }
    else
    {
        WEBLOG_INFO("<%s> Failed to remove %s.\n", __FUNCTION__, vpath);
        return handle_http_error(403, req, rsp);
    }
}
예제 #4
0
파일: server_uv.c 프로젝트: mneumann/chttpd
static void
on_read_cb(uv_stream_t *stream, ssize_t nread, uv_buf_t buf)
{
  Connection *conn = (Connection*) stream;

  assert(conn->read_clear == false);

  if (nread < 0) {
    //
    // XXX: Do we have to call uv_read_stop(), or is it implicit?
    //
    // on_read_cb will never be called again for this connection, so we don't
    // have to reset anything.
    //
    uv_close((uv_handle_t*) conn, on_close_cb);
  }
  else if (nread > 0) {
    conn->read_buffer.increase_size(nread);
    conn->read_clear = true;

    if (conn->in_body) {
      // We are reading in the body. No need to call the parser!
      handle_http_body(conn);
    }
    else {
      conn->parse_offset = 
        http_parser_run(&conn->parser, &conn->req, conn->read_buffer.data(), conn->read_buffer.size(), conn->parse_offset);

      if (http_parser_is_finished(&conn->parser)) {
        handle_http_header_parsed(conn);
      }
      else if (http_parser_has_error(&conn->parser)) {
        handle_http_error(conn);
      }
    }
  }
  else {
    //
    // This happens when libuv calls alloc_read_buffer, but does not need the buffer.
    // We don't have to free the buffer, as it is part of the connection.
    //
    assert(nread == 0);
    conn->read_clear = true;
  }
}
예제 #5
0
파일: http.c 프로젝트: ccpgames/wine
static void HttpProtocol_on_error(Protocol *prot, DWORD error)
{
    HttpProtocol *This = impl_from_Protocol(prot);
    HRESULT hres;

    TRACE("(%p) %d\n", prot, error);

    if(prot->flags & FLAG_FIRST_CONTINUE_COMPLETE) {
        FIXME("Not handling error %d\n", error);
        return;
    }

    while((hres = handle_http_error(This, error)) == RPC_E_RETRY) {
        error = send_http_request(This);

        if(error == ERROR_IO_PENDING || error == ERROR_SUCCESS)
            return;
    }

    protocol_abort(prot, hres);
    protocol_close_connection(prot);
    return;
}
예제 #6
0
int handle_http_propfind(http_req * req, http_rsp * rsp)
{
    int ret = OK;
    HashElement * e = NULL;
    int depth = -1;
    HashHandle props = NULL_HANDLE;
    CacheHandle cache = NULL_HANDLE;
    char * propxml = NULL;
    int contentlen = 0;
    char * vpath = req->uri;
    struct stat buf;

    WEBLOG_API();

#ifdef WEBCFG_SUPPORT_AUTH
    /* Authentication has a very high priority. */
    if (OK != CheckAuthorization(req, rsp))
    {
        return handle_http_error(401, req, rsp);
    }
#endif

    if(OK != Webdav_CheckPath(req->uri))
    {
        WEBLOG_ERROR("<%s> PROPFIND is not allowed for non-webdav path [%s].\n", __FUNCTION__, req->uri);
        handle_http_error(403, req, rsp);
        ret = NG;
        goto __error_out;
    }

    if(0 == strlen(vpath))
    {
        strcat(vpath, "/");
        WEBLOG_VERBOSE("<%s> redirect to root path. [%s].\n", __FUNCTION__, vpath);
    }

    WEBLOG_INFO("<%s> stat the file \"%s\".\n", __FUNCTION__, vpath);
    ret = stat(vpath, &buf);

    /* Check if statistics are valid: */
    if(ret != 0)
    {
        WEBLOG_ERROR("<%s> fail to stat the file \"%s\".\n", __FUNCTION__, vpath);
        switch (errno)
        {
            case ENOENT:
                WEBLOG_ERROR("<%s> File %s not found.\n", __FUNCTION__, vpath);
                handle_http_error(404, req, rsp);
                ret = NG;
                goto __error_out;

            case EINVAL: /* no break */
            default:
                /* Should never be reached. */
                WEBLOG_ERROR("<%s> Unexpected error in _stat.\n", __FUNCTION__);
                handle_http_error(500, req, rsp);
                ret = NG;
                goto __error_out;
        }
    }


    props = HashTableCreate(64);
    ASSERT(props != NULL_HANDLE);

    /* get depth. */
    e = HashLookup(req->headOptions, "Depth");
    if(!e) depth = -1;
    else if(e->value.data.string[0] == '0') depth = 0;
    else if(e->value.data.string[0] == '1') depth = 1;
    else depth = -1;

    if(depth == -1 && TRUE == Webdav_isFolder(vpath))
    {
        WEBLOG_ERROR("<%s> PROPFIND a collection with infinite depth is not allowed.\n", __FUNCTION__);
        handle_http_error(403, req, rsp);
        ret = NG;
        goto __error_out;
    }

#ifdef WEBCFG_MINIMIZE_SERVER
#else
    e = HashLookup(req->headOptions, "Content-Type");
    if(e && strstr(e->value.data.string, "xml"))
    {
        char * xmlsockbuf = NULL;
        char strbuf[128] = {0};
        char *end, *p, *q;
        HashValue eeee = HashString("", FALSE); // empty value!

        WEBLOG_INFO("<%s> Client request props in a xml body.\n", __FUNCTION__);

        e = HashLookup(req->headOptions, "Content-Length");
        if(!e)
        {
            /* RFC2616, 14.23. */
            WEBLOG_ERROR("<%s> Missing \"Content-Length\" for xml body.\n", __FUNCTION__);
            handle_http_error(400, req, rsp);
            ret = NG;
            goto __error_out;
        }
        contentlen = atoi(e->value.data.string);

        xmlsockbuf = (char *)webmalloc(contentlen+1);
        memset(xmlsockbuf, 0, contentlen+1);

        if(req->datalen > 0) // data left in head buffer.
        {
            memcpy(xmlsockbuf, req->sockbuf, req->datalen);
            WEBLOG_VERBOSE("<%s> previous buffered %d/%d bytes consumed.\n",
                           __FUNCTION__, req->datalen, contentlen);
        }
        /* if there's more data in socket.... */
        if (req->datalen < contentlen)
        {
            /* read rest of data from socket. */
            p = xmlsockbuf + req->datalen;
            req->datalen = recv(req->sock, p, contentlen-req->datalen, 0);
            WEBLOG_VERBOSE("<%s> %d/%d bytes read from socket.\n",
                           __FUNCTION__, req->datalen, contentlen);
            dumpText(xmlsockbuf, contentlen);
        }

        p = strstr(xmlsockbuf, "<prop>") + 6;
        end = strstr(xmlsockbuf, "</prop>");

        if(strstr(xmlsockbuf, "<allprop/>"))
        {
            WEBLOG_INFO("<%s> client request all props.\n", __FUNCTION__);
        }
        else
        {
            ASSERT(p<end);
            *end = '\0'; /* good for str api. */

            /* Possible Value:
            WinXP: <propname/>
            Cadaver: <propname xmlns="DAV:"/>
            */
            do
            {
                p = strchr(p, '<');
                if(!p) break;
                else p++;
                q = strstr(p, "/>");
                ASSERT(q && (q-p < sizeof(strbuf)));

                strncpy(strbuf, p, q-p);
                p = strchr(strbuf, ' ');
                if(p) *p = '\0';
                p = strtrim(strbuf);

                WEBLOG_INFO("<%s> client request prop: <%s>\n", __FUNCTION__, p);
                HashAdd(props, p, eeee);
                p = q + 2;
            }
            while(p<end); /* <xxx/>\r\n</prop> */
        }
    }

#endif

    cache = CacheCreate();
    Webdav_Props(props, cache, vpath, depth);
    contentlen = CacheGetData(cache, &propxml);
    ASSERT(propxml);
    dumpText(propxml, contentlen);
    WEBLOG_INFO("<%s> response xml ready. len %d.\n", __FUNCTION__, contentlen);

    rsp->code = 207;
    rsp->body = propxml;
    http_add_rspoption(rsp, "Content-Type", "text/xml");
    http_send_response(rsp);

__error_out:

    if (props != NULL_HANDLE) HashTableDestroy(props);
    if (cache != NULL_HANDLE) CacheDestroy(cache);
    return ret;
}
예제 #7
0
int handle_http_connect(http_req * req, http_rsp * rsp)
{
    WEBLOG_API();
    return handle_http_error(501, req, rsp);
}
예제 #8
0
int handle_http_put(http_req * req, http_rsp * rsp)
{
    HashElement * e = NULL;
    char * vpath = NULL;
    int httpbodylen = 0;
    int readlen = 0;
    FILE * fp = NULL;
    int i = 0;
    unsigned char * buffer = NULL;
    int buflen = 1024*1024;
    char strbuf[128] = {0};

    WEBLOG_API();

#ifdef WEBCFG_SUPPORT_AUTH
    /* Authentication has a very high priority. */
    if (OK != CheckAuthorization(req, rsp))
    {
        return handle_http_error(401, req, rsp);
    }
#endif

    vpath = req->uri;
    ASSERT(vpath && vpath[0]);

    if(0 == strlen(vpath))
    {
        strcat(vpath, "/");
        WEBLOG_VERBOSE("<%s> redirect to root path. [%s].\n", __FUNCTION__, vpath);
    }

    e = HashLookup(req->headOptions, "Content-Length");
    if(!e)
    {
        /* RFC2616, 14.23. */
        WEBLOG_ERROR("<%s> Missing \"Content-Length\" in POST/PUT.\n", __FUNCTION__);
        return handle_http_error(400, req, rsp);
    }
    httpbodylen = atoi(e->value.data.string);
    WEBLOG_INFO("<%s> Content-Length:%d.\n", __FUNCTION__, httpbodylen);

    if(OK != Webdav_CheckPath(vpath))
        return handle_http_error(501, req, rsp);

    if(WEBDAVR_OK != Webdav_CreateFile(vpath))
        return handle_http_error(501, req, rsp);

    /* read data from socket and save it into target file. */
    fp = fopen(vpath, "wb");
    if(!fp)
        return handle_http_error(501, req, rsp);

    if(req->datalen > 0) // data left in head buffer.
    {
        i = fwrite(req->sockbuf, 1, req->datalen, fp);
        ASSERT(i == req->datalen);
        WEBLOG_VERBOSE("<%s> write previous buffered %d bytes into %s.\n",
                       __FUNCTION__, req->datalen, vpath);
        readlen += req->datalen;
    }

    /* if there's more data in socket....
    req->sockbuf is too small for large files.
    */
    do
    {
        buflen /= 2;
        buffer = (char *)webmalloc(buflen);
    }
    while(!buffer);

    while(readlen < httpbodylen)
    {
        req->datalen = recv(req->sock, buffer, buflen, 0);
        if(req->datalen < 0)
        {
            print_socket_error();
            break;
        }
        else if(req->datalen == 0)
        {
            WEBLOG_INFO("<%s> client closed. data progress: %d/%d.\n",
                        __FUNCTION__, readlen, httpbodylen);
            break;
        }
        readlen += req->datalen;
        WEBLOG_VERBOSE("<%s> progress: %10d/%d, ", __FUNCTION__, readlen, httpbodylen);
        i = fwrite(buffer, 1, req->datalen, fp);
        WEBLOG_VERBOSE("R %d <- socket, W %d -> %s.\n", req->datalen, i, vpath);
        ASSERT(i == req->datalen);
    }

    rsp->code = 201;
    e = HashLookup(req->headOptions, "Host");
    if(!e)
    {
        /* RFC2616, 14.23. */
        WEBLOG_ERROR("<%s> Missing \"Host\" in POST/PUT.\n", __FUNCTION__);
        sprintf(strbuf, "/webdav%s", vpath);
    }
    else
    {
        sprintf(strbuf, "http://%s/webdav%s", e->value.data.string, vpath);
    }
    http_add_rspoption(rsp, "Location", strbuf);
    http_send_response(rsp);

    /******************************
    Double Confirm File Size!
    *******************************/

    fseek(fp, 0, SEEK_END);
    i = ftell(fp);
    WEBLOG_INFO("<%s> Double Confirm. file-size: %d. content-length: %d.\n",
                __FUNCTION__, i, httpbodylen);
    ASSERT(i == httpbodylen);

    webfree(buffer);
    fclose(fp);
    return OK;
}
예제 #9
0
int handle_http_get(http_req * req, http_rsp * rsp)
{
    int ret           = OK;
    HashElement * e     = NULL;
    /* ------------------------------------ */
    FILE * fp           = NULL;
    char * timebuf      = NULL;
    /* ------------------------------------ */
    size_t total_length = 0;    /* total length of the file. */
    size_t task_length  = 0;    /* requested length. */
    char   strbuf[64]   = {0};
    size_t from         = -1;
    size_t to           = -1;
    char   path[256]    = {0};
    char * vpath        = path;
    struct stat buf;

    WEBLOG_API();

#ifdef WEBCFG_SUPPORT_AUTH
    /* Authentication has a very high priority. */
    if (OK != CheckAuthorization(req, rsp))
    {
        return handle_http_error(401, req, rsp);
    }
#endif

    vpath = req->uri;
    ASSERT(vpath && vpath[0]);
    ASSERT(rsp->headOptions != NULL_HANDLE);

    if(0 == strlen(vpath))
    {
        strcat(vpath, "/");
        WEBLOG_VERBOSE("<%s> redirect to root path. [%s].\n", __FUNCTION__, vpath);
    }

    /* Make sure the requesting URI is authorized. */
    if(strstr(vpath, "..") || strstr(vpath, "./"))
        return handle_http_error(403, req, rsp);

    /* Check if the requesting URI is a directory. */
    WEBLOG_INFO("<%s> stat the file \"%s\".\n", __FUNCTION__, vpath);
    ret = web_stat(vpath, &buf);

    /* Check if statistics are valid: */
    if(ret != 0)
    {
        WEBLOG_ERROR("<%s> fail to stat the file \"%s\".\n", __FUNCTION__, vpath);
        switch (errno)
        {
            case ENOENT:
                WEBLOG_ERROR("<%s> File %s not found.\n", __FUNCTION__, vpath);
                return handle_http_error(404, req, rsp);

            case EINVAL: /* no break */
            default:
                /* Should never be reached. */
                WEBLOG_ERROR("<%s> Unexpected error in _stat.\n", __FUNCTION__);
                return handle_http_error(500, req, rsp);
        }
    }
    else
    {
        WEBLOG_INFO("<%s> File size     : "sizett"\n", __FUNCTION__, buf.st_size );
        //WEBLOG_INFO("<%s> Drive         : %c:\n", __FUNCTION__, buf.st_dev + 'A' );
        timebuf = ctime(&buf.st_mtime);
        WEBLOG_INFO("<%s> Time modified : %s", __FUNCTION__, timebuf);

        if(S_IFDIR & buf.st_mode)
        {
#if 1 //#ifdef WEBCFG_SUPPORT_WEBDAV
            CacheHandle cache = CacheCreate();
            if (NULL_HANDLE == cache)
                return handle_http_error(500, req, rsp);
            rsp->code = 200;

            web_lsdir(cache, vpath);
            http_add_rspoption(rsp, "Content-Type", "text/html; charset=\"utf-8\"");
            CacheGetData(cache, &rsp->body);
            http_send_response(rsp);
            if (cache != NULL_HANDLE) CacheDestroy(cache);
            return OK;

#else
            WEBLOG_INFO("<%s> client requesting a directory!\n", __FUNCTION__);
            return handle_http_error(403, req, rsp);
#endif
        }
    }

#ifdef WEBCFG_SUPPORT_HTTPTIME
    /* RFC2616, 14.25. If-Modified-Since */
    e = HashLookup(req->headOptions, "If-Modified-Since");
    if(e)
    {
        time_t reqtime, acctime;
        ASSERT(e->value.type == eHashString);
        reqtime = get_http_time(e->value.data.string);
        acctime = get_http_time(timebuf);

        //WEBLOG_INFO("<%s> reqtime=[%u] vs [%u]=acctime\n", __FUNCTION__, reqtime, acctime);
        if(reqtime >= acctime)
        {
            rsp->code = 304;
            rsp->body = using_customized_body; // 304 has no body.
            http_add_rspoption(rsp, "Content-Length", "0");
            return http_send_response(rsp);
        }
    }
#endif

    fp = web_fopen(vpath,"rb");
    WEBLOG_INFO("<%s> fopen(%s) == %p \n", __FUNCTION__, vpath, fp);
    if(!fp)
    {
        WEBLOG_ERROR("<%s> failed to open file \"%s\" %s \n",
                     __FUNCTION__, vpath, strerror(errno));
        return handle_http_error(500, req, rsp);
    }
    ASSERT(fp); /* check if fp is NULL. */

    fseek(fp, 0, SEEK_END);
    total_length = ftell(fp);
    fseek(fp, 0, SEEK_SET);

#ifdef WEBCFG_SUPPORT_HTTPRANGE
    /* handle range request */
    e = HashLookup(req->headOptions, "Range");
    if(e)
    {
        char * p = e->value.data.string;
        ASSERT(e->value.type == eHashString);
        WEBLOG_INFO("<%s> client range request: %s\n", __FUNCTION__, p);

        /* figure out FROM-TO */
        if(0 == strncmp(p, " bytes=-", 8))
        {
            sscanf(p," bytes=-"sizett"", &task_length);
            from = total_length-task_length;
            to = total_length-1;
        }
        else
        {
            sscanf(p," bytes="sizett"-"sizett"", &from, &to);
            if(to < 0)
            {
                task_length = total_length - from;
                to = total_length-1;
            }
            else
            {
                task_length = to - from + 1;
            }
        }


        WEBLOG_INFO("<%s> request "sizett"-"sizett", total "sizett", we have "sizett".\n",
                    __FUNCTION__, from, to, task_length, total_length);

        if(from < 0 || to < 0 || to >= total_length || from >= total_length || from > to)
        {
            http_add_rspoption(rsp, "Accept-Ranges", "bytes");
            //http_add_rspoption(rsp, "Content-Type", mimetype(req->uri));
            http_add_rspoption(rsp, "Content-Range", "*/*");
            return handle_http_error(416, req, rsp);
        }
        else
        {
            rsp->code = 206;
            rsp->body = using_customized_body;
            http_add_rspoption(rsp, "Accept-Ranges", "bytes");
            //http_add_rspoption(rsp, "Content-Type", mimetype(req->uri));
            sprintf(strbuf, "bytes "sizett"-"sizett"/"sizett"", from, to, total_length);
            http_add_rspoption(rsp, "Content-Range", strbuf);
            sprintf(strbuf, sizett, task_length);
            http_add_rspoption(rsp, "Content-Length", strbuf);

            http_send_response(rsp);
        }
    }
    else
#endif /* WEBCFG_SUPPORT_HTTPRANGE */
    {
        from = 0;
        task_length = total_length;
        to = total_length-1;
        sprintf(strbuf, sizett, task_length);

        rsp->code = 200;
        rsp->body = using_customized_body;
#ifdef WEBCFG_SUPPORT_HTTPRANGE
        http_add_rspoption(rsp, "Accept-Ranges", "bytes");
#endif
        //http_add_rspoption(rsp, "Content-Type", mimetype(req->uri));
        http_add_rspoption(rsp, "Content-Length", strbuf);
        http_send_response(rsp);
    }

    ret = OK;

    /* Respond with data. For HEAD request, skip this. */
    if(HTTP_GET == req->method)
    {
        size_t  i           = 0;
        size_t  buflen      = 1024*1024;
        size_t  readsize    = 0;
        size_t  counter     = 0;
        char  * buffer      = NULL;

#define SPEED_REPORT
#ifdef SPEED_REPORT
        /* speed test */
        //size_t  data_1 = 0, data_2 = 0;
        time_t  time_1 = time(NULL), time_2;
#endif
        do
        {
            buflen /= 2;
            buffer = (char *)webmalloc(buflen);
        }
        while(!buffer);

        fseek(fp, from, SEEK_SET);
        while(1)
        {
            memset(buffer, 0, buflen);
            if(task_length-counter > buflen)
                readsize=fread(buffer, 1, buflen, fp);
            else
                readsize=fread(buffer, 1, task_length-counter, fp);

            if(readsize <= 0)
            {
                WEBLOG_ERROR("<%s> fread fail "sizett". %s.\n", __FUNCTION__, readsize, strerror(socketGetError()));
                ret = NG;
                break;
            }
            WEBLOG_VERBOSE("<%s> read "sizett" from %s, sent "sizett" to socket.\n ", __FUNCTION__, readsize, vpath, i);
            i = WebWrite(req->sock, buffer, readsize);
            if(i != readsize)
            {
                WEBLOG_ERROR("<%s> WebWrite fail "sizett". %s.\n", __FUNCTION__, i, strerror(socketGetError()));
                ret = NG;
                break;
            }
            //ASSERT(i==readsize);
            counter += readsize;
#ifdef SPEED_REPORT
            time_2 = time(NULL);
            if (time_2 - time_1 > 1)
                WEBLOG_VERBOSE("<%s> "sizett"KB/s\n", __FUNCTION__, counter/1024/(time_2-time_1));
#endif
            WEBLOG_VERBOSE("<%s> "sizett"/"sizett"\n", __FUNCTION__, counter, task_length);
            if(counter >= task_length)
                break;
        }

        webfree(buffer);
    }

    if(fp) fclose(fp);
    return ret;
}
예제 #10
0
int handle_http_unlock(http_req * req, http_rsp * rsp)
{
    WEBLOG_API();
    return handle_http_error(501, req, rsp);
}
예제 #11
0
int handle_http_move(http_req * req, http_rsp * rsp)
{
    int ret = 0;
    char * from = NULL;
    char * to = NULL;
    char * tooooo = NULL;
    char * host = NULL;
    HashElement * e = NULL;

    WEBLOG_API();

#ifdef WEBCFG_SUPPORT_AUTH
    /* Authentication has a very high priority. */
    if (OK != CheckAuthorization(req, rsp))
    {
        return handle_http_error(401, req, rsp);
    }
#endif

    from = req->uri;
    ASSERT(from && from[0]);

    if(0 == strlen(from))
    {
        strcat(from, "/");
        WEBLOG_VERBOSE("<%s> redirect to root path. [%s].\n", __FUNCTION__, from);
    }

    e = HashLookup(req->headOptions, "Destination");
    if(!e)
    {
        WEBLOG_ERROR("<%s> Missing \"Destination\" in Move/Copy.\n", __FUNCTION__);
        return handle_http_error(400, req, rsp);
    }

    ASSERT(e->value.type == eHashString);
    to = e->value.data.string;

    e = HashLookup(req->headOptions, "Host");
    ASSERT(e); // static int _simple_validation(http_req * req)
    host = e->value.data.string;

    /* example
    To: [http://x.x.x.x:y/webdav/1.txt]
    Host: [x.x.x.x:y]
    */

    tooooo = to + 7 + strlen(host); // 7 for "http://"

    if(0 == strlen(tooooo))
    {
        strcat(from, "/");
        WEBLOG_VERBOSE("<%s> redirect to root path. [%s].\n", __FUNCTION__, tooooo);
    }

    url_decode(tooooo);

    WEBLOG_INFO("<%s> %s from %s to %s.\n", __FUNCTION__,
                (HTTP_MOVE == req->method)?"Move":"Copy", from, tooooo);

    e = HashLookup(req->headOptions, "Overwrite");
    if(e && e->value.data.string[0] == 'T')
    {
        if(HTTP_MOVE == req->method)
            ret = Webdav_Move(from, tooooo, TRUE);
        else
            ret = Webdav_Copy(from, tooooo, TRUE);
    }
    else
    {
        if(HTTP_MOVE == req->method)
            ret = Webdav_Move(from, tooooo, FALSE);
        else
            ret = Webdav_Copy(from, tooooo, FALSE);
    }

    switch(ret)
    {
        case WEBDAVR_OK:
            rsp->code = 201;
            http_add_rspoption(rsp, "Location", to);
            http_send_response(rsp);
            break;
        default:
            handle_http_error(502, req, rsp);
            break;
    }

    return OK;
}
예제 #12
0
int handle_http_proppatch(http_req * req, http_rsp * rsp)
{
    HashElement * e = NULL;
    char * propxml = NULL;
    int contentlen = 0;
    char * vpath = req->uri;

    WEBLOG_API();

#ifdef WEBCFG_SUPPORT_AUTH
    /* Authentication has a very high priority. */
    if (OK != CheckAuthorization(req, rsp))
    {
        return handle_http_error(401, req, rsp);
    }
#endif

    if(OK != Webdav_CheckPath(req->uri))
    {
        WEBLOG_ERROR("<%s> PROPFIND is not allowed for non-webdav path [%s].\n", __FUNCTION__, req->uri);
        return handle_http_error(403, req, rsp);
    }

    if(0 == strlen(vpath))
    {
        strcat(vpath, "/");
        WEBLOG_VERBOSE("<%s> redirect to root path. [%s].\n", __FUNCTION__, vpath);
    }

#ifdef WEBCFG_MINIMIZE_SERVER
#else
    if(OK != Webdav_CheckPath(req->uri))
    {
        WEBLOG_ERROR("<%s> PROPFIND is not allowed for non-webdav path [%s].\n", __FUNCTION__, req->uri);
        return handle_http_error(403, req, rsp);
    }


    e = HashLookup(req->headOptions, "Content-Type");
    if(e && strstr(e->value.data.string, "xml"))
    {
        char * xmlsockbuf = NULL;
        char * p = NULL;

        WEBLOG_INFO("<%s> Client provide props value in a xml body.\n", __FUNCTION__);

        e = HashLookup(req->headOptions, "Content-Length");
        if(!e)
        {
            /* RFC2616, 14.23. */
            WEBLOG_ERROR("<%s> Missing \"Content-Length\" for xml body.\n", __FUNCTION__);
            return handle_http_error(400, req, rsp);
        }
        contentlen = atoi(e->value.data.string);

        xmlsockbuf = (char *)webmalloc(contentlen+1);
        memset(xmlsockbuf, 0, contentlen+1);

        if(req->datalen > 0) // data left in head buffer.
        {
            memcpy(xmlsockbuf, req->sockbuf, req->datalen);
            WEBLOG_VERBOSE("<%s> previous buffered %d/%d bytes consumed.\n",
                           __FUNCTION__, req->datalen, contentlen);
        }
        /* if there's more data in socket.... */
        if (req->datalen < contentlen)
        {
            /* read rest of data from socket. */
            p = xmlsockbuf + req->datalen;
            req->datalen = recv(req->sock, p, contentlen-req->datalen, 0);
            WEBLOG_VERBOSE("<%s> %d/%d bytes read from socket.\n",
                           __FUNCTION__, req->datalen, contentlen);
            dumpText(xmlsockbuf, contentlen);
        }

    }

#endif

    return handle_http_error(501, req, rsp);
}
예제 #13
0
파일: http.c 프로젝트: ccpgames/wine
static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD request_flags,
        HINTERNET internet_session, IInternetBindInfo *bind_info)
{
    HttpProtocol *This = impl_from_Protocol(prot);
    WCHAR *addl_header = NULL, *post_cookie = NULL, *rootdoc_url = NULL;
    IServiceProvider *service_provider = NULL;
    IHttpNegotiate2 *http_negotiate2 = NULL;
    BSTR url, host, user, pass, path;
    LPOLESTR accept_mimes[257];
    const WCHAR **accept_types;
    BYTE security_id[512];
    DWORD len, port, flags;
    ULONG num, error;
    BOOL res, b;
    HRESULT hres;

    static const WCHAR wszBindVerb[BINDVERB_CUSTOM][5] =
        {{'G','E','T',0},
         {'P','O','S','T',0},
         {'P','U','T',0}};

    hres = IUri_GetPort(uri, &port);
    if(FAILED(hres))
        return hres;

    hres = IUri_GetHost(uri, &host);
    if(FAILED(hres))
        return hres;

    hres = IUri_GetUserName(uri, &user);
    if(SUCCEEDED(hres)) {
        hres = IUri_GetPassword(uri, &pass);

        if(SUCCEEDED(hres)) {
            This->base.connection = InternetConnectW(internet_session, host, port, user, pass,
                    INTERNET_SERVICE_HTTP, This->https ? INTERNET_FLAG_SECURE : 0, (DWORD_PTR)&This->base);
            SysFreeString(pass);
        }
        SysFreeString(user);
    }
    SysFreeString(host);
    if(FAILED(hres))
        return hres;
    if(!This->base.connection) {
        WARN("InternetConnect failed: %d\n", GetLastError());
        return INET_E_CANNOT_CONNECT;
    }

    num = 0;
    hres = IInternetBindInfo_GetBindString(bind_info, BINDSTRING_ROOTDOC_URL, &rootdoc_url, 1, &num);
    if(hres == S_OK && num) {
        FIXME("Use root doc URL %s\n", debugstr_w(rootdoc_url));
        CoTaskMemFree(rootdoc_url);
    }

    num = sizeof(accept_mimes)/sizeof(accept_mimes[0])-1;
    hres = IInternetBindInfo_GetBindString(bind_info, BINDSTRING_ACCEPT_MIMES, accept_mimes, num, &num);
    if(hres == INET_E_USE_DEFAULT_SETTING) {
        static const WCHAR default_accept_mimeW[] = {'*','/','*',0};
        static const WCHAR *default_accept_mimes[] = {default_accept_mimeW, NULL};

        accept_types = default_accept_mimes;
        num = 0;
    }else if(hres == S_OK) {
        accept_types = (const WCHAR**)accept_mimes;
    }else {
        WARN("GetBindString BINDSTRING_ACCEPT_MIMES failed: %08x\n", hres);
        return INET_E_NO_VALID_MEDIA;
    }
    accept_mimes[num] = 0;

    if(This->https)
        request_flags |= INTERNET_FLAG_SECURE;

    hres = IUri_GetPathAndQuery(uri, &path);
    if(SUCCEEDED(hres)) {
        This->base.request = HttpOpenRequestW(This->base.connection,
                This->base.bind_info.dwBindVerb < BINDVERB_CUSTOM
                    ? wszBindVerb[This->base.bind_info.dwBindVerb] : This->base.bind_info.szCustomVerb,
                path, NULL, NULL, accept_types, request_flags, (DWORD_PTR)&This->base);
        SysFreeString(path);
    }
    while(num--)
        CoTaskMemFree(accept_mimes[num]);
    if(FAILED(hres))
        return hres;
    if (!This->base.request) {
        WARN("HttpOpenRequest failed: %d\n", GetLastError());
        return INET_E_RESOURCE_NOT_FOUND;
    }

    hres = IInternetProtocolSink_QueryInterface(This->base.protocol_sink, &IID_IServiceProvider,
            (void **)&service_provider);
    if (hres != S_OK) {
        WARN("IInternetProtocolSink_QueryInterface IID_IServiceProvider failed: %08x\n", hres);
        return hres;
    }

    hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate,
            &IID_IHttpNegotiate, (void **)&This->http_negotiate);
    if (hres != S_OK) {
        WARN("IServiceProvider_QueryService IID_IHttpNegotiate failed: %08x\n", hres);
        IServiceProvider_Release(service_provider);
        return hres;
    }

    hres = IUri_GetAbsoluteUri(uri, &url);
    if(FAILED(hres)) {
        IServiceProvider_Release(service_provider);
        return hres;
    }

    hres = IHttpNegotiate_BeginningTransaction(This->http_negotiate, url, default_headersW,
            0, &addl_header);
    SysFreeString(url);
    if(hres != S_OK) {
        WARN("IHttpNegotiate_BeginningTransaction failed: %08x\n", hres);
        IServiceProvider_Release(service_provider);
        return hres;
    }

    len = addl_header ? strlenW(addl_header) : 0;

    This->full_header = heap_alloc(len*sizeof(WCHAR)+sizeof(default_headersW));
    if(!This->full_header) {
        IServiceProvider_Release(service_provider);
        return E_OUTOFMEMORY;
    }

    if(len)
        memcpy(This->full_header, addl_header, len*sizeof(WCHAR));
    CoTaskMemFree(addl_header);
    memcpy(This->full_header+len, default_headersW, sizeof(default_headersW));

    hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate2,
            &IID_IHttpNegotiate2, (void **)&http_negotiate2);
    IServiceProvider_Release(service_provider);
    if(hres != S_OK) {
        WARN("IServiceProvider_QueryService IID_IHttpNegotiate2 failed: %08x\n", hres);
        /* No goto done as per native */
    }else {
        len = sizeof(security_id)/sizeof(security_id[0]);
        hres = IHttpNegotiate2_GetRootSecurityId(http_negotiate2, security_id, &len, 0);
        IHttpNegotiate2_Release(http_negotiate2);
        if (hres != S_OK)
            WARN("IHttpNegotiate2_GetRootSecurityId failed: %08x\n", hres);
    }

    /* FIXME: Handle security_id. Native calls undocumented function IsHostInProxyBypassList. */

    if(This->base.bind_info.dwBindVerb == BINDVERB_POST) {
        num = 0;
        hres = IInternetBindInfo_GetBindString(bind_info, BINDSTRING_POST_COOKIE, &post_cookie, 1, &num);
        if(hres == S_OK && num) {
            if(!InternetSetOptionW(This->base.request, INTERNET_OPTION_SECONDARY_CACHE_KEY,
                                   post_cookie, lstrlenW(post_cookie)))
                WARN("InternetSetOption INTERNET_OPTION_SECONDARY_CACHE_KEY failed: %d\n", GetLastError());
            CoTaskMemFree(post_cookie);
        }
    }

    flags = INTERNET_ERROR_MASK_COMBINED_SEC_CERT;
    res = InternetSetOptionW(This->base.request, INTERNET_OPTION_ERROR_MASK, &flags, sizeof(flags));
    if(!res)
        WARN("InternetSetOption(INTERNET_OPTION_ERROR_MASK) failed: %u\n", GetLastError());

    b = TRUE;
    res = InternetSetOptionW(This->base.request, INTERNET_OPTION_HTTP_DECODING, &b, sizeof(b));
    if(!res)
        WARN("InternetSetOption(INTERNET_OPTION_HTTP_DECODING) failed: %u\n", GetLastError());

    do {
        error = send_http_request(This);

        switch(error) {
        case ERROR_IO_PENDING:
            return S_OK;
        case ERROR_SUCCESS:
            /*
             * If sending response ended synchronously, it means that we have the whole data
             * available locally (most likely in cache).
             */
            return protocol_syncbinding(&This->base);
        default:
            hres = handle_http_error(This, error);
        }
    } while(hres == RPC_E_RETRY);

    WARN("HttpSendRequest failed: %d\n", error);
    return hres;
}