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

« back to all changes in this revision

Viewing changes to third-party/shttpd/io_file.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
 
static int
14
 
write_file(struct stream *stream, const void *buf, size_t len)
15
 
{
16
 
        struct stat     st;
17
 
        struct stream   *rem = &stream->conn->rem;
18
 
        int             n, fd = stream->chan.fd;
19
 
 
20
 
        assert(fd != -1);
21
 
        n = write(fd, buf, len);
22
 
 
23
 
        DBG(("put_file(%p, %d): %d bytes", (void *) stream, (int) len, n));
24
 
 
25
 
        if (n <= 0 || (rem->io.total >= (big_int_t) rem->headers_len)) {
26
 
                (void) fstat(fd, &st);
27
 
                stream->io.head = stream->headers_len =
28
 
                    my_snprintf(stream->io.buf,
29
 
                    stream->io.size, "HTTP/1.1 %d OK\r\n"
30
 
                    "Content-Length: %lu\r\nConnection: close\r\n\r\n",
31
 
                    stream->conn->status, st.st_size);
32
 
                stop_stream(stream);
33
 
        }
34
 
 
35
 
        return (n);
36
 
}
37
 
 
38
 
static int
39
 
read_file(struct stream *stream, void *buf, size_t len)
40
 
{
41
 
#ifdef USE_SENDFILE
42
 
        struct  iovec   vec;
43
 
        struct  sf_hdtr hd = {&vec, 1, NULL, 0}, *hdp = &hd;
44
 
        int             sock, fd, n;
45
 
        size_t          nbytes;
46
 
        off_t           sent;
47
 
 
48
 
        sock = stream->conn->rem.chan.sock;
49
 
        fd = stream->chan.fd;
50
 
 
51
 
        /* If this is the first call for this file, send the headers */
52
 
        vec.iov_base = stream->io.buf;
53
 
        vec.iov_len = stream->headers_len;
54
 
        if (stream->io.total > 0)
55
 
                hdp = NULL;
56
 
 
57
 
        nbytes = stream->content_len - stream->io.total;
58
 
        n = sendfile(fd, sock, lseek(fd, 0, SEEK_CUR), nbytes, hdp, &sent, 0);
59
 
 
60
 
        if (n == -1 && ERRNO != EAGAIN) {
61
 
                stream->flags &= ~FLAG_DONT_CLOSE;
62
 
                return (n);
63
 
        }
64
 
 
65
 
        stream->conn->ctx->out += sent;
66
 
 
67
 
        /* If we have sent the HTTP headers in this turn, clear them off */
68
 
        if (stream->io.total == 0) {
69
 
                assert(sent >= stream->headers_len);
70
 
                sent -= stream->headers_len;
71
 
                io_clear(&stream->io);
72
 
        }
73
 
 
74
 
        (void) lseek(fd, sent, SEEK_CUR);
75
 
        stream->io.total += sent;
76
 
        stream->flags |= FLAG_DONT_CLOSE;
77
 
 
78
 
        return (0);
79
 
#endif /* USE_SENDFILE */
80
 
 
81
 
        assert(stream->chan.fd != -1);
82
 
        return (read(stream->chan.fd, buf, len));
83
 
}
84
 
 
85
 
static void
86
 
close_file(struct stream *stream)
87
 
{
88
 
        assert(stream->chan.fd != -1);
89
 
        (void) close(stream->chan.fd);
90
 
}
91
 
 
92
 
void
93
 
get_file(struct conn *c, struct stat *stp)
94
 
{
95
 
        char            date[64], lm[64], etag[64], range[64] = "";
96
 
        size_t          n, status = 200;
97
 
        unsigned long   r1, r2;
98
 
        const char      *fmt = "%a, %d %b %Y %H:%M:%S GMT", *msg = "OK";
99
 
        big_int_t       cl; /* Content-Length */
100
 
 
101
 
        if (c->mime_type.len == 0)
102
 
                get_mime_type(c->ctx, c->uri, strlen(c->uri), &c->mime_type); 
103
 
        cl = (big_int_t) stp->st_size;
104
 
 
105
 
        /* If Range: header specified, act accordingly */
106
 
        if (c->ch.range.v_vec.len > 0 &&
107
 
            (n = sscanf(c->ch.range.v_vec.ptr,"bytes=%lu-%lu",&r1, &r2)) > 0) {
108
 
                status = 206;
109
 
                (void) lseek(c->loc.chan.fd, r1, SEEK_SET);
110
 
                cl = n == 2 ? r2 - r1 + 1: cl - r1;
111
 
                (void) my_snprintf(range, sizeof(range),
112
 
                    "Content-Range: bytes %lu-%lu/%lu\r\n",
113
 
                    r1, r1 + cl - 1, (unsigned long) stp->st_size);
114
 
                msg = "Partial Content";
115
 
        }
116
 
 
117
 
        /* Prepare Etag, Date, Last-Modified headers */
118
 
        (void) strftime(date, sizeof(date), fmt, localtime(&current_time));
119
 
        (void) strftime(lm, sizeof(lm), fmt, localtime(&stp->st_mtime));
120
 
        (void) my_snprintf(etag, sizeof(etag), "%lx.%lx",
121
 
            (unsigned long) stp->st_mtime, (unsigned long) stp->st_size);
122
 
 
123
 
        /*
124
 
         * We do not do io_inc_head here, because it will increase 'total'
125
 
         * member in io. We want 'total' to be equal to the content size,
126
 
         * and exclude the headers length from it.
127
 
         */
128
 
        c->loc.io.head = c->loc.headers_len = my_snprintf(c->loc.io.buf,
129
 
            c->loc.io.size,
130
 
            "HTTP/1.1 %d %s\r\n"
131
 
            "Date: %s\r\n"
132
 
            "Last-Modified: %s\r\n"
133
 
            "Etag: \"%s\"\r\n"
134
 
            "Content-Type: %.*s\r\n"
135
 
            "Content-Length: %lu\r\n"
136
 
            "Accept-Ranges: bytes\r\n"
137
 
            "%s\r\n",
138
 
            status, msg, date, lm, etag,
139
 
            c->mime_type.len, c->mime_type.ptr, cl, range);
140
 
 
141
 
        c->status = status;
142
 
        c->loc.content_len = cl;
143
 
        c->loc.io_class = &io_file;
144
 
        c->loc.flags |= FLAG_R | FLAG_ALWAYS_READY;
145
 
 
146
 
        if (c->method == METHOD_HEAD)
147
 
                stop_stream(&c->loc);
148
 
}
149
 
 
150
 
const struct io_class   io_file =  {
151
 
        "file",
152
 
        read_file,
153
 
        write_file,
154
 
        close_file
155
 
};