handler.c

来自「开放源码实时操作系统源码.」· C语言 代码 · 共 597 行 · 第 1/2 页

C
597
字号
    0x50, 0x60, 0x02, 0x04, 0x13, 0x27, 0x56, 0x04,
    0x70, 0x20, 0xa3, 0xc6, 0x87, 0x02, 0x1b, 0x30,
    0xc8, 0x58, 0x71, 0x60, 0x04, 0x03, 0x10, 0x28,
    0x82, 0x24, 0xa8, 0x60, 0x80, 0x84, 0x95, 0x09,
    0x05, 0x38, 0x08, 0x08, 0x00, 0x3b
};
#endif

// =============================================================================
// Internal resources
// =============================================================================
CYG_HAL_TABLE_BEGIN(cyg_httpd_ires_table, httpd_ires_table);
CYG_HAL_TABLE_END(cyg_httpd_ires_table_end, httpd_ires_table);
__externC cyg_httpd_ires_table_entry cyg_httpd_ires_table[];
__externC cyg_httpd_ires_table_entry cyg_httpd_ires_table_end[];

#ifdef CYGOPT_NET_ATHTTPD_USE_DIRLIST
// These threes internal resources are used for the directory listing.
CYG_HTTPD_IRES_TABLE_ENTRY(cyg_httpd_ires_folder, \
                           "/___folder__gif.gif", \
                           folder_gif,            \
                           sizeof(folder_gif));
CYG_HTTPD_IRES_TABLE_ENTRY(cyg_httpd_ires_doc,    \
                           "/___doc__gif.gif",    \
                           doc_gif,               \
                           sizeof(doc_gif));
CYG_HTTPD_IRES_TABLE_ENTRY(cyg_httpd_ires_back,   \
                           "/___back__gif.gif",   \
                           back_gif,              \
                           sizeof(back_gif));
#endif                           

cyg_httpd_ires_table_entry *
cyg_httpd_find_ires(char *path_name)
{
    cyg_httpd_ires_table_entry *entry = cyg_httpd_ires_table;
    
    while (entry != cyg_httpd_ires_table_end)
    {
        if (!strcasecmp((char*)path_name, entry->f_pname))
            return entry;
        entry++;
    }
            
    return (cyg_httpd_ires_table_entry*)NULL;
}

void 
cyg_httpd_send_ires(cyg_httpd_ires_table_entry *entry)
{
    httpstate.status_code  = CYG_HTTPD_STATUS_OK;

    // Here we'll look for extension to the file. Consider the case where
    //  there might be more than one dot in the file name. We'll look for
    //  the last dot, then we'll check the extension.
    char *extension = rindex(entry->f_pname, '.');
    if (extension == NULL)
        // No extension in the file name.
        httpstate.mime_type = 0;
    else
        httpstate.mime_type = cyg_httpd_find_mime_string(++extension);

    httpstate.payload_len  = entry->f_size;
    cyg_int32 header_length = cyg_httpd_format_header();
    
    // As always, the header is always sent out.
    send(httpstate.sockets[httpstate.client_index].descriptor, 
         httpstate.outbuffer, 
         header_length,
         0);
    if (httpstate.mode & CYG_HTTPD_MODE_SEND_HEADER_ONLY) 
        return;
    cyg_httpd_write(entry->f_ptr, entry->f_size);
}

// =============================================================================
// C callbacks
// =============================================================================
CYG_HAL_TABLE_BEGIN(cyg_httpd_handler_table, httpd_handler_table);
CYG_HAL_TABLE_END(cyg_httpd_handler_table_end, httpd_handler_table);

__externC cyg_httpd_handler_table_entry cyg_httpd_handler_table[];
__externC cyg_httpd_handler_table_entry cyg_httpd_handler_table_end[];

handler
cyg_httpd_find_handler(void)
{
    cyg_httpd_handler_table_entry *entry = cyg_httpd_handler_table;
    while (entry != cyg_httpd_handler_table_end)
    {
        if (strcmp((const char*)httpstate.url, entry->path) == 0)
            return entry->h;
        entry++;
    }
            
    return (handler)NULL;
}

// =============================================================================
// Directory listing
// =============================================================================
#ifdef CYGOPT_NET_ATHTTPD_USE_DIRLIST
void
cyg_httpd_print_directory_entry(char *path_name, 
                                struct stat *s, 
                                struct dirent *de)
{
    char fname[CYG_HTTPD_MAXPATH];
    char time_str[32];
    time_t last_mod = s->st_mtime;

    struct tm *mod_time = gmtime(&last_mod);
    sprintf(time_str,
            "%02d-%s-%04d %02d:%02d",
            mod_time->tm_mday,
            month_of_year[mod_time->tm_mon],
            mod_time->tm_year + 1900,
            mod_time->tm_hour,
            mod_time->tm_min);

    if (S_ISREG(s->st_mode))
    {
        strcpy(fname, path_name);
        if (fname[strlen(fname)-1] != '/')
            strcat(fname, "/");
        strcat(fname, de->d_name);
        cyg_httpd_cleanup_filename(fname);
        sprintf(httpstate.outbuffer,
                "<tr><td><img src='/___doc__gif.gif'></td>"
                "<td><a href='%s'>%s</a></td>"
                "<td>&nbsp &nbsp &nbsp &nbsp &nbsp &nbsp</td>"
                "<td>%s&nbsp;&nbsp;</td>"
                "<td style='color:black'>%d</td></tr>",
                fname,
                de->d_name,
                time_str,
                (int)s->st_size);
    }
    else
    {
        strcpy(fname, "/");
        strcat(fname, path_name);
        if (fname[strlen(fname)-1] != '/')
            strcat(fname, "/");
        strcat(fname, de->d_name);
        cyg_httpd_cleanup_filename(fname);
        sprintf(httpstate.outbuffer,
                "<tr><td><img src='/___folder__gif.gif'></td>"
                "<td><a href='%s/'>%s</a></td>"
                "<td>&nbsp &nbsp &nbsp &nbsp &nbsp &nbsp</td>"
                "<td>%s&nbsp;&nbsp;</td>"
                "<td style='color:black'></td></tr>",
                fname,
                de->d_name,
                time_str);
    }
    cyg_httpd_write_chunked(httpstate.outbuffer, strlen(httpstate.outbuffer));
}

void
cyg_httpd_send_directory_listing(char *path_name)
{
    struct dirent next_file;
    struct dirent last_printed;
    struct stat s;
    char fname[CYG_HTTPD_MAXPATH];

    cyg_httpd_start_chunked("html");
    sprintf(httpstate.outbuffer,
            "<html><body><h3>Index of %s</h3><p></p>"
            "<table style='font-family:courier'>",
            path_name);
    cyg_httpd_write_chunked(httpstate.outbuffer, strlen(httpstate.outbuffer));

    sprintf(httpstate.outbuffer,
            "<tr><td></td><td align='center' style='border-style:none none"
            " solid none;border-width:thin'>Name</td>"
            "<td style='border-style:none none solid none; border-width:thin'>"
            "&nbsp &nbsp &nbsp &nbsp &nbsp &nbsp</td>"
             "<td  align='center' style='border-style:none none solid none;"
             " border-width:thin'>Last Modified</td>"
             "<td style='border-style:none none solid none; border-width:thin'>"
            "Size</td></tr>");
    cyg_httpd_write_chunked(httpstate.outbuffer, strlen(httpstate.outbuffer));

    // Provide a pointer to the parent directory.
    strcpy(fname, path_name);
    if (fname[strlen(fname)-1] == '/')
        fname[strlen(fname)-1] = '\0';
    char *slash = rindex(fname, '/');
    slash[1] = '\0';
    sprintf(httpstate.outbuffer,
            "<tr><td><img src='/___back__gif.gif'></td></td>"
            "<td><a href='%s' style='color:red'>Parent "
            "Directory</a></td>"
            "<td>&nbsp &nbsp &nbsp &nbsp &nbsp &nbsp</td>"
            "<td>&nbsp &nbsp &nbsp &nbsp &nbsp &nbsp</td>"
            "<td style='color:black'>-</td></tr>",
            fname);
    cyg_httpd_write_chunked(httpstate.outbuffer, strlen(httpstate.outbuffer));

    strcpy(fname, CYGDAT_NET_ATHTTPD_SERVEROPT_ROOTDIR);
    if (fname[strlen(fname)-1] != '/')
        strcat(fname, "/");
    strcat(fname, path_name);
    if (fname[strlen(fname)-1] != '/')
        strcat(fname, "/");
    cyg_httpd_cleanup_filename(fname);
    int abs_path_len = strlen(fname);

    DIR* pdir = opendir(fname);
    struct dirent *dirent = readdir(pdir);

    // First time for the directories.
    rewinddir(pdir);
    memset((void*)&last_printed, 0, sizeof(struct dirent));
    dirent = readdir(pdir);
    int new_entry = 1;
    while (1)
    {
        memset((void*)&next_file, 0, sizeof(struct dirent));
        new_entry = 0;
        while(dirent)
        {
            if (strcmp(dirent->d_name, "..") &&
                                     strcmp(dirent->d_name, "."))
                if ((next_file.d_name[0] == '\0') ||
                      (strcmp(next_file.d_name, dirent->d_name) > 0))
                    if ((last_printed.d_name[0] == '\0') ||
                      (strcmp(last_printed.d_name, dirent->d_name) < 0))
                    {
                        fname[abs_path_len] = '\0';
                        strcat(fname, dirent->d_name);
                        struct stat sp;
                        stat(fname, &sp);
                        if (S_ISDIR(sp.st_mode))
                        {
                            memcpy(&next_file, dirent, sizeof(struct dirent));
                            memcpy(&s, &sp, sizeof(struct stat));
                            new_entry = 1;
                        }
                    }
            dirent = readdir(pdir);
        }
        if (new_entry == 0)
            break;
        cyg_httpd_print_directory_entry(path_name, &s, &next_file);
        memcpy(&last_printed, &next_file, sizeof(struct dirent));
        rewinddir(pdir);
        dirent = readdir(pdir);
    }

    // A second time for the files.
    rewinddir(pdir);
    memset((void*)&last_printed, 0, sizeof(struct dirent));
    dirent = readdir(pdir);
    new_entry = 1;
    while (1)
    {
        memset((void*)&next_file, 0, sizeof(struct dirent));
        new_entry = 0;
        while(dirent)
        {
            if (strcmp(dirent->d_name, "..") &&
                                     strcmp(dirent->d_name, "."))
                if ((next_file.d_name[0] == '\0') ||
                      (strcmp(next_file.d_name, dirent->d_name) > 0))
                    if ((last_printed.d_name[0] == '\0') ||
                      (strcmp(last_printed.d_name, dirent->d_name) < 0))
                    {
                        fname[abs_path_len] = '\0';
                        strcat(fname, dirent->d_name);
                        struct stat sp;
                        stat(fname, &sp);
                        if (S_ISREG(sp.st_mode))
                        {
                            memcpy(&next_file, dirent, sizeof(struct dirent));
                            memcpy(&s, &sp, sizeof(struct stat));
                            new_entry = 1;
                        }
                    }
            dirent = readdir(pdir);
        }
        if (new_entry == 0)
            break;
        cyg_httpd_print_directory_entry(path_name, &s, &next_file);
        memcpy(&last_printed, &next_file, sizeof(struct dirent));
        rewinddir(pdir);
        dirent = readdir(pdir);
    }

    strcpy(httpstate.outbuffer, "</table><html><body>");
    cyg_httpd_write_chunked(httpstate.outbuffer, strlen(httpstate.outbuffer));
    cyg_httpd_end_chunked();
    closedir(pdir);
}
#endif

⌨️ 快捷键说明

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