⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 server.c

📁 xmlrpc,用 XML表示得远程过程调用,基于web上得远程计算
💻 C
📖 第 1 页 / 共 2 页
字号:
/*******************************************************************************
**
** server.c
**
** This file is part of the ABYSS Web server project.
**
** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
** 1. Redistributions of source code must retain the above copyright
**    notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
**    notice, this list of conditions and the following disclaimer in the
**    documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
**    derived from this software without specific prior written permission.
** 
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
** SUCH DAMAGE.
**
*******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef ABYSS_WIN32
#include <io.h>
#else
/* Check this
#include <sys/io.h>
*/
#endif	/* ABYSS_WIN32 */
#include <fcntl.h>
#include "abyss.h"

#define BOUNDARY	"##123456789###BOUNDARY"

typedef int (*TQSortProc)(const void *, const void *);

int cmpfilenames(const TFileInfo **f1,const TFileInfo **f2)
{
	if (((*f1)->attrib & A_SUBDIR) && !((*f2)->attrib & A_SUBDIR))
		return (-1);
	if (!((*f1)->attrib & A_SUBDIR) && ((*f2)->attrib & A_SUBDIR))
		return 1;

	return strcmp((*f1)->name,(*f2)->name);
}

int cmpfiledates(const TFileInfo **f1,const TFileInfo **f2)
{
	if (((*f1)->attrib & A_SUBDIR) && !((*f2)->attrib & A_SUBDIR))
		return (-1);
	if (!((*f1)->attrib & A_SUBDIR) && ((*f2)->attrib & A_SUBDIR))
		return 1;

	return ((*f1)->time_write-(*f2)->time_write);
}

abyss_bool ServerDirectoryHandler(TSession *r,char *z,TDate *dirdate)
{
	TFileInfo fileinfo,*fi;
	TFileFind findhandle;
	char *p,z1[26],z2[20],z3[9],u,*z4;
	TList list;
	int16 i;
	uint32 k;
	abyss_bool text=FALSE;
	abyss_bool ascending=TRUE;
	uint16 sort=1;	/* 1=by name, 2=by date */
	struct tm ftm;
	TPool pool;
	TDate date;

	if (r->query)
		if (strcmp(r->query,"plain")==0)
			text=TRUE;
		else if (strcmp(r->query,"name-up")==0)
		{
			sort=1;
			ascending=TRUE;
		}
		else if (strcmp(r->query,"name-down")==0)
		{
			sort=1;
			ascending=FALSE;
		}
		else if (strcmp(r->query,"date-up")==0)
		{
			sort=2;
			ascending=TRUE;
		}
		else if (strcmp(r->query,"date-down")==0)
		{
			sort=2;
			ascending=FALSE;
		}
		else 
		{
			ResponseStatus(r,400);
			return TRUE;
		};

	if (DateCompare(&r->date,dirdate)<0)
		dirdate=&r->date;

	if (p=RequestHeaderValue(r,"If-Modified-Since"))
		if (DateDecode(p,&date))
			if (DateCompare(dirdate,&date)<=0)
			{
				ResponseStatus(r,304);
				ResponseWrite(r);
				return TRUE;
			};

	if (!FileFindFirst(&findhandle,z,&fileinfo))
	{
		ResponseStatusErrno(r);
		return TRUE;
	};

	ListInit(&list);

	if (!PoolCreate(&pool,1024))
	{
		ResponseStatus(r,500);
		return TRUE;
	};

	do
	{
		/* Files which names start with a dot are ignored */
		/* This includes implicitly the ./ and ../ */
		if (*fileinfo.name=='.')
			if (strcmp(fileinfo.name,"..")==0)
			{
				if (strcmp(r->uri,"/")==0)
					continue;
			}
			else
				continue;

		if (fi=(TFileInfo *)PoolAlloc(&pool,sizeof(fileinfo)))
		{
			memcpy(fi,&fileinfo,sizeof(fileinfo));
			if (ListAdd(&list,fi))
				continue;
		};

		ResponseStatus(r,500);
		FileFindClose(&findhandle);
		ListFree(&list);
		PoolFree(&pool);
		return TRUE;

	} while (FileFindNext(&findhandle,&fileinfo));

	FileFindClose(&findhandle);

	/* Send something to the user to show that we are still alive */
	ResponseStatus(r,200);
	ResponseContentType(r,(text?"text/plain":"text/html"));

	if (DateToString(dirdate,z))
		ResponseAddField(r,"Last-Modified",z);
	
	ResponseChunked(r);
	ResponseWrite(r);

	if (r->method!=m_head)
	{
		if (text)
		{
			sprintf(z,"Index of %s" CRLF,r->uri);
			i=strlen(z)-2;
			p=z+i+2;

			while (i>0)
			{
				*(p++)='-';
				i--;
			};

			*p='\0';
			strcat(z,CRLF CRLF
				"Name                      Size      Date-Time             Type" CRLF
				"--------------------------------------------------------------------------------"CRLF);
		}
		else
		{
			sprintf(z,"<HTML><HEAD><TITLE>Index of %s</TITLE></HEAD><BODY>"
					"<H1>Index of %s</H1><PRE>",r->uri,r->uri);
			strcat(z,"Name                      Size      Date-Time             Type<HR WIDTH=100%>"CRLF);
 		};

		HTTPWrite(r,z,strlen(z));

		/* Sort the files */
			qsort(list.item,list.size,sizeof(void *),(TQSortProc)(sort==1?cmpfilenames:cmpfiledates));
		
		/* Write the listing */
		if (ascending)
			i=0;
		else
			i=list.size-1;

		while ((i<list.size) && (i>=0))
		{
			fi=list.item[i];

			if (ascending)
				i++;
			else
				i--;
			
			strcpy(z,fi->name);

			k=strlen(z);

			if (fi->attrib & A_SUBDIR)
			{
				z[k++]='/';
				z[k]='\0';
			};

			if (k>24)
			{
				z[10]='\0';
				strcpy(z1,z);
				strcat(z1,"...");
				strcat(z1,z+k-11);
				k=24;
				p=z1+24;
			}
			else
			{
				strcpy(z1,z);
				
				k++;
				p=z1+k;
				while (k<25)
					z1[k++]=' ';

				z1[25]='\0';
			};

			ftm=*(gmtime(&fi->time_write));
			sprintf(z2,"%02u/%02u/%04u %02u:%02u:%02u",ftm.tm_mday,ftm.tm_mon,
				ftm.tm_year+1900,ftm.tm_hour,ftm.tm_min,ftm.tm_sec);

			if (fi->attrib & A_SUBDIR)
			{
				strcpy(z3,"   --  ");
				z4="Directory";
			}
			else
			{
				if (fi->size<9999)
					u='b';
				else 
				{
					fi->size/=1024;
					if (fi->size<9999)
						u='K';
					else
					{
						fi->size/=1024;
						if (fi->size<9999)
							u='M';
						else
							u='G';
					};
				};

				sprintf(z3,"%5lu %c",fi->size,u);

				if (strcmp(fi->name,"..")==0)
					z4="";
				else
					z4=MIMETypeFromFileName(fi->name);

				if (!z4)
					z4="Unknown";
			};

			if (text)
				sprintf(z,"%s%s %s    %s   %s"CRLF,
					z1,p,z3,z2,z4);
			else
				sprintf(z,"<A HREF=\"%s%s\">%s</A>%s %s    %s   %s"CRLF,
					fi->name,(fi->attrib & A_SUBDIR?"/":""),z1,p,z3,z2,z4);

			HTTPWrite(r,z,strlen(z));
		};
		
		/* Write the tail of the file */
		if (text)
			strcpy(z,SERVER_PLAIN_INFO);
		else
			strcpy(z,"</PRE>" SERVER_HTML_INFO "</BODY></HTML>" CRLF CRLF);

		HTTPWrite(r,z,strlen(z));
	};
	
	HTTPWriteEnd(r);
	/* Free memory and exit */
	ListFree(&list);
	PoolFree(&pool);

	return TRUE;
}

abyss_bool ServerFileHandler(TSession *r,char *z,TDate *filedate)
{
	char *mediatype;
	TFile file;
	uint64 filesize,start,end;
	uint16 i;
	TDate date;
	char *p;

	mediatype=MIMETypeGuessFromFile(z);

	if (!FileOpen(&file,z,O_BINARY | O_RDONLY))
	{
		ResponseStatusErrno(r);
		return TRUE;
	};

	if (DateCompare(&r->date,filedate)<0)
		filedate=&r->date;

	if (p=RequestHeaderValue(r,"if-modified-since"))
		if (DateDecode(p,&date))
			if (DateCompare(filedate,&date)<=0)
			{
				ResponseStatus(r,304);
				ResponseWrite(r);
				return TRUE;
			}
			else
				r->ranges.size=0;

	filesize=FileSize(&file);

	switch (r->ranges.size)
	{
	case 0:
		ResponseStatus(r,200);
		break;

	case 1:
		if (!RangeDecode((char *)(r->ranges.item[0]),filesize,&start,&end))
		{
			ListFree(&(r->ranges));
			ResponseStatus(r,200);
			break;
		}
		
		sprintf(z,"bytes %ld-%ld/%ld",start,end,filesize);

		ResponseAddField(r,"Content-range",z);
		ResponseContentLength(r,end-start+1);
		ResponseStatus(r,206);
		break;

	default:
		ResponseContentType(r,"multipart/ranges; boundary=" BOUNDARY);
		ResponseStatus(r,206);
		break;
	};
	
	if (r->ranges.size==0)
	{
		ResponseContentLength(r,filesize);
		ResponseContentType(r,mediatype);
	};
	
	if (DateToString(filedate,z))
		ResponseAddField(r,"Last-Modified",z);

	ResponseWrite(r);

	if (r->method!=m_head)
	{
		if (r->ranges.size==0)
			ConnWriteFromFile(r->conn,&file,0,filesize-1,z,4096,0);
		else if (r->ranges.size==1)
			ConnWriteFromFile(r->conn,&file,start,end,z,4096,0);
		else
			for (i=0;i<=r->ranges.size;i++)
			{
				ConnWrite(r->conn,"--",2);
				ConnWrite(r->conn,BOUNDARY,strlen(BOUNDARY));
				ConnWrite(r->conn,CRLF,2);

				if (i<r->ranges.size)
					if (RangeDecode((char *)(r->ranges.item[i]),filesize,&start,&end))
					{
						/* Entity header, not response header */
						sprintf(z,"Content-type: %s" CRLF
									"Content-range: bytes %ld-%ld/%ld" CRLF
									"Content-length: %lu" CRLF
									CRLF,mediatype,start,end,filesize,end-start+1);

						ConnWrite(r->conn,z,strlen(z));

						ConnWriteFromFile(r->conn,&file,start,end,z,4096,0);
					};
			};
	};

	FileClose(&file);

	return TRUE;
}

abyss_bool ServerDefaultHandlerFunc(TSession *r)
{
	char *p,z[4096];
	TFileStat fs;
	uint16 i;
	abyss_bool endingslash=FALSE;
	TDate objdate;

	if (!RequestValidURIPath(r))
	{
		ResponseStatus(r,400);
		return TRUE;
	};

	/* Must check for * (asterisk uri) in the future */
	if (r->method==m_options)
	{
		ResponseAddField(r,"Allow","GET, HEAD");
		ResponseContentLength(r,0);
		ResponseStatus(r,200);
		return TRUE;
	};

	if ((r->method!=m_get) && (r->method!=m_head))
	{
		ResponseAddField(r,"Allow","GET, HEAD");
		ResponseStatus(r,405);
		return TRUE;
	};

⌨️ 快捷键说明

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