On Wed, Dec 12, 2001 at 02:53:19PM +0300, Alex Tutubalin wrote:
> > > но есть ranges) или mathopd (есть keep-alive, но в публичной доступности
> > > нет ranges).
> >
> > У меня есть. Кому нужно -- пишите. Или же могу прислать прямо сюда.
>
> Давай прямо сюда - оно ляжет в архив и можно будет потом давать ссылку.
На всякий случай: условия использования -- такие же, как сам mathopd
(кажется, BSD-style).
>
>
> Алексей Тутубалин
> mailto: lexa@xxxxxxx
__
AT
diff -ur src-1.4b13/Makefile src/Makefile
--- src-1.4b13/Makefile Mon Aug 6 22:40:10 2001
+++ src/Makefile Tue Oct 9 17:47:31 2001
@@ -1,14 +1,14 @@
BIN = mathopd
CC = gcc
CFLAGS = -O -Wall
-CPPFLAGS =
+CPPFLAGS = -DPARTIAL_CONTENT
LDFLAGS =
LIBS = -lcrypt
PREFIX = /usr/local
SBINDIR = $(PREFIX)/sbin
# On Solaris, uncomment the following
-# CPPFLAGS = -DNEED_INET_ATON -DHAVE_CRYPT_H
+# CPPFLAGS = -DNEED_INET_ATON -DHAVE_CRYPT_H -DPARTIAL_CONTENT
# LIBS = -lsocket -lnsl
OBJS = base64.o cgi.o config.o core.o dump.o imap.o log.o main.o \
diff -ur src-1.4b13/core.c src/core.c
--- src-1.4b13/core.c Mon Aug 6 22:40:10 2001
+++ src/core.c Tue Oct 9 17:47:31 2001
@@ -405,6 +405,11 @@
cn->action = HC_CLOSING;
return;
}
+#ifdef PARTIAL_CONTENT
+ if (cn->r->status == 206)
+ cn->left = cn->r->range_length;
+ else
+#endif
cn->left = cn->r->content_length;
if (fill_connection(cn) == -1) {
cn->action = HC_CLOSING;
diff -ur src-1.4b13/dump.c src/dump.c
--- src-1.4b13/dump.c Mon Aug 6 22:40:10 2001
+++ src/dump.c Tue Oct 9 17:47:31 2001
@@ -44,6 +44,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
+#include <string.h>
#include <fcntl.h>
#include "mathopd.h"
diff -ur src-1.4b13/main.c src/main.c
--- src-1.4b13/main.c Mon Aug 6 22:40:10 2001
+++ src/main.c Tue Oct 9 17:47:31 2001
@@ -47,6 +47,7 @@
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
+#include <stdlib.h>
#include <pwd.h>
#include <grp.h>
#include <string.h>
diff -ur src-1.4b13/mathopd.h src/mathopd.h
--- src-1.4b13/mathopd.h Mon Aug 6 22:40:10 2001
+++ src/mathopd.h Tue Oct 9 17:47:31 2001
@@ -231,6 +231,13 @@
char newloc[PATHLEN];
const char *allowedmethods;
size_t location_length;
+#ifdef PARTIAL_CONTENT
+ char *in_range;
+ char *if_range_s;
+ time_t if_range;
+ long range_offset;
+ long range_length;
+#endif
};
struct connection {
diff -ur src-1.4b13/request.c src/request.c
--- src-1.4b13/request.c Mon Aug 6 22:40:10 2001
+++ src/request.c Tue Oct 9 17:47:31 2001
@@ -278,8 +278,20 @@
if (r->num_content >= 0) {
b += sprintf(b, "Content-type: %s\r\n", r->content_type);
cl = r->content_length;
+#ifdef PARTIAL_CONTENT
+ if (cl >= 0) {
+ if (r->status == 206)
+ b += sprintf(b, "Content-Range: bytes %ld-%ld/%ld\r\n"
+ "Content-Length: %ld\r\n",
+ r->range_offset, r->range_offset + r->range_length - 1, cl,
+ r->range_length);
+ else
+ b += sprintf(b, "Content-Length: %ld\r\n", cl);
+ }
+#else
if (cl >= 0)
b += sprintf(b, "Content-length: %ld\r\n", cl);
+#endif
if (r->last_modified)
b += sprintf(b, "Last-Modified: %s\r\n", rfctime(r->last_modified, gbuf));
}
@@ -524,6 +536,10 @@
static int process_fd(struct request *r)
{
int fd;
+#ifdef PARTIAL_CONTENT
+ int status_2xx;
+ char *range;
+#endif
if (r->path_args[0] && r->c->path_args_ok == 0 && (r->path_args[1] || r->isindex == 0)) {
r->error_file = r->c->error_404_file;
@@ -558,12 +574,78 @@
r->num_content = -1;
return 304;
}
+#ifdef PARTIAL_CONTENT
+ status_2xx = 200;
+ range = r->in_range;
+#define SKIP_SPACE(str) while(isspace(*(str))) (str)++
+ if (range && (!r->if_range_s || r->last_modified <= r->if_range) &&
+ !strncasecmp(range, "bytes=", 6))
+ {
+ long rv, cl;
+
+ range += 6;
+ SKIP_SPACE(range);
+ cl = r->content_length;
+ r->range_offset = r->range_length = -1L;
+
+ if (isdigit(*range)) {
+ rv = strtol(range, &range, 10);
+ SKIP_SPACE(range);
+ if (*range++ == '-') {
+ r->range_offset = rv;
+ SKIP_SPACE(range);
+ if (*range == '\0')
+ r->range_length = cl - r->range_offset;
+ else if (isdigit(*range)) {
+ rv = strtol(range, &range, 10);
+ SKIP_SPACE(range);
+ if (*range == '\0' && rv >= r->range_offset)
+ r->range_length = rv - r->range_offset + 1;
+ }
+ }
+ } else if (*range++ == '-') {
+ SKIP_SPACE(range);
+ if (isdigit(*range)) {
+ rv = strtol(range, &range, 10);
+ SKIP_SPACE(range);
+ if (*range == '\0') {
+ if (rv > cl) {
+ r->range_length = cl;
+ r->range_offset = 0;
+ } else {
+ r->range_length = rv;
+ r->range_offset = cl - rv;
+ }
+ }
+ }
+ }
+
+ if (r->range_offset >= 0 && r->range_length > 0) {
+ if (cl > r->range_offset) {
+ status_2xx = 206;
+ if (r->range_offset && lseek(fd, r->range_offset, SEEK_SET) != r->range_offset) {
+ lerror("lseek");
+ close(fd);
+ return 500;
+ }
+ } else {
+ log_d("range %s not satisfiable for %s", r->in_range, r->path_translated);
+ close(fd);
+ return 416;
+ }
+ }
+ }
+#endif
if (r->method == M_GET) {
fcntl(fd, F_SETFD, FD_CLOEXEC);
r->cn->rfd = fd;
} else
close(fd);
+#ifdef PARTIAL_CONTENT
+ return status_2xx;
+#else
return 200;
+#endif
}
static int add_fd(struct request *r, const char *filename)
@@ -830,6 +912,12 @@
r->in_content_type = s;
else if (!strcasecmp(l, "Content-length"))
r->in_content_length = s;
+#ifdef PARTIAL_CONTENT
+ else if (!strcasecmp(l, "Range") || !strcasecmp(l, "Request-Range"))
+ r->in_range = s;
+ else if (!strcasecmp(l, "If-Range") || !strcasecmp(l, "Range-If"))
+ r->if_range_s = s;
+#endif
}
s = r->method_s;
if (s == 0) {
@@ -897,7 +985,11 @@
else
r->cn->keepalive = s && strcasecmp(s, "Keep-Alive") == 0;
}
+#ifdef PARTIAL_CONTENT
+ if (r->method == M_GET || r->method == M_HEAD) {
+#else
if (r->method == M_GET) {
+#endif
s = r->ims_s;
if (s) {
i = timerfc(s);
@@ -907,6 +999,17 @@
}
r->ims = i;
}
+#ifdef PARTIAL_CONTENT
+ s = r->if_range_s;
+ if (s) {
+ i = timerfc(s);
+ if (i == -1) {
+ log_d("illegal date \"%s\" in If-Range", s);
+ return 400;
+ }
+ r->if_range = i;
+ }
+#endif
}
return 0;
}
@@ -929,6 +1032,12 @@
r->status_line = "204 No Content";
send_message = 0;
break;
+#ifdef PARTIAL_CONTENT
+ case 206:
+ r->status_line = "206 Partial Content";
+ send_message = 0;
+ break;
+#endif
case 302:
r->status_line = "302 Moved";
break;
@@ -952,6 +1061,11 @@
r->status_line = "405 Method Not Allowed";
r->allowedmethods = "GET, HEAD";
break;
+#ifdef PARTIAL_CONTENT
+ case 416:
+ r->status_line = "416 Requested Range Not Satisfiable";
+ break;
+#endif
case 501:
r->status_line = "501 Not Implemented";
break;
@@ -992,6 +1106,11 @@
case 404:
b += sprintf(b, "The resource requested could not be found on this server.\n");
break;
+#ifdef PARTIAL_CONTENT
+ case 416:
+ b += sprintf(b, "None of the range-specifier values in the Range request-header field overlap the current extent of the selected resource.\n");
+ break;
+#endif
case 503:
b += sprintf(b, "The server is temporarily busy.\n");
break;
@@ -1049,6 +1168,11 @@
r->servername = 0;
r->allowedmethods = 0;
r->location_length = 0;
+#ifdef PARTIAL_CONTENT
+ r->in_range = 0;
+ r->if_range_s = 0;
+ r->if_range = 0;
+#endif
}
int process_request(struct request *r)
"Russian Apache" includes software developed
by the Apache Group for use in the Apache HTTP server project
(http://www.apache.org/) See
Apache LICENSE.
Copyright (C) 1995-2001 The Apache Group. All rights reserved.
Copyright (C) 1996 Dm. Kryukov; Copyright (C)
1997-2009 Alex Tutubalin. Design (C) 1998 Max Smolev.