OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [net/] [athttpd/] [current/] [src/] [forms.c] - Blame information for rev 867

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
/* =================================================================
2
 *
3
 *      forms.c
4
 *
5
 *      Handles form variables of GET and POST requests.
6
 *
7
 * =================================================================
8
 * ####ECOSGPLCOPYRIGHTBEGIN####
9
 * -------------------------------------------
10
 * This file is part of eCos, the Embedded Configurable Operating System.
11
 * Copyright (C) 2005 Free Software Foundation, Inc.
12
 *
13
 * eCos is free software; you can redistribute it and/or modify it under
14
 * the terms of the GNU General Public License as published by the Free
15
 * Software Foundation; either version 2 or (at your option) any later
16
 * version.
17
 *
18
 * eCos is distributed in the hope that it will be useful, but WITHOUT
19
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21
 * for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with eCos; if not, write to the Free Software Foundation, Inc.,
25
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
26
 *
27
 * As a special exception, if other files instantiate templates or use
28
 * macros or inline functions from this file, or you compile this file
29
 * and link it with other works to produce a work based on this file,
30
 * this file does not by itself cause the resulting work to be covered by
31
 * the GNU General Public License. However the source code for this file
32
 * must still be made available in accordance with section (3) of the GNU
33
 * General Public License v2.
34
 *
35
 * This exception does not invalidate any other reasons why a work based
36
 * on this file might be covered by the GNU General Public License.
37
 * -------------------------------------------
38
 * ####ECOSGPLCOPYRIGHTEND####
39
 * =================================================================
40
 * #####DESCRIPTIONBEGIN####
41
 *
42
 *  Author(s):    Anthony Tonizzo (atonizzo@gmail.com)
43
 *  Contributors: Sergei Gavrikov (w3sg@SoftHome.net)
44
 *                Lars Povlsen    (lpovlsen@vitesse.com)
45
 *                Tad Artis       (ecos@ds3switch.com)
46
 *  Date:         2006-06-12
47
 *  Purpose:
48
 *  Description:
49
 *
50
 * ####DESCRIPTIONEND####
51
 *
52
 * =================================================================
53
 */
54
#include <pkgconf/hal.h>
55
#include <pkgconf/kernel.h>
56
#include <pkgconf/io_fileio.h>
57
#include <cyg/kernel/kapi.h>           // Kernel API.
58
#include <cyg/kernel/ktypes.h>         // base kernel types.
59
#include <cyg/infra/diag.h>            // For diagnostic printing.
60
#include <network.h>
61
#include <sys/uio.h>
62
 
63
#include <cyg/hal/hal_tables.h>
64
#include <stdlib.h>
65
 
66
#include <cyg/athttpd/http.h>
67
#include <cyg/athttpd/socket.h>
68
#include <cyg/athttpd/handler.h>
69
#include <cyg/athttpd/forms.h>
70
 
71
CYG_HAL_TABLE_BEGIN(cyg_httpd_fvars_table, httpd_fvars_table);
72
CYG_HAL_TABLE_END(cyg_httpd_fvars_table_end, httpd_fvars_table);
73
 
74
cyg_int8 blank[] = "";
75
 
76
cyg_int8
77
cyg_httpd_from_hex(cyg_int8 c)
78
{
79
    if ((c >= '0') && (c <= '9'))
80
        return (c - '0');
81
    if ((c >= 'A') && (c <= 'F'))
82
        return (c - 'A' + 10);
83
    if ((c >= 'a') && (c <= 'f'))
84
        return (c - 'a' + 10);
85
    return -1;
86
}
87
 
88
char*
89
cyg_httpd_store_form_variable(char *query, cyg_httpd_fvars_table_entry *entry)
90
{
91
    char *p = query;
92
    char *q = entry->buf;
93
    int   len = 0;
94
 
95
    while (len < (entry->buflen - 1))
96
        switch(*p)
97
        {
98
        case '%':
99
            p++;
100
            if (*p)
101
                *q = cyg_httpd_from_hex(*p++) * 16;
102
            if (*p)
103
                *q = (*q + cyg_httpd_from_hex(*p++));
104
            q++;
105
            len++;
106
            break;
107
        case '+':
108
            *q++ = ' ';
109
            p++;
110
            len++;
111
            break;
112
        case '&':
113
        case ' ':
114
        case '\0':        // Don't parse past the end of the packet.
115
            *q++ = '\0';
116
            return p;
117
        default:
118
            *q++ = *p++;
119
            len++;
120
        }
121
        while ((*p != ' ') && (*p != '&') && *p)
122
            p++;
123
        return p;
124
}
125
 
126
// We'll try to parse the data from the form, and store it in the variables
127
//  that have been defined by the user in the 'form_variable_table'.
128
char*
129
cyg_httpd_store_form_data(char *p)
130
{
131
    char      *p2;
132
    cyg_int32 var_length;
133
    cyg_httpd_fvars_table_entry *entry = cyg_httpd_fvars_table;
134
 
135
    // We'll clear all the variables first, to avoid stale data.
136
    while (entry != cyg_httpd_fvars_table_end)
137
    {
138
        entry->buf[0] = '\0';
139
        entry++;
140
    }
141
 
142
    if (!p)    // No form data? just return after clearing variables.
143
        return NULL;
144
 
145
    while (*p && *p != ' ')
146
    {
147
        if (!(p2 = strchr(p, '=')))
148
            return NULL;        // Malformed post?
149
        var_length = (cyg_int32)p2 - (cyg_int32)p;
150
        entry = cyg_httpd_fvars_table;
151
        while (entry != cyg_httpd_fvars_table_end)
152
        {
153
            // Compare both lenght and name.
154
            // If we do not compare the lenght of the variables as well we
155
            //  risk the the case where, for instance, the variable name 'foo'
156
            //  hits a match with a variable name 'foobar' because the first
157
            //  3 letters of the latter are the same as the former.
158
            if ((strlen(entry->name) == var_length) &&
159
                (strncmp((const char*)p, entry->name, var_length ) == 0))
160
               break;
161
            entry++;
162
        }
163
 
164
        if (entry == cyg_httpd_fvars_table_end)
165
        {
166
            // No such variable. Run through the data.
167
            while ((*p != '&') && (*p && *p != ' '))
168
                p++;
169
            if(*p == '&')
170
                p++;
171
            continue;
172
        }
173
 
174
        // Found the variable, store the name.
175
        p = cyg_httpd_store_form_variable(++p2, entry);
176
#if CYGOPT_NET_ATHTTPD_DEBUG_LEVEL > 1
177
        diag_printf("Stored form variable: %s Value: %s\n",
178
                    entry->name,
179
                    entry->buf);
180
#endif    
181
        if (*p == '&')
182
            p++;
183
    }
184
    return p;
185
}
186
 
187
char*
188
cyg_httpd_find_form_variable(char *p)
189
{
190
    cyg_httpd_fvars_table_entry *entry = cyg_httpd_fvars_table;
191
 
192
    while (entry != cyg_httpd_fvars_table_end)
193
    {
194
        if (!strcmp((const char*)p, entry->name))
195
            return entry->buf;
196
        entry++;
197
    }
198
 
199
    return (char*)0;
200
}
201
 
202
static inline void release_post_buffer(void)
203
{
204
    free(httpstate.post_data);
205
    httpstate.post_data = NULL;
206
    return;
207
}
208
 
209
void
210
cyg_httpd_handle_method_POST(void)
211
{
212
    CYG_ASSERT(httpstate.post_data == NULL, "Leftover content data");
213
    CYG_ASSERT(httpstate.request_end != NULL, "Cannot see POST data");
214
    if (httpstate.content_len == 0 ||
215
        httpstate.content_len > CYGNUM_ATHTTPD_SERVER_MAX_POST) {
216
        cyg_httpd_send_error(CYG_HTTPD_STATUS_BAD_REQUEST);
217
        return;
218
    }
219
 
220
    // The content data is only valid during a POST.
221
    httpstate.post_data = (char*)malloc(httpstate.content_len + 1);
222
    CYG_ASSERT(httpstate.post_data != NULL, "Cannot malloc POST buffer");
223
    if (httpstate.post_data == NULL)
224
    {
225
        cyg_httpd_send_error(CYG_HTTPD_STATUS_SYSTEM_ERROR);
226
        return;
227
    }
228
 
229
    // Grab partial/all content from data read with headers.
230
    int header_len = (int)httpstate.request_end - (int)httpstate.inbuffer;
231
    unsigned int post_data_available = httpstate.inbuffer_len - header_len;
232
    if (httpstate.content_len < post_data_available)
233
        post_data_available = httpstate.content_len;
234
 
235
    // Some POST data might have come along with the header frame, and the
236
    //  rest is coming in on following frames. Copy the data that already
237
    //  arrived into the post buffer.
238
    memcpy(httpstate.post_data, httpstate.request_end, post_data_available);
239
    httpstate.request_end += post_data_available;
240
    unsigned int total_data_read = post_data_available;
241
 
242
    // Do we need additional data?
243
    if (total_data_read < httpstate.content_len)
244
    {
245
        while (total_data_read < httpstate.content_len)
246
        {
247
            // Read only the data that belongs to the POST request.
248
            post_data_available = read(
249
                          httpstate.sockets[httpstate.client_index].descriptor,
250
                          httpstate.post_data + total_data_read,
251
                          httpstate.content_len - total_data_read);
252
            if (post_data_available < 0)
253
            {
254
                release_post_buffer();
255
                return;
256
            }
257
            total_data_read += post_data_available;
258
        }
259
    }
260
 
261
    // httpstate.content remains available in handler.
262
    httpstate.post_data[total_data_read] = '\0';
263
 
264
    // The assumption here is that the data that arrived in the POST body is of
265
    //  'multipart/form-data' MIME type. We need to change this if we are to
266
    //  support things such as HTTP file transfer.
267
    if (httpstate.mode & CYG_HTTPD_MODE_FORM_DATA)
268
        cyg_httpd_store_form_data(httpstate.post_data);
269
 
270
#if defined(CYGOPT_NET_ATHTTPD_USE_CGIBIN_OBJLOADER) || \
271
                           defined(CYGOPT_NET_ATHTTPD_USE_CGIBIN_TCL)
272
    // See if we are trying to execute a CGI via one of the supported methods.
273
    // If we the GET request is trying to access a file in the 
274
    //  CYGDAT_NET_ATHTTPD_SERVEROPT_CGIDIR directory then it is assumed that
275
    //  we are trying to execute a CGI script. The extension of the file will
276
    //  determine the appropriate interpreter to use.
277
    if (httpstate.url[0] == '/' &&
278
                    !strncmp(httpstate.url + 1,
279
                              CYGDAT_NET_ATHTTPD_SERVEROPT_CGIDIR,
280
                              strlen(CYGDAT_NET_ATHTTPD_SERVEROPT_CGIDIR)))
281
    {
282
        // Here we'll look for extension to the file. We'll call the cgi
283
        //  handler only if the extension is '.o'.
284
        cyg_httpd_exec_cgi();
285
        release_post_buffer();
286
        return;
287
    }
288
#endif    
289
 
290
    handler h = cyg_httpd_find_handler();
291
    if (h != 0)
292
    {
293
        // A handler was found. We'll call the function associated to it.
294
        h(&httpstate);
295
        release_post_buffer();
296
        return;
297
    }
298
 
299
 
300
    // No handler of any kind for a post request. Must send 404.
301
    cyg_httpd_send_error(CYG_HTTPD_STATUS_NOT_FOUND);
302
    release_post_buffer();
303
    return;
304
}
305
 
306
 

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.