GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 1 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 1 /******************************************************************** 2 * wilkinson 3 * 3.75VMS 4 * 1995/05/25 15:30 5 * gopher_root1:[gopher.g2.vms2_13.object]GSgopherobj.c,v 6 * Exp 7 * 8 * Paul Lindner, University of Minnesota CIS. 9 * 10 * Copyright 1991, 1992 by the Regents of the University of Minnesota 11 * see the file "Copyright" in the distribution for conditions of use. 12 ********************************************************************* 13 * MODULE: GSgopherobj.c 14 * Implement gopher directory functions. 15 ********************************************************************* 16 * Revision History: 17 * GSgopherobj.c,v 18 * Revision 3.75VMS 1995/05/25 15:30 wilkinson 19 * Consolodate VMS/Unix source code for server as well as client 20 * - add create/modify date display flag (default is modify) 21 * 22 * Revision 3.75 1995/02/22 05:30:25 lindner 23 * reintroduce gsinit to gsnew 24 * 25 * Revision 3.74 1995/02/17 18:29:37 lindner 26 * Abstract display support 27 * 28 * Revision 3.73 1995/02/16 22:32:44 lindner 29 * HTML icon support 30 * 31 * Revision 3.72 1995/02/07 07:12:55 lindner 32 * oops! 33 * 34 * Revision 3.71 1995/02/07 07:06:58 lindner 35 * performance fixes 36 * 37 * Revision 3.70 1995/02/06 22:13:52 lindner 38 * Performance fixes 39 * 40 * Revision 3.69 1995/02/02 17:14:46 lindner 41 * Fix for memory leaks and accesses 42 * 43 * Revision 3.68 1995/02/01 22:08:02 lindner 44 * Put back GSaddmerge 45 * 46 * Revision 3.67 1995/02/01 21:44:41 lindner 47 * Remove GSmerge fcns, Add message/rfc822 and application/gopher to GSisText 48 * 49 * Revision 3.66 1994/12/15 17:30:49 lindner 50 * Allow multi-line abstracts in link files, Fix for ftp URL generation 51 * 52 * Revision 3.65 1994/12/05 22:39:55 lindner 53 * Fix Name and Path settings in GSfromURL 54 * 55 * Revision 3.64 1994/11/17 06:33:58 lindner GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 2 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 56 * Fixes for VMS internationalization 57 * 58 * Revision 3.63 1994/11/13 06:30:48 lindner 59 * Better GSfromURL 60 * 61 * Revision 3.62 1994/10/24 22:15:53 lindner 62 * Add PDF type 63 * 64 * Revision 3.61 1994/10/18 21:37:03 lindner 65 * Make sure buf is set 66 * 67 * Revision 3.60 1994/10/13 05:27:18 lindner 68 * Compiler complaint fixes 69 * 70 * Revision 3.59 1994/09/29 19:26:45 lindner 71 * Fix for debug messages and NULL values 72 * 73 * Revision 3.58 1994/08/19 16:13:09 lindner 74 * mktime() etc, fixes from Alan Coopersmith 75 * 76 * Revision 3.57 1994/08/03 20:03:44 lindner 77 * Fix for adding ask stuff 78 * 79 * Revision 3.56 1994/07/31 04:57:20 lindner 80 * Fix for .names messup... 81 * 82 * Revision 3.55 1994/07/21 22:29:18 lindner 83 * misc hacks 84 * 85 * Revision 3.54 1994/07/06 19:21:34 lindner 86 * use strftime to get localized date and time 87 * 88 * Revision 3.53 1994/06/29 06:51:21 lindner 89 * ifdef GINTERNATIONAL, use strftime to localize the date string 90 * returned by GSgetModDate() 91 * 92 * in GSplusfromNet(), if there's anything in the ADMIN block other than 93 * Admin, ModDate, or TTL entries, save it for the client's showinfo() 94 * Server Information 95 * 96 * Move GSfromURL() return code definitions to header so other files can 97 * call it 98 * 99 * Fix GStoNetURL() & HTML display of directories 100 * 101 * Round sizes in GSaddView 102 * 103 * Make GSfromURL() lie and say all http: is HTML so the client 104 * passes it off to a http-speaking program anyway (assuming 105 * all HTML viewers speak http, that is) (Coopersmith) 106 * 107 * Revision 3.52 1994/06/29 05:45:56 lindner 108 * Mods to pump tickets to the net 109 * 110 * Revision 3.51 1994/05/25 20:57:46 lindner 111 * Remove unused var 112 * GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 3 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 113 * Revision 3.50 1994/05/06 02:29:46 lindner 114 * Fix from Robert Beckett for binhex files 115 * 116 * Revision 3.49 1994/04/25 03:36:58 lindner 117 * Modifications for Debug() and mismatched NULL arguments, added Debugmsg 118 * 119 * Revision 3.48 1994/04/25 02:26:30 lindner 120 * Fix for url problems 121 * 122 * Revision 3.47 1994/04/25 02:16:31 lindner 123 * Fix for |= mistype 124 * 125 * Revision 3.46 1994/04/22 06:41:35 lindner 126 * More pacbell hacks for Domain= 127 * 128 * Revision 3.45 1994/04/22 03:26:15 lindner 129 * pacbell hack 130 * 131 * Revision 3.44 1994/04/19 14:32:29 lindner 132 * Change GD and GSfromLink routines to use FIO 133 * 134 * Revision 3.43 1994/04/13 19:16:17 lindner 135 * Fix for ASK block bug 136 * 137 * Revision 3.42 1994/04/08 20:05:52 lindner 138 * gcc -Wall fixes 139 * 140 * Revision 3.41 1994/04/07 17:27:09 lindner 141 * Fix for pyramids 142 * 143 * Revision 3.40 1994/04/01 04:38:06 lindner 144 * Fix for conditional macros 145 * 146 * Revision 3.39 1994/03/31 22:48:55 lindner 147 * fix for Hgopher and ask requests 148 * 149 * Revision 3.38 1994/03/31 21:05:11 lindner 150 * More debug code, and fix for Socket return values 151 * 152 * Revision 3.37 1994/03/17 04:37:41 lindner 153 * Fix for spinning clients 154 * 155 * Revision 3.36 1994/03/08 15:56:17 lindner 156 * gcc -Wall fixes 157 * 158 * Revision 3.35 1994/03/04 17:59:16 lindner 159 * More URL fixes from A.C. 160 * 161 * Revision 3.34 1994/02/20 16:27:44 lindner 162 * Remove dead code for GDtoNetHTML 163 * 164 * Revision 3.33 1994/01/25 06:51:21 lindner 165 * Many additions for URL/HTML support, removed insidious dot at end of host.. 166 * 167 * Revision 3.32 1994/01/10 03:28:12 lindner 168 * Allow bangs in Domain= lines, to negate classes of hosts 169 * GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 4 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 170 * Revision 3.31 1994/01/06 06:10:53 lindner 171 * fix for cvs entries 172 * 173 * 174 * Revision 3.30 1994/01/06 05:43:46 lindner 175 * Fix for type=1 and ask blocks. 176 * 177 * Revision 3.29 1993/12/27 16:25:39 lindner 178 * Add fix for appending a period to domain names 179 * 180 * Revision 3.28 1993/11/29 01:07:23 lindner 181 * In GSfromLink(), disable handling of "Domain_pat:" for VMS to keep the 182 * compiler from complaining about the lack of re_comp() and re_exec(). 183 * "Domain_pat:" handling isn't needed in the client anyway. (Wolfe) 184 * 185 * Add "AddInfo" argument to GStoLink(). This option decides whether to 186 * add the Admin and ModDate fields to the basic information about the 187 * gopher object. Bookmarks should not include them, but requested 188 * technical information ('=' and '^') should. This change requires 189 * changes to gopher/gopher.c and object/GDgopherdir.c; see below. 190 * (Macrides) 191 * 192 * Revision 3.27 1993/11/05 07:24:46 lindner 193 * Allow Type=1? etc.. in .link files 194 * 195 * Revision 3.26 1993/11/04 04:50:50 lindner 196 * Add quotes around HREFs 197 * 198 * Revision 3.25 1993/11/04 02:10:47 lindner 199 * Added Domain_pat= line to check for a regexp domains 200 * 201 * Revision 3.24 1993/11/03 15:35:40 lindner 202 * Fix problems with bookmarks of gopher+ items 203 * 204 * Revision 3.23 1993/11/02 06:15:24 lindner 205 * HTML additions 206 * 207 * Revision 3.22 1993/10/26 17:49:50 lindner 208 * Fix for NULL view in GSisText() 209 * 210 * Revision 3.21 1993/10/22 20:02:33 lindner 211 * Add Movie (;) and Info (i) type support 212 * 213 * Revision 3.20 1993/09/18 04:44:41 lindner 214 * Additions to fix caching of Multiple view items 215 * 216 * Revision 3.19 1993/09/11 06:41:08 lindner 217 * Fix for picky compilers 218 * 219 * Revision 3.18 1993/09/11 06:32:52 lindner 220 * URL support 221 * 222 * Revision 3.17 1993/09/01 21:51:59 lindner 223 * Remove GSnewSet, better initialization in GSnew() 224 * 225 * Revision 3.16 1993/08/19 20:24:11 lindner 226 * Mitra's Debug patch GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 5 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 227 * 228 * Revision 3.15 1993/07/29 20:02:55 lindner 229 * Removed dead variables 230 * 231 * Revision 3.14 1993/07/27 20:17:25 lindner 232 * Fix improper bracketed debug output 233 * 234 * Revision 3.13 1993/07/27 05:30:23 lindner 235 * Mondo Debug overhaul from Mitra 236 * 237 * Revision 3.12 1993/07/27 00:30:09 lindner 238 * plus patch from Mitra 239 * 240 * Revision 3.11 1993/07/23 04:50:17 lindner 241 * Mods to allow abstract/admin setting in .names files 242 * 243 * Revision 3.10 1993/07/21 03:31:09 lindner 244 * Askdata can be stored locally, plus GSfromLink doesn't core dump with 245 * mangled items 246 * 247 * Revision 3.9 1993/07/14 20:37:11 lindner 248 * Negative numbering patches 249 * 250 * Revision 3.8 1993/07/07 19:30:12 lindner 251 * Split off socket based fcns to Sockets.c 252 * 253 * Revision 3.7 1993/07/06 20:22:40 lindner 254 * Added listener and accept fcns 255 * 256 * Revision 3.6 1993/06/22 06:07:14 lindner 257 * Added Domain= hacks.. 258 * 259 * Revision 3.5 1993/04/15 17:44:52 lindner 260 * Fixed link processing, mods from Mitra 261 * 262 * Revision 3.4 1993/03/26 19:50:46 lindner 263 * Mitra fixes for better/clearer fromNet code 264 * 265 * Revision 3.3 1993/03/24 17:05:33 lindner 266 * Additions for Localfile for each GopherObj 267 * 268 * Revision 3.2 1993/03/18 22:15:50 lindner 269 * filtering, memory leaks fixed, GSmerge problems 270 * 271 *********************************************************************/ 272 273 274 #ifdef VMS_SERVER 275 X #define GSGOPHEROBJ_C 276 X #include "GopherD.h" 277 #endif 278 279 #include "GSgopherobj.h" 3025 3026 #if defined(mips) && defined(ultrix) /*** Gross hack, yuck! ***/ 3027 X #define _SIZE_T 3028 #endif GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 6 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 3029 3030 #include "String.h" 3547 #include "STRstring.h" 3626 #include 3875 #include "compatible.h" 4258 #include 4357 #include "Malloc.h" 5015 #include "Sockets.h" 6936 #include "util.h" 6994 #include "Debug.h" 7309 #include "fileio.h" 8419 #include 8536 8537 #ifdef pyr 8538 X unsigned long errno; 8539 #endif 8540 8541 /* 8542 * Make a new gopherobj... Should reuse destroyed GopherObjs... 8543 */ 8544 8545 GopherObj * 8546 GSnew() 8547 { 8548 1 GopherObj *temp; 8549 1 8550 1 temp = (GopherObj *) malloc(sizeof(GopherObj)); 8551 1 temp->Selstr = STRnew(); 8552 1 temp->Title = STRnew(); 8553 1 temp->Host = STRnew(); 8554 1 temp->Localfile = STRnew(); 8555 1 temp->Localview = STRnew(); 8556 1 temp->gplus = NULL; 8557 1 temp->isask = FALSE; 8558 1 temp->url = NULL; 8559 1 8560 1 #ifdef VMS_SERVER 8561 X temp->date_cr = FALSE; 8562 X temp->Access = NULL; 8563 X temp->Defaccess=ACC_FULL; 8564 X temp->Head = STRnew(); 8565 X temp->Foot = STRnew(); 8566 X temp->RHead = STRnew(); 8567 X temp->RFoot = STRnew(); 8568 1 #endif 8569 1 8570 1 GSinit(temp); 8571 1 8572 1 return(temp); 8573 1 } 8574 8575 8576 /* 8577 * Initialize the gopherplus components of the object 8578 * (Only called for a gplus item) 8579 */ 8580 GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 7 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 8581 void 8582 GSplusnew(gs) 8583 GopherObj *gs; 8584 { 8585 1 if (gs->gplus == NULL) { 8586 2 gs->gplus = (GplusObj *) malloc(sizeof(GplusObj)); 8587 2 } 8588 1 8589 1 gs->gplus->Admin = STRnew(); 8590 1 gs->gplus->ModDate = STRnew(); 8591 1 8592 1 gs->gplus->Views = VIAnew(10); 8593 1 gs->gplus->OtherBlocks = BLAnew(5); 8594 1 gs->gplus->Askdata = NULL; 8595 1 } 8596 8597 8598 /*** Destroy gopher object ***/ 8599 8600 void 8601 GSdestroy(gs) 8602 GopherObj *gs; 8603 { 8604 1 STRdestroy(gs->Selstr); 8605 1 STRdestroy(gs->Title); 8606 1 STRdestroy(gs->Host); 8607 1 if (GSgetLocalFile(gs) != NULL) 8608 1 unlink(GSgetLocalFile(gs)); 8609 1 STRdestroy(gs->Localfile); 8610 1 STRdestroy(gs->Localview); 8611 1 8612 1 GSplusdestroy(gs); 8613 1 if (gs->url != NULL) 8614 1 URLdestroy(gs->url); 8615 1 8616 1 #ifdef VMS_SERVER 8617 X if (gs->Access != NULL) 8618 X SiteArrDestroy(gs->Access); 8619 X STRdestroy(gs->Head); 8620 X STRdestroy(gs->Foot); 8621 X STRdestroy(gs->RHead); 8622 X STRdestroy(gs->RFoot); 8623 1 #endif 8624 1 8625 1 free(gs); 8626 1 } 8627 8628 8629 /*** Destroy Gopher+ attributes ***/ 8630 8631 void 8632 GSplusdestroy(gs) 8633 GopherObj *gs; 8634 { 8635 1 if (gs->gplus != NULL) { 8636 2 STRdestroy(gs->gplus->Admin); 8637 2 STRdestroy(gs->gplus->ModDate); GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 8 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 8638 2 VIAdestroy(gs->gplus->Views); 8639 2 BLAdestroy(gs->gplus->OtherBlocks); 8640 2 8641 2 (void)GSsetAskdata(gs, NULL); 8642 2 8643 2 free(gs->gplus); 8644 2 gs->gplus = NULL; 8645 2 } 8646 1 } 8647 8648 8649 /* 8650 * Clear out all the crud 8651 */ 8652 8653 void 8654 GSinit(gs) 8655 GopherObj *gs; 8656 { 8657 1 GSsetType(gs, '\0'); 8658 1 8659 1 STRinit(gs->Title); 8660 1 STRinit(gs->Selstr); 8661 1 STRinit(gs->Host); 8662 1 if (GSgetLocalFile(gs) != NULL) 8663 1 unlink(GSgetLocalFile(gs)); 8664 1 STRinit(gs->Localfile); 8665 1 STRinit(gs->Localview); 8666 1 8667 1 gs->ttl = -1; 8668 1 gs->iPort = 0; 8669 1 GSsetNum(gs, 0); 8670 1 GSsetWeight(gs, 0); 8671 1 8672 1 GSsetGplus(gs,FALSE); /** Default is no gplus **/ 8673 1 GSsetAsk(gs, FALSE); 8674 1 8675 1 if (gs->url != NULL) 8676 1 URLdestroy(gs->url); 8677 1 gs->url = NULL; 8678 1 GSplusInit(gs); 8679 1 8680 1 #ifdef VMS_SERVER 8681 X gs->date_cr = FALSE; 8682 X if (gs->Access != NULL) 8683 X SiteArrDestroy(gs->Access); 8684 X gs->Access = NULL; 8685 X gs->Defaccess = ACC_FULL; 8686 X STRinit(gs->Head); 8687 X STRinit(gs->Foot); 8688 X STRinit(gs->RHead); 8689 X STRinit(gs->RFoot); 8690 1 #endif 8691 1 8692 1 } 8693 8694 GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 9 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 8695 /* 8696 * Clear out gopher+ crud if it exists 8697 */ 8698 8699 void 8700 GSplusInit(gs) 8701 GopherObj *gs; 8702 { 8703 1 if (gs->gplus != NULL) { 8704 2 STRinit(gs->gplus->Admin); 8705 2 STRinit(gs->gplus->ModDate); 8706 2 VIAinit(gs->gplus->Views); 8707 2 STAinit(gs->gplus->OtherBlocks); 8708 2 8709 2 } 8710 1 } 8711 8712 8713 /* 8714 * Set a URL for the gopherobject.. 8715 */ 8716 8717 void 8718 GSsetURL(gs, url) 8719 GopherObj *gs; 8720 char *url; 8721 { 8722 1 if (gs->url == NULL) 8723 1 gs->url = URLnew(); 8724 1 8725 1 URLset(gs->url, url); 8726 1 } 8727 8728 int 8729 GSgetNumBlocks(gs) 8730 GopherObj *gs; 8731 { 8732 1 if (gs->gplus == NULL) 8733 1 return(-1); 8734 1 8735 1 return(BLAgetTop(gs->gplus->OtherBlocks)); 8736 1 } 8737 8738 Blockobj* 8739 GSgetBlock(gs, bnum) 8740 GopherObj *gs; 8741 int bnum; 8742 { 8743 1 if (gs->gplus == NULL) 8744 1 return(NULL); 8745 1 8746 1 return(BLAgetEntry(gs->gplus->OtherBlocks, bnum)); 8747 1 } 8748 8749 /* 8750 * Return the number of views if item is gopher+ 8751 */ GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 10 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 8752 8753 int 8754 GSgetNumViews(gs) 8755 GopherObj *gs; 8756 { 8757 1 if (gs->gplus == NULL) 8758 1 return(0); 8759 1 8760 1 return(VIAgetTop(gs->gplus->Views)); 8761 1 } 8762 8763 /* 8764 * Find out what a specific view is 8765 */ 8766 8767 VIewobj * 8768 GSgetView(gs, viewnum) 8769 GopherObj *gs; 8770 int viewnum; 8771 { 8772 1 if (gs->gplus == NULL) 8773 1 return(NULL); 8774 1 8775 1 return(VIAgetEntry(gs->gplus->Views, viewnum)); 8776 1 } 8777 8778 8779 char * 8780 GSgetURL(gs) 8781 GopherObj *gs; 8782 { 8783 1 if (gs->url == NULL) { 8784 2 gs->url = URLnew(); 8785 2 URLfromGS(gs->url, gs); 8786 2 } 8787 1 8788 1 return(URLget(gs->url)); 8789 1 } 8790 8791 8792 char * 8793 GSgetURLhtml(gs) 8794 GopherObj *gs; 8795 { 8796 1 char *cp = GSgetURL(gs); 8797 1 char *cp2; 8798 1 int views; 8799 1 8800 1 if ((cp != NULL) && (strncmp(cp, "gopher://", 9) == 0)) { 8801 2 if ( GSgplusInited(gs) ) { 8802 3 for (views=0; views< GSgetNumViews(gs); views++) { 8803 4 if (!(strncasecmp(VIgetType(GSgetView(gs,views)), 8804 4 "text/html", 9))) { 8805 5 8806 5 cp = strdup(cp); 8807 5 8808 5 /** find the type character **/ GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 11 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 8809 5 cp2 = strchr(cp+10, '/'); 8810 5 if (cp2 != NULL) { 8811 6 *(++cp2) = 'h'; 8812 6 *(++cp2) = 'h'; 8813 6 } 8814 5 } 8815 4 } 8816 3 } 8817 2 } 8818 1 8819 1 return cp; 8820 1 8821 1 } 8822 8823 char * 8824 GStoNetURL(gs,url) 8825 GopherObj *gs; 8826 char *url; 8827 { 8828 1 char *path, *ftphost, *ftppath; 8829 1 8830 1 *url = '\0'; 8831 1 path = GSgetPath(gs); 8832 1 8833 1 /** This is a server specific hack for now.. **/ 8834 1 8835 1 if ( (path != NULL) && (strncmp(path, "ftp:", 4) == 0) ) { 8836 2 ftphost = path+4; 8837 2 ftppath = strchr(ftphost, '@'); 8838 2 8839 2 if (ftppath != NULL) 8840 2 { 8841 3 sprintf(url, "ftp://%.*s/", ftppath-ftphost, ftphost); 8842 3 8843 3 ftppath++; 8844 3 8845 3 /*** The rest is the file/path ***/ 8846 3 if (*ftppath == '/') 8847 3 ftppath++; 8848 3 8849 3 strcat(url, ftppath); 8850 3 return(url); 8851 3 } 8852 2 } 8853 1 strcpy(url,GSgetURLhtml(gs)); 8854 1 return(url); 8855 1 } 8856 8857 8858 void 8859 GSsetstringAsk(gs,ask) 8860 GopherObj *gs; 8861 char *ask; 8862 { 8863 1 GSsetBlock(gs,"ASK",ask,TRUE); 8864 1 GSsetAsk(gs,TRUE); 8865 1 } GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 12 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 8866 8867 8868 Blockobj* 8869 GSfindBlock(gs, blockname) 8870 GopherObj *gs; 8871 char *blockname; 8872 { 8873 1 int x; 8874 1 8875 1 x = BLAsearch(GSgetOtherBlocks(gs), blockname); 8876 1 8877 1 Debug("GSfind num is %d\n", x); 8878 1 if (x < 0) 8879 1 return(NULL); 8880 1 else 8881 1 return(GSgetBlock(gs, x)); 8882 1 } 8883 8884 void 8885 GSsetBlock(gs, blockname, text, appendIfPoss) 8886 GopherObj *gs; 8887 char *blockname; 8888 char *text; 8889 boolean appendIfPoss; 8890 { 8891 1 Blockobj *bl = NULL; 8892 1 boolean newbl = FALSE; 8893 1 8894 1 Debug("GSsetBlock:%s;",blockname); 8895 1 Debug("%s\r\n", text); 8896 1 8897 1 if (appendIfPoss) 8898 1 bl = GSfindBlock(gs, blockname); 8899 1 8900 1 if (bl == NULL) { 8901 2 newbl = TRUE; 8902 2 bl = BLnew(); 8903 2 } 8904 1 8905 1 BLsetName(bl, blockname); 8906 1 BLaddText(bl, text); 8907 1 8908 1 #ifdef DEBUGGING 8909 1 if (DEBUG) 8910 1 BLtoNet(bl, fileno(stderr), TRUE); 8911 1 #endif 8912 1 if (gs->gplus == NULL) 8913 1 GSplusnew(gs); 8914 1 8915 1 if (newbl) { 8916 2 BLApush(gs->gplus->OtherBlocks, bl); 8917 2 BLdestroy(bl); 8918 2 } 8919 1 8920 1 } 8921 8922 /* GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 13 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 8923 * Set the Askdata, destroy if necessary.. 8924 */ 8925 8926 char ** 8927 GSsetAskdata(gs, askdata) 8928 GopherObj *gs; 8929 char **askdata; 8930 { 8931 1 if (!GSgplusInited(gs)) 8932 1 return(NULL); 8933 1 8934 1 /** Destroy data if necessary **/ 8935 1 if (gs->gplus->Askdata != NULL) { 8936 2 int i=0; 8937 2 char **Askmoo = gs->gplus->Askdata; 8938 2 8939 2 while (Askmoo[i] != NULL) { 8940 3 free(Askmoo[i++]); 8941 3 } 8942 2 free(Askmoo); 8943 2 } 8944 1 8945 1 gs->gplus->Askdata = askdata; 8946 1 8947 1 return(askdata); 8948 1 8949 1 } 8950 8951 8952 /* 8953 * Set the administrator line as defined in Gopher+ protocol 8954 * Name 8955 */ 8956 8957 8958 /* Converts the gopher+ moddate from to a struct tm ptr */ 8959 struct tm * 8960 GSgetModDateTM(gs) 8961 GopherObj *gs ; 8962 { 8963 1 static struct tm time; 8964 1 char *cp; 8965 1 #ifndef NO_MKTIME 8966 1 time_t converted; 8967 1 #endif 8968 1 8969 1 if ( (gs->gplus == NULL) || (STRget(gs->gplus->ModDate) == NULL) ) 8970 1 return NULL; 8971 1 8972 1 cp = strchr(STRget(gs->gplus->ModDate), '<'); 8973 1 if (cp == NULL) 8974 1 return NULL; 8975 1 8976 1 #define ASCII_TO_INT(a) (a - '0') 8977 1 /* Should really do some sanity checking on the input here */ 8978 1 time.tm_year = ((ASCII_TO_INT(cp[1]) * 1000) + (ASCII_TO_INT(cp[2]) * 100) 8979 1 + (ASCII_TO_INT(cp[3]) * 10) + ASCII_TO_INT(cp[4]) ) - 1900; GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 14 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 8980 1 time.tm_mon = (ASCII_TO_INT(cp[5]) * 10) + ASCII_TO_INT(cp[6]) - 1; 8981 1 time.tm_mday = (ASCII_TO_INT(cp[7]) * 10) + ASCII_TO_INT(cp[8]); 8982 1 time.tm_hour = (ASCII_TO_INT(cp[9]) * 10) + ASCII_TO_INT(cp[10]); 8983 1 time.tm_min = (ASCII_TO_INT(cp[11]) * 10) + ASCII_TO_INT(cp[12]); 8984 1 time.tm_sec = (ASCII_TO_INT(cp[13]) * 10) + ASCII_TO_INT(cp[14]); 8985 1 time.tm_isdst = -1; /* make the system figure it out */ 8986 1 8987 1 #ifndef NO_MKTIME 8988 1 /* if mktime() is present, let it do sanity checking and day of 8989 1 week setting for us */ 8990 1 converted = mktime(&time); 8991 1 if (converted != -1) 8992 1 return (localtime(&converted)); 8993 1 #endif 8994 1 return (&time); 8995 1 8996 1 } 8997 8998 8999 #if defined(VMS) || (defined(GINTERNATIONAL) && !defined(NO_STRFTIME)) 9000 /* In internationalized environments, convert the ModDate string to the 9001 * native language when it's requested. 9002 * If i18n is not on, the macro from GSgopherobj.h is used. 9003 * (The i18n definition's are turned on or off in Locale.h) 9004 */ 9005 char * 9006 GSgetModDate(gs) 9007 GopherObj *gs; 9008 { 9009 1 char dateBuf[256]; 9010 1 char *datetime; 9011 1 struct tm *modTime; 9012 1 9013 1 if ( (gs->gplus == NULL) || (STRget(gs->gplus->ModDate) == NULL) ) 9014 1 return NULL; 9015 1 9016 1 modTime = GSgetModDateTM(gs); 9017 1 9018 1 if ( (modTime != NULL) && 9019 1 strftime(dateBuf, sizeof(dateBuf) - 16, "%c ", modTime) ) 9020 1 { 9021 2 datetime = strchr(STRget(gs->gplus->ModDate), '<'); 9022 2 if (datetime != NULL) 9023 2 strncat(dateBuf, datetime, 16); 9024 2 9025 2 STRset(gs->gplus->ModDate, dateBuf); 9026 2 } 9027 1 9028 1 return STRget(gs->gplus->ModDate); 9029 1 } 9030 #endif /* GINTERNATIONAL */ 9031 9032 9033 9034 void 9035 GSsetAdmin(gs, admin) 9036 GopherObj *gs; GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 15 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 9037 char *admin; 9038 { 9039 1 if (gs->gplus == NULL) 9040 1 GSplusnew(gs); 9041 1 9042 1 STRset(gs->gplus->Admin, admin); 9043 1 } 9044 9045 9046 9047 void 9048 GSsetModDate(gs, str) 9049 GopherObj *gs; 9050 char *str; 9051 { 9052 1 if (gs->gplus == NULL) GSplusnew(gs); 9053 1 STRset(gs->gplus->ModDate, str); 9054 1 } 9055 9056 9057 9058 /** Add a view for a specific gopherobj **/ 9059 9060 void 9061 GSaddView(gs, view, language, estsize) 9062 GopherObj *gs; 9063 char *view; 9064 char *language; 9065 int estsize; 9066 { 9067 1 char tmpstr[64]; 9068 1 VIewobj *temp; 9069 1 9070 1 if (estsize > 960) 9071 1 sprintf(tmpstr, "%dk", (estsize + 512)/1024); 9072 1 else 9073 1 sprintf(tmpstr, ".%dk", ((estsize+64)*10)/1024); 9074 1 9075 1 temp = VInew(); 9076 1 9077 1 VIsetType(temp, view); 9078 1 VIsetLang(temp, language); 9079 1 VIsetSize(temp, tmpstr); 9080 1 9081 1 VIApush(gs->gplus->Views, temp); 9082 1 VIdestroy(temp); 9083 1 } 9084 9085 9086 void 9087 GSaddBlock(gs, Blockname, file) 9088 GopherObj *gs; 9089 char *Blockname; 9090 char *file; 9091 { 9092 1 Blockobj *bl; 9093 1 GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 16 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 9094 1 bl = BLnew(); 9095 1 BLsetName(bl, Blockname); 9096 1 BLsetFile(bl, file); 9097 1 ; 9098 1 if (gs->gplus == NULL) 9099 1 GSplusnew(gs); 9100 1 9101 1 BLApush(gs->gplus->OtherBlocks, bl); 9102 1 9103 1 BLdestroy(bl); 9104 1 } 9105 9106 9107 9108 /* 9109 * Send a gopher reference into an fd 9110 */ 9111 9112 void 9113 GStoNet(gs, sockfd, fmt, ticket) 9114 GopherObj *gs; 9115 int sockfd; 9116 GSformat fmt; 9117 char *ticket; 9118 { 9119 1 char buf[1024]; 9120 1 static char *nullword = "(NULL)"; 9121 1 if (ticket == NULL) 9122 1 ticket = ""; 9123 1 9124 1 buf[0] = GSgetType(gs); 9125 1 9126 1 if (buf[0] == '\0') /* For example a .names with no Type */ 9127 1 buf[0] = '3'; 9128 1 9129 1 if (fmt == GSFORM_G0) { 9130 2 sprintf(buf + 1, "%s\t%s%s\t%s\t%d", 9131 2 GSgetTitle(gs) ? GSgetTitle(gs) : nullword, 9132 2 ticket ? ticket : nullword, 9133 2 GSgetPath(gs) ? GSgetPath(gs) : nullword, 9134 2 GSgetHost(gs) ? GSgetHost(gs) : nullword, 9135 2 GSgetPort(gs)); 9136 2 9137 2 if (GSisAsk(gs)) 9138 2 strcat(buf, "\t?\r\n"); 9139 2 else if (GSisGplus(gs)) 9140 2 strcat(buf, "\t+\r\n"); 9141 2 else 9142 2 strcat(buf, "\r\n"); 9143 2 9144 2 writestring(sockfd, buf); 9145 2 Debug("GStoNet:%s", buf); 9146 2 } 9147 1 else if (fmt == GSFORM_GPLUS) { 9148 2 ; 9149 2 } 9150 1 else if (fmt == GSFORM_HTML) { GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 17 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 9151 2 char url[256]; 9152 2 9153 2 if (GSgetType(gs) == A_INFO) { 9154 3 writestring(sockfd, GSgetTitle(gs)); 9155 3 return; 9156 3 } 9157 2 GStoNetURL(gs, url); 9158 2 if (url[0] == '\0') 9159 2 return; 9160 2 sprintf(buf, "%s\r\n", url, GSgetTitle(gs)); 9161 2 writestring(sockfd, buf); 9162 2 9163 2 if (GSgplusInited(gs)) { 9164 3 int j; 9165 3 Blockobj *bl; 9166 3 9167 3 bl = GSfindBlock(gs, "ABSTRACT"); 9168 3 if (bl != NULL) { 9169 4 writestring(sockfd, "
"); 9170 4 BLtoNet(bl, sockfd, FALSE); 9171 4 writestring(sockfd, "\r\n"); 9172 4 } 9173 3 } 9174 2 9175 2 if (GSgetWeight(gs) != 0) { 9176 3 sprintf(buf, "
Score: %d\r\n", GSgetWeight(gs)); 9177 3 writestring(buf); 9178 3 } 9179 2 } 9180 1 9181 1 } 9182 9183 9184 /* 9185 * Send a long gopher data descriptor 9186 * 9187 * filter is a character array of blocks to send 9188 */ 9189 9190 void 9191 GSplustoNet(gs, sockfd, filter, ticket) 9192 GopherObj *gs; 9193 int sockfd; 9194 char **filter; 9195 char *ticket; 9196 { 9197 1 int i; 9198 1 char tmpstr[256]; 9199 1 boolean sendviews, sendadmin, sendothers; 9200 1 9201 1 if (filter == NULL) 9202 1 sendviews = sendadmin = sendothers = TRUE; 9203 1 else { 9204 2 sendviews = sendadmin = sendothers = FALSE; 9205 2 for (i=0; filter[i] != NULL ;i++) { 9206 3 if (strcasecmp(filter[i], "VIEWS")==0) 9207 3 sendviews = TRUE; GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 18 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 9208 3 else if (strcasecmp(filter[i], "ADMIN")==0) 9209 3 sendadmin = TRUE; 9210 3 else 9211 3 sendothers = TRUE; 9212 3 } 9213 2 } 9214 1 9215 1 9216 1 /** Send out the old style INFO stuff **/ 9217 1 writestring(sockfd, "+INFO: "); 9218 1 GStoNet(gs,sockfd, GSFORM_G0, ticket); 9219 1 9220 1 9221 1 /** Only write out "interesting" URLs **/ 9222 1 9223 1 if (GSgetURL(gs) != NULL) { 9224 2 if (strncmp(GSgetURL(gs), "gopher:", 7) != 0) { 9225 3 writestring(sockfd, "+URL:\r\n "); 9226 3 writestring(sockfd, GSgetURL(gs)); 9227 3 writestring(sockfd, "\r\n"); 9228 3 } 9229 2 } 9230 1 9231 1 9232 1 if (GSgplusInited(gs)) { 9233 2 /*** Should special case for local filename.... ***/ 9234 2 9235 2 if (GSgetAdmin(gs) != NULL && GSgetModDate(gs) != NULL && sendadmin){ 9236 3 writestring(sockfd, "+ADMIN:\r\n Admin: "); 9237 3 writestring(sockfd, GSgetAdmin(gs)); 9238 3 writestring(sockfd, "\r\n Mod-Date: "); 9239 3 writestring(sockfd, GSgetModDate(gs)); 9240 3 if (GSgetTTL(gs) > -1) { 9241 4 writestring(sockfd, "\r\n TTL: "); 9242 4 sprintf(tmpstr, "%d", GSgetTTL(gs)); 9243 4 writestring(sockfd, tmpstr); 9244 4 } 9245 3 writestring(sockfd, "\r\n"); 9246 3 } 9247 2 if (GSgetNumViews(gs) > 0 && sendviews) { 9248 3 writestring(sockfd, "+VIEWS:\r\n"); 9249 3 for (i=0 ; i< GSgetNumViews(gs); i++) { 9250 4 VItoLine(GSgetView(gs, i), tmpstr); 9251 4 writestring(sockfd, tmpstr); 9252 4 writestring(sockfd, "\r\n"); 9253 4 } 9254 3 } 9255 2 9256 2 if (sendothers) { 9257 3 9258 3 for (i=0; i< GSgetNumBlocks(gs); i++) 9259 3 BLtoNet(GSgetBlock(gs, i),sockfd, TRUE); 9260 3 } 9261 2 } 9262 1 } 9263 9264 GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 19 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 9265 /*** GSplusfromnet() assumes that the leading +INFO text has been read from 9266 the file descriptor. 9267 9268 It returns 1 if there's more data (and another INFO block) 9269 0 if there's EOF 9270 SOFTERROR caller can keep reading 9271 HARDERROR caller should stop reading 9272 ***/ 9273 9274 int 9275 GSplusfromNet(gs, fd) 9276 GopherObj *gs; 9277 int fd; 9278 { 9279 1 int result,readok,i; 9280 1 boolean nextinfo = FALSE; 9281 1 char plusfield; 9282 1 Blockobj *bl; 9283 1 char inputline[512]; 9284 1 9285 1 if (gs->gplus == NULL) 9286 1 GSplusnew(gs); 9287 1 9288 1 bl = BLnew(); 9289 1 9290 1 /** get the gopher-data descriptor **/ 9291 1 readok = GSfromNet(gs, fd); 9292 1 9293 1 if (readok == HARDERROR) 9294 1 return(HARDERROR); 9295 1 9296 1 /** If readok is softerror we still need to look for blocks to throw 9297 1 away any data before next item **/ 9298 1 9299 1 /** Now start looking for blocks. Process blocks if we know how. **/ 9300 1 /** State: _GotGREF_ **/ 9301 1 9302 1 if ((result = readrecvbuf(fd, &plusfield, 1))<0) 9303 1 return(HARDERROR); 9304 1 9305 1 while (!nextinfo) { 9306 2 if (result == 0) { /*** We're done ***/ 9307 3 BLdestroy(bl); 9308 3 9309 3 if (readok == SOFTERROR) 9310 3 return(SOFTERROR); 9311 3 else 9312 3 return(FOUNDEOF); 9313 3 } 9314 2 switch (plusfield) { 9315 3 9316 3 case '.': 9317 3 readline(fd, inputline, sizeof(inputline)); 9318 3 result = FOUNDEOF; 9319 3 break; 9320 3 9321 3 case '+': GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 20 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 9322 3 /*** State _NewBlock_ ***/ 9323 3 9324 3 if (readtoken(fd,inputline, sizeof(inputline), ':') <= 0) 9325 3 return(HARDERROR); 9326 3 9327 3 if (strcasecmp(inputline, "INFO")==0) { 9328 4 /** Get rid of the space. **/ 9329 4 readrecvbuf(fd, &plusfield,1); 9330 4 BLdestroy(bl); 9331 4 if (readok == SOFTERROR) 9332 4 return(SOFTERROR); 9333 4 else 9334 4 return(MORECOMING); 9335 4 } 9336 3 9337 3 /** Specialized fromNets here **/ 9338 3 9339 3 BLinit(bl); 9340 3 if ((result=BLfromNet(bl, fd, inputline)) <0) { 9341 4 /** Bad read **/ 9342 4 BLdestroy(bl); 9343 4 return(HARDERROR); 9344 4 } 9345 3 else if (result == FOUNDEOF) /** EOF, block read ok **/ 9346 3 nextinfo = TRUE; 9347 3 else 9348 3 nextinfo = FALSE; 9349 3 9350 3 9351 3 /*** See what the block is. Transform it if necessary ***/ 9352 3 if (strcasecmp(BLgetName(bl), "VIEWS")==0) { 9353 4 VIAfromBL(gs->gplus->Views, bl); 9354 4 } else if (strcasecmp(BLgetName(bl), "ADMIN")==0) { 9355 4 int saveAdminBlock = 0; 9356 4 9357 4 for (i=0; igplus->OtherBlocks, bl); 9373 4 9374 4 } else if (strcasecmp(BLgetName(bl), "URL")==0) { 9375 4 char *cp; 9376 4 9377 4 cp = BLgetLine(bl, 0); 9378 4 if (cp != NULL) GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 21 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 9379 4 GSsetURL(gs, cp); 9380 4 } 9381 3 else 9382 3 BLApush(gs->gplus->OtherBlocks, bl); 9383 3 9384 3 break; /** '+' **/ 9385 3 9386 3 default: /*** Hmmm plusfield wasn't a plus or '.' **/ 9387 3 return(HARDERROR); 9388 3 9389 3 } /** switch plusfield **/ 9390 2 9391 2 } /** While **/ 9392 1 9393 1 BLdestroy(bl); 9394 1 9395 1 return(FOUNDEOF); 9396 1 } 9397 9398 9399 9400 /* GSfromNet - no comments on the original, so this is my (Mitra's) guess 9401 GSfromNet reads a gopher style line, it is called from: 9402 GDfromNet - in which case the gopher line is the whole item or; 9403 GSplusfromNet - in which case it is the part after the +INFO. 9404 It should return after reading the whole line, however in gopher+1.2b2 9405 this is not always the case, especially if it sees a Type=3 9406 returns: 9407 1 blank line (I think?) 9408 0 ok 9409 -1 HARDERROR readfield etc error - give up 9410 -2 SOFTERROR unrecognized or unhandleable type - skip on to next one 9411 */ 9412 9413 9414 9415 9416 extern int readfield(); 9417 extern int readline(); 9418 9419 int 9420 GSfromNet(gs, sockfd) 9421 GopherObj *gs; 9422 int sockfd; 9423 { 9424 1 char foo[1024], *cp; 9425 1 9426 1 if (readtoken(sockfd, foo, 1024, '\t')<= 0) { 9427 2 /* EOF or error */ 9428 2 return(HARDERROR); 9429 2 } 9430 1 9431 1 GSsetType(gs, foo[0]); 9432 1 9433 1 /** Get the kind of file from the first character **/ 9434 1 /** Filter out files that we can't deal with **/ 9435 1 GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 22 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 9436 1 switch (GSgetType(gs)) { 9437 2 case A_PDF: 9438 2 case A_FILE: 9439 2 case A_DIRECTORY: 9440 2 case A_MACHEX: 9441 2 case A_PCBIN: 9442 2 case A_CSO: 9443 2 case A_INDEX: 9444 2 case A_TELNET: 9445 2 case A_SOUND: 9446 2 case A_UNIXBIN: 9447 2 case A_GIF: 9448 2 case A_HTML: 9449 2 case A_TN3270: 9450 2 case A_MIME: 9451 2 case A_IMAGE: 9452 2 case A_INFO: 9453 2 case A_MOVIE: 9454 2 case A_APP: 9455 2 #ifdef VMS_SERVER 9456 X case A_UUENCODE: 9457 2 #endif 9458 2 break; 9459 2 case A_ERROR: 9460 2 GSsetPath(gs, ""); 9461 2 GSsetHost(gs, ""); 9462 2 GSsetGplus(gs, FALSE); 9463 2 ZapCRLF(foo+1); 9464 2 cp = foo + strlen(foo+1); 9465 2 while (*cp == '.' && (*(cp-1) == '\n' || *(cp-1) == '\r')) { 9466 3 *cp = '\0'; 9467 3 ZapCRLF(foo+1); 9468 3 } 9469 2 break; 9470 2 case A_EOI: 9471 2 if (foo[1] == '\r' && foo[2] == '\n') 9472 2 return(1); 9473 2 default: 9474 2 /** Can't handle this type **/ 9475 2 readline(sockfd, foo, 1024);/** Cleanup **/ 9476 2 return(SOFTERROR); 9477 2 } 9478 1 9479 1 /** Suck off the User Displayable name **/ 9480 1 cp = foo+1; 9481 1 while (*cp == '\n' || *cp == '\r') 9482 1 cp++; 9483 1 GSsetTitle(gs, cp); 9484 1 9485 1 /** Suck off the Pathname **/ 9486 1 if (readtoken(sockfd, foo, 1024, '\t') <= 0) 9487 1 return(GSgetType(gs)==A_ERROR?0:HARDERROR); 9488 1 GSsetPath(gs, foo); 9489 1 9490 1 /** Suck off the hostname **/ 9491 1 if (readtoken(sockfd, foo, 1024, '\t') <= 0) 9492 1 return(GSgetType(gs)==A_ERROR?0:HARDERROR); GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 23 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 9493 1 9494 1 GSsetHost(gs, foo); 9495 1 9496 1 if (readline(sockfd, foo, 1024)<=0) 9497 1 return(GSgetType(gs)==A_ERROR?0:HARDERROR); 9498 1 9499 1 GSsetPort(gs, 0); 9500 1 9501 1 /** Get the port number **/ 9502 1 if ((cp = strchr(foo, '\t')) != NULL) { 9503 2 *cp = '\0'; 9504 2 switch (*(cp+1)) { 9505 3 case '?': 9506 3 GSsetAsk(gs, TRUE); 9507 3 case '+': 9508 3 GSsetGplus(gs, TRUE); 9509 3 break; 9510 3 } 9511 2 } 9512 1 9513 1 GSsetPort(gs, atoi(foo)); 9514 1 DebugGSplusPrint(gs,"GSfromNet end:"); 9515 1 9516 1 return(0); 9517 1 } 9518 9519 9520 /** Copy a GopherObj ***/ 9521 9522 void 9523 GScpy(dest, orig) 9524 GopherObj *dest, *orig; 9525 { 9526 1 dest->sFileType = orig->sFileType; 9527 1 dest->iPort = orig->iPort; 9528 1 dest->Itemnum = orig->Itemnum; 9529 1 9530 1 #ifdef VMS_SERVER 9531 X dest->date_cr = orig->date_cr; 9532 X if (dest->Access != NULL) 9533 X SiteArrDestroy(dest->Access); 9534 X dest->Access = NULL; 9535 X if (orig->Access != NULL) { 9536 X Site *temp; 9537 X int i; 9538 X dest->Access = SiteArrayNew(); 9539 X for (i=0; i< DAgetTop(orig->Access); i++) { 9540 X temp = SiteArrgetEntry(orig->Access, i); 9541 X SiteArrayAdd(dest->Access,temp->domain,temp->Level); 9542 X } 9543 X } 9544 X dest->Defaccess = orig->Defaccess; 9545 X GSsetHeader(dest, GSgetHeader(orig)); 9546 X GSsetFooter(dest, GSgetFooter(orig)); 9547 X GSsetRHeader(dest, GSgetRHeader(orig)); 9548 X GSsetRFooter(dest, GSgetRFooter(orig)); 9549 1 #endif GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 24 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 9550 1 9551 1 GSsetTitle(dest, GSgetTitle(orig)); 9552 1 GSsetPath(dest, GSgetPath(orig)); 9553 1 GSsetHost(dest, GSgetHost(orig)); 9554 1 9555 1 GSsetGplus(dest, GSisGplus(orig)); 9556 1 GSsetAsk(dest, GSisAsk(orig)); 9557 1 GSsetURL(dest, GSgetURL(orig)); 9558 1 GSsetTTL(dest, GSgetTTL(orig)); 9559 1 9560 1 STRinit(dest->Localfile); 9561 1 STRinit(dest->Localview); 9562 1 GSpluscpy(dest, orig); 9563 1 9564 1 } 9565 9566 void 9567 GSpluscpy(dest, orig) 9568 GopherObj *dest, *orig; 9569 { 9570 1 if (GSgplusInited(orig)) { 9571 2 if (!GSgplusInited(dest)) 9572 2 GSplusnew(dest); 9573 2 GSsetAdmin(dest, GSgetAdmin(orig)); 9574 2 GSsetModDate(dest, GSgetModDate(orig)); 9575 2 VIAcpy(dest->gplus->Views, orig->gplus->Views); 9576 2 BLAcpy(dest->gplus->OtherBlocks, orig->gplus->OtherBlocks); 9577 2 (void)GSsetAskdata(dest, GSgetAskdata(orig)); 9578 2 } 9579 1 } 9580 9581 /** GSmerge combines 2 gopher objects overwriting fields defined in overlay **/ 9582 /* Called by GDaddGSmerge to merge gs into directory, that is only called 9583 by function to do this from a link */ 9584 void 9585 GSmerge(gs, overlay) 9586 GopherObj *gs, *overlay; 9587 { 9588 1 char *tempstr; 9589 1 9590 1 DebugGSplusPrint(gs,"GSmerge: Original"); 9591 1 DebugGSplusPrint(overlay,"GSmerge: Overlay"); 9592 1 9593 1 if (GSgetHost(overlay) != NULL) { 9594 2 9595 2 if (GSgetType(overlay) != '\0') { 9596 3 /* Just setting Type wont work, since they interelated with Path 9597 3 * so set first char of path as well */ 9598 3 GSsetType(gs, GSgetType(overlay)); 9599 3 tempstr = GSgetPath(gs); 9600 3 9601 3 if (*tempstr != A_DIRECTORY) { 9602 4 tempstr[0] = GSgetType(overlay); 9603 4 GSsetPath(gs, tempstr); 9604 4 } 9605 3 if (GSisAsk(overlay) && GSgetType(overlay) == A_DIRECTORY) 9606 3 GSaddView(gs, "application/gopher+-menu", "En_US", 0); GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 25 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 9607 3 /* lang==GDCgetLang(Config), 0 == dummy size here */ 9608 3 /* need this patch for proper protocol & Hgopher, 9609 3 which ignores gopher0 type in favor of +VIEW */ 9610 3 } 9611 2 9612 2 if (GSgetTitle(overlay) != NULL) 9613 2 GSsetTitle(gs, GSgetTitle(overlay)); 9614 2 /* Don't set path - that is the key to the merge, and in the overlay 9615 2 most probably has the first char set to ' ' ????*/ 9616 2 if (GSgetHost(overlay) != NULL) 9617 2 GSsetHost(gs, GSgetHost(overlay)); 9618 2 if (GSgetPort(overlay) != 0) 9619 2 GSsetPort(gs, GSgetPort(overlay)); 9620 2 if (GSgetNum(overlay) != -1) 9621 2 GSsetNum(gs, GSgetNum(overlay)); 9622 2 if (GSgetWeight(overlay) != 0) 9623 2 GSsetWeight(gs, GSgetWeight(overlay)); 9624 2 if (GSgetAdmin(overlay) != NULL) 9625 2 GSsetAdmin(gs, GSgetAdmin(overlay)); 9626 2 9627 2 #ifdef VMS_SERVER 9628 X if (GSisCreateDate(gs)) 9629 X GSsetCreateDate(overlay); 9630 X if (overlay->Access != NULL) { 9631 X Site *temp; 9632 X int i; 9633 X if (gs->Access != NULL) { 9634 X SiteArrDestroy(gs->Access); 9635 X gs->Access = NULL; 9636 X } 9637 X gs->Access = SiteArrayNew(); 9638 X for (i=0; i< DAgetTop(overlay->Access); i++) { 9639 X temp = SiteArrgetEntry(overlay->Access, i); 9640 X SiteArrayAdd(gs->Access,temp->domain,temp->Level); 9641 X } 9642 X } 9643 X if (GSgetHeader(overlay) != NULL) 9644 X GSsetHeader(gs, GSgetHeader(overlay)); 9645 X if (GSgetFooter(overlay) != NULL) 9646 X GSsetFooter(gs, GSgetFooter(overlay)); 9647 X if (GSgetRHeader(overlay) != NULL) 9648 X GSsetRHeader(gs, GSgetRHeader(overlay)); 9649 X if (GSgetRFooter(overlay) != NULL) 9650 X GSsetRFooter(gs, GSgetRFooter(overlay)); 9651 2 #endif 9652 2 9653 2 if (overlay->gplus != NULL) 9654 2 { 9655 3 if (!GSgplusInited(gs)) 9656 3 GSplusnew(gs); 9657 3 BLAcpy(gs->gplus->OtherBlocks, 9658 3 overlay->gplus->OtherBlocks); 9659 3 } 9660 2 } 9661 1 DebugGSplusPrint(gs,"GSmerge: Result"); 9662 1 } 9663 GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 26 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 9664 9665 /** Compare two GopherObjs ***/ 9666 9667 int 9668 GScmp(gs1, gs2) 9669 GopherObj *gs1, *gs2; 9670 { 9671 1 if (GSgetTitle(gs1) == NULL) 9672 1 return(1); 9673 1 if (GSgetTitle(gs2) == NULL) 9674 1 return(-1); 9675 1 9676 1 return(strcasecmp(GSgetTitle(gs1), GSgetTitle(gs2))); 9677 1 } 9678 9679 9680 /*********** The following functions implement the gopher/gopher+ 9681 protocol, mostly 9682 GSconnect(), then GStransmit(), GSsendHeader() GSrecvHeader(); 9683 ************/ 9684 9685 9686 9687 /* GSconnect performs a connection to socket 'service' on host 9688 * 'host'. Host can be a hostname or ip-address. If 'host' is null, the 9689 * local host is assumed. The parameter full_hostname will, on return, 9690 * contain the expanded hostname (if possible). Note that full_hostname is a 9691 * pointer to a char *, and is allocated by connect_to_gopher() 9692 * 9693 * returns Errors : ErrSocket* defined in Sockets.h or socket 9694 * 9695 */ 9696 9697 int 9698 GSconnect(gs) 9699 GopherObj *gs; 9700 { 9701 1 int sockfd; 9702 1 9703 1 Debug("GSconnect: Host=%s",GSgetHost(gs)); 9704 1 Debug("Port=%d\r\n",GSgetPort(gs)); 9705 1 9706 1 sockfd = SOCKconnect(GSgetHost(gs), GSgetPort(gs)); 9707 1 9708 1 return(sockfd); 9709 1 } 9710 9711 9712 /* 9713 * GStransmit sends the request from the client to the server 9714 * 9715 * All parameters are optional except for gs and sockfd. 9716 * 9717 * the rest pertain to gopher+ transmission. 9718 */ 9719 9720 void GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 27 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 9721 GStransmit(gs, sockfd, search, command, view) 9722 GopherObj *gs; 9723 int sockfd; 9724 char *search; 9725 char *command; 9726 char *view; 9727 { 9728 1 char *cp; 9729 1 char **ask = GSgetAskdata(gs); 9730 1 int i; 9731 1 9732 1 writestring(sockfd, GSgetPath(gs)); 9733 1 if (search != NULL) { 9734 2 writestring(sockfd, "\t"); 9735 2 writestring(sockfd, search); 9736 2 } 9737 1 9738 1 /** Only send if gplus **/ 9739 1 if (!GSisGplus(gs)) { 9740 2 writestring(sockfd, "\r\n"); 9741 2 return; 9742 2 } 9743 1 9744 1 if (command != NULL) { 9745 2 writestring(sockfd, "\t"); 9746 2 writestring(sockfd, command); 9747 2 } 9748 1 9749 1 if (view != NULL) { 9750 2 writestring(sockfd, view); 9751 2 } 9752 1 if (ask == NULL) 9753 1 writestring(sockfd, "\r\n"); 9754 1 else { 9755 2 writestring(sockfd, "\t1\r\n"); 9756 2 9757 2 GSsendHeader(sockfd, -1); 9758 2 9759 2 for (i=0; ;i++) { 9760 3 cp = ask[i]; 9761 3 9762 3 if (cp == NULL) 9763 3 break; 9764 3 9765 3 writestring(sockfd, cp); 9766 3 writestring(sockfd, "\r\n"); 9767 3 } 9768 2 writestring(sockfd, ".\r\n"); 9769 2 } 9770 1 } 9771 9772 9773 9774 /* 9775 * GSsendHeader generates an appropriate header on sockfd 9776 * 9777 */ GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 28 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 9778 void 9779 GSsendHeader(sockfd, size) 9780 int sockfd; 9781 int size; 9782 { 9783 1 char sizestr[64]; 9784 1 9785 1 sprintf(sizestr, "+%d\r\n", size); 9786 1 writestring(sockfd, sizestr); 9787 1 } 9788 9789 9790 /** GSsendErrorHeader sends an error message header/message to the client **/ 9791 void 9792 GSsendErrorHeader(gs,sockfd,errortype,errormsg) 9793 GopherObj *gs; 9794 int sockfd; 9795 int errortype; 9796 char *errormsg; 9797 { 9798 1 char tmpstr[512]; 9799 1 9800 1 sprintf(tmpstr, "-%d %s\r\n", errortype, errormsg); 9801 1 writestring(sockfd, tmpstr); 9802 1 } 9803 9804 9805 9806 /* 9807 * GSrecvHeader will retrieve a gopher+ header, if it exists 9808 * 9809 * It returns the expected number of bytes that are headed our 9810 * way, if it can. 9811 * 9812 * Otherwise it returns -1 to indicate to read until \r\n.\r\n 9813 * or -2 to indicate to read to EOF 9814 * 9815 * If it encounters an error, it returns 0 and sets errno to the 9816 * gopher error class. 9817 */ 9818 9819 int 9820 GSrecvHeader(gs, sockfd) 9821 GopherObj *gs; 9822 int sockfd; 9823 { 9824 1 char headerline[256]; 9825 1 9826 1 Debugmsg("GSrecvHeader\n"); 9827 1 if (GSisGplus(gs)) { 9828 2 if (readline(sockfd, headerline, sizeof(headerline))<=0) 9829 2 return(0); 9830 2 ZapCRLF(headerline); 9831 2 if (*headerline == '+') { 9832 3 if (*(headerline+1) == '-') 9833 3 return(- (atoi(headerline+2))); 9834 3 else GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 29 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 9835 3 return(atoi(headerline+1)); 9836 3 } 9837 2 else if (*headerline == '-') { 9838 3 /*** Oh no! an error! ***/ 9839 3 errno = atoi(headerline+1); 9840 3 return(0); 9841 3 } 9842 2 } 9843 1 /*** Guess if we're running old style gopher ***/ 9844 1 else { 9845 2 switch (GSgetType(gs)) { 9846 3 case A_SOUND: 9847 3 case A_IMAGE: 9848 3 case A_GIF: 9849 3 case A_UNIXBIN: 9850 3 case A_PCBIN: 9851 3 return(-2); 9852 3 break; 9853 3 default: 9854 3 return(-1); 9855 3 } 9856 2 } 9857 1 return(-1); /** Should never get here **/ 9858 1 } 9859 9860 9861 /* 9862 * This routine will load up the item information from a gopher item 9863 * if the item hasn't transferred it already... 9864 * 9865 * The savename param, if TRUE will keep the current name and type 9866 */ 9867 9868 void 9869 GSgetginfo(gs, savename) 9870 GopherObj *gs; 9871 boolean savename; 9872 { 9873 1 int sockfd, bytes; 9874 1 char inputline[256]; 9875 1 String *tempname = NULL; 9876 1 char temptype; 9877 1 9878 1 if (!GSisGplus(gs)) 9879 1 return; 9880 1 9881 1 /** Try not to overwrite stuff unnecessarily.. **/ 9882 1 9883 1 if (GSgplusInited(gs)) { 9884 2 if (GSgetAdmin(gs)!=NULL) 9885 2 return; 9886 2 if (GSgetAskdata(gs) != NULL) 9887 2 return; 9888 2 } 9889 1 9890 1 if (savename) { 9891 2 tempname = STRnew(); GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 30 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 9892 2 STRset(tempname, GSgetTitle(gs)); 9893 2 temptype = GSgetType(gs); 9894 2 } 9895 1 9896 1 GSplusnew(gs); 9897 1 9898 1 /** Send out the request **/ 9899 1 if ((sockfd = GSconnect(gs)) <0) { 9900 2 /*check_sock(sockfd, GSgetHost(gs), GSgetPort(gs));*/ 9901 2 return; 9902 2 } 9903 1 9904 1 GStransmit(gs, sockfd, NULL, "!", NULL, NULL); 9905 1 bytes = GSrecvHeader(gs,sockfd); 9906 1 9907 1 if (bytes == 0) 9908 1 return; 9909 1 9910 1 /*** Read off the first info block ***/ 9911 1 readtoken(sockfd, inputline, sizeof(inputline), ' '); 9912 1 9913 1 GSplusfromNet(gs, sockfd); 9914 1 9915 1 if (savename) { 9916 2 GSsetTitle(gs, STRget(tempname)); 9917 2 GSsetType(gs, temptype); 9918 2 STRdestroy(tempname); 9919 2 } 9920 1 9921 1 } 9922 9923 9924 /* 9925 * GSfromLink takes an FIO structure and starts reading from it. 9926 * 9927 * It reads until it finds a line it recognizes, then 9928 * 9929 * It keeps going until it finds 9930 * eof, a non-recognized line, as long as there is a valid Path= line 9931 * 9932 * returns -1 on an error, 0 for EOF, 1 for success 9933 */ 9934 9935 int 9936 GSfromLink(gs, fio, host, port, directory, peer) 9937 GopherObj *gs; 9938 FileIO *fio; 9939 char *host; 9940 int port; 9941 char *directory; 9942 char *peer; 9943 { 9944 1 int doneflags = 0; 9945 1 char buf[1024]; 9946 1 int bytesread; 9947 1 9948 1 boolean DomainDefault = TRUE; /** Default for using domain stuff yes/no */ GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 31 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 9949 1 boolean BadDomain = FALSE; /** For use with the Domain= line **/ 9950 1 boolean DidDomain = FALSE; /** Needed to make Domain= lines 9951 1 into logical or's **/ 9952 1 buf[0] = '\0'; 9953 1 9954 1 9955 1 Debugmsg("GSfromLink...\n"); 9956 1 while ((bytesread = FIOreadlinezap(fio, buf, sizeof(buf)))>0) { 9957 2 if (buf[0] == '#') { 9958 3 if (doneflags & G_PATH) 9959 3 break; /* comment */ 9960 3 else 9961 3 continue; 9962 3 } 9963 2 9964 2 ZapCRLF(buf); 9965 2 9966 2 #ifdef VMS_SERVER 9967 X /* This'd be nice, but since most link file i/o is done using 9968 X standard i/o, and this routines's i/o is done using unix i/o 9969 X they're incompatible... let's see what can be done? */ 9970 X /* VMS$Continuation(buf, fio->fd, sizeof(buf), '-'); */ 9971 2 #endif 9972 2 9973 2 if (strncasecmp(buf, GS_TYPE, strlen(GS_TYPE))==0) { 9974 3 GSsetType(gs, buf[strlen(GS_TYPE)]); 9975 3 9976 3 if (buf[strlen(GS_TYPE)+1] == '+') 9977 3 GSsetGplus(gs, TRUE); 9978 3 if (buf[strlen(GS_TYPE)+1] == '?') 9979 3 GSsetAsk(gs, TRUE); 9980 3 doneflags |= G_TYPE; 9981 3 } 9982 2 9983 2 else if (strncasecmp(buf, GS_NAME, strlen(GS_NAME))==0) { 9984 3 GSsetTitle(gs, buf+strlen(GS_NAME)); 9985 3 doneflags |= G_NAME; 9986 3 } 9987 2 9988 2 else if (strncasecmp(buf, GS_PATH, strlen(GS_PATH))==0) { 9989 3 if (strncmp(buf+strlen(GS_PATH), "~/",2) == 0 || 9990 3 strncmp(buf+strlen(GS_PATH), "./",2) == 0) { 9991 4 char tmpstr[256]; 9992 4 9993 4 *tmpstr = '.'; 9994 4 strcpy(tmpstr+1, directory); 9995 4 if (directory[strlen(directory)-1] == '/') 9996 4 strcat(tmpstr, buf+strlen(GS_PATH)+2); 9997 4 else 9998 4 strcat(tmpstr, buf+strlen(GS_PATH)+1); 9999 4 GSsetPath(gs, tmpstr); 10000 4 } else 10001 3 GSsetPath(gs, buf+strlen(GS_PATH)); 10002 3 doneflags |= G_PATH; 10003 3 } 10004 2 10005 2 else if (strncasecmp(buf, GS_HOST, strlen(GS_HOST))==0) { GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 32 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 10006 3 if (buf[strlen(GS_HOST)] == '+' 10007 3 && buf[strlen(GS_HOST)+1] == '\0') 10008 3 GSsetHost(gs, host); 10009 3 else 10010 3 GSsetHost(gs, buf+strlen(GS_HOST)); 10011 3 10012 3 doneflags |= G_HOST; 10013 3 } 10014 2 10015 2 else if (strncasecmp(buf, GS_PORT, strlen(GS_PORT))==0) { 10016 3 if (buf[strlen(GS_PORT)] == '+' 10017 3 && buf[strlen(GS_PORT)+1] == '\0') 10018 3 GSsetPort(gs, port); 10019 3 else 10020 3 GSsetPort(gs, atoi(buf+strlen(GS_PORT))); 10021 3 10022 3 doneflags |= G_PORT; 10023 3 } 10024 2 10025 2 else if (strncasecmp(buf, GS_NUMB, strlen(GS_NUMB))==0) 10026 2 GSsetNum(gs, atoi(buf+strlen(GS_NUMB))); 10027 2 10028 2 else if (strncasecmp(buf, GS_ABSTRACT, strlen(GS_ABSTRACT))==0) { 10029 3 char *acp; 10030 3 10031 3 acp = buf+strlen(GS_ABSTRACT); 10032 3 10033 3 while (*(buf + strlen(buf)-1) == '\\' && bytesread >0) { 10034 4 /* A continuation line */ 10035 4 *(buf + strlen(buf)-1) = '\0'; 10036 4 GSsetAbstract(gs, acp); 10037 4 bytesread = FIOreadlinezap(fio, buf, sizeof(buf)); 10038 4 acp = buf; 10039 4 } 10040 3 GSsetAbstract(gs, acp); 10041 3 } 10042 2 else if (strncasecmp(buf, GS_ADMIN, strlen(GS_ADMIN)) == 0) 10043 2 GSsetAdmin(gs, buf +strlen(GS_ADMIN)); 10044 2 else if (strncasecmp(buf, GS_URL, strlen(GS_URL)) == 0) 10045 2 doneflags |= GSfromURL(gs, buf + strlen(GS_URL), host, port); 10046 2 #ifndef VMS_SERVER 10047 2 else if (strncmp(buf, "Domaindef=", 10)==0 && peer != NULL) { 10048 3 DomainDefault = (strcasecmp(buf+10, "no")!=0); 10049 3 Debug("Default Domain is %s\n", buf+10); 10050 3 } 10051 2 else if (strncmp(buf, "Domain=", 7) ==0 && peer != NULL) { 10052 3 /** Check to see if the peer matches the domain **/ 10053 3 int peerlen,domainlen; 10054 3 boolean TestResult = !DomainDefault; 10055 3 char *host = buf+7; 10056 3 10057 3 if (*host == '!') { 10058 4 TestResult = TRUE; 10059 4 host++; 10060 4 } 10061 3 10062 3 peerlen = strlen(peer); GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 33 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 10063 3 domainlen = strlen(host); 10064 3 10065 3 if (DidDomain == TRUE && BadDomain == FALSE) 10066 3 break; 10067 3 10068 3 if (domainlen > peerlen) { 10069 4 BadDomain = !TestResult; 10070 4 } else if (strncasecmp(buf+7, peer + peerlen - domainlen, domainlen)== 0) { 10071 4 /** Domains match, do it! **/ 10072 4 BadDomain = TestResult; 10073 4 } else 10074 3 BadDomain = !TestResult; 10075 3 10076 3 DidDomain = TRUE; 10077 3 } 10078 2 #endif 10079 2 #ifndef VMS 10080 X else if (strncmp(buf, "Domain_pat=", 11) ==0 && peer != NULL) { 10081 X char *host = buf+11; 10082 X boolean TestResult = !DomainDefault; 10083 X 10084 X if (DidDomain == TRUE && BadDomain == FALSE) 10085 X break; 10086 X 10087 X if (*host == '!') { 10088 X host++; 10089 X TestResult = TRUE; 10090 X } 10091 X 10092 X /** Check for domain using regexps **/ 10093 X if (re_comp(host) != NULL) 10094 X break; 10095 X if (re_exec(peer) == 1) 10096 X BadDomain = TestResult; 10097 X else 10098 X BadDomain = !TestResult; 10099 X 10100 X DidDomain = TRUE; 10101 X } 10102 2 #endif 10103 2 else if (strncasecmp(buf, GS_TTL, strlen(GS_TTL)) == 0) { 10104 3 GSsetTTL(gs, atoi(buf+strlen(GS_TTL))); 10105 3 } 10106 2 #ifdef VMS_SERVER 10107 X else 10108 X if (strncasecmp(buf, GS_CREATE, strlen(GS_CREATE))==0) 10109 X GSsetCreateDate(gs); 10110 X if (strncasecmp(buf, GS_MODIFY, strlen(GS_MODIFY))==0) 10111 X GSsetModifyDate(gs); 10112 X else 10113 X if (strncasecmp(buf, GS_HDDN, strlen(GS_HDDN))==0) 10114 X GSsetNum(gs, -99); 10115 X else 10116 X if (strncasecmp(buf, GS_ACCS, strlen(GS_ACCS))==0) { 10117 X if (GSgetAccess(gs) == NULL) 10118 X GSsetAccess(gs, SiteArrayNew()); 10119 X GSsetAccessSite(gs, buf+strlen(GS_ACCS)); GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 34 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 10120 X GSsetDefAcc(gs,GSgetSiteAccess(gs, "default")); 10121 X if (GSgetDefAcc(gs) == ACC_UNKNOWN) 10122 X GSsetDefAcc(gs,ACC_FULL); 10123 X } 10124 X else 10125 X if (strncasecmp(buf, GS_HEAD, strlen(GS_HEAD))==0) 10126 X GSsetHeader(gs, buf+strlen(GS_HEAD)); 10127 X else 10128 X if (strncasecmp(buf, GS_FOOT, strlen(GS_FOOT))==0) 10129 X GSsetFooter(gs, buf+strlen(GS_FOOT)); 10130 X else 10131 X if (strncasecmp(buf, GS_RHEAD, strlen(GS_RHEAD))==0) 10132 X GSsetRHeader(gs, buf+strlen(GS_RHEAD)); 10133 X else 10134 X if (strncasecmp(buf, GS_RFOOT, strlen(GS_RFOOT))==0) 10135 X GSsetRFooter(gs, buf+strlen(GS_RFOOT)); 10136 2 #endif 10137 2 else 10138 2 break; /*** Unknown name/item ***/ 10139 2 } 10140 1 10141 1 Debugmsg("Done with this link item\n"); 10142 1 10143 1 #ifdef VMS_SERVER 10144 X if (GSgetPort(gs)==0) { 10145 X char *cp; 10146 X if (cp=GSgetPath(gs)) 10147 X switch(*cp) 10148 X { 10149 X case A_INDEX: GSsetPort(gs, GDCgetSRCHPort(Config)); break; 10150 X case A_FTP: GSsetPort(gs, GDCgetFTPPort(Config)); break; 10151 X case A_EVENT: GSsetPort(gs, GDCgetEXECPort(Config)); break; 10152 X default: GSsetPort(gs,port); 10153 X } 10154 X else 10155 X GSsetPort(gs,port); 10156 X } 10157 1 #endif 10158 1 10159 1 if (BadDomain) 10160 1 return(SOFTERROR); 10161 1 10162 1 if (bytesread == 0) { 10163 2 if (doneflags & G_PATH) 10164 2 return(FOUNDEOF); /** Found the eof, plus there's a g item **/ 10165 2 else 10166 2 return(HARDERROR); /** Mangled item, plus eof, stop the game **/ 10167 2 } 10168 1 10169 1 if (doneflags & G_PATH) 10170 1 return(MORECOMING); /** Found item, more coming. **/ 10171 1 else 10172 1 return(SOFTERROR); /** Mangled item, more coming.. **/ 10173 1 } 10174 10175 10176 GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 35 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 10177 /* 10178 * Fill in a GopherObj, given a URL 10179 */ 10180 10181 10182 int 10183 GSfromURL(gs, urltxt, host, port, doneflags) 10184 GopherObj *gs; 10185 char *urltxt; 10186 char *host; 10187 int port; 10188 int doneflags; 10189 { 10190 1 char tempbuf[256]; 10191 1 Url *url; 10192 1 UrlServiceType serviceType; 10193 1 10194 1 url = URLnew(); 10195 1 URLset(url, urltxt); 10196 1 10197 1 Debug("GSfromURL: %s\r\n",urltxt); 10198 1 GSsetURL(gs, urltxt); 10199 1 serviceType = URLgetService(url); 10200 1 10201 1 switch (serviceType) { 10202 2 case http: 10203 2 if (! (doneflags & G_TYPE)) { 10204 3 /* It may not be HTML, but we lie and say it is so the */ 10205 3 /* client passes it off to a http-speaking program */ 10206 3 GSsetType(gs, A_HTML); 10207 3 doneflags |= G_TYPE; 10208 3 } 10209 2 10210 2 if (! (doneflags & G_PATH)) { 10211 3 sprintf(tempbuf, "GET /%s", URLgetPath(url)); 10212 3 GSsetPath(gs, tempbuf); 10213 3 } 10214 2 doneflags |= G_PATH; 10215 2 10216 2 break; 10217 2 10218 2 case ftp: 10219 2 if (! (doneflags & G_HOST)) { 10220 3 GSsetHost(gs, host); 10221 3 doneflags |= G_HOST; 10222 3 } 10223 2 if (! (doneflags & G_PORT)) { 10224 3 GSsetPort(gs, port); 10225 3 doneflags |= G_PORT; 10226 3 } 10227 2 break; 10228 2 10229 2 case telnet: 10230 2 if (! (doneflags & G_TYPE)) { 10231 3 GSsetType(gs, A_TELNET); 10232 3 doneflags |= G_TYPE; 10233 3 } GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 36 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 10234 2 10235 2 case tn3270: 10236 2 if (! (doneflags & G_TYPE)) { 10237 3 GSsetType(gs, A_TN3270); 10238 3 doneflags |= G_TYPE; 10239 3 } 10240 2 break; 10241 2 10242 2 case gopher: 10243 2 10244 2 if (! (doneflags & G_TYPE)) { 10245 3 GSsetType(gs, URLgetGophType(url)); 10246 3 doneflags |= G_TYPE; 10247 3 } 10248 2 10249 2 break; 10250 2 10251 2 default: 10252 2 /* A type we can't deal with... */ 10253 2 return(doneflags); 10254 2 } 10255 1 10256 1 if (! (doneflags & G_NAME)) { 10257 2 GSsetTitle(gs, URLget(url)); 10258 2 doneflags |= G_NAME; 10259 2 } 10260 1 10261 1 /* Use login & password if needed & present */ 10262 1 switch (serviceType) { 10263 2 case telnet: 10264 2 case tn3270: 10265 2 if (URLgetUser(url) != NULL) 10266 2 GSsetPath(gs, URLgetUser(url)); 10267 2 else 10268 2 GSsetPath(gs, ""); 10269 2 doneflags |= G_PATH; 10270 2 break; 10271 2 } 10272 1 10273 1 if (serviceType == ftp) { 10274 2 if (!(doneflags & G_PATH)) { 10275 3 if (URLgetPath(url) != NULL && *URLgetPath(url) != '\0') 10276 3 sprintf(tempbuf, "ftp:%s@/%s", URLgetHost(url), 10277 3 URLgetPath(url)); 10278 3 else 10279 3 sprintf(tempbuf, "ftp:%s@/", URLgetHost(url)); 10280 3 10281 3 GSsetPath(gs, tempbuf); 10282 3 doneflags |= G_PATH; 10283 3 } 10284 2 if (! (doneflags & G_TYPE)) { 10285 3 if ((*(URLgetPath(url)) == '\0') || 10286 3 *(URLgetPath(url) + strlen(URLgetPath(url))-1) == '/') 10287 3 GSsetType(gs, A_DIRECTORY); 10288 3 else 10289 3 GSsetType(gs, A_FILE); 10290 3 GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 37 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 10291 3 doneflags |= G_TYPE; 10292 3 } 10293 2 } else { 10294 2 if (! (doneflags & G_HOST)) { 10295 3 GSsetHost(gs, URLgetHost(url)); 10296 3 doneflags |= G_HOST; 10297 3 } 10298 2 if (! (doneflags & G_PORT)) { 10299 3 GSsetPort(gs, URLgetPort(url)); 10300 3 doneflags |= G_PORT; 10301 3 } 10302 2 } 10303 1 10304 1 10305 1 if (! (doneflags & G_PATH) || GSgetPath(gs) == NULL) { 10306 2 char *cp; 10307 2 GSsetPath(gs, (cp=URLgetPath(url)) ? cp : ""); 10308 2 doneflags |= G_PATH; 10309 2 } 10310 1 10311 1 return doneflags; 10312 1 } 10313 10314 10315 10316 10317 void 10318 GStoLink(gs, fd, AddInfo) 10319 GopherObj *gs; 10320 int fd; 10321 BOOLEAN AddInfo; 10322 { 10323 1 char gtype[2]; 10324 1 char portnum[16]; 10325 1 10326 1 gtype[0] = GSgetType(gs); 10327 1 gtype[1] = '\0'; 10328 1 10329 1 writestring(fd, "#"); 10330 1 writestring(fd, "\nType="); 10331 1 writestring(fd, gtype); 10332 1 if (GSisGplus(gs)) 10333 1 writestring(fd, "+"); 10334 1 writestring(fd, "\nName="); 10335 1 writestring(fd, GSgetTitle(gs)); 10336 1 writestring(fd, "\nPath="); 10337 1 writestring(fd, GSgetPath(gs)); 10338 1 writestring(fd, "\nHost="); 10339 1 writestring(fd, GSgetHost(gs)); 10340 1 writestring(fd, "\nPort="); 10341 1 sprintf(portnum, "%d", GSgetPort(gs)); 10342 1 writestring(fd, portnum); 10343 1 writestring(fd, "\n"); 10344 1 if (GSisGplus(gs) && GSgplusInited(gs) && AddInfo) { 10345 2 writestring(fd, "Admin="); 10346 2 writestring(fd, GSgetAdmin(gs)); 10347 2 writestring(fd, "\nModDate="); GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 38 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 10348 2 writestring(fd, GSgetModDate(gs)); 10349 2 writestring(fd, "\n"); 10350 2 } 10351 1 } 10352 10353 10354 boolean 10355 GSisText(gs, view) 10356 GopherObj *gs; 10357 char *view; 10358 { 10359 1 if (view == NULL) { 10360 2 switch (GSgetType(gs)) { 10361 3 case A_DIRECTORY: 10362 3 case A_FILE: 10363 3 case A_MIME: 10364 3 case A_CSO: 10365 3 case A_MACHEX: 10366 3 case A_HTML: 10367 3 return(TRUE); 10368 3 10369 3 default: 10370 3 return(FALSE); 10371 3 } 10372 2 } 10373 1 else { 10374 2 char viewstowage[64], *cp; 10375 2 10376 2 strcpy(viewstowage, view); 10377 2 if ((cp=strchr(viewstowage, ' '))!=NULL) { 10378 3 *cp = '\0'; 10379 3 view = viewstowage; 10380 3 } 10381 2 10382 2 if (strncasecmp(view, "Text",4) == 0 || 10383 2 strncasecmp(view, "message/rfc822", 14)==0 || 10384 2 strncasecmp(view, "application/postscript", 21)==0 || 10385 2 strncasecmp(view, "application/mac-binhex40", 24)==0 || 10386 2 strncasecmp(view, "application/rtf", 15) == 0 || 10387 2 strncasecmp(view, "application/gopher", 18) == 0) 10388 2 10389 2 10390 2 10391 2 return(TRUE); 10392 2 else 10393 2 return(FALSE); 10394 2 } 10395 1 } 10396 10397 #ifdef DEBUGGING 10398 void 10399 GSplusPrint(gs,head) 10400 GopherObj *gs; 10401 char *head; 10402 { 10403 1 int i; 10404 1 int oldDebug = DEBUG; GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 39 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 10405 1 DEBUG=FALSE; 10406 1 fprintf(stderr,"%s: Type=%c,Title=%s,Path=%s,Host=%s,Port=%d,Num=%d,Weight=%d,Plus=%d,Ask=%d\r\n", 10407 1 head, 10408 1 GSgetType(gs), 10409 1 GSgetTitle(gs), 10410 1 GSgetPath(gs), 10411 1 GSgetHost(gs), 10412 1 GSgetPort(gs), 10413 1 GSgetNum(gs), 10414 1 GSgetWeight(gs), 10415 1 GSisGplus(gs), 10416 1 GSisAsk(gs) 10417 1 ); 10418 1 10419 1 #ifdef VMS_SERVER 10420 X fprintf(stderr,"%*c%sAccess=%d,Head=%s,Foot=%s,RHead=%s,RFoot=%s\r\n", 10421 X strlen(head)+2,' ', 10422 X (gs->date_cr)?"Display=Create":"Display=Modify", 10423 X (gs->Access)?1:0, 10424 X GSgetHeader(gs), 10425 X GSgetFooter(gs), 10426 X GSgetRHeader(gs), 10427 X GSgetRFooter(gs) 10428 X ); 10429 1 #endif 10430 1 10431 1 if (GSgplusInited(gs)) 10432 1 for (i=0; i< GSgetNumBlocks(gs); i++) { 10433 2 BLtoNet(GSgetBlock(gs, i), fileno(stderr), TRUE); 10434 2 } 10435 1 fprintf(stderr,"===============\r\n"); 10436 1 DEBUG = oldDebug; 10437 1 } 10438 #endif 10439 10440 #ifdef VMS_SERVER 10441 X /* 10442 X * This tests to see if the current Gopher Object has an access specification 10443 X * matches the current client's address, which allows the specified access. 10444 X */ 10445 X boolean 10446 X GScanAccess(int sockfd, GopherObj *gs, int access) 10447 X { 10448 X boolean test; 10449 X 10450 X if (GSgetAccess(gs) == NULL) 10451 X return(TRUE); 10452 X 10453 X Debug("GScanAccess: Testing %s/", CurrentPeerName); 10454 X Debug("%s ", CurrentPeerIP); 10455 X Debug("for %s\n", (access==ACC_SEARCH)?"searching": 10456 X (access==ACC_READ)?"reading": 10457 X (access==ACC_BROWSE)?"browsing": 10458 X (access==ACC_FTP)?"ftping": 10459 X (access==ACC_EXEC)?"script execution": 10460 X "some unexpected access"); 10461 X test = SiteAccess(GSgetAccess(gs), CurrentPeerName, CurrentPeerIP, GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 40 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 10462 X access, 0); 10463 X if (test != SITE_OK) 10464 X if ((GSgetDefAcc(gs) & access) == access) 10465 X return(TRUE); 10466 X return(FALSE); 10467 X } 10468 X 10469 X 10470 X /* 10471 X * Fill in a GopherObj, given an HREF= link from a WWW anchor.. 10472 X * So far only works with http 10473 X */ 10474 X 10475 X void 10476 X GSfromHREF(gs, href) 10477 X GopherObj *gs; 10478 X char *href; 10479 X { 10480 X char *cp; 10481 X char *host; 10482 X char path[1024]; 10483 X 10484 X Debug("GSfromHREF %s\r\n",href) 10485 X 10486 X if (strncasecmp(href, "http://", 7)==0) { 10487 X host = href +7; 10488 X cp = strchr(href+7, '/'); 10489 X if (cp == NULL) 10490 X return; 10491 X 10492 X *cp = '\0'; 10493 X strcpy(path, "GET "); 10494 X strcat(path, cp+1); 10495 X GSsetPath(gs, path); 10496 X 10497 X GSsetType(gs, A_HTML); 10498 X 10499 X GSsetPath(gs, path); 10500 X 10501 X cp = strchr(host, ':'); 10502 X if (cp==NULL) 10503 X GSsetPort(gs, 80); /** default WWW port **/ 10504 X else { 10505 X GSsetPort(gs, atoi(cp+1)); 10506 X *cp = '\0'; 10507 X } 10508 X 10509 X GSsetHost(gs, host); 10510 X } 10511 X } 10512 X 10513 X void 10514 X GStoNetHTML(gs, sockfd) 10515 X GopherObj *gs; 10516 X int sockfd; 10517 X { 10518 X static char buf[1024]; GSGOPHEROBJ 22-SEP-1995 18:31:01 VAX C V3.2-044 Page 41 V1.0 21-SEP-1995 12:54:05 GSGOPHEROBJ.C;8 (1) 10519 X static char pathbuf[1024]; 10520 X 10521 X buf[0] = '\0'; 10522 X pathbuf[0] = '\0'; 10523 X 10524 X /** Convert Path so that spaces are %20 **/ 10525 X Tohexstr(GSgetPath(gs), pathbuf); 10526 X 10527 X sprintf(buf, "%s", 10528 X GSgetHost(gs), 10529 X GSgetPort(gs), 10530 X pathbuf, 10531 X GSgetTitle(gs)); 10532 X 10533 X writestring(sockfd, buf); 10534 X 10535 X Debug("HTML: %s\n", buf); 10536 X 10537 X if (GSgetWeight(gs) != 0) { 10538 X sprintf(buf, "Score: %d\r\n", GSgetWeight(gs)); 10539 X writestring(sockfd, buf); 10540 X } 10541 X else 10542 X writestring(sockfd, "\r\n"); 10543 X 10544 X } 10545 #endif Command Line ------------ CC/INCL=([-],[-.OBJECT])/DEFINE=(MULTINET=1,DEBUGGING,__VMS)/DEBUG/NOOPT/OBJ=[.VAX.DBG]/LIS=[.VAX.LIS] GSGOPHEROBJ.C .