示例#1
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);
}
示例#2
0
void HashInsert(void *entry,unsigned int key,Hash hash) 
{
  HashEntry ent;
  int j;
  
  assert(3,!HashLookup(key,hash));
  
  j = (hash->mapfunc)(key);
  ent = (HashEntry) localmalloc(sizeof(*ent));
  ent->next = hash->array[j];
  hash->array[j]=ent;
  ent->key = key;
  ent->entry = entry;
}
示例#3
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;
}
示例#4
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;
}
示例#5
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;
}
示例#6
0
int http_send_response(http_rsp * rsp)
{
    CacheHandle cache = NULL_HANDLE;
    char * datapointer      = NULL;
    int datalength        = 0;
    char strbuf[64]         = {0};
    char bodybuf[256]       = {0};
    HashElement * e         = NULL;
    http_status * stt       = get_http_status(rsp->code);

    WEBLOG_API();
    ASSERT(stt);


    if(using_customized_body != rsp->body)
    {
        /* if body is empty, make a default body. */
        if(!rsp->body)
        {
            WEBLOG_VERBOSE("<%s> body empty. add default body.\n", __FUNCTION__);
            sprintf(bodybuf, "<HTML><BODY><b>%s</b></BODY></HTML>", stt->s_name);
            rsp->body = bodybuf;
            http_add_rspoption(rsp, "Content-Type", "text/html");
        }

        /* if Content-Length is not given, try caculating it here. */
        if(!HashLookup(rsp->headOptions, "Content-Length"))
        {
            if(rsp->body)
                sprintf(strbuf, sizett, strlen(rsp->body));
            else
                sprintf(strbuf, "%d", 0);
            http_add_rspoption(rsp, "Content-Length", strbuf);
        }
    }

    /* server info is always present. */
    http_add_rspoption(rsp, "Server", SERVER_VER);
#ifdef WEBCFG_SUPPORT_HTTPRANGE
    http_add_rspoption(rsp, "Accept-Ranges", "bytes");
#endif

    if(NULL_HANDLE == cache) cache = CacheCreate();
    ASSERT(NULL_HANDLE != cache);
    CacheClean(cache);

    /* send first line! */
    CacheWriteString(cache, "HTTP/1.1 ");
    CacheWriteString(cache, stt->s_code);
    CacheWriteString(cache, " ");
    CacheWriteString(cache, stt->s_name);
    CacheWriteString(cache, "\r\n");

    //HashDump(rsp->headOptions);

    /* send head options! */
    e = HashFirst(rsp->headOptions);
    while(e)
    {
        CacheWriteString(cache, e->name);
        CacheWriteString(cache, ": ");
        if(e->value.type == eHashString)
        {
            CacheWriteString(cache, e->value.data.string);
        }
        else if(e->value.type == eHashInt)
        {
            sprintf(strbuf, "%d", e->value.data.integer);
            CacheWriteString(cache, strbuf);
        }
        CacheWriteString(cache, "\r\n");

        e = HashNext(rsp->headOptions, e);
    }

    CacheWriteString(cache, "\r\n");

    /* send body */
    if(rsp->body && rsp->body != using_customized_body)
        CacheWriteString(cache, rsp->body);

    datalength = CacheGetData(cache, &datapointer);
    ASSERT(datapointer && datalength > 0);

    WebWrite(rsp->sock, datapointer, datalength);
    CacheDestroy(cache);
    return OK;
}
示例#7
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;
}
示例#8
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);
}