/** This proc adds a GopherObj to a gopherdir.
It will attempt to merge two items if need be..
**/
void
GDaddGSmerge(gd, gs)
GopherDirObj *gd;
GopherObj *gs;
{
int num;
#ifdef VMS_SERVER
if (GSgetNum(gs) == -99) {
return; /** Historical Hidden item for VMS Server **/
}
#endif
if (GSgetType(gs) != 'X')
DApush(gd->Gophers, gs);
}
/*
* Really weird!!! We need this for qsort, don't know why we can't use
* GScmp...
*/
#define sgn(a) ((a) == 0 ? 0 : (a) < 0 ? -1 : 1)
int
GSqsortcmp(gs1, gs2)
GopherObj **gs1, **gs2;
{
if (GSgetTitle(*gs1) == NULL)
return(1);
if (GSgetTitle(*gs2) == NULL)
return(-1);
/** No numbering set on either entry, or both numbered
entries have the same number **/
if (GSgetNum(*gs1) == GSgetNum(*gs2))
#ifdef NeXT /* Next has a goofy strcoll */
#define strcoll(a,b) strcmp(a,b)
#endif
return(strcoll(GSgetTitle(*gs1), GSgetTitle(*gs2)));
#ifdef NeXT
#undef strcoll
#endif
/** If the signs are equal, compare the numbers conventionally **/
/** N.B. If the signs ARE equal, they cannot be 0 (otherwise we would **/
/** have had the above case, because only the sign of 0 is 0) */
if (sgn(GSgetNum(*gs1)) == sgn(GSgetNum(*gs2)))
return(GSgetNum(*gs1) < GSgetNum(*gs2) ? -1 : 1);
/** The signs must be different, so we can use a conventional test, **/
/** remembering only to say positive numbers go before negative ones **/
return(GSgetNum(*gs1) > GSgetNum(*gs2) ? -1 : 1);
}
/*
* Sorts a gopher directory
*/
void
GDsort(gd)
GopherDirObj *gd;
{
DAsort(gd->Gophers, GSqsortcmp);
}
void
GDtoNet(gd, sockfd, fmt, ticket, prefcn)
GopherDirObj *gd;
int sockfd;
GSformat fmt;
char *ticket;
int (*prefcn)();
{
int i;
GopherObj *gs;
Debugmsg("GDplustoNet\n");
if (fmt == GSFORM_HTML) {
writestring(sockfd, "<DL COMPACT>\r\n");
}
for (i=0; i< GDgetNumitems(gd); i++) {
gs = GDgetEntry(gd, i);
if (fmt == GSFORM_HTML)
writestring(sockfd, "<DT>");
if (prefcn)
prefcn(gs, sockfd);
GStoNet(GDgetEntry(gd, i), sockfd, fmt, ticket);
}
if (fmt == GSFORM_HTML) {
writestring(sockfd, "</DL>\r\n");
}
}
void
GDplustoNet(gd, sockfd, filter, ticket)
GopherDirObj *gd;
int sockfd;
char **filter;
char *ticket;
{
int i;
/*
* Gopher+ counterpart to GDfromNet()
* returns number of items found
*/
int
GDplusfromNet(gd, fd, eachitem)
GopherDirObj *gd;
int fd;
int (*eachitem)();
{
static GopherObj *TempGopher = NULL;
int j, result;
char inputline[256];
Debugmsg("GDplusfromNet:: start\r\n");
if (TempGopher == NULL)
TempGopher = GSnew();
/** State: _begin_ **/
result = readrecvbuf(fd, inputline, 1);
if (result <=0)
return(0);
else if (*inputline == '.') {
/*** Read off the rest of the junk... ***/
readline(fd,inputline,sizeof(inputline));
return(0);
}
else if (*inputline != '+')
return(0);
Debugmsg("after readrecvbuf");
/** State _FirstPlus_ **/
result = readtoken(fd, inputline, sizeof(inputline), ':');
if (result <=0)
return(result);
Debugmsg("after readtoken");
if (strcmp(inputline, "INFO")!=0) {
return(0);
}
Debugmsg("after INFO");
/** Read the space **/
readrecvbuf(fd, inputline, 1);
/*** State _FirstINFO_ ***/
for (j=0; ; j++) {
Debugmsg("for start");
GSinit(TempGopher);
result = GSplusfromNet(TempGopher, fd);
switch (result) {
case MORECOMING:
GDaddGS(gd, TempGopher);
if (eachitem != NULL)
eachitem();
break;
case FOUNDEOF:
GDaddGS(gd, TempGopher);
return(j+1);
case HARDERROR: /** Give up reading - bad read or protocol error **/
return(j);
case SOFTERROR: /** This one was bad, but we can try for next **/
j= j-1;
if (j<0) j=0;
break;
}
} /* for */
/** Never get here **/
}
/*
* Fill up a GopherDirObj with GopherObjs, given a gopher directory coming
* from sockfd.
*
* For each GopherObj retrieved, eachitem() is executed.
*
*/
void
GDfromNet(gd, sockfd, eachitem)
GopherDirObj *gd;
int sockfd;
int (*eachitem)();
{
static GopherObj *TempGopher;
int i;
char *cp1, *cp2;
Debugmsg("GDfromNet...");
if (TempGopher == NULL)
TempGopher = GSnew();
for (; ;) {
GSinit(TempGopher);
i = GSfromNet(TempGopher, sockfd);
/* In gopher+1.2b2 this routine clears up if GSfromNet returns
a failure, better to clear up in GSfromNet so that the
system returns in a known state - note that other callers of
GSfromNet didn't clean up and crashed! */
/*** Search for a specific gopher item ***/
int
GDSearch(gd, text)
GopherDirObj *gd;
char *text; /* Note first char is G0 type and is ignored*/
{
int i;
GopherObj *gs;
int cplen;
char *cp;