(HZK1-D652): Use A-cgnU+8609 instead of U+8609 as its mother.
[chise/xemacs-chise.git.1] / netinstall / nio-http.cc
1 /*
2  * Copyright (c) 2000, Red Hat, Inc.
3  *
4  *     This program is free software; you can redistribute it and/or modify
5  *     it under the terms of the GNU General Public License as published by
6  *     the Free Software Foundation; either version 2 of the License, or
7  *     (at your option) any later version.
8  *
9  *     A copy of the GNU General Public License can be found at
10  *     http://www.gnu.org/
11  *
12  * Written by DJ Delorie <dj@cygnus.com>
13  *
14  */
15
16 /* This file is responsible for implementing all direct HTTP protocol
17    channels.  It is intentionally simplistic. */
18
19 #include "win32.h"
20 #include "winsock.h"
21 #include <stdio.h>
22 #include <stdlib.h>
23
24 #include "resource.h"
25 #include "state.h"
26 #include "simpsock.h"
27 #include "msg.h"
28
29 #include "netio.h"
30 #include "nio-http.h"
31
32 static char six2pr[64] = {
33     'A','B','C','D','E','F','G','H','I','J','K','L','M',
34     'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
35     'a','b','c','d','e','f','g','h','i','j','k','l','m',
36     'n','o','p','q','r','s','t','u','v','w','x','y','z',
37     '0','1','2','3','4','5','6','7','8','9','+','/'
38 };
39
40 static char *
41 base64_encode (char *username, char *password)
42 {
43   unsigned char *ep;
44   char *rp;
45   static char *rv = 0;
46   if (rv)
47     free (rv);
48   rv = (char *) malloc (2 * (strlen (username) + strlen (password)) + 5);
49
50   char *up = (char *) malloc (strlen (username) + strlen (password) + 6);
51   strcpy (up, username);
52   strcat (up, ":");
53   strcat (up, password);
54   ep = (unsigned char *)up + strlen (up);
55   *ep++ = 0;
56   *ep++ = 0;
57   *ep++ = 0;
58
59   char block[4];
60
61   rp = rv;
62
63   for (ep = (unsigned char *)up; *ep; ep += 3)
64     {
65       block[0] = six2pr[ep[0] >> 2];
66       block[1] = six2pr[((ep[0] << 4) & 0x30) | ((ep[1] >> 4) & 0x0f)];
67       block[2] = six2pr[((ep[1] << 2) & 0x3c) | ((ep[2] >> 6) & 0x03)];
68       block[3] = six2pr[ep[2] & 0x3f];
69
70       if (ep[1] == 0)
71         block[2] = block[3] = '=';
72       if (ep[2] == 0)
73         block[3] = '=';
74       memcpy (rp, block, 4);
75       rp += 4;
76     }
77   *rp = 0;
78
79   free (up);
80
81   return rv;
82 }
83
84 NetIO_HTTP::NetIO_HTTP (char *Purl)
85   : NetIO (Purl)
86 {
87  retry_get:
88   if (port == 0)
89     port = 80;
90
91   if (net_method == IDC_NET_PROXY)
92     s = new SimpleSocket (net_proxy_host, net_proxy_port);
93   else
94     s = new SimpleSocket (host, port);
95
96   if (!s->ok())
97     {
98       s = 0;
99       return;
100     }
101
102   if (net_method == IDC_NET_PROXY)
103     s->printf ("GET %s HTTP/1.0\r\n", url);
104   else
105     s->printf ("GET %s HTTP/1.0\r\n", path);
106   s->printf ("Host: %s:%d\r\n", host, port);
107
108   if (net_user && net_passwd)
109     s->printf ("Authorization: Basic %s\r\n",
110                base64_encode (net_user, net_passwd));
111
112   if (net_proxy_user && net_proxy_passwd)
113     s->printf ("Proxy-Authorization: Basic %s\r\n",
114                base64_encode (net_proxy_user, net_proxy_passwd));
115
116   s->printf ("\r\n");
117
118   char *l = s->gets ();
119   int code;
120   sscanf (l, "%*s %d", &code);
121   if (code >= 300 && code < 400)
122     {
123       do {
124         l = s->gets ();
125         if (_strnicmp (l, "Location:", 9) == 0)
126           {
127             char *u = l + 9;
128             while (*u == ' ' || *u == '\t')
129               u++;
130             set_url (u);
131             delete s;
132             goto retry_get;
133           }
134       } while (*l);
135     }
136   if (code == 401) /* authorization required */
137     {
138       get_auth ();
139       delete s;
140       goto retry_get;
141     }
142   if (code == 407) /* proxy authorization required */
143     {
144       get_proxy_auth ();
145       delete s;
146       goto retry_get;
147     }
148   if (code >= 300)
149     {
150       delete s;
151       s = 0;
152       return;
153     }
154   do {
155     l = s->gets ();
156     if (_strnicmp (l, "Content-Length:", 15) == 0)
157       sscanf (l, "%*s %d", &file_size);
158   } while (*l);
159 }
160
161 NetIO_HTTP::~NetIO_HTTP ()
162 {
163   if (s)
164     delete s;
165 }
166
167 int
168 NetIO_HTTP::ok ()
169 {
170   if (s)
171     return 1;
172   return 0;
173 }
174
175 int
176 NetIO_HTTP::read (char *buf, int nbytes)
177 {
178   return s->read (buf, nbytes);
179 }