⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 server.c

📁 一个很好用的解析
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Copyright information is at end of file */#include <assert.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <errno.h>#ifdef WIN32  #include <io.h>#else  #include <unistd.h>  #include <grp.h>#endif#include <fcntl.h>#include "xmlrpc_config.h"#include "mallocvar.h"#include "xmlrpc-c/string_int.h"#include "xmlrpc-c/sleep_int.h"#include "xmlrpc-c/abyss.h"#include "trace.h"#include "session.h"#include "conn.h"#include "socket.h"#ifdef WIN32  #include "socket_win.h"#else  #include "socket_unix.h"#endif#include "http.h"#include "date.h"#include "abyss_info.h"#include "server.h"voidServerTerminate(TServer * const serverP) {    struct _TServer * const srvP = serverP->srvP;    srvP->terminationRequested = true;}voidServerResetTerminate(TServer * const serverP) {    struct _TServer * const srvP = serverP->srvP;    srvP->terminationRequested = false;}typedef int (*TQSortProc)(const void *, const void *);static intcmpfilenames(const TFileInfo **f1,const TFileInfo **f2) {    if (((*f1)->attrib & A_SUBDIR) && !((*f2)->attrib & A_SUBDIR))        return (-1);    if (!((*f1)->attrib & A_SUBDIR) && ((*f2)->attrib & A_SUBDIR))        return 1;    return strcmp((*f1)->name,(*f2)->name);}static intcmpfiledates(const TFileInfo **f1,const TFileInfo **f2) {    if (((*f1)->attrib & A_SUBDIR) && !((*f2)->attrib & A_SUBDIR))        return (-1);    if (!((*f1)->attrib & A_SUBDIR) && ((*f2)->attrib & A_SUBDIR))        return 1;    return ((*f1)->time_write-(*f2)->time_write);}static voiddetermineSortType(const char *  const query,                  abyss_bool *  const ascendingP,                  uint16_t *    const sortP,                  abyss_bool *  const textP,                  const char ** const errorP) {    *ascendingP = TRUE;    *sortP = 1;    *textP = FALSE;    *errorP = NULL;        if (query) {        if (xmlrpc_streq(query, "plain"))            *textP = TRUE;        else if (xmlrpc_streq(query, "name-up")) {            *sortP = 1;            *ascendingP = TRUE;        } else if (xmlrpc_streq(query, "name-down")) {            *sortP = 1;            *ascendingP = FALSE;        } else if (xmlrpc_streq(query, "date-up")) {            *sortP = 2;            *ascendingP = TRUE;        } else if (xmlrpc_streq(query, "date-down")) {            *sortP = 2;            *ascendingP = FALSE;        } else  {            xmlrpc_asprintf(errorP, "invalid query value '%s'", query);        }    }}static voidgenerateListing(TList *       const listP,                char *        const z,                const char *  const uri,                TPool *       const poolP,                const char ** const errorP,                uint16_t *    const responseStatusP) {        TFileInfo fileinfo;    TFileFind findhandle;    *errorP = NULL;    if (!FileFindFirst(&findhandle, z, &fileinfo)) {        *responseStatusP = ResponseStatusFromErrno(errno);        xmlrpc_asprintf(errorP, "Can't read first entry in directory");    } else {        ListInit(listP);        do {            TFileInfo * fi;            /* Files whose names start with a dot are ignored */            /* This includes implicitly the ./ and ../ */            if (*fileinfo.name == '.') {                if (xmlrpc_streq(fileinfo.name, "..")) {                    if (xmlrpc_streq(uri, "/"))                        continue;                } else                    continue;            }            fi = (TFileInfo *)PoolAlloc(poolP, sizeof(fileinfo));            if (fi) {                abyss_bool success;                memcpy(fi, &fileinfo, sizeof(fileinfo));                success =  ListAdd(listP, fi);                if (!success)                    xmlrpc_asprintf(errorP, "ListAdd() failed");            } else                xmlrpc_asprintf(errorP, "PoolAlloc() failed.");        } while (!*errorP && FileFindNext(&findhandle, &fileinfo));        if (*errorP) {            *responseStatusP = 500;            ListFree(listP);        }                    FileFindClose(&findhandle);    }}static voidsendDirectoryDocument(TList *      const listP,                      abyss_bool   const ascending,                      uint16_t     const sort,                      abyss_bool   const text,                      const char * const uri,                      MIMEType *   const mimeTypeP,                      TSession *   const sessionP,                      char *       const z) {    char *p,z1[26],z2[20],z3[9],u;    const char * z4;    int16_t i;    uint32_t k;    if (text) {        sprintf(z, "Index of %s" CRLF, uri);        i = strlen(z)-2;        p = z + i + 2;        while (i > 0) {            *(p++) = '-';            --i;        }        *p = '\0';        strcat(z, CRLF CRLF               "Name                      Size      "               "Date-Time             Type" CRLF               "------------------------------------"               "--------------------------------------------"CRLF);    } else {        sprintf(z, "<HTML><HEAD><TITLE>Index of %s</TITLE></HEAD><BODY>"                "<H1>Index of %s</H1><PRE>",                uri, uri);        strcat(z, "Name                      Size      "               "Date-Time             Type<HR WIDTH=100%>"CRLF);    }    HTTPWriteBodyChunk(sessionP, z, strlen(z));    /* Sort the files */    qsort(listP->item, listP->size, sizeof(void *),          (TQSortProc)(sort == 1 ? cmpfilenames : cmpfiledates));        /* Write the listing */    if (ascending)        i = 0;    else        i = listP->size - 1;    while ((i < listP->size) && (i >= 0)) {        TFileInfo * fi;        struct tm ftm;        fi = listP->item[i];        if (ascending)            ++i;        else            --i;                    strcpy(z, fi->name);        k = strlen(z);        if (fi->attrib & A_SUBDIR) {            z[k++] = '/';            z[k] = '\0';        }        if (k > 24) {            z[10] = '\0';            strcpy(z1, z);            strcat(z1, "...");            strcat(z1, z + k - 11);            k = 24;            p = z1 + 24;        } else {            strcpy(z1, z);                        ++k;            p = z1 + k;            while (k < 25)                z1[k++] = ' ';                        z1[25] = '\0';        }        ftm = *gmtime(&fi->time_write);        sprintf(z2, "%02u/%02u/%04u %02u:%02u:%02u",ftm.tm_mday,ftm.tm_mon+1,                ftm.tm_year+1900,ftm.tm_hour,ftm.tm_min,ftm.tm_sec);        if (fi->attrib & A_SUBDIR) {            strcpy(z3, "   --  ");            z4 = "Directory";        } else {            if (fi->size < 9999)                u = 'b';            else {                fi->size /= 1024;                if (fi->size < 9999)                    u = 'K';                else {                    fi->size /= 1024;                    if (fi->size < 9999)                        u = 'M';                    else                        u = 'G';                }            }                            sprintf(z3, "%5llu %c", fi->size, u);                        if (xmlrpc_streq(fi->name, ".."))                z4 = "";            else                z4 = MIMETypeFromFileName2(mimeTypeP, fi->name);            if (!z4)                z4 = "Unknown";        }        if (text)            sprintf(z, "%s%s %s    %s   %s"CRLF, z1, p, z3, z2, z4);        else            sprintf(z, "<A HREF=\"%s%s\">%s</A>%s %s    %s   %s"CRLF,                    fi->name, fi->attrib & A_SUBDIR ? "/" : "",                    z1, p, z3, z2, z4);        HTTPWriteBodyChunk(sessionP, z, strlen(z));    }            /* Write the tail of the file */    if (text)        strcpy(z, SERVER_PLAIN_INFO);    else        strcpy(z, "</PRE>" SERVER_HTML_INFO "</BODY></HTML>" CRLF CRLF);        HTTPWriteBodyChunk(sessionP, z, strlen(z));}static voidfileDate(TSession * const sessionP,         time_t     const statFilemodTime,         TDate *    const fileDateP) {    abyss_bool haveDate;    TDate filemodDate;    haveDate = DateFromLocal(&filemodDate, statFilemodTime);    if (haveDate) {        if (DateCompare(&sessionP->date, &filemodDate) < 0)            *fileDateP = sessionP->date;        else            *fileDateP = filemodDate;    } else        *fileDateP = sessionP->date;}static abyss_boolServerDirectoryHandler(TSession * const r,                       char *     const z,                       time_t     const fileModTime,                       MIMEType * const mimeTypeP) {    TList list;    abyss_bool text;    abyss_bool ascending;    uint16_t sort;    /* 1=by name, 2=by date */    TPool pool;    TDate date;    const char * error;    uint16_t responseStatus;    TDate dirdate;    const char * imsHdr;        determineSortType(r->request_info.query, &ascending, &sort, &text, &error);    if (error) {        ResponseStatus(r,400);        xmlrpc_strfree(error);        return TRUE;    }    fileDate(r, fileModTime, &dirdate);    imsHdr = RequestHeaderValue(r, "If-Modified-Since");    if (imsHdr) {        if (DateDecode(imsHdr, &date)) {            if (DateCompare(&dirdate, &date) <= 0) {                ResponseStatus(r, 304);                ResponseWrite(r);                return TRUE;            }        }    }    if (!PoolCreate(&pool, 1024)) {        ResponseStatus(r, 500);        return TRUE;    }    generateListing(&list, z, r->request_info.uri,                    &pool, &error, &responseStatus);    if (error) {        ResponseStatus(r, responseStatus);        xmlrpc_strfree(error);        PoolFree(&pool);        return TRUE;    }    /* Send something to the user to show that we are still alive */    ResponseStatus(r, 200);    ResponseContentType(r, (text ? "text/plain" : "text/html"));    if (DateToString(&dirdate, z))        ResponseAddField(r, "Last-Modified", z);        ResponseChunked(r);    ResponseWrite(r);    if (r->request_info.method!=m_head)        sendDirectoryDocument(&list, ascending, sort, text,                              r->request_info.uri, mimeTypeP, r, z);    HTTPWriteEndChunk(r);    /* Free memory and exit */    ListFree(&list);    PoolFree(&pool);    return TRUE;}#define BOUNDARY    "##123456789###BOUNDARY"static voidsendBody(TSession *   const sessionP,         TFile *      const fileP,         uint64_t     const filesize,         const char * const mediatype,         uint64_t     const start0,         uint64_t     const end0,         char *       const z) {    if (sessionP->ranges.size == 0)        ConnWriteFromFile(sessionP->conn, fileP, 0, filesize - 1, z, 4096, 0);    else if (sessionP->ranges.size == 1)        ConnWriteFromFile(sessionP->conn, fileP, start0, end0, z, 4096, 0);    else {        uint64_t i;        for (i = 0; i <= sessionP->ranges.size; ++i) {            ConnWrite(sessionP->conn,"--", 2);            ConnWrite(sessionP->conn, BOUNDARY, strlen(BOUNDARY));            ConnWrite(sessionP->conn, CRLF, 2);            if (i < sessionP->ranges.size) {                uint64_t start;                uint64_t end;                abyss_bool decoded;                                    decoded = RangeDecode((char *)(sessionP->ranges.item[i]),                                      filesize,                                      &start, &end);                if (decoded) {                    /* Entity header, not response header */                    sprintf(z, "Content-type: %s" CRLF                            "Content-range: bytes %llu-%llu/%llu" CRLF                            "Content-length: %llu" CRLF                            CRLF, mediatype, start, end,                            filesize, end-start+1);                    ConnWrite(sessionP->conn, z, strlen(z));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -