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