Upstream tarball
This commit is contained in:
commit
21863d7241
134 changed files with 40816 additions and 0 deletions
11
common/Imakefile
Normal file
11
common/Imakefile
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include <../Common.tmpl>
|
||||
|
||||
SRCS = mime.c list.c ml.c mempool.c dmem.c util.c dir.c url.c uproc.c
|
||||
OBJS = mime.o list.o ml.o mempool.o dmem.o util.o dir.o url.o uproc.o
|
||||
|
||||
EXTRA_DEFINES = $(CHIMERA_DEFINES)
|
||||
EXTRA_INCLUDES = -I./ -I../port
|
||||
|
||||
NormalLibraryTarget(xcommon, $(OBJS))
|
||||
|
||||
DependTarget()
|
84
common/common.h
Normal file
84
common/common.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* common.h
|
||||
*
|
||||
* Copyright (c) 1996-1997, John Kilburg <john@cs.unlv.edu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __COMMON_H__
|
||||
#define __COMMON_H__ 1
|
||||
|
||||
/* mempool.c */
|
||||
typedef struct MemPoolP *MemPool;
|
||||
|
||||
#define MPCreate() MPCreateTrack(__LINE__, __FILE__)
|
||||
MemPool MPCreateTrack _ArgProto((int, char *));
|
||||
void *MPGet _ArgProto((MemPool, size_t));
|
||||
void *MPCGet _ArgProto((MemPool, size_t));
|
||||
char *MPStrDup _ArgProto((MemPool, const char *));
|
||||
void MPDestroy _ArgProto((MemPool));
|
||||
void MPPrintStatus _ArgProto((void));
|
||||
|
||||
/* dmem.c */
|
||||
void free_mem _ArgProto((void *));
|
||||
void *alloc_mem _ArgProto((size_t));
|
||||
void *calloc_mem _ArgProto((size_t, size_t));
|
||||
void *realloc_mem _ArgProto((void *, size_t));
|
||||
char *alloc_string _ArgProto((char *));
|
||||
|
||||
/* util.c */
|
||||
char *FixPath _ArgProto((MemPool, char *));
|
||||
char *mystrtok _ArgProto((char *, size_t, char **));
|
||||
char *GetBaseFilename _ArgProto((char *));
|
||||
char *mytmpnam _ArgProto((MemPool));
|
||||
#ifdef NDEBUG
|
||||
#define myassert(a, b)
|
||||
#else
|
||||
#define myassert(a, b) xmyassert(a, b, __FILE__, __LINE__)
|
||||
void xmyassert _ArgProto((bool, char *, char *, int));
|
||||
#endif
|
||||
|
||||
/* dir.c */
|
||||
char *compress_path _ArgProto((MemPool, char *, char *));
|
||||
char *whack_filename _ArgProto((MemPool, char *));
|
||||
|
||||
/* list.c */
|
||||
typedef struct GListP *GList;
|
||||
|
||||
#define GListCreate() GListCreateTrack(__LINE__, __FILE__)
|
||||
GList GListCreateTrack _ArgProto((int, char *));
|
||||
GList GListCreateX _ArgProto((MemPool));
|
||||
void GListAddHead _ArgProto((GList, void *));
|
||||
#define GListPush(a, b) GListAddHead(a, b)
|
||||
void GListAddTail _ArgProto((GList, void *));
|
||||
void GListDestroy _ArgProto((GList));
|
||||
void *GListGetHead _ArgProto((GList));
|
||||
void *GListGetTail _ArgProto((GList));
|
||||
void *GListGetNext _ArgProto((GList));
|
||||
void *GListGetPrev _ArgProto((GList));
|
||||
void GListRemoveItem _ArgProto((GList, void *));
|
||||
bool GListEmpty _ArgProto((GList));
|
||||
void *GListPop _ArgProto((GList));
|
||||
void *GListGetCurrent _ArgProto((GList));
|
||||
void GListPrintStatus _ArgProto((void));
|
||||
void GListClear _ArgProto((GList));
|
||||
void *GListCurrent _ArgProto((GList));
|
||||
|
||||
/* uproc.c */
|
||||
void StartReaper _ArgProto((void));
|
||||
int PipeCommand _ArgProto((char *, int *));
|
||||
|
||||
#endif /* __COMMON_H__ */
|
135
common/dir.c
Normal file
135
common/dir.c
Normal file
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* dir.c
|
||||
*
|
||||
* Copyright (c) 1996-1997, John Kilburg <john@cs.unlv.edu>
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
* whack_filename
|
||||
*/
|
||||
char *
|
||||
whack_filename(mp, p)
|
||||
MemPool mp;
|
||||
char *p;
|
||||
{
|
||||
char *n = MPStrDup(mp, p);
|
||||
size_t last;
|
||||
|
||||
last = strlen(n) - 1;
|
||||
if (*(n + last) != '/')
|
||||
{
|
||||
for (p = n + last; p >= n; p--)
|
||||
{
|
||||
if (*p == '/')
|
||||
{
|
||||
*(p + 1) = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(n);
|
||||
}
|
||||
|
||||
/*
|
||||
* compress_path
|
||||
*
|
||||
* This assumes sizeof(char) == 1 which is probably a really bad idea.
|
||||
*/
|
||||
char *
|
||||
compress_path(mp, c, cwd)
|
||||
MemPool mp;
|
||||
char *c;
|
||||
char *cwd;
|
||||
{
|
||||
char *r;
|
||||
char *p, *p1, *p2, *p3;
|
||||
char *ps;
|
||||
|
||||
if (*c != '/')
|
||||
{
|
||||
if (*cwd != '/') return(NULL);
|
||||
r = (char *)MPGet(mp, strlen("/") + strlen(c) + strlen(cwd) + 1);
|
||||
strcpy(r, cwd);
|
||||
strcat(r, "/");
|
||||
strcat(r, c);
|
||||
}
|
||||
else r = MPStrDup(mp, c);
|
||||
|
||||
for (p = r; *p != '\0'; )
|
||||
{
|
||||
if (*p == '/')
|
||||
{
|
||||
p1 = p + 1;
|
||||
if (*p1 == '/')
|
||||
{
|
||||
memmove(p, p1, strlen(p1) + 1);
|
||||
continue;
|
||||
}
|
||||
else if (*p1 == '.')
|
||||
{
|
||||
p2 = p1 + 1;
|
||||
if (*p2 == '/')
|
||||
{
|
||||
memmove(p, p2, strlen(p2) + 1);
|
||||
continue;
|
||||
}
|
||||
else if (*p2 == '\0')
|
||||
{
|
||||
*p1 = '\0';
|
||||
return(r);
|
||||
}
|
||||
else if (*p2 == '.')
|
||||
{
|
||||
p3 = p2 + 1;
|
||||
if (*p3 == '/' || *p3 == '\0')
|
||||
{
|
||||
for (ps = p - 1; ps >= r; ps--)
|
||||
{
|
||||
if (*ps == '/') break;
|
||||
}
|
||||
if (ps < r) ps = r;
|
||||
if (*p3 == '/') memmove(ps, p3, strlen(p3) + 1);
|
||||
else
|
||||
{
|
||||
*(ps + 1) = '\0';
|
||||
return(r);
|
||||
}
|
||||
p = ps;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
return(r);
|
||||
}
|
87
common/dmem.c
Normal file
87
common/dmem.c
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* dmem.c
|
||||
*
|
||||
* Copyright (C) 1995-1997, John Kilburg <john@cs.unlv.edu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
* free_mem
|
||||
*/
|
||||
void
|
||||
free_mem(m)
|
||||
void *m;
|
||||
{
|
||||
free(m);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* calloc_mem
|
||||
*/
|
||||
void *
|
||||
calloc_mem(len, elen)
|
||||
size_t len, elen;
|
||||
{
|
||||
return(calloc(len, elen));
|
||||
}
|
||||
|
||||
/*
|
||||
* alloc_mem
|
||||
*/
|
||||
void *
|
||||
alloc_mem(len)
|
||||
size_t len;
|
||||
{
|
||||
return(malloc(len));
|
||||
}
|
||||
|
||||
/*
|
||||
* realloc_mem
|
||||
*/
|
||||
void *
|
||||
realloc_mem(s, len)
|
||||
void *s;
|
||||
size_t len;
|
||||
{
|
||||
return(realloc(s, len));
|
||||
}
|
||||
|
||||
/*
|
||||
* alloc_string
|
||||
*/
|
||||
char *
|
||||
alloc_string(str)
|
||||
char *str;
|
||||
{
|
||||
char *ns;
|
||||
|
||||
ns = (char *)malloc(strlen(str) + 1);
|
||||
strcpy(ns, str);
|
||||
return(ns);
|
||||
}
|
353
common/list.c
Normal file
353
common/list.c
Normal file
|
@ -0,0 +1,353 @@
|
|||
/*
|
||||
* list.c
|
||||
*
|
||||
* Copyright (c) 1996-1997, John Kilburg <john@cs.unlv.edu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
struct GNodeP
|
||||
{
|
||||
void *thing;
|
||||
struct GNodeP *prev, *next;
|
||||
};
|
||||
|
||||
struct GListP
|
||||
{
|
||||
bool localmp;
|
||||
MemPool mp;
|
||||
struct GNodeP *f;
|
||||
struct GNodeP *head, *tail;
|
||||
struct GNodeP *c;
|
||||
};
|
||||
|
||||
/*
|
||||
#define TRACKER 1
|
||||
*/
|
||||
|
||||
#ifdef TRACKER
|
||||
struct track
|
||||
{
|
||||
GList gl;
|
||||
int line;
|
||||
char *file;
|
||||
struct track *next;
|
||||
};
|
||||
|
||||
static struct track *track_list = NULL;
|
||||
#endif
|
||||
|
||||
static void FreeListNode _ArgProto((GList, struct GNodeP *));
|
||||
static struct GNodeP *GetFreedNode _ArgProto((GList));
|
||||
|
||||
static void
|
||||
FreeListNode(gl, f)
|
||||
GList gl;
|
||||
struct GNodeP *f;
|
||||
{
|
||||
#ifdef TRACKER
|
||||
memset(f, 0, sizeof(struct GNodeP));
|
||||
#endif
|
||||
f->next = gl->f;
|
||||
gl->f = f;
|
||||
return;
|
||||
}
|
||||
|
||||
static struct GNodeP *
|
||||
GetFreedNode(gl)
|
||||
GList gl;
|
||||
{
|
||||
struct GNodeP *f;
|
||||
|
||||
return(NULL);
|
||||
|
||||
if (gl->f == NULL) return(NULL);
|
||||
f = gl->f;
|
||||
gl->f = f->next;
|
||||
memset(f, 0, sizeof(struct GNodeP));
|
||||
return(f);
|
||||
}
|
||||
|
||||
GList
|
||||
GListCreateX(mp)
|
||||
MemPool mp;
|
||||
{
|
||||
GList gl;
|
||||
|
||||
gl = (GList)MPCGet(mp, sizeof(struct GListP));
|
||||
gl->mp = mp;
|
||||
gl->localmp = false;
|
||||
|
||||
return(gl);
|
||||
}
|
||||
|
||||
GList
|
||||
GListCreateTrack(line, file)
|
||||
int line;
|
||||
char *file;
|
||||
{
|
||||
MemPool mp;
|
||||
GList gl;
|
||||
#ifdef TRACKER
|
||||
struct track *f;
|
||||
#endif
|
||||
|
||||
mp = MPCreate();
|
||||
gl = (GList)MPCGet(mp, sizeof(struct GListP));
|
||||
gl->mp = mp;
|
||||
gl->localmp = true;
|
||||
|
||||
#ifdef TRACKER
|
||||
f = (struct track *)malloc(sizeof(struct track));
|
||||
f->gl = gl;
|
||||
f->line = line;
|
||||
f->file = file;
|
||||
f->next = track_list;
|
||||
track_list = f;
|
||||
#endif
|
||||
|
||||
return(gl);
|
||||
}
|
||||
|
||||
void *
|
||||
GListPop(gl)
|
||||
GList gl;
|
||||
{
|
||||
void *thing;
|
||||
struct GNodeP *f;
|
||||
|
||||
if (gl->head != NULL)
|
||||
{
|
||||
thing = gl->head->thing;
|
||||
f = gl->head;
|
||||
if (gl->head != NULL) gl->head = gl->head->next;
|
||||
if (gl->head != NULL) gl->head->prev = NULL;
|
||||
gl->c = gl->head;
|
||||
FreeListNode(gl, f);
|
||||
|
||||
return(thing);
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
void
|
||||
GListAddHead(gl, thing)
|
||||
GList gl;
|
||||
void *thing;
|
||||
{
|
||||
struct GNodeP *gn;
|
||||
|
||||
if ((gn = GetFreedNode(gl)) == NULL)
|
||||
{
|
||||
gn = (struct GNodeP *)MPCGet(gl->mp, sizeof(struct GNodeP));
|
||||
}
|
||||
gn->next = gl->head;
|
||||
if (gl->head != NULL) gl->head->prev = gn;
|
||||
gl->head = gn;
|
||||
if (gl->tail == NULL) gl->tail = gn;
|
||||
gn->thing = thing;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
GListAddTail(gl, thing)
|
||||
GList gl;
|
||||
void *thing;
|
||||
{
|
||||
struct GNodeP *gn;
|
||||
|
||||
if ((gn = GetFreedNode(gl)) == NULL)
|
||||
{
|
||||
gn = (struct GNodeP *)MPCGet(gl->mp, sizeof(struct GNodeP));
|
||||
}
|
||||
gn->prev = gl->tail;
|
||||
if (gl->tail != NULL) gl->tail->next = gn;
|
||||
gl->tail = gn;
|
||||
if (gl->head == NULL) gl->head = gn;
|
||||
gn->thing = thing;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
GListDestroy(gl)
|
||||
GList gl;
|
||||
{
|
||||
#ifdef TRACKER
|
||||
struct track *f;
|
||||
#endif
|
||||
|
||||
if (gl->localmp) MPDestroy(gl->mp);
|
||||
|
||||
#ifdef TRACKER
|
||||
for (f = track_list; f != NULL; f = f->next)
|
||||
{
|
||||
if (f->gl == gl)
|
||||
{
|
||||
f->gl = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void *
|
||||
GListGetHead(gl)
|
||||
GList gl;
|
||||
{
|
||||
if (gl->head == NULL) return(NULL);
|
||||
gl->c = gl->head;
|
||||
return(gl->head->thing);
|
||||
}
|
||||
|
||||
void *
|
||||
GListGetTail(gl)
|
||||
GList gl;
|
||||
{
|
||||
if (gl->tail == NULL) return(NULL);
|
||||
gl->c = gl->tail;
|
||||
return(gl->tail->thing);
|
||||
}
|
||||
|
||||
void *
|
||||
GListGetNext(gl)
|
||||
GList gl;
|
||||
{
|
||||
if (gl->c == NULL) return(NULL);
|
||||
gl->c = gl->c->next;
|
||||
if (gl->c == NULL) return(NULL);
|
||||
return(gl->c->thing);
|
||||
}
|
||||
|
||||
void *
|
||||
GListGetPrev(gl)
|
||||
GList gl;
|
||||
{
|
||||
if (gl->c == NULL) return(NULL);
|
||||
gl->c = gl->c->prev;
|
||||
if (gl->c == NULL) return(NULL);
|
||||
return(gl->c->thing);
|
||||
}
|
||||
|
||||
void *
|
||||
GListGetCurrent(gl)
|
||||
GList gl;
|
||||
{
|
||||
if (gl->c == NULL) return(NULL);
|
||||
return(gl->c->thing);
|
||||
}
|
||||
|
||||
void
|
||||
GListRemoveItem(gl, thing)
|
||||
GList gl;
|
||||
void *thing;
|
||||
{
|
||||
struct GNodeP *c, *n;
|
||||
|
||||
for (c = gl->head; c != NULL; )
|
||||
{
|
||||
if (c->thing == thing)
|
||||
{
|
||||
if (gl->c == c) gl->c = NULL;
|
||||
|
||||
n = c->next;
|
||||
|
||||
if (c == gl->head) gl->head = c->next;
|
||||
if (c == gl->tail) gl->tail = c->prev;
|
||||
if (c->next != NULL) c->next->prev = c->prev;
|
||||
if (c->prev != NULL) c->prev->next = c->next;
|
||||
|
||||
FreeListNode(gl, c);
|
||||
|
||||
c = n;
|
||||
}
|
||||
else c = c->next;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool
|
||||
GListEmpty(gl)
|
||||
GList gl;
|
||||
{
|
||||
return(gl == NULL || gl->head == NULL);
|
||||
}
|
||||
|
||||
MemPool
|
||||
GListMP(gl)
|
||||
GList gl;
|
||||
{
|
||||
return(gl->mp);
|
||||
}
|
||||
|
||||
void
|
||||
GListPrintStatus()
|
||||
{
|
||||
#ifdef TRACKER
|
||||
struct track *f;
|
||||
|
||||
for (f = track_list; f != NULL; f = f->next)
|
||||
{
|
||||
if (f->gl != NULL)
|
||||
{
|
||||
fprintf (stderr, "GList unfreed: Line %d, File %s\n", f->line, f->file);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
GListClear(gl)
|
||||
GList gl;
|
||||
{
|
||||
struct GNodeP *c, *t;
|
||||
gl->c = NULL;
|
||||
c = gl->head;
|
||||
t = NULL;
|
||||
while (c != NULL)
|
||||
{
|
||||
t = c;
|
||||
c = c->next;
|
||||
}
|
||||
if (t != NULL)
|
||||
{
|
||||
t->next = gl->f;
|
||||
gl->f = gl->head;
|
||||
}
|
||||
gl->head = NULL;
|
||||
gl->tail = NULL;
|
||||
return;
|
||||
}
|
318
common/mempool.c
Normal file
318
common/mempool.c
Normal file
|
@ -0,0 +1,318 @@
|
|||
/*
|
||||
* mempool.c
|
||||
*
|
||||
* Copyright (c) 1995-1997, John Kilburg <john@cs.unlv.edu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
* MPDEBUG - If this is defined then all memory pooling goes away and
|
||||
* malloc is used. This is useful if you suspect problems
|
||||
* with the memory pooling code (e.g. alignment problems)
|
||||
* or you want to use a malloc checker.
|
||||
*
|
||||
* MPALIGN - If the alignment size is guessed wrong then this can be
|
||||
* defined to be the appropriate alignment size to override
|
||||
* the automatic thing.
|
||||
*
|
||||
* MPPOOLSIZE - This is the minimum allocation size. Maybe changing
|
||||
* it would result in better performance. Must be
|
||||
* larger than sizeof(struct pool)...probably much larger.
|
||||
*/
|
||||
|
||||
/*
|
||||
#define MPDEBUG 1
|
||||
*/
|
||||
|
||||
#define MPPOOLSIZE BUFSIZ
|
||||
|
||||
#ifndef MPALIGN
|
||||
typedef struct Alignment
|
||||
{
|
||||
union { int a; char *b; size_t c; off_t d; long e; } align;
|
||||
} Alignment;
|
||||
#define MPALIGNSIZE(x) ((x / sizeof(Alignment) + 1) * sizeof(Alignment))
|
||||
#else
|
||||
#define MPALIGNSIZE(x) ((x / MPALIGN + 1) * MPALIGN)
|
||||
#endif
|
||||
|
||||
/*
|
||||
#define TRACKER 1
|
||||
*/
|
||||
|
||||
#ifdef TRACKER
|
||||
struct track
|
||||
{
|
||||
MemPool mp;
|
||||
int line;
|
||||
char *file;
|
||||
struct track *next;
|
||||
};
|
||||
|
||||
static struct track *track_list = NULL;
|
||||
#endif
|
||||
|
||||
struct pool
|
||||
{
|
||||
size_t used, len;
|
||||
#ifdef MPDEBUG
|
||||
void *mem;
|
||||
#endif
|
||||
struct pool *next;
|
||||
};
|
||||
|
||||
struct MemPoolP
|
||||
{
|
||||
struct pool *plist;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
#ifndef MPDEBUG
|
||||
static struct pool *create_pool _ArgProto((size_t));
|
||||
static void *use_pool _ArgProto((struct pool *, size_t));
|
||||
|
||||
/*
|
||||
* create_pool
|
||||
*/
|
||||
static struct pool *
|
||||
create_pool(alen)
|
||||
size_t alen;
|
||||
{
|
||||
size_t blen, len, plen;
|
||||
struct pool *pool;
|
||||
|
||||
plen = MPALIGNSIZE(sizeof(struct pool));
|
||||
len = MPALIGNSIZE(alen) + plen;
|
||||
blen = (len / MPPOOLSIZE + 1) * MPPOOLSIZE;
|
||||
pool = (struct pool *)malloc(blen);
|
||||
if (pool == NULL)
|
||||
{
|
||||
fprintf (stderr, "create_pool malloc failed: %ld\n", (long)blen);
|
||||
return(NULL);
|
||||
}
|
||||
pool->len = blen;
|
||||
pool->used = plen;
|
||||
pool->next = NULL;
|
||||
|
||||
return(pool);
|
||||
}
|
||||
|
||||
/*
|
||||
* use_pool
|
||||
*/
|
||||
static void *
|
||||
use_pool(pool, len)
|
||||
struct pool *pool;
|
||||
size_t len;
|
||||
{
|
||||
byte *mem;
|
||||
|
||||
len = MPALIGNSIZE(len);
|
||||
if (pool->used + len > pool->len) return(NULL);
|
||||
mem = (byte *)pool + pool->used;
|
||||
pool->used += len;
|
||||
return((void *)mem);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MPCreate
|
||||
*/
|
||||
MemPool
|
||||
MPCreateTrack(line, file)
|
||||
int line;
|
||||
char *file;
|
||||
{
|
||||
MemPool mp;
|
||||
struct pool *pool;
|
||||
#ifdef TRACKER
|
||||
struct track *f;
|
||||
#endif
|
||||
|
||||
#ifndef MPDEBUG
|
||||
pool = create_pool(sizeof(struct MemPoolP));
|
||||
if (pool == NULL) return(NULL);
|
||||
mp = (MemPool)use_pool(pool, sizeof(struct MemPoolP));
|
||||
myassert(mp != NULL, "MPCreate: use_pool failed!");
|
||||
mp->plist = pool;
|
||||
mp->len = pool->len;
|
||||
#else
|
||||
mp = (MemPool)malloc(sizeof(struct MemPoolP));
|
||||
if (mp == NULL) return(NULL);
|
||||
memset(mp, 0, sizeof(struct MemPoolP));
|
||||
#endif
|
||||
|
||||
#ifdef TRACKER
|
||||
f = (struct track *)malloc(sizeof(struct track));
|
||||
if (f == NULL) abort();
|
||||
f->mp = mp;
|
||||
f->line = line;
|
||||
f->file = file;
|
||||
f->next = track_list;
|
||||
track_list = f;
|
||||
#endif
|
||||
|
||||
return(mp);
|
||||
}
|
||||
|
||||
/*
|
||||
* MPGet
|
||||
*/
|
||||
void *
|
||||
MPGet(mp, len)
|
||||
MemPool mp;
|
||||
size_t len;
|
||||
{
|
||||
struct pool *pool;
|
||||
void *mem;
|
||||
|
||||
myassert(len > 0, "MPGet: must allocate sizes greater than zero!");
|
||||
|
||||
#ifndef MPDEBUG
|
||||
pool = mp->plist;
|
||||
if ((mem = use_pool(pool, len)) == NULL)
|
||||
{
|
||||
pool = create_pool(len);
|
||||
pool->next = mp->plist;
|
||||
mp->len += pool->len;
|
||||
mp->plist = pool;
|
||||
mem = use_pool(pool, len);
|
||||
myassert(mem != NULL, "MPGet: use_pool failed!");
|
||||
}
|
||||
#else
|
||||
pool = (struct pool *)malloc(sizeof(struct pool));
|
||||
if (pool == NULL) return(NULL);
|
||||
pool->next = mp->plist;
|
||||
mp->plist = pool;
|
||||
mem = pool->mem = malloc(len);
|
||||
#endif
|
||||
|
||||
return(mem);
|
||||
}
|
||||
|
||||
/*
|
||||
* MPCGet
|
||||
*/
|
||||
void *
|
||||
MPCGet(mp, len)
|
||||
MemPool mp;
|
||||
size_t len;
|
||||
{
|
||||
void *m;
|
||||
m = MPGet(mp, len);
|
||||
memset(m, 0, len);
|
||||
return(m);
|
||||
}
|
||||
|
||||
/*
|
||||
* MPStrDup
|
||||
*/
|
||||
char *
|
||||
MPStrDup(mp, s)
|
||||
MemPool mp;
|
||||
const char *s;
|
||||
{
|
||||
size_t len;
|
||||
char *ns;
|
||||
|
||||
if (s == NULL) return(NULL);
|
||||
len = strlen(s);
|
||||
ns = (char *)MPGet(mp, len + 1);
|
||||
strcpy(ns, s);
|
||||
return(ns);
|
||||
}
|
||||
|
||||
/*
|
||||
* MPDestroy
|
||||
*/
|
||||
void
|
||||
MPDestroy(mp)
|
||||
MemPool mp;
|
||||
{
|
||||
struct pool *m, *t;
|
||||
#ifdef TRACKER
|
||||
struct track *f;
|
||||
#endif
|
||||
|
||||
for (m = mp->plist; m != NULL; )
|
||||
{
|
||||
t = m;
|
||||
m = m->next;
|
||||
#ifdef MPDEBUG
|
||||
free(t->mem);
|
||||
#endif
|
||||
free(t);
|
||||
}
|
||||
#ifdef MPDEBUG
|
||||
free(mp);
|
||||
#endif
|
||||
|
||||
#ifdef TRACKER
|
||||
for (f = track_list; f != NULL; f = f->next)
|
||||
{
|
||||
if (f->mp == mp)
|
||||
{
|
||||
f->mp = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* MPPrintStats
|
||||
*/
|
||||
void
|
||||
MPPrintStatus()
|
||||
{
|
||||
#ifdef TRACKER
|
||||
struct track *f;
|
||||
size_t total;
|
||||
|
||||
total = 0;
|
||||
for (f = track_list; f != NULL; f = f->next)
|
||||
{
|
||||
if (f->mp != NULL)
|
||||
{
|
||||
fprintf (stderr, "MP unfreed: Line %d, File %s, Length %ld\n",
|
||||
f->line, f->file, (long)f->mp->len);
|
||||
total += f->mp->len;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf (stderr, "Total unfreed: %ld\n", (long)total);
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
432
common/mime.c
Normal file
432
common/mime.c
Normal file
|
@ -0,0 +1,432 @@
|
|||
/*
|
||||
* mime.c
|
||||
*
|
||||
* Copyright (c) 1997, John Kilburg <john@cs.unlv.edu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "mime.h"
|
||||
|
||||
typedef struct MIMEFieldP *MIMEField;
|
||||
typedef struct MIMEParamP *MIMEParam;
|
||||
|
||||
/*
|
||||
* MIMEish parsing thing.
|
||||
*
|
||||
* Tries to deal with stuff of the form:
|
||||
*
|
||||
* field-name: field-value; param[=value]; param[=value]; ...
|
||||
*/
|
||||
|
||||
struct MIMEHeaderP
|
||||
{
|
||||
GList list; /* list of MIMEField */
|
||||
MemPool mp;
|
||||
size_t i;
|
||||
size_t len;
|
||||
bool data_found;
|
||||
};
|
||||
|
||||
struct MIMEFieldP
|
||||
{
|
||||
char *name;
|
||||
char *value;
|
||||
GList list; /* list of param */
|
||||
};
|
||||
|
||||
struct MIMEParamP
|
||||
{
|
||||
char *name;
|
||||
char *value;
|
||||
};
|
||||
|
||||
static MIMEParam parse_param _ArgProto((char *));
|
||||
static MIMEField parse_line _ArgProto((MemPool, char *));
|
||||
|
||||
MIMEHeader
|
||||
MIMECreateHeader()
|
||||
{
|
||||
MemPool mp;
|
||||
MIMEHeader mh;
|
||||
|
||||
mp = MPCreate();
|
||||
mh = MPCGet(mp, sizeof(struct MIMEHeaderP));
|
||||
mh->mp = mp;
|
||||
mh->list = GListCreateX(mp);
|
||||
mh->data_found = false;
|
||||
|
||||
return(mh);
|
||||
}
|
||||
|
||||
static MIMEParam
|
||||
parse_param(line)
|
||||
char *line;
|
||||
{
|
||||
MIMEParam p = NULL;
|
||||
|
||||
return(p);
|
||||
}
|
||||
|
||||
static MIMEField
|
||||
parse_line(mp, line)
|
||||
MemPool mp;
|
||||
char *line;
|
||||
{
|
||||
MIMEField mf = NULL;
|
||||
MIMEParam param;
|
||||
char *cp;
|
||||
char *ps = NULL;
|
||||
bool inquote = false;
|
||||
char *t;
|
||||
|
||||
for (cp = line; *cp != '\0'; cp++)
|
||||
{
|
||||
if (mf != NULL)
|
||||
{
|
||||
if (inquote)
|
||||
{
|
||||
if (*cp == '"') inquote = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*cp == '"') inquote = true;
|
||||
else if (*cp == ';' || *cp == '\0')
|
||||
{
|
||||
while (isspace8(*ps) && ps < cp) ps++;
|
||||
if (ps < cp)
|
||||
{
|
||||
t = (char *)MPGet(mp, cp - ps + 1);
|
||||
strncpy(t, ps, cp - ps);
|
||||
t[cp - ps] = '\0';
|
||||
|
||||
if (mf->value == NULL) mf->value = t;
|
||||
else
|
||||
{
|
||||
if (mf->list == NULL) mf->list = GListCreateX(mp);
|
||||
if ((param = parse_param(t)) != NULL)
|
||||
{
|
||||
GListAddTail(mf->list, param);
|
||||
}
|
||||
}
|
||||
}
|
||||
ps = cp + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (*cp == ':')
|
||||
{
|
||||
mf = (MIMEField)MPCGet(mp, sizeof(struct MIMEFieldP));
|
||||
mf->name = (char *)MPGet(mp, cp - line + 1);
|
||||
strncpy(mf->name, line, cp - line);
|
||||
mf->name[cp - line] = '\0';
|
||||
ps = cp + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Catch the value or parameter that is terminated with \0
|
||||
*/
|
||||
if (mf != NULL && ps < cp)
|
||||
{
|
||||
while (isspace8(*ps) && ps < cp) ps++;
|
||||
if (ps < cp)
|
||||
{
|
||||
t = (char *)MPGet(mp, cp - ps + 1);
|
||||
strncpy(t, ps, cp - ps);
|
||||
t[cp - ps] = '\0';
|
||||
|
||||
if (mf->value == NULL) mf->value = t;
|
||||
else
|
||||
{
|
||||
if (mf->list == NULL) mf->list = GListCreateX(mp);
|
||||
if ((param = parse_param(t)) != NULL)
|
||||
{
|
||||
GListAddTail(mf->list, param);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(mf);
|
||||
}
|
||||
|
||||
/*
|
||||
* MIMEParseBuffer
|
||||
*
|
||||
* This is the entry point for code to parse a buffer that contains
|
||||
* a MIME-like thing chunk of chars.
|
||||
*/
|
||||
int
|
||||
MIMEParseBuffer(mh, buf, len)
|
||||
MIMEHeader mh;
|
||||
char *buf;
|
||||
size_t len;
|
||||
{
|
||||
MIMEField mf;
|
||||
size_t j;
|
||||
char *cp, *pcp, *ls, *le;
|
||||
char *line;
|
||||
size_t usedlen;
|
||||
size_t linelen;
|
||||
|
||||
myassert(mh->data_found, "Must call MIMEFindData before MIMEParseBuffer");
|
||||
|
||||
usedlen = 0;
|
||||
linelen = BUFSIZ;
|
||||
line = (char *)alloc_mem(linelen);
|
||||
|
||||
le = NULL;
|
||||
ls = cp = buf;
|
||||
pcp = "";
|
||||
for (j = 0; j < len; j++, pcp = cp, cp++)
|
||||
{
|
||||
if (*cp != '\n') continue;
|
||||
|
||||
/*
|
||||
* If line ends with \r\n then shift EOL back one character so that
|
||||
* \r doesn't get included in the line.
|
||||
*/
|
||||
if (*pcp == '\r') le = pcp;
|
||||
else le = cp;
|
||||
|
||||
/*
|
||||
* If the line start is the same as the line end then it must be
|
||||
* a blank line and its time to bail out.
|
||||
*/
|
||||
if (ls == le) break;
|
||||
|
||||
/*
|
||||
* If the line doesn't begin with a space character then flush the
|
||||
* previous line (if there was a previous) as a complete field.
|
||||
* Otherwise remove the blank space from the continuation line.
|
||||
*/
|
||||
if (!isspace8(*ls))
|
||||
{
|
||||
if (usedlen > 0)
|
||||
{
|
||||
if ((mf = parse_line(mh->mp, line)) != NULL)
|
||||
{
|
||||
GListAddTail(mh->list, mf);
|
||||
}
|
||||
usedlen = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while(isspace8(*ls) && ls < le) ls++;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is something besides whitespace then stick it in the line
|
||||
* buffer.
|
||||
*/
|
||||
if (ls < le)
|
||||
{
|
||||
if (linelen < usedlen + (le - ls))
|
||||
{
|
||||
linelen += ((le - ls) / BUFSIZ + 1) * BUFSIZ;
|
||||
line = (char *)realloc(line, linelen);
|
||||
}
|
||||
strncpy(line + usedlen, ls, le - ls);
|
||||
usedlen += le - ls;
|
||||
line[usedlen] = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the next line after the \n
|
||||
*/
|
||||
ls = cp + 1;
|
||||
}
|
||||
|
||||
if (usedlen > 0)
|
||||
{
|
||||
if ((mf = parse_line(mh->mp, line)) != NULL)
|
||||
{
|
||||
GListAddTail(mh->list, mf);
|
||||
}
|
||||
usedlen = 0;
|
||||
}
|
||||
|
||||
free_mem(line);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* MIMEDestroyHeader
|
||||
*/
|
||||
void
|
||||
MIMEDestroyHeader(mh)
|
||||
MIMEHeader mh;
|
||||
{
|
||||
MPDestroy(mh->mp);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* MIMEFindData
|
||||
*
|
||||
* Searches for \n\n and \r\n\r\n in a string. Returns the offset after
|
||||
* the pattern;
|
||||
*/
|
||||
int
|
||||
MIMEFindData(mh, data, len, doff)
|
||||
MIMEHeader mh;
|
||||
char *data;
|
||||
size_t len;
|
||||
size_t *doff;
|
||||
{
|
||||
char *cp;
|
||||
char n[4];
|
||||
size_t j;
|
||||
|
||||
myassert(mh->i < len, "MIMEFindData: Inconsistent buffer sizes");
|
||||
|
||||
memset(n, 0, sizeof(n));
|
||||
j = 0;
|
||||
for (cp = data + mh->i; mh->i < len; mh->i++, j++, cp++)
|
||||
{
|
||||
n[j % 4] = *cp;
|
||||
|
||||
/*
|
||||
* Mmmm fun. If there are two or more characters and the current
|
||||
* and previous character are '\n' (i.e. blank line) then the end
|
||||
* of the header has been reached. If there are 4 or more characters
|
||||
* and the sequence of characters (in reverse order) is \n\r\n\r then
|
||||
* the end of header has been reached.
|
||||
*/
|
||||
if (j >= 2 && n[j % 4] == '\n' &&
|
||||
(n[(j - 1) % 4] == '\n' ||
|
||||
(j >= 4 && n[(j - 1) % 4] == '\r' && n[(j - 2) % 4] == '\n' &&
|
||||
n[(j - 3) % 4] == '\r')))
|
||||
{
|
||||
mh->data_found = true;
|
||||
*doff = mh->i + 1;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* MIMEGetField
|
||||
*/
|
||||
int
|
||||
MIMEGetField(mh, name, value)
|
||||
MIMEHeader mh;
|
||||
char *name;
|
||||
char **value;
|
||||
{
|
||||
MIMEField f;
|
||||
|
||||
for (f = (MIMEField)GListGetHead(mh->list); f != NULL;
|
||||
f = (MIMEField)GListGetNext(mh->list))
|
||||
{
|
||||
if (strlen(f->name) == strlen(name) && strcasecmp(f->name, name) == 0)
|
||||
{
|
||||
*value = f->value;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* MIMEAddLine
|
||||
*
|
||||
* Adds a field to a header. Parses out parameters into structures.
|
||||
*/
|
||||
void
|
||||
MIMEAddLine(mh, line)
|
||||
MIMEHeader mh;
|
||||
char *line;
|
||||
{
|
||||
MIMEField f;
|
||||
|
||||
if ((f = parse_line(mh->mp, line)) != NULL)
|
||||
{
|
||||
GListAddTail(mh->list, f);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* MIMEAddField
|
||||
*/
|
||||
void
|
||||
MIMEAddField(mh, name, value)
|
||||
MIMEHeader mh;
|
||||
char *name;
|
||||
char *value;
|
||||
{
|
||||
MIMEField mf;
|
||||
mf = (MIMEField)MPCGet(mh->mp, sizeof(struct MIMEFieldP));
|
||||
mf->name = MPStrDup(mh->mp, name);
|
||||
mf->value = MPStrDup(mh->mp, value);
|
||||
GListAddTail(mh->list, mf);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* MIMEWriteHeader
|
||||
*
|
||||
* This doesn't break long lines.
|
||||
*/
|
||||
int
|
||||
MIMEWriteHeader(mh, fp)
|
||||
MIMEHeader mh;
|
||||
FILE *fp;
|
||||
{
|
||||
MIMEField mf;
|
||||
MIMEParam param;
|
||||
|
||||
for (mf = (MIMEField)GListGetHead(mh->list); mf != NULL;
|
||||
mf = (MIMEField)GListGetNext(mh->list))
|
||||
{
|
||||
fprintf (fp, "%s: %s", mf->name, mf->value);
|
||||
if (mf->list != NULL)
|
||||
{
|
||||
for (param = (MIMEParam)GListGetHead(mf->list); param != NULL;
|
||||
param = (MIMEParam)GListGetNext(mf->list))
|
||||
{
|
||||
fprintf (fp, "; %s", param->name);
|
||||
if (param->value != NULL) fprintf (fp, "=%s", param->value);
|
||||
}
|
||||
}
|
||||
fprintf (fp, "\n");
|
||||
}
|
||||
fprintf (fp, "\n");
|
||||
|
||||
return(0);
|
||||
}
|
37
common/mime.h
Normal file
37
common/mime.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* mime.h
|
||||
*
|
||||
* Copyright (c) 1997, John Kilburg <john@cs.unlv.edu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __MIME_H__
|
||||
#define __MIME_H__ 1
|
||||
|
||||
typedef struct MIMEHeaderP *MIMEHeader;
|
||||
|
||||
MIMEHeader MIMECreateHeader _ArgProto((void));
|
||||
int MIMEParseBuffer _ArgProto((MIMEHeader, char *, size_t));
|
||||
void MIMEDestroyHeader _ArgProto((MIMEHeader));
|
||||
int MIMEGetField _ArgProto((MIMEHeader, char *, char **));
|
||||
void MIMEAddField _ArgProto((MIMEHeader, char *, char *));
|
||||
void MIMEAddLine _ArgProto((MIMEHeader, char *));
|
||||
int MIMEGetHeaderEnd _ArgProto((MIMEHeader, size_t *));
|
||||
int MIMEFindData _ArgProto((MIMEHeader, char *, size_t, size_t *));
|
||||
int MIMEWriteHeader _ArgProto((MIMEHeader, FILE *));
|
||||
|
||||
#endif
|
||||
|
788
common/ml.c
Normal file
788
common/ml.c
Normal file
|
@ -0,0 +1,788 @@
|
|||
/*
|
||||
* ml.c
|
||||
*
|
||||
* Copyright (c) 1995-1997, John Kilburg <john@cs.unlv.edu>
|
||||
*
|
||||
* Bogus parser for things that kind of maybe look like HTML/SGML.
|
||||
* Or something.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "ml.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MLS_TAG, /* inside tag */
|
||||
MLS_AVS, /* inside attribute value (single quote) */
|
||||
MLS_AVD, /* inside attribute value (double quote) */
|
||||
MLS_PSCOMMENT, /* possible start comment */
|
||||
MLS_PECOMMENT, /* possible end comment */
|
||||
MLS_COMMENT, /* inside comment */
|
||||
MLS_DATA, /* between tags */
|
||||
MLS_START /* start state */
|
||||
} MLStateID;
|
||||
|
||||
#define IN_STATE(a, b) ((a)->plist->state == (b))
|
||||
|
||||
struct MLAttributeP
|
||||
{
|
||||
char *name;
|
||||
char *value;
|
||||
struct MLAttributeP *next;
|
||||
};
|
||||
|
||||
struct MLElementP
|
||||
{
|
||||
MLElementType type;
|
||||
char *ptext; /* processed text */
|
||||
size_t plen; /* processed text length */
|
||||
MLAttribute ta; /* attribute list */
|
||||
};
|
||||
|
||||
struct PState
|
||||
{
|
||||
MLStateID state;
|
||||
size_t off;
|
||||
struct PState *next;
|
||||
};
|
||||
|
||||
struct MLStateP
|
||||
{
|
||||
MemPool tmp; /* temporary memory pool */
|
||||
MemPool mp; /* memory pool descriptor */
|
||||
char *data; /* address of HTML buffer */
|
||||
size_t len; /* length of HTML buffer */
|
||||
size_t off; /* offset of parse */
|
||||
MLElementHandler func; /* called when part created */
|
||||
void *closure; /* state info for callback */
|
||||
MLElement head, tail; /* element list */
|
||||
MLElement curr; /* next unprocessed element */
|
||||
struct PState *plist; /* parser state stack */
|
||||
int count; /* call count */
|
||||
};
|
||||
|
||||
static MLAttribute hs_parse_tag _ArgProto((MLState, char *, size_t));
|
||||
static void hs_add_element _ArgProto((MLState, MLElement));
|
||||
static MLElement hs_create_element _ArgProto((MLState, char *, size_t));
|
||||
static MLElement hs_create_text _ArgProto((MLState, char *, size_t));
|
||||
static MLElement hs_create_tag _ArgProto((MLState, char *, size_t));
|
||||
static char *hs_condense _ArgProto((MLState, char *, size_t, size_t *));
|
||||
static MLAttribute hs_create_attribute _ArgProto((MLState, char *, size_t));
|
||||
static void hs_push _ArgProto((MLState, int));
|
||||
static size_t hs_pop _ArgProto((MLState));
|
||||
static void hs_handle_data _ArgProto((MLState, char *, size_t, bool));
|
||||
|
||||
/*
|
||||
* hs_push
|
||||
*/
|
||||
static void
|
||||
hs_push(hs, state)
|
||||
MLState hs;
|
||||
int state;
|
||||
{
|
||||
struct PState *ps;
|
||||
ps = (struct PState *)MPCGet(hs->tmp, sizeof(struct PState));
|
||||
ps->off = hs->off;
|
||||
ps->state = state;
|
||||
ps->next = hs->plist;
|
||||
hs->plist = ps;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* hs_pop
|
||||
*/
|
||||
static size_t
|
||||
hs_pop(hs)
|
||||
MLState hs;
|
||||
{
|
||||
size_t off;
|
||||
if (hs->plist == NULL) abort();
|
||||
off = hs->plist->off;
|
||||
hs->plist = hs->plist->next;
|
||||
return(off);
|
||||
}
|
||||
|
||||
/*
|
||||
* hs_create_attribute
|
||||
*/
|
||||
static MLAttribute
|
||||
hs_create_attribute(hs, text, len)
|
||||
MLState hs;
|
||||
char *text;
|
||||
size_t len;
|
||||
{
|
||||
MLAttribute ta;
|
||||
|
||||
ta = (MLAttribute)MPCGet(hs->mp, sizeof(struct MLAttributeP));
|
||||
|
||||
ta->name = (char *)MPGet(hs->mp, len + 1);
|
||||
strncpy(ta->name, text, len);
|
||||
ta->name[len] = '\0';
|
||||
|
||||
return(ta);
|
||||
}
|
||||
|
||||
struct entity
|
||||
{
|
||||
char *text;
|
||||
int len;
|
||||
unsigned char c;
|
||||
} clist[] =
|
||||
{
|
||||
{ "amp", 3, '&' },
|
||||
{ "lt", 2, '<' },
|
||||
{ "gt", 2, '>' },
|
||||
{ "copy", 4, 169 },
|
||||
{ "AElig", 5, 198 },
|
||||
{ "Aacute", 6, 193 },
|
||||
{ "Acirc", 5, 194 },
|
||||
{ "Agrave", 6, 192 },
|
||||
{ "Aring", 5, 197 },
|
||||
{ "Atilde", 6, 195 },
|
||||
{ "Auml", 4, 196 },
|
||||
{ "Ccedil", 6, 199 },
|
||||
{ "ETH", 3, 208 },
|
||||
{ "Eacute", 6, 201 },
|
||||
{ "Ecirc", 5, 202 },
|
||||
{ "Egrave", 6, 200 },
|
||||
{ "Euml", 4, 203 },
|
||||
{ "Iacute", 6, 205 },
|
||||
{ "Icirc", 5, 206 },
|
||||
{ "Igrave", 6, 204 },
|
||||
{ "Iuml", 4, 207 },
|
||||
{ "Ntilde", 6, 209 },
|
||||
{ "Oacute", 6, 211 },
|
||||
{ "Ocirc", 5, 212 },
|
||||
{ "Ograve", 6, 210 },
|
||||
{ "Oslash", 6, 216 },
|
||||
{ "Otilde", 6, 213 },
|
||||
{ "Ouml", 4, 214 },
|
||||
{ "THORN", 5, 222 },
|
||||
{ "Uacute", 6, 218 },
|
||||
{ "Ucirc", 5, 219 },
|
||||
{ "Ugrave", 6, 217 },
|
||||
{ "Uuml", 4, 220 },
|
||||
{ "Yacute", 6, 221 },
|
||||
{ "aacute", 6, 225 },
|
||||
{ "acirc", 5, 226 },
|
||||
{ "aelig", 5, 230 },
|
||||
{ "agrave", 6, 224 },
|
||||
{ "aring", 5, 229 },
|
||||
{ "atilde", 6, 227 },
|
||||
{ "auml", 4, 228 },
|
||||
{ "ccedil", 6, 231 },
|
||||
{ "eacute", 6, 233 },
|
||||
{ "ecirc", 5, 234 },
|
||||
{ "egrave", 6, 232 },
|
||||
{ "eth", 3, 240 },
|
||||
{ "euml", 4, 235 },
|
||||
{ "iacute", 6, 237 },
|
||||
{ "icirc", 5, 238 },
|
||||
{ "igrave", 6, 236 },
|
||||
{ "iuml", 4, 239 },
|
||||
{ "ntilde", 6, 241 },
|
||||
{ "oacute", 6, 243 },
|
||||
{ "ocirc", 5, 244 },
|
||||
{ "ograve", 6, 242 },
|
||||
{ "oslash", 6, 248 },
|
||||
{ "otilde", 6, 245 },
|
||||
{ "ouml", 4, 246 },
|
||||
{ "szlig", 5, 223 },
|
||||
{ "thorn", 5, 254 },
|
||||
{ "uacute", 6, 250 },
|
||||
{ "ucirc", 5, 251 },
|
||||
{ "ugrave", 6, 249 },
|
||||
{ "uuml", 4, 252 },
|
||||
{ "yacute", 6, 253 },
|
||||
{ "yuml", 4, 255 },
|
||||
{ "reg", 3, 174 },
|
||||
{ "comma", 5, 44 },
|
||||
{ "colon", 5, 58 },
|
||||
{ "quot", 4, '\"' },
|
||||
{ "nbsp", 4, ' ' },
|
||||
{ NULL, 0, '\0' },
|
||||
};
|
||||
|
||||
/*
|
||||
* hs_condense
|
||||
*/
|
||||
static char *
|
||||
hs_condense(hs, text, len, newlen)
|
||||
MLState hs;
|
||||
char *text;
|
||||
size_t len;
|
||||
size_t *newlen;
|
||||
{
|
||||
char *cp, *lastcp;
|
||||
size_t i;
|
||||
char *b, *bcp;
|
||||
char *x;
|
||||
|
||||
/*
|
||||
* allocate a buffer for the new text. the new text will be smaller than
|
||||
* the incoming text
|
||||
*/
|
||||
b = (char *)MPGet(hs->mp, len + 1);
|
||||
bcp = b;
|
||||
|
||||
for (cp = text, lastcp = text + len; cp < lastcp; cp++)
|
||||
{
|
||||
/*
|
||||
* Found entity and there is at least one more character?
|
||||
*/
|
||||
if (*cp == '&')
|
||||
{
|
||||
for (x = cp; x < lastcp && *x != ';' && !isspace8(*x); x++)
|
||||
;
|
||||
if (x < lastcp) /* found end of entity ? */
|
||||
{
|
||||
if (*x == '\r') x++; /* this may die */
|
||||
if (*(cp + 1) == '#') /* number given ? */
|
||||
{
|
||||
*bcp = (char)atoi(cp + 2); /* get the character */
|
||||
bcp++;
|
||||
cp = x;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *crap;
|
||||
|
||||
/* Search in the table of entity names */
|
||||
for (i = 0, crap = cp + 1; clist[i].text != NULL; i++)
|
||||
{
|
||||
if (strncmp(clist[i].text, crap, clist[i].len) == 0)
|
||||
{
|
||||
*bcp = clist[i].c;
|
||||
bcp++;
|
||||
cp = x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cp < x)
|
||||
{
|
||||
*bcp = *cp;
|
||||
bcp++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*bcp = *cp; /* not part of entity */
|
||||
bcp++;
|
||||
}
|
||||
}
|
||||
|
||||
*newlen = bcp - b;
|
||||
*bcp = '\0';
|
||||
|
||||
return(b);
|
||||
}
|
||||
|
||||
/*
|
||||
* hs_parse_tag
|
||||
*/
|
||||
MLAttribute
|
||||
hs_parse_tag(hs, text, len)
|
||||
MLState hs;
|
||||
char *text;
|
||||
size_t len;
|
||||
{
|
||||
char *cp, *start, *lastcp;
|
||||
MLAttribute tahead, tatail, ta;
|
||||
size_t newlen;
|
||||
|
||||
tahead = NULL;
|
||||
tatail = NULL;
|
||||
lastcp = text + len;
|
||||
for (cp = text; cp < lastcp; )
|
||||
{
|
||||
/* Eat leading spaces */
|
||||
for (; cp < lastcp && isspace8(*cp); cp++)
|
||||
;
|
||||
if (cp == lastcp) break;
|
||||
|
||||
/* Look for value */
|
||||
for (start = cp; cp < lastcp && !isspace8(*cp) && *cp != '='; cp++)
|
||||
;
|
||||
|
||||
ta = hs_create_attribute(hs, start, cp - start);
|
||||
|
||||
if (isspace8(*cp))
|
||||
{
|
||||
for (; cp < lastcp && isspace8(*cp); cp++)
|
||||
;
|
||||
}
|
||||
|
||||
/* Found value */
|
||||
if (cp < lastcp && *cp == '=')
|
||||
{
|
||||
cp++; /* past '=' */
|
||||
|
||||
/* Eat leading spaces */
|
||||
for (; cp < lastcp && isspace8(*cp); cp++)
|
||||
;
|
||||
if (cp < lastcp)
|
||||
{
|
||||
/* Quoted value */
|
||||
if (*cp == '"')
|
||||
{
|
||||
cp++; /* past '"' */
|
||||
|
||||
for (start = cp; cp < lastcp && *cp != '"'; cp++)
|
||||
;
|
||||
}
|
||||
else if (*cp == '\'') /* single quoted value */
|
||||
{
|
||||
cp++; /* past ' */
|
||||
|
||||
for (start = cp; cp < lastcp && *cp != '\''; cp++)
|
||||
;
|
||||
}
|
||||
else /* Unquoted value */
|
||||
{
|
||||
for (start = cp; cp < lastcp && !isspace8(*cp); cp++)
|
||||
;
|
||||
}
|
||||
|
||||
ta->value = hs_condense(hs, start, cp - start, &newlen);
|
||||
}
|
||||
}
|
||||
|
||||
if (tatail == NULL) tahead = ta;
|
||||
else tatail->next = ta;
|
||||
tatail = ta;
|
||||
}
|
||||
|
||||
return(tahead);
|
||||
}
|
||||
|
||||
/*
|
||||
* hs_add_element
|
||||
*/
|
||||
static void
|
||||
hs_add_element(hs, p)
|
||||
MLState hs;
|
||||
MLElement p;
|
||||
{
|
||||
(hs->func)(hs->closure, p);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* hs_create_element
|
||||
*/
|
||||
static MLElement
|
||||
hs_create_element(hs, ptext, plen)
|
||||
MLState hs;
|
||||
char *ptext;
|
||||
size_t plen;
|
||||
{
|
||||
MLElement p;
|
||||
|
||||
p = (MLElement)MPCGet(hs->mp, sizeof(struct MLElementP));
|
||||
p->ptext = ptext;
|
||||
p->plen = plen;
|
||||
|
||||
return(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* hs_create_text
|
||||
*/
|
||||
static MLElement
|
||||
hs_create_text(hs, text, len)
|
||||
MLState hs;
|
||||
char *text;
|
||||
size_t len;
|
||||
{
|
||||
char *cp;
|
||||
size_t newlen;
|
||||
size_t i;
|
||||
MLElement p;
|
||||
|
||||
/* Check for an entity */
|
||||
for (cp = text, i = 0; i < len && *cp != '&'; cp++, i++)
|
||||
;
|
||||
|
||||
if (i == len) p = hs_create_element(hs, text, len);
|
||||
else
|
||||
{
|
||||
/* found an entity...condense */
|
||||
cp = hs_condense(hs, text, len, &newlen);
|
||||
p = hs_create_element(hs, cp, newlen);
|
||||
}
|
||||
|
||||
p->type = ML_DATA;
|
||||
|
||||
return(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* hs_create_tag
|
||||
*/
|
||||
static MLElement
|
||||
hs_create_tag(hs, text, len)
|
||||
MLState hs;
|
||||
char *text;
|
||||
size_t len;
|
||||
{
|
||||
MLElement p;
|
||||
|
||||
p = hs_create_element(hs, text, len);
|
||||
p->ta = hs_parse_tag(hs, text + 1, len - 2);
|
||||
|
||||
if (p->ta != NULL && p->ta->name != NULL && p->ta->name[0] == '/')
|
||||
{
|
||||
p->ta->name++; /* this should be OK because it is not free'd */
|
||||
p->type = ML_ENDTAG;
|
||||
}
|
||||
else p->type = ML_BEGINTAG;
|
||||
|
||||
return(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* MLInit
|
||||
*/
|
||||
MLState
|
||||
MLInit(func, closure)
|
||||
MLElementHandler func;
|
||||
void *closure;
|
||||
{
|
||||
MLState hs;
|
||||
MemPool mp;
|
||||
|
||||
mp = MPCreate();
|
||||
hs = (MLState)MPCGet(mp, sizeof(struct MLStateP));
|
||||
hs->mp = mp;
|
||||
hs->func = func;
|
||||
hs->closure = closure;
|
||||
|
||||
hs->tmp = MPCreate();
|
||||
|
||||
hs_push(hs, MLS_START);
|
||||
hs_push(hs, MLS_DATA);
|
||||
|
||||
return(hs);
|
||||
}
|
||||
|
||||
/*
|
||||
* MLDestroy
|
||||
*/
|
||||
void
|
||||
MLDestroy(hs)
|
||||
MLState hs;
|
||||
{
|
||||
MPDestroy(hs->mp);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* hs_handle_data
|
||||
*/
|
||||
void
|
||||
hs_handle_data(hs, data, len, dend)
|
||||
MLState hs;
|
||||
char *data;
|
||||
size_t len;
|
||||
bool dend;
|
||||
{
|
||||
char *cp;
|
||||
size_t poff;
|
||||
MLElement n;
|
||||
|
||||
if (data == NULL || len == 0) return;
|
||||
|
||||
hs->data = data;
|
||||
hs->len = len;
|
||||
|
||||
while (hs->off < len)
|
||||
{
|
||||
cp = data + hs->off;
|
||||
|
||||
if (IN_STATE(hs, MLS_DATA))
|
||||
{
|
||||
if (*cp == '<')
|
||||
{
|
||||
poff = hs_pop(hs);
|
||||
if (hs->off - poff > 0)
|
||||
{
|
||||
n = hs_create_text(hs, hs->data + poff, hs->off - poff);
|
||||
hs_add_element(hs, n);
|
||||
}
|
||||
hs_push(hs, MLS_TAG);
|
||||
}
|
||||
hs->off++;
|
||||
}
|
||||
else if (IN_STATE(hs, MLS_TAG))
|
||||
{
|
||||
if (*cp == '<') hs->off++;
|
||||
else if (*cp == '>')
|
||||
{
|
||||
poff = hs_pop(hs);
|
||||
n = hs_create_tag(hs, hs->data + poff, hs->off - poff + 1);
|
||||
hs_add_element(hs, n);
|
||||
hs->off++;
|
||||
hs_push(hs, MLS_DATA);
|
||||
}
|
||||
else if (*cp == '-')
|
||||
{
|
||||
hs_push(hs, MLS_PSCOMMENT);
|
||||
hs->off++;
|
||||
}
|
||||
else if (*cp == '"')
|
||||
{
|
||||
hs_push(hs, MLS_AVD);
|
||||
hs->off++;
|
||||
}
|
||||
else if (*cp == '\'')
|
||||
{
|
||||
hs_push(hs, MLS_AVS);
|
||||
hs->off++;
|
||||
}
|
||||
else hs->off++;
|
||||
}
|
||||
else if (IN_STATE(hs, MLS_PSCOMMENT))
|
||||
{
|
||||
hs_pop(hs);
|
||||
if (*cp == '-')
|
||||
{
|
||||
hs_push(hs, MLS_COMMENT);
|
||||
hs->off++;
|
||||
}
|
||||
else if (*cp == '>')
|
||||
{
|
||||
poff = hs_pop(hs);
|
||||
n = hs_create_tag(hs, hs->data + poff, hs->off - poff + 1);
|
||||
hs_add_element(hs, n);
|
||||
hs->off++;
|
||||
hs_push(hs, MLS_DATA);
|
||||
}
|
||||
else hs->off++;
|
||||
}
|
||||
else if (IN_STATE(hs, MLS_AVS))
|
||||
{
|
||||
if (*cp == '\'')
|
||||
{
|
||||
hs_pop(hs);
|
||||
hs->off++;
|
||||
}
|
||||
else if (*cp == '>') hs_pop(hs);
|
||||
else hs->off++;
|
||||
}
|
||||
else if (IN_STATE(hs, MLS_AVD))
|
||||
{
|
||||
if (*cp == '"')
|
||||
{
|
||||
hs_pop(hs);
|
||||
hs->off++;
|
||||
}
|
||||
else if (*cp == '>') hs_pop(hs);
|
||||
else hs->off++;
|
||||
}
|
||||
else if (IN_STATE(hs, MLS_COMMENT))
|
||||
{
|
||||
if (*cp == '-') hs_push(hs, MLS_PECOMMENT);
|
||||
hs->off++;
|
||||
}
|
||||
else if (IN_STATE(hs, MLS_PECOMMENT))
|
||||
{
|
||||
/* Depends on only COMMENT state pushing PECOMMENT state */
|
||||
hs_pop(hs);
|
||||
if (*cp == '-')
|
||||
{
|
||||
hs->off++;
|
||||
hs_pop(hs);
|
||||
}
|
||||
else if (*cp == '>')
|
||||
{
|
||||
poff = hs_pop(hs);
|
||||
n = hs_create_tag(hs, hs->data + poff, hs->off - poff + 1);
|
||||
hs_add_element(hs, n);
|
||||
hs->off++;
|
||||
hs_push(hs, MLS_DATA);
|
||||
}
|
||||
else hs->off++;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "Invalid markup parser state.\n");
|
||||
hs->off++;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* MLAddData
|
||||
*/
|
||||
void
|
||||
MLAddData(hs, data, len)
|
||||
MLState hs;
|
||||
char *data;
|
||||
size_t len;
|
||||
{
|
||||
hs_handle_data(hs, data, len, false);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* MLEndData
|
||||
*/
|
||||
void
|
||||
MLEndData(hs, data, len)
|
||||
MLState hs;
|
||||
char *data;
|
||||
size_t len;
|
||||
{
|
||||
MLElement p;
|
||||
size_t poff;
|
||||
|
||||
if (data == NULL || len == 0 || len < hs->off) return;
|
||||
|
||||
hs_handle_data(hs, data, len, true);
|
||||
|
||||
poff = hs_pop(hs);
|
||||
if (len - poff > 0)
|
||||
{
|
||||
if (IN_STATE(hs, MLS_DATA))
|
||||
{
|
||||
p = hs_create_text(hs, hs->data + poff, len - poff);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = hs_create_tag(hs, hs->data + poff, len - poff);
|
||||
}
|
||||
hs_add_element(hs, p);
|
||||
}
|
||||
|
||||
p = (MLElement)MPCGet(hs->mp, sizeof(struct MLElementP));
|
||||
p->type = ML_EOF;
|
||||
hs_add_element(hs, p);
|
||||
|
||||
MPDestroy(hs->tmp);
|
||||
hs->tmp = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* MLFindAttribute
|
||||
*/
|
||||
char *
|
||||
MLFindAttribute(p, name)
|
||||
MLElement p;
|
||||
char *name;
|
||||
{
|
||||
MLAttribute ta;
|
||||
|
||||
for (ta = p->ta; ta != NULL; ta = ta->next)
|
||||
{
|
||||
if (strcasecmp(ta->name, name) == 0)
|
||||
{
|
||||
return(ta->value == NULL ? "":ta->value);
|
||||
}
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* MLGetText
|
||||
*/
|
||||
void
|
||||
MLGetText(p, text, len)
|
||||
MLElement p;
|
||||
char **text;
|
||||
size_t *len;
|
||||
{
|
||||
*text = p->ptext;
|
||||
*len = p->plen;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* MLGetType
|
||||
*/
|
||||
MLElementType
|
||||
MLGetType(p)
|
||||
MLElement p;
|
||||
{
|
||||
return(p->type);
|
||||
}
|
||||
|
||||
/*
|
||||
* MLTagName
|
||||
*/
|
||||
char *
|
||||
MLTagName(p)
|
||||
MLElement p;
|
||||
{
|
||||
if ((p->type == ML_BEGINTAG || p->type == ML_ENDTAG) && p->ta != NULL)
|
||||
{
|
||||
return(p->ta->name);
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* MLCreateTag
|
||||
*/
|
||||
MLElement
|
||||
MLCreateTag(hs, text, len)
|
||||
MLState hs;
|
||||
char *text;
|
||||
size_t len;
|
||||
{
|
||||
return(hs_create_tag(hs, text, len));
|
||||
}
|
||||
|
||||
/*
|
||||
* MLAttributeToInt
|
||||
*/
|
||||
int
|
||||
MLAttributeToInt(p, name)
|
||||
MLElement p;
|
||||
char *name;
|
||||
{
|
||||
char *value;
|
||||
|
||||
if ((value = MLFindAttribute(p, name)) == NULL) return(-1);
|
||||
|
||||
return(atoi(value));
|
||||
}
|
||||
|
59
common/ml.h
Normal file
59
common/ml.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* ml.h
|
||||
*
|
||||
* Copyright (c) 1996-1997, John Kilburg <john@cs.unlv.edu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
typedef struct MLElementP *MLElement;
|
||||
typedef struct MLAttributeP *MLAttribute;
|
||||
typedef struct MLStateP *MLState;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ML_BEGINTAG,
|
||||
ML_ENDTAG,
|
||||
ML_DATA,
|
||||
ML_CONTROLTAG,
|
||||
ML_EOF
|
||||
} MLElementType;
|
||||
|
||||
/*
|
||||
* Public functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* Functions for providing raw data to the markup-language code.
|
||||
*/
|
||||
typedef void (*MLElementHandler) _ArgProto((void *, MLElement));
|
||||
|
||||
MLState MLInit _ArgProto((MLElementHandler, void *));
|
||||
void MLAddData _ArgProto((MLState, char *, size_t));
|
||||
void MLEndData _ArgProto((MLState, char *, size_t));
|
||||
void MLDestroy _ArgProto((MLState));
|
||||
|
||||
/*
|
||||
* Functions for extracting information about elements created
|
||||
*/
|
||||
char *MLFindAttribute _ArgProto((MLElement, char *));
|
||||
char *MLTagName _ArgProto((MLElement));
|
||||
void MLGetText _ArgProto((MLElement, char **, size_t *));
|
||||
MLElementType MLGetType(MLElement);
|
||||
int MLAttributeToInt _ArgProto((MLElement, char *));
|
||||
|
||||
/*
|
||||
* Random stuff
|
||||
*/
|
||||
MLElement MLCreateTag _ArgProto((MLState, char *, size_t));
|
147
common/uproc.c
Normal file
147
common/uproc.c
Normal file
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* uproc.c
|
||||
*
|
||||
* Code grabbed from chimera 1.65.
|
||||
*/
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#ifndef __QNX__
|
||||
#include <sys/signal.h>
|
||||
#else
|
||||
#include <signal.h>
|
||||
#endif
|
||||
#include <sys/wait.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
* ReapChild
|
||||
*
|
||||
* This code grabs the status from an exiting child process. We really
|
||||
* don't care about the status, we just want to keep zombie's from
|
||||
* cropping up.
|
||||
*/
|
||||
static void
|
||||
ReapChild()
|
||||
{
|
||||
#if defined(WNOHANG) && !defined(SYSV) && !defined(SVR4)
|
||||
int pid;
|
||||
#endif
|
||||
extern int errno;
|
||||
int old_errno = errno;
|
||||
|
||||
/*
|
||||
* It would probably be better to use the POSIX mechanism here,but I have not
|
||||
* checked into it. This gets us off the ground with SYSV. RSE@GMI
|
||||
*/
|
||||
#if defined(WNOHANG) && !defined(SYSV) && !defined(SVR4) && !defined(__QNX__) && !defined(__EMX__)
|
||||
union wait st;
|
||||
|
||||
do
|
||||
{
|
||||
errno = 0;
|
||||
pid = wait3(&st, WNOHANG, 0);
|
||||
}
|
||||
while (pid <= 0 && errno == EINTR);
|
||||
#else
|
||||
int st;
|
||||
|
||||
wait(&st);
|
||||
#endif
|
||||
StartReaper();
|
||||
errno = old_errno;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* StartReaper
|
||||
*
|
||||
* This code inits the code which reaps child processes that where
|
||||
* fork'd off for external viewers.
|
||||
*/
|
||||
void
|
||||
StartReaper()
|
||||
{
|
||||
#ifdef SIGCHLD
|
||||
signal(SIGCHLD, ReapChild);
|
||||
#else
|
||||
signal(SIGCLD, ReapChild);
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* PipeCommand
|
||||
*
|
||||
* fork and exec to get a program running and supply it with
|
||||
* a stdin, stdout, stderr that so we can talk to it.
|
||||
*/
|
||||
int
|
||||
PipeCommand(command, fd)
|
||||
char *command;
|
||||
int *fd;
|
||||
{
|
||||
int pout[2];
|
||||
int pin[2];
|
||||
int pid;
|
||||
|
||||
/*
|
||||
if (pipe(pout) == -1) return(-1);
|
||||
*/
|
||||
if (pipe(pin) == -1)
|
||||
{
|
||||
close(pout[0]);
|
||||
close(pout[1]);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
if (pid == -1)
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
else if (pid == 0)
|
||||
{
|
||||
/*
|
||||
if (pout[1] != 1)
|
||||
{
|
||||
dup2(pout[1], 1);
|
||||
close(pout[1]);
|
||||
}
|
||||
*/
|
||||
if (pin[0] != 0)
|
||||
{
|
||||
dup2(pin[0], 0);
|
||||
close(pin[0]);
|
||||
}
|
||||
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
|
||||
execl(command, command, (char *)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
close(pout[1]);
|
||||
close(pin[0]);
|
||||
}
|
||||
|
||||
fd[0] = pin[1];
|
||||
/*
|
||||
fd[1] = pout[0];
|
||||
*/
|
||||
|
||||
return(0);
|
||||
}
|
614
common/url.c
Normal file
614
common/url.c
Normal file
|
@ -0,0 +1,614 @@
|
|||
/*
|
||||
* url.c
|
||||
*
|
||||
* Copyright (C) 1993-1997, John Kilburg <john@cs.unlv.edu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "url.h"
|
||||
|
||||
#define URLDELIMS ":/?#"
|
||||
|
||||
#ifndef NullString
|
||||
#define NullString(s) (s == NULL || *s == '\0')
|
||||
#endif
|
||||
|
||||
static URLParts *URLCreate _ArgProto((MemPool));
|
||||
static char *resolve_filename _ArgProto((MemPool, char *, char *));
|
||||
|
||||
/*
|
||||
* URLcmp
|
||||
*
|
||||
* Return 0 if equal.
|
||||
*/
|
||||
int
|
||||
URLcmp(u1, u2)
|
||||
URLParts *u1, *u2;
|
||||
{
|
||||
if (strcasecmp(u1->scheme, u2->scheme) == 0 &&
|
||||
strcasecmp(u1->hostname, u2->hostname) == 0 &&
|
||||
u1->port == u2->port &&
|
||||
strcasecmp(u1->filename, u2->filename) == 0)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* URLEscape
|
||||
*
|
||||
* Puts escape codes in URLs. NOT complete.
|
||||
*/
|
||||
char *
|
||||
URLEscape(mp, url, s2p)
|
||||
MemPool mp;
|
||||
char *url;
|
||||
bool s2p;
|
||||
{
|
||||
char *cp;
|
||||
char *n, *s;
|
||||
static char *hex = "0123456789ABCDEF";
|
||||
|
||||
/*
|
||||
* use a bit of memory so i don't have to mess around here
|
||||
*/
|
||||
s = n = (char *)MPGet(mp, strlen(url) * 3 + 2);
|
||||
|
||||
for (cp = url; *cp; cp++, n++)
|
||||
{
|
||||
if (*cp == ' ' && s2p)
|
||||
{
|
||||
*n = '+';
|
||||
}
|
||||
else if (*cp == '+' && s2p)
|
||||
{
|
||||
*n = '%';
|
||||
n++;
|
||||
*n = hex[*cp / 16];
|
||||
n++;
|
||||
*n = hex[*cp % 16];
|
||||
}
|
||||
#ifdef ORIGINAL_CODE
|
||||
/*
|
||||
else if (isalnum(*cp) || strchr("$-_.'(),+!*", *cp))
|
||||
*/
|
||||
else if (strchr("<>\"#{}|\\^~[]`",*cp))
|
||||
#else
|
||||
/* My CGI scripts and the Apache daemon say it's closer the first way - djhjr */
|
||||
else if (isalnum(*cp) || strchr("$-_.'(),+!*", *cp))
|
||||
#endif
|
||||
{
|
||||
*n = *cp;
|
||||
}
|
||||
else
|
||||
{
|
||||
*n = '%';
|
||||
n++;
|
||||
*n = hex[*cp / 16];
|
||||
n++;
|
||||
*n = hex[*cp % 16];
|
||||
}
|
||||
}
|
||||
|
||||
*n = '\0';
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* UnescapeURL
|
||||
*
|
||||
* Converts the escape codes (%xx) into actual characters. NOT complete.
|
||||
* Could do everthing in place I guess.
|
||||
*/
|
||||
char *
|
||||
URLUnescape(mp, url)
|
||||
MemPool mp;
|
||||
char *url;
|
||||
{
|
||||
char *cp, *n, *s;
|
||||
char hex[3];
|
||||
|
||||
s = n = (char *)MPGet(mp, strlen(url) + 2);
|
||||
for (cp = url; *cp; cp++, n++)
|
||||
{
|
||||
if (*cp == '%')
|
||||
{
|
||||
cp++;
|
||||
if (*cp == '%')
|
||||
{
|
||||
*n = *cp;
|
||||
}
|
||||
else
|
||||
{
|
||||
hex[0] = *cp;
|
||||
cp++;
|
||||
hex[1] = *cp;
|
||||
hex[2] = '\0';
|
||||
*n = (char)strtol(hex, NULL, 16);
|
||||
}
|
||||
}
|
||||
else if (*cp == '+') *n = ' ';
|
||||
else
|
||||
{
|
||||
*n = *cp;
|
||||
}
|
||||
}
|
||||
|
||||
*n = '\0';
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* URLMakeString
|
||||
*/
|
||||
char *
|
||||
URLMakeString(mp, up, addfrag)
|
||||
MemPool mp;
|
||||
URLParts *up;
|
||||
bool addfrag;
|
||||
{
|
||||
size_t len;
|
||||
char *u;
|
||||
char *delim;
|
||||
char *delim2;
|
||||
char *filename;
|
||||
char *hostname;
|
||||
char *scheme;
|
||||
char *delim3;
|
||||
char *fragment;
|
||||
|
||||
if (NullString(up->scheme)) scheme = "file";
|
||||
else scheme = up->scheme;
|
||||
|
||||
if (NullString(up->hostname))
|
||||
{
|
||||
delim = "";
|
||||
hostname = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
delim = "//";
|
||||
hostname = up->hostname;
|
||||
}
|
||||
|
||||
if (NullString(up->filename)) filename = "/";
|
||||
else filename = up->filename;
|
||||
|
||||
delim2 = "";
|
||||
|
||||
if (up->fragment != NULL && addfrag)
|
||||
{
|
||||
fragment = up->fragment;
|
||||
delim3 = "#";
|
||||
}
|
||||
else
|
||||
{
|
||||
fragment = "";
|
||||
delim3 = "";
|
||||
}
|
||||
|
||||
len = strlen(scheme) + strlen(hostname) + strlen(filename) +
|
||||
strlen(delim) + strlen(fragment) + 11;
|
||||
u = (char *)MPGet(mp, len + 1);
|
||||
if (up->port == 0)
|
||||
{
|
||||
snprintf (u, len, "%s:%s%s%s%s%s%s", scheme, delim, hostname, delim2,
|
||||
filename, delim3, fragment);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf (u, len, "%s:%s%s:%d%s%s%s%s", scheme, delim, hostname, up->port,
|
||||
delim2, filename, delim3, fragment);
|
||||
}
|
||||
|
||||
return(u);
|
||||
}
|
||||
|
||||
/*
|
||||
* URLCreate
|
||||
*
|
||||
* Allocate URLParts and initialize to NULLs
|
||||
*/
|
||||
static URLParts *
|
||||
URLCreate(mp)
|
||||
MemPool mp;
|
||||
{
|
||||
URLParts *up;
|
||||
|
||||
up = (URLParts *)MPCGet(mp, sizeof(URLParts));
|
||||
|
||||
return(up);
|
||||
}
|
||||
|
||||
/*
|
||||
* resolve_filename
|
||||
*
|
||||
* I'm not sure this is much better than the original.
|
||||
*/
|
||||
static char *
|
||||
resolve_filename(mp, c, p)
|
||||
MemPool mp;
|
||||
char *c, *p;
|
||||
{
|
||||
char *r;
|
||||
char *t;
|
||||
MemPool tmp;
|
||||
|
||||
/*
|
||||
* If current is an absolute path then use it otherwise
|
||||
* build an absolute path using the parent as a reference.
|
||||
*/
|
||||
if (c == NULL || c[0] == '/') r = MPStrDup(mp, c);
|
||||
else if (c[0] == '~')
|
||||
{
|
||||
r = MPGet(mp, strlen(c) + 2);
|
||||
r[0] = '/';
|
||||
strcpy(r + 1, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = MPCreate();
|
||||
if (p == NULL || p[0] != '/') p = "/";
|
||||
else p = whack_filename(tmp, p);
|
||||
t = compress_path(tmp, c, p);
|
||||
if (t == NULL) r = MPStrDup(mp, "/");
|
||||
else r = MPStrDup(mp, t);
|
||||
MPDestroy(tmp);
|
||||
}
|
||||
|
||||
return(r);
|
||||
}
|
||||
|
||||
/*
|
||||
* URLResolve
|
||||
*
|
||||
* c - current
|
||||
* p - parent
|
||||
* r - result
|
||||
*/
|
||||
URLParts *
|
||||
URLResolve(mp, c, p)
|
||||
MemPool mp;
|
||||
URLParts *c, *p;
|
||||
{
|
||||
URLParts *r;
|
||||
|
||||
/*
|
||||
* If the protocols are different then just return the original with
|
||||
* some empty fields filled in.
|
||||
*/
|
||||
if (c->scheme != NULL && p->scheme != NULL &&
|
||||
strcasecmp(c->scheme, p->scheme) != 0)
|
||||
{
|
||||
r = URLDup(mp, c);
|
||||
if (r->hostname == NULL) r->hostname = MPStrDup(mp, "localhost");
|
||||
r->filename = resolve_filename(mp, c->filename, p->filename);
|
||||
return(r);
|
||||
}
|
||||
|
||||
r = URLCreate(mp);
|
||||
|
||||
/*
|
||||
* If current has a protocol then use it, otherwise
|
||||
* use the parent's protocol. If the parent doesn't have a protocol for
|
||||
* some reason then use "file".
|
||||
*/
|
||||
if (c->scheme == NULL)
|
||||
{
|
||||
if (p->scheme != NULL) r->scheme = MPStrDup(mp, p->scheme);
|
||||
else r->scheme = MPStrDup(mp, "file");
|
||||
}
|
||||
else r->scheme = MPStrDup(mp, c->scheme);
|
||||
|
||||
/*
|
||||
* If current has a hostname then use it, otherwise
|
||||
* use the parent's hostname. If neither has a hostname then
|
||||
* fallback to "localhost".
|
||||
*/
|
||||
if (c->hostname == NULL)
|
||||
{
|
||||
if (p->hostname != NULL)
|
||||
{
|
||||
r->hostname = MPStrDup(mp, p->hostname);
|
||||
r->port = p->port;
|
||||
}
|
||||
else
|
||||
{
|
||||
r->hostname = MPStrDup(mp, "localhost"); /* fallback */
|
||||
r->port = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
r->hostname = MPStrDup(mp, c->hostname);
|
||||
r->port = c->port;
|
||||
}
|
||||
|
||||
r->filename = resolve_filename(mp, c->filename, p->filename);
|
||||
|
||||
/*
|
||||
* Copy misc. fields.
|
||||
*/
|
||||
r->username = MPStrDup(mp, c->username);
|
||||
r->password = MPStrDup(mp, c->password);
|
||||
r->fragment = MPStrDup(mp, c->fragment);
|
||||
|
||||
return(r);
|
||||
}
|
||||
|
||||
URLParts *
|
||||
URLDup(mp, up)
|
||||
MemPool mp;
|
||||
URLParts *up;
|
||||
{
|
||||
URLParts *dp;
|
||||
|
||||
dp = URLCreate(mp);
|
||||
dp->scheme = MPStrDup(mp, up->scheme);
|
||||
dp->hostname = MPStrDup(mp, up->hostname);
|
||||
dp->port = up->port;
|
||||
|
||||
dp->filename = up->filename != NULL ?
|
||||
MPStrDup(mp, up->filename):MPStrDup(mp, "/");
|
||||
|
||||
dp->fragment = MPStrDup(mp, up->fragment);
|
||||
|
||||
dp->username = MPStrDup(mp, up->username);
|
||||
dp->password = MPStrDup(mp, up->password);
|
||||
|
||||
return(dp);
|
||||
}
|
||||
|
||||
/*
|
||||
* URLParse
|
||||
*
|
||||
* Turns a URL into a URLParts structure
|
||||
*
|
||||
* The good stuff was written by Rob May <robert.may@rd.eng.bbc.co.uk>
|
||||
* and heavily mangled/modified by john to suite his own weird style.
|
||||
*/
|
||||
URLParts *
|
||||
URLParse(mp, url)
|
||||
MemPool mp;
|
||||
char *url;
|
||||
{
|
||||
URLParts *up;
|
||||
char *start;
|
||||
char *colon, *slash, *fslash;
|
||||
char *pound; /* link pound (#) sign */
|
||||
char *at; /* username/password @ */
|
||||
char *ucolon; /* username colon */
|
||||
char *pcolon; /* port number colon */
|
||||
|
||||
up = URLCreate(mp);
|
||||
|
||||
/* skip leading white-space (if any)*/
|
||||
for (start = url; isspace8(*start); start++)
|
||||
;
|
||||
|
||||
/*
|
||||
* Look for indication of a scheme.
|
||||
*/
|
||||
colon = strchr(start, ':');
|
||||
|
||||
/*
|
||||
* Search for characters that indicate the beginning of the
|
||||
* path/params/query/fragment part.
|
||||
*/
|
||||
slash = strchr(start, '/');
|
||||
if (slash == NULL) slash = strchr(start, ';');
|
||||
if (slash == NULL) slash = strchr(start, '?');
|
||||
if (slash == NULL) slash = strchr(start, '#');
|
||||
|
||||
/*
|
||||
* Check to see if there is a scheme. There is a scheme only if
|
||||
* all other separators appear after the colon.
|
||||
*/
|
||||
if (colon != NULL && (slash == NULL || colon < slash))
|
||||
{
|
||||
up->scheme = MPGet(mp, colon - start + 1);
|
||||
strncpy(up->scheme, start, colon - start);
|
||||
up->scheme[colon - start] = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is a slash then sort out the hostname and filename.
|
||||
* If there is no slash then there is no hostname but there is a
|
||||
* filename.
|
||||
*/
|
||||
if (slash != NULL)
|
||||
{
|
||||
/*
|
||||
* Check for leading //. If its there then there is a host string.
|
||||
*/
|
||||
if ((*(slash + 1) == '/') && ((colon == NULL && slash == start) ||
|
||||
(colon != NULL && slash == colon + 1)))
|
||||
{
|
||||
/*
|
||||
* Check for filename at end of host string.
|
||||
*/
|
||||
slash += 2;
|
||||
if ((fslash = strchr(slash, '/')) != NULL)
|
||||
{
|
||||
up->hostname = MPGet(mp, fslash - slash + 1);
|
||||
strncpy(up->hostname, slash, fslash - slash);
|
||||
up->hostname[fslash - slash] = '\0';
|
||||
up->filename = MPStrDup(mp, fslash);
|
||||
}
|
||||
else
|
||||
{ /* there is no filename */
|
||||
up->hostname = MPStrDup(mp, slash);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* the rest is a filename because there is no // or it appears
|
||||
* after other characters
|
||||
*/
|
||||
if (colon != NULL && colon < slash)
|
||||
{
|
||||
up->filename = MPStrDup(mp, colon + 1);
|
||||
}
|
||||
else up->filename = MPStrDup(mp, start);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* No slashes at all so the rest must be a filename.
|
||||
*/
|
||||
if (colon == NULL) up->filename = MPStrDup(mp, start);
|
||||
else up->filename = MPStrDup(mp, colon + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is a host string then divide it into
|
||||
* username:password@hostname:port as needed.
|
||||
*/
|
||||
if (up->hostname != NULL)
|
||||
{
|
||||
/*
|
||||
* Look for username:password.
|
||||
*/
|
||||
if ((at = strchr(up->hostname, '@')) != NULL)
|
||||
{
|
||||
char *mumble;
|
||||
|
||||
up->username = MPGet(mp, at - up->hostname + 1);
|
||||
strncpy(up->username, up->hostname, at - up->hostname);
|
||||
up->username[at - up->hostname] = '\0';
|
||||
|
||||
mumble = MPStrDup(mp, at + 1);
|
||||
up->hostname = mumble;
|
||||
|
||||
if ((ucolon = strchr(up->username, ':')) != NULL)
|
||||
{
|
||||
up->password = MPStrDup(mp, ucolon + 1);
|
||||
*ucolon = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Grab the port.
|
||||
*/
|
||||
if ((pcolon = strchr(up->hostname, ':')) != NULL)
|
||||
{
|
||||
up->port = atoi(pcolon + 1);
|
||||
*pcolon = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the filename for a '#foo' string.
|
||||
*/
|
||||
if (up->filename != NULL)
|
||||
{
|
||||
if ((pound = strchr(up->filename, '#')) != NULL)
|
||||
{
|
||||
*pound = '\0';
|
||||
up->fragment = MPStrDup(mp, pound + 1);
|
||||
|
||||
if (strlen(up->filename) == 0) up->filename = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return(up);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* URLIsAbsolute
|
||||
*/
|
||||
bool
|
||||
URLIsAbsolute(up)
|
||||
URLParts *up;
|
||||
{
|
||||
if (up->scheme == NULL) return(false);
|
||||
return(true);
|
||||
}
|
||||
|
||||
/*
|
||||
* URLBaseFilename
|
||||
*/
|
||||
char *
|
||||
URLBaseFilename(mp, up)
|
||||
MemPool mp;
|
||||
URLParts *up;
|
||||
{
|
||||
char *cp;
|
||||
|
||||
if (up->filename == NULL) return(NULL);
|
||||
|
||||
for (cp = up->filename + strlen(up->filename) - 1;
|
||||
cp >= up->filename; cp--)
|
||||
{
|
||||
if (*cp == '/') break;
|
||||
}
|
||||
cp++;
|
||||
if (*cp == '\0') return(NULL);
|
||||
|
||||
return(MPStrDup(mp, cp));
|
||||
}
|
||||
|
||||
/*
|
||||
* URLGetScheme
|
||||
*/
|
||||
char *
|
||||
URLGetScheme(mp, url)
|
||||
MemPool mp;
|
||||
char *url;
|
||||
{
|
||||
char *cp, *dp;
|
||||
char *r;
|
||||
|
||||
for (cp = url; *cp != '\0'; cp++)
|
||||
{
|
||||
for (dp = URLDELIMS; *dp != '\0'; dp++)
|
||||
{
|
||||
if (*cp == *dp)
|
||||
{
|
||||
if (*cp == ':')
|
||||
{
|
||||
r = (char *)MPCGet(mp, cp - url + 1);
|
||||
strncpy(r, url, cp - url);
|
||||
return(r);
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
}
|
61
common/url.h
Normal file
61
common/url.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* url.h
|
||||
*
|
||||
* Copyright (c) 1995-1997, John Kilburg <john@cs.unlv.edu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifndef __URL_H__
|
||||
#define __URL_H__ 1
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
* <scheme>://<net_loc>/<path>;<params>?<query>#<fragment>
|
||||
*
|
||||
* net_loc = username:password@hostname:port
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
char *scheme;
|
||||
char *username;
|
||||
char *password;
|
||||
char *hostname;
|
||||
int port;
|
||||
char *filename;
|
||||
char *params;
|
||||
char *query;
|
||||
char *fragment;
|
||||
} URLParts;
|
||||
|
||||
int URLcmp _ArgProto((URLParts *, URLParts *));
|
||||
char *URLMakeString _ArgProto((MemPool, URLParts *, bool));
|
||||
URLParts *URLResolve _ArgProto((MemPool, URLParts *, URLParts *));
|
||||
URLParts *URLParse _ArgProto((MemPool, char *));
|
||||
char *URLUnescape _ArgProto((MemPool, char *));
|
||||
char *URLEscape _ArgProto((MemPool, char *, bool));
|
||||
URLParts *URLDup _ArgProto((MemPool, URLParts *));
|
||||
bool URLIsAbsolute _ArgProto((URLParts *));
|
||||
char *URLBaseFilename _ArgProto((MemPool, URLParts *));
|
||||
char *URLGetScheme _ArgProto((MemPool, char *));
|
||||
|
||||
/*
|
||||
* url_translate.c
|
||||
*/
|
||||
int URLReadTranslations _ArgProto((GList, char *));
|
||||
char *URLTranslate _ArgProto((MemPool, GList, char *));
|
||||
|
||||
#endif
|
||||
|
196
common/util.c
Normal file
196
common/util.c
Normal file
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
* util.c
|
||||
*
|
||||
* Copyright (C) 1993-1997, John Kilburg <john@cs.unlv.edu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <pwd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
* FixPath
|
||||
*
|
||||
* The only thing this does right now is to handle the '~' stuff.
|
||||
*/
|
||||
char *
|
||||
FixPath(mp, filename)
|
||||
MemPool mp;
|
||||
char *filename;
|
||||
{
|
||||
struct passwd *p;
|
||||
char *cp, *cp2;
|
||||
char username[BUFSIZ];
|
||||
char *fname;
|
||||
char *home;
|
||||
char *newfilename;
|
||||
|
||||
if (filename[0] == '~') fname = filename;
|
||||
else if (filename[0] == '/' && filename[1] == '~') fname = filename + 1;
|
||||
else fname = NULL;
|
||||
|
||||
if (fname != NULL)
|
||||
{
|
||||
if (fname[1] == '/')
|
||||
{
|
||||
if ((home = getenv("HOME")) == NULL) return(NULL);
|
||||
cp = fname + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (cp = fname + 1, cp2 = username; *cp && *cp != '/'; cp++, cp2++)
|
||||
{
|
||||
*cp2 = *cp;
|
||||
}
|
||||
*cp2 = '\0';
|
||||
|
||||
p = getpwnam(username);
|
||||
if (p == NULL) return(NULL);
|
||||
home = p->pw_dir;
|
||||
}
|
||||
|
||||
newfilename = (char *)MPGet(mp, strlen(home) + strlen(cp) + 1);
|
||||
strcpy(newfilename, home);
|
||||
strcat(newfilename, cp);
|
||||
}
|
||||
else
|
||||
{
|
||||
newfilename = MPStrDup(mp, filename);
|
||||
}
|
||||
|
||||
return(newfilename);
|
||||
}
|
||||
|
||||
/*
|
||||
* mystrtok
|
||||
*
|
||||
*/
|
||||
char *
|
||||
mystrtok(s, c, cdr)
|
||||
char *s;
|
||||
size_t c;
|
||||
char **cdr;
|
||||
{
|
||||
char *cp, *cp2;
|
||||
static char str[BUFSIZ];
|
||||
|
||||
if (s == NULL) return(NULL);
|
||||
|
||||
for (cp = s, cp2 = str; ; cp++)
|
||||
{
|
||||
if (*cp == '\0') break;
|
||||
else if (*cp == c)
|
||||
{
|
||||
for (cp++; *cp == c; )
|
||||
{
|
||||
cp++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else *cp2++ = *cp;
|
||||
if (cp2 == str + BUFSIZ - 1) break;
|
||||
}
|
||||
|
||||
*cp2 = '\0';
|
||||
|
||||
if (*cp == '\0') *cdr = NULL;
|
||||
else *cdr = cp;
|
||||
|
||||
return(str);
|
||||
}
|
||||
|
||||
/*
|
||||
* GetBaseFilename
|
||||
*/
|
||||
char *
|
||||
GetBaseFilename(path)
|
||||
char *path;
|
||||
{
|
||||
char *cp;
|
||||
|
||||
if (path == NULL) return(NULL);
|
||||
for (cp = path + strlen(path) - 1; cp >= path; cp--)
|
||||
{
|
||||
if (*cp == '/') break;
|
||||
}
|
||||
cp++;
|
||||
if (*cp == '\0') return(NULL);
|
||||
return(cp);
|
||||
}
|
||||
|
||||
/*
|
||||
* xmyassert
|
||||
*/
|
||||
void
|
||||
xmyassert(isok, msg, file, line)
|
||||
bool isok;
|
||||
char *msg;
|
||||
char *file;
|
||||
int line;
|
||||
{
|
||||
if (!isok)
|
||||
{
|
||||
fprintf (stderr, "%s: %d\n", file, line);
|
||||
fprintf (stderr, "%s\n", msg);
|
||||
fflush(stderr);
|
||||
abort();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef P_tmpdir
|
||||
#define P_tmpdir "/tmp"
|
||||
#endif
|
||||
|
||||
#ifndef L_tmpnam
|
||||
#define L_tmpnam 256
|
||||
#endif
|
||||
|
||||
/*
|
||||
* mytmpnam
|
||||
*/
|
||||
char *
|
||||
mytmpnam(mp)
|
||||
MemPool mp;
|
||||
{
|
||||
char *n;
|
||||
|
||||
n = (char *)MPGet(mp, L_tmpnam + 1);
|
||||
snprintf (n, L_tmpnam, "%s/%d%ld",
|
||||
P_tmpdir, getpid(), (long)time(NULL));
|
||||
return(n);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue