1 /********************************************************************
2  * $Author: jgoerzen $
3  * $Revision: 1.4 $
4  * $Date: 2002/03/19 16:57:41 $
5  * $Source: /home/jgoerzen/tmp/gopher-umn/gopher/head/object/url.c,v $
6  * $State: 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: url.c
14  * Simplified method of getting urls..
15  *********************************************************************
16  * Revision History:
17  * $Log: url.c,v $
18  * Revision 1.4  2002/03/19 16:57:41  jgoerzen
19  * Fixed type handling.
20  *
21  * Revision 1.3  2001/01/17 21:16:35  jgoerzen
22  * More psinrtf -> snprintf changes
23  *
24  * Revision 1.2  2000/12/20 01:19:20  jgoerzen
25  * Added patches from David Allen <s2mdalle@titan.vcu.edu>
26  *
27  * Revision 1.1.1.1  2000/08/19 00:28:56  jgoerzen
28  * Import from UMN Gopher 2.3.1 after GPLization
29  *
30  * Revision 3.19  1995/10/31  16:53:57  lindner
31  * Small fix for ftp urls..
32  *
33  * Revision 3.18  1995/09/25  22:07:24  lindner
34  * Ansification
35  *
36  * Revision 3.17  1995/08/29  07:13:07  lindner
37  * Add tickets to urls
38  *
39  * Revision 3.16  1995/02/06  22:10:47  lindner
40  * Fix for systems without strstr, compiler casts
41  *
42  * Revision 3.15  1994/12/05  22:47:19  lindner
43  * Fixed settings of Gopher Type in URLparse()
44  *
45  * Revision 3.14  1994/11/18  22:45:55  lindner
46  * Remove unused variable
47  *
48  * Revision 3.13  1994/11/18  21:41:48  lindner
49  * Fix order of FTP arguments
50  *
51  * Revision 3.12  1994/11/13  06:30:06  lindner
52  * Expanded URL parsing routines
53  *
54  * Revision 3.11  1994/10/13  05:25:56  lindner
55  * Compiler complaint fixes
56  *
57  * Revision 3.10  1994/08/19  16:28:30  lindner
58  * More hexification of URL strings
59  *
60  * Revision 3.9  1994/07/25  03:51:41  lindner
61  * Compiler fix
62  *
63  * Revision 3.8  1994/07/21  22:17:20  lindner
64  * Add ftp urls
65  *
66  * Revision 3.7  1994/03/04  17:42:57  lindner
67  * Fixes from Alan Coopersmith
68  *
69  * Revision 3.6  1994/01/21  04:25:41  lindner
70  * Add support for tn3270 and better gopher url handling
71  *
72  * Revision 3.5  1993/12/30  04:18:08  lindner
73  * translate telnet url correctly
74  *
75  * Revision 3.4  1993/12/27  16:14:03  lindner
76  * Enlarge buffer size, make html docs on gopher server into http: refs
77  *
78  * Revision 3.3  1993/11/02  06:14:09  lindner
79  * Add url html hack
80  *
81  *
82  *********************************************************************/
83 
84 #include "url.h"
85 #include "GSgopherobj.h"
86 #include "Malloc.h"
87 #include "String.h"
88 #include "compatible.h"
89 
90 Url *
URLnew()91 URLnew()
92 {
93      Url *temp;
94 
95      temp = (Url *) malloc(sizeof(Url));
96      temp->url  = STRnew();
97      temp->Host = STRnew();
98      temp->Port = -1;
99      temp->Path = STRnew();
100      temp->User = STRnew();
101      temp->Pass = STRnew();
102      temp->Gtype = '\0';
103 
104      URLsetService(temp, unset);
105      return(temp);
106 }
107 
108 
109 void
URLdestroy(Url * url)110 URLdestroy(Url *url)
111 {
112      STRdestroy(url->url);
113      STRdestroy(url->Host);
114      STRdestroy(url->Path);
115      STRdestroy(url->User);
116      STRdestroy(url->Pass);
117 
118      free(url);
119 }
120 
121 
122 
123 /*
124  * Make a default url from the current Gopher Object...
125  */
126 
127 void
URLfromGS(Url * url,GopherObj * gs,char * ticket)128 URLfromGS(Url *url, GopherObj *gs, char *ticket)
129 {
130      char u[2048], *path, *cp;
131 
132      *u = '\0';
133      path  = GSgetPath(gs);
134 
135      if (GSgetHost(gs) == NULL)
136 	  return;
137 
138      if ((GSgetType(gs) == A_TN3270) || (GSgetType(gs) == A_TELNET)) {
139 	  /* [telnet|tn3270]://[host]@[login]:[port] */
140 	  if (GSgetType(gs) == A_TELNET)
141 	       strcpy(u,"telnet://");
142 	  else
143 	       strcpy(u,"tn3270://");
144 	  Tohexstr(GSgetHost(gs), u + 9);
145 	  if ( (path != NULL) && (*path != '\0') ) {
146 	       cp = u + strlen(u);
147 	       *(cp++) = '@';
148 	       Tohexstr(path, cp);
149 	  }
150 	  snprintf(u + strlen(u),
151 		   sizeof(u) - strlen(u) - 1,
152 		   ":%d", GSgetPort(gs));
153      }
154      else if (path != NULL)
155      {
156 	  if (strncmp(path, "GET /", 5) == 0) {
157 	       /* http://[host]:[port][path without "GET "] */
158 	       strcpy(u, "http://");
159 	       Tohexstr(GSgetHost(gs), u+7);
160 	       snprintf(u + strlen(u),
161 			sizeof(u) - strlen(u) - 1,
162 			":%d", GSgetPort(gs));
163 	       Tohexstr(path + 4, u + strlen(u));
164 	  } else if (strncmp(path, "ftp:", 4) == 0) {
165 	       /** ftp://[host]/[pathname]; **/
166 	       char *atsign;
167 	       if (path[4] == '/' && path [5] == '/') {
168 		    strcpy(u, path);
169 	       } else {
170 		    strcpy(u, "ftp://");
171 		    strcat(u, path + 4);
172 		    atsign = strchr(u, '@');
173 		    if (atsign != NULL)
174 			 Tohexstr( path + (atsign-u)-1, atsign );
175 	       }
176 	  } else {
177 	       /* gopher://[host]:[port]/[type][path] */
178 	       strcpy(u, "gopher://");
179 	       Tohexstr(GSgetHost(gs), u + 9);
180 	       snprintf(u + strlen(u),
181 			sizeof(u) - strlen(u) - 1,
182 			":%d/%c", GSgetPort(gs), GSgetType(gs));
183 	       if (ticket != NULL && strlen(ticket) > 0)
184 		    Tohexstr(ticket, u+strlen(u));
185 	       Tohexstr(path, u + strlen(u));
186 	  }
187      }
188      URLset(url, u);
189 }
190 
191 /*
192  * Hack gopher directories into an HTML type...
193  */
194 
195 void
URLmakeHTML(Url * url)196 URLmakeHTML(Url *url)
197 {
198      char *cp = URLget(url);
199 
200      if (cp == NULL)
201 	  return;
202 
203      if (strncmp(cp, "gopher://", 9) != 0)
204 	  return;
205 
206      /** find the type character **/
207      cp = strchr(cp+10, '/');
208 
209      if (cp ==NULL)
210 	  return;
211 
212      /** Test link for current host **/
213 /*   host = cp+10;
214      if (strcasecmp(host, hostname) != 0)
215 	  return;*/
216 
217      cp ++;
218      /** cp is now pointed at the type character **/
219 
220      if (*cp == '1' && *(cp+1) == '1') {
221 	  /** It's a directory **/
222 	  *cp = 'h';
223 	  *(cp+1) = 'h';
224      }
225 }
226 
227 
228 /*
229  * Get the transport of the specified URL
230  */
231 
232 UrlServiceType
URLgetService(Url * url)233 URLgetService(Url *url)
234 {
235      UrlServiceType st;
236 
237      if (url->service == unset) {
238 	  char *urlcp;
239 
240 	  urlcp = URLget(url);
241 
242 	  if (urlcp == NULL)
243 	       return(unknown);
244 
245 	  st = unknown;
246 
247 	  if (strncasecmp("ftp:", urlcp, 4)==0)
248 	       st = ftp;
249 	  else if (strncasecmp(urlcp, "gopher:", 7)==0)
250 	       st = gopher;
251 	  else if (strncasecmp(urlcp, "telnet:", 7)==0)
252 	       st = telnet;
253 	  else if (strncasecmp(urlcp, "tn3270:", 7)==0)
254 	       st = tn3270;
255 	  else if (strncasecmp(urlcp, "http:", 5)==0)
256 	       st = http;
257 
258 	  URLsetService(url, st);
259      }
260      return(url->service);
261 }
262 
263 static boolean
URLparse(Url * url)264 URLparse(Url *url)
265 {
266      char *cp, *cp2, *cp3, *urlcp;
267      UrlServiceType serviceType;
268 
269      serviceType = URLgetService(url);
270 
271      if (serviceType == unknown)
272 	  return(FALSE);
273 
274      urlcp = URLget(url);
275 
276      if (urlcp == NULL)
277 	  return(FALSE);
278 
279      urlcp = strdup(urlcp);       /* This lets us scribble on the string */
280 
281      cp = strstr(urlcp, "://");   /* skip over servicetype + "://" */
282 
283      if (cp == NULL)
284 	  return(FALSE);
285 
286      cp += 3;
287 
288      cp3 = strchr(cp, '/');  /* end of login:passwd@host:port/ section */
289 
290      if (cp3 == NULL) {
291 	  cp3 = cp + strlen(cp) + 1; /* No slash at the end... */
292 	  URLsetPath(url, "/");
293      } else {
294 	  Fromhexstr(cp3, cp3);
295 	  URLsetPath(url,cp3);
296 	  *(cp3++) = '\0';      /* trunc the host part, remove sep slash, now
297                                    cp3 points at the type. */
298      }
299 
300      if (serviceType == gopher) {
301 	  if (cp3 != NULL && (int)strlen(cp3) > 1) {
302 	       URLsetGophType(url, *(cp3++));
303 	       URLsetPath(url,cp3++);
304 	  } else {
305 	       URLsetGophType(url, '1');
306           }
307      }
308 
309 
310      /*
311       * Find Username/pass for ftp/telnet
312       */
313 
314      cp2 = strchr(cp, '@');
315      if ((cp2 != NULL) && (cp2 < cp3)) {
316 	  char *pass;
317 
318 
319 	  *cp2 = '\0';
320 	  cp2++;
321 
322 	  pass = strchr(cp, ':');
323 	  if ((pass != NULL) && (pass < cp3)) {
324 	       *pass = '\0';
325 	       pass++;
326 	       Fromhexstr(pass, pass);
327 
328 	       URLsetPass(url, pass);
329 
330 	  }
331 	  URLsetUser(url, cp);
332 
333 	  cp = cp2;               /** cp now points to hostname **/
334      }
335 
336      /*
337       * Find port
338       */
339 
340      cp2 = strchr(cp, ':');
341 
342      if ((cp2 != NULL) && (cp2 < cp3)) {
343 	  *cp2 = '\0';
344 	  cp2++;
345 	  URLsetPort(url, atoi(cp2));
346 	  URLsetHost(url, cp);
347      } else {
348 	  switch (serviceType) {
349 	  case http:
350 	       URLsetPort(url, 80);
351 	       break;
352 	  case telnet:
353 	  case tn3270:
354 	       URLsetPort(url, 23);
355 	       break;
356 	  case gopher:
357 	       URLsetPort(url, 70);
358 	       break;
359 	  case news:
360 	       URLsetPort(url, 119);
361                break;
362           case ftp:
363           case unset:
364           case unknown:
365 	  break;
366 	}
367 	  URLsetHost(url, cp);
368      }
369 
370 
371      return(TRUE);
372 }
373 
374 
375 
376 char *
URLgetHost(Url * url)377 URLgetHost(Url *url)
378 {
379      if (STRget(url->Host) == NULL)
380 	  URLparse(url);
381 
382      return(STRget(url->Host));
383 }
384 
385 int
URLgetPort(Url * url)386 URLgetPort(Url *url)
387 {
388      if (url->Port == -1)
389 	  URLparse(url);
390 
391      return(url->Port);
392 }
393 
394 
395 char *
URLgetPath(Url * url)396 URLgetPath(Url *url)
397 {
398      if (STRget(url->Path) == NULL)
399 	  URLparse(url);
400      return(STRget(url->Path));
401 }
402 
403 char *
URLgetUser(Url * url)404 URLgetUser(Url *url)
405 {
406      if (STRget(url->User) == NULL)
407 	  URLparse(url);
408      return(STRget(url->User));
409 }
410 
411 char *
URLgetPass(Url * url)412 URLgetPass(Url *url)
413 {
414      if (STRget(url->Pass) == NULL)
415 	  URLparse(url);
416      return(STRget(url->Pass));
417 }
418 
419 
420 char
URLgetGophType(Url * url)421 URLgetGophType(Url *url)
422 {
423      if (URLgetService(url) != gopher)
424 	  return('\0');
425 
426      if (url->Gtype == '\0')
427 	  URLparse(url);
428      return(url->Gtype);
429 }
430 
431