~ubuntu-branches/ubuntu/jaunty/transmission/jaunty-security

« back to all changes in this revision

Viewing changes to third-party/shttpd/io_emb.c

  • Committer: Bazaar Package Importer
  • Author(s): Chris Coulson
  • Date: 2008-11-28 15:33:48 UTC
  • mfrom: (1.1.19 upstream)
  • Revision ID: james.westby@ubuntu.com-20081128153348-it70trfnxiroblmc
Tags: 1.40-0ubuntu1
* New upstream release (LP: #302672)
  - Tracker communication uses fewer resources
  - More accurate bandwidth limits
  - Reduce disk fragmentation by preallocating files (LP: #287726)
  - Stability, security and performance improvements to the RPC /
    Web UI server (closes LP: #290423)
  - Support compression when serving Web UI and RPC responses
  - Simplify the RPC whitelist
  - Fix bug that prevented handshakes with encrypted BitComet peers
  - Fix 1.3x bug that could re-download some data unnecessarily
    (LP: #295040)
  - Option to automatically update the blocklist weekly
  - Added off-hour bandwidth scheduling
  - Simplify file/priority selection in the details dialog
  - Fix a couple of crashes
  - New / updated translations
  - Don't inhibit hibernation by default (LP: #292929)
  - Use "close" animation when sending to notification area (LP: #130811)
  - Fix resize problems (LP: #269872)
  - Support "--version" option when launching from command line
    (LP: #292011)
  - Correctly parse announce URLs that have leading or trailing
    spaces (LP: #262411)
  - Display an error when "Open Torrent" fails (LP: #281463)
* Dropped 10_fix_crasher_from_upstream.dpatch: Fix is in this
  upstream release.
* debian/control: Don't just build-depend on libcurl-dev, which is
  a virtual package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
3
 
 * All rights reserved
4
 
 *
5
 
 * "THE BEER-WARE LICENSE" (Revision 42):
6
 
 * Sergey Lyubka wrote this file.  As long as you retain this notice you
7
 
 * can do whatever you want with this stuff. If we meet some day, and you think
8
 
 * this stuff is worth it, you can buy me a beer in return.
9
 
 */
10
 
 
11
 
#include "defs.h"
12
 
 
13
 
const char *
14
 
shttpd_version(void)
15
 
{
16
 
        return (VERSION);
17
 
}
18
 
 
19
 
static void
20
 
call_user(struct conn *c, struct shttpd_arg *arg, shttpd_callback_t func)
21
 
{
22
 
        arg->priv               = c;
23
 
        arg->state              = c->loc.chan.emb.state;
24
 
        arg->out.buf            = io_space(&c->loc.io);
25
 
        arg->out.len            = io_space_len(&c->loc.io);
26
 
        arg->out.num_bytes      = 0;
27
 
        arg->in.buf             = io_data(&c->rem.io);;
28
 
        arg->in.len             = io_data_len(&c->rem.io);
29
 
        arg->in.num_bytes       = 0;
30
 
 
31
 
        if (io_data_len(&c->rem.io) >= c->rem.io.size)
32
 
                arg->flags |= SHTTPD_POST_BUFFER_FULL;
33
 
 
34
 
        if (c->rem.content_len > 0 && c->rem.io.total < c->rem.content_len)
35
 
                arg->flags |= SHTTPD_MORE_POST_DATA;
36
 
 
37
 
        func(arg);
38
 
 
39
 
        io_inc_head(&c->loc.io, arg->out.num_bytes);
40
 
        io_inc_tail(&c->rem.io, arg->in.num_bytes);
41
 
        c->loc.chan.emb.state = arg->state;             /* Save state */
42
 
 
43
 
        /*
44
 
         * If callback finished output, that means it did all cleanup.
45
 
         * If the connection is terminated unexpectedly, we canna call
46
 
         * the callback via the stream close() method from disconnect.
47
 
         * However, if cleanup is already done, we set close() method to
48
 
         * NULL, to prevent the call from disconnect().
49
 
         */
50
 
 
51
 
        if (arg->flags & SHTTPD_END_OF_OUTPUT)
52
 
                c->loc.flags &= ~FLAG_DONT_CLOSE;
53
 
        else
54
 
                c->loc.flags |= FLAG_DONT_CLOSE;
55
 
 
56
 
        if (arg->flags & SHTTPD_SUSPEND)
57
 
                c->loc.flags |= FLAG_SUSPEND;
58
 
}
59
 
 
60
 
static int
61
 
do_embedded(struct stream *stream, void *buf, size_t len)
62
 
{
63
 
        struct shttpd_arg       arg;
64
 
        buf = NULL; len = 0;            /* Squash warnings */
65
 
 
66
 
        arg.user_data   = stream->conn->loc.chan.emb.data;
67
 
        arg.flags       = 0;
68
 
 
69
 
        call_user(stream->conn, &arg, (shttpd_callback_t)
70
 
                        stream->conn->loc.chan.emb.func.v_func);
71
 
 
72
 
        return (0);
73
 
}
74
 
 
75
 
static void
76
 
close_embedded(struct stream *stream)
77
 
{
78
 
        struct shttpd_arg       arg;
79
 
        struct conn             *c = stream->conn;
80
 
 
81
 
        arg.flags       = SHTTPD_CONNECTION_ERROR;
82
 
        arg.user_data   = c->loc.chan.emb.data;
83
 
 
84
 
        /*
85
 
         * Do not call the user function if SHTTPD_END_OF_OUTPUT was set,
86
 
         * i.e. the callback already terminated correctly
87
 
         */
88
 
        if (stream->flags & FLAG_DONT_CLOSE)
89
 
                call_user(stream->conn, &arg, (shttpd_callback_t)
90
 
                    c->loc.chan.emb.func.v_func);
91
 
}
92
 
 
93
 
size_t
94
 
shttpd_printf(struct shttpd_arg *arg, const char *fmt, ...)
95
 
{
96
 
        char            *buf = arg->out.buf + arg->out.num_bytes;
97
 
        int             buflen = arg->out.len - arg->out.num_bytes, len = 0;
98
 
        va_list         ap;
99
 
 
100
 
        if (buflen > 0) {
101
 
                va_start(ap, fmt);
102
 
                len = vsnprintf(buf, buflen, fmt, ap);
103
 
                va_end(ap);
104
 
 
105
 
                if (len < 0 || len > buflen)
106
 
                        len = buflen;
107
 
                arg->out.num_bytes += len;
108
 
        }
109
 
 
110
 
        return (len);
111
 
}
112
 
 
113
 
const char *
114
 
shttpd_get_header(struct shttpd_arg *arg, const char *header_name)
115
 
{
116
 
        struct conn     *c = arg->priv;
117
 
        char            *p, *s, *e;
118
 
        size_t          len;
119
 
 
120
 
        p = c->headers;
121
 
        e = c->request + c->rem.headers_len;
122
 
        len = strlen(header_name);
123
 
 
124
 
        while (p < e) {
125
 
                if ((s = strchr(p, '\n')) != NULL)
126
 
                        s[s[-1] == '\r' ? -1 : 0] = '\0';
127
 
                if (my_strncasecmp(header_name, p, len) == 0)
128
 
                        return (p + len + 2);
129
 
 
130
 
                p += strlen(p) + 1;
131
 
        }
132
 
 
133
 
        return (NULL);
134
 
}
135
 
 
136
 
const char *
137
 
shttpd_get_env(struct shttpd_arg *arg, const char *env_name)
138
 
{
139
 
        struct conn     *c = arg->priv;
140
 
        struct vec      *vec;
141
 
 
142
 
        if (strcmp(env_name, "REQUEST_METHOD") == 0) {
143
 
                return (known_http_methods[c->method].ptr);
144
 
        } else if (strcmp(env_name, "REQUEST_URI") == 0) {
145
 
                return (c->uri);
146
 
        } else if (strcmp(env_name, "QUERY_STRING") == 0) {
147
 
                return (c->query);
148
 
        } else if (strcmp(env_name, "REMOTE_USER") == 0) {
149
 
                vec = &c->ch.user.v_vec;
150
 
                if (vec->len > 0) {
151
 
                        ((char *) vec->ptr)[vec->len] = '\0';
152
 
                        return (vec->ptr);
153
 
                }
154
 
        } else if (strcmp(env_name, "REMOTE_ADDR") == 0) {
155
 
                return (inet_ntoa(c->sa.u.sin.sin_addr));/* FIXME NOT MT safe */
156
 
        }
157
 
 
158
 
        return (NULL);
159
 
}
160
 
 
161
 
void
162
 
shttpd_get_http_version(struct shttpd_arg *arg, unsigned long *major, unsigned long *minor)
163
 
{
164
 
        struct conn *c = arg->priv;
165
 
        
166
 
        *major = c->major_version;
167
 
        *minor = c->minor_version;
168
 
}
169
 
 
170
 
void
171
 
shttpd_register_uri(struct shttpd_ctx *ctx,
172
 
                const char *uri, shttpd_callback_t callback, void *data)
173
 
{
174
 
        struct registered_uri   *e;
175
 
 
176
 
        if ((e = malloc(sizeof(*e))) != NULL) {
177
 
                e->uri                  = my_strdup(uri);
178
 
                e->callback.v_func      = (void (*)(void)) callback;
179
 
                e->callback_data        = data;
180
 
                LL_TAIL(&ctx->registered_uris, &e->link);
181
 
        }
182
 
}
183
 
 
184
 
int
185
 
shttpd_get_var(const char *var, const char *buf, int buf_len,
186
 
                char *value, int value_len)
187
 
{
188
 
        const char      *p, *e, *s;
189
 
        size_t          var_len;
190
 
 
191
 
        var_len = strlen(var);
192
 
        e = buf + buf_len;              /* End of QUERY_STRING buffer   */
193
 
 
194
 
        /* buf is "var1=val1&var2=val2...". Find variable first */
195
 
        for (p = buf; p + var_len < e; p++)
196
 
                if ((p == buf || p[-1] == '&') &&
197
 
                    p[var_len] == '=' &&
198
 
                    !my_strncasecmp(var, p, var_len)) {
199
 
 
200
 
                        /* Point 'p' to var value, 's' to the end of value */
201
 
                        p += var_len + 1;       
202
 
                        if ((s = memchr(p, '&', e - p)) == NULL)
203
 
                                s = e;
204
 
 
205
 
                        /* URL-decode value. Return result length */
206
 
                        return (url_decode(p, s - p, value, value_len));
207
 
                }
208
 
 
209
 
        return (-1);
210
 
}
211
 
 
212
 
static int
213
 
match_regexp(const char *regexp, const char *text)
214
 
{
215
 
        if (*regexp == '\0')
216
 
                return (*text == '\0');
217
 
 
218
 
        if (*regexp == '*')
219
 
                do {
220
 
                        if (match_regexp(regexp + 1, text))
221
 
                                return (1);
222
 
                } while (*text++ != '\0');
223
 
 
224
 
        if (*text != '\0' && *regexp == *text)
225
 
                return (match_regexp(regexp + 1, text + 1));
226
 
 
227
 
        return (0);
228
 
}
229
 
 
230
 
struct registered_uri *
231
 
is_registered_uri(struct shttpd_ctx *ctx, const char *uri)
232
 
{
233
 
        struct llhead           *lp;
234
 
        struct registered_uri   *reg_uri;
235
 
 
236
 
        LL_FOREACH(&ctx->registered_uris, lp) {
237
 
                reg_uri = LL_ENTRY(lp, struct registered_uri, link);
238
 
                if (match_regexp(reg_uri->uri, uri))
239
 
                        return (reg_uri);
240
 
        }
241
 
 
242
 
        return (NULL);
243
 
}
244
 
 
245
 
void
246
 
setup_embedded_stream(struct conn *c, union variant func, void *data)
247
 
{
248
 
        c->loc.chan.emb.state = NULL;
249
 
        c->loc.chan.emb.func = func;
250
 
        c->loc.chan.emb.data = data;
251
 
        c->loc.io_class = &io_embedded;
252
 
        c->loc.flags |= FLAG_R | FLAG_W |FLAG_ALWAYS_READY;
253
 
}
254
 
 
255
 
void
256
 
shttpd_handle_error(struct shttpd_ctx *ctx, int code,
257
 
                shttpd_callback_t func, void *data)
258
 
{
259
 
        struct error_handler    *e;
260
 
 
261
 
        if ((e = malloc(sizeof(*e))) != NULL) {
262
 
                e->code = code;
263
 
                e->callback.v_func = (void (*)(void)) func;
264
 
                e->callback_data = data;
265
 
                LL_TAIL(&ctx->error_handlers, &e->link);
266
 
        }
267
 
}
268
 
 
269
 
void
270
 
shttpd_wakeup(const void *priv)
271
 
{
272
 
        const struct conn       *conn = priv;
273
 
        char                    buf[sizeof(int) + sizeof(void *)];
274
 
        int                     cmd = CTL_WAKEUP;
275
 
 
276
 
#if 0
277
 
        conn->flags &= ~SHTTPD_SUSPEND;
278
 
#endif
279
 
        (void) memcpy(buf, &cmd, sizeof(cmd));
280
 
        (void) memcpy(buf + sizeof(cmd), conn, sizeof(conn));
281
 
 
282
 
        (void) send(conn->worker->ctl[1], buf, sizeof(buf), 0);
283
 
}
284
 
 
285
 
const struct io_class   io_embedded =  {
286
 
        "embedded",
287
 
        do_embedded,
288
 
        (int (*)(struct stream *, const void *, size_t)) do_embedded,
289
 
        close_embedded
290
 
};