OSDN Git Service

Initial commit
[wordring-tm/wordring-tm.git] / third_party / tidy-html5-master / experimental / httpio.c
1 #include "tmbstr.h"
2
3 #include "httpio.h"
4
5 int
6 makeConnection ( HTTPInputSource *pHttp )
7 {
8     struct sockaddr_in sock;
9     struct hostent *pHost;
10
11     /* Get internet address of the host. */
12     if (!(pHost = gethostbyname ( pHttp->pHostName )))
13     {
14         return -1;
15     }
16     /* Copy the address of the host to socket description.  */
17     memcpy (&sock.sin_addr, pHost->h_addr, pHost->h_length);
18
19     /* Set port and protocol */
20     sock.sin_family = AF_INET;
21     sock.sin_port = htons( pHttp->nPort );
22
23     /* Make an internet socket, stream type.  */
24     if ((pHttp->s = socket (AF_INET, SOCK_STREAM, 0)) == -1)
25         return -1;
26
27     /* Connect the socket to the remote host.  */
28     if (connect (pHttp->s, (struct sockaddr *) &sock, sizeof( sock )))
29     {
30         if (errno == ECONNREFUSED)
31             return ECONNREFUSED;
32         else
33             return -1;
34     }
35     return 0;
36 }
37
38
39 int parseURL( HTTPInputSource *pHttp, tmbstr url )
40 {
41   int i, j = 0;
42   ctmbstr pStr;
43
44     pStr = tmbsubstr( url, "://" );
45
46     /* If protocol is there, but not http, bail out, else assume http.  */
47     if (NULL != pStr)
48     {
49         if (tmbstrncasecmp( url, "http://", 7 ))
50             return -1;
51     }
52
53     if (NULL != pStr)
54         j = pStr - url + 3;
55     for (i = j; url[i] && url[i] != ':' && url[i] != '/'; i++) {}
56     if (i == j)
57         return -1;
58
59     /* Get the hostname.  */
60     pHttp->pHostName = tmbstrndup (&url[j], i - j );
61
62     if (url[i] == ':')
63     {
64         /* We have a colon delimiting the hostname.  It should mean that
65         a port number is following it */
66         pHttp->nPort = 0;
67         if (isdigit( url[++i] ))    /* A port number */
68         {
69             for (; url[i] && url[i] != '/'; i++)
70             {
71                 if (isdigit( url[i] ))
72                     pHttp->nPort = 10 * pHttp->nPort + (url[i] - '0');
73                 else
74                     return -1;
75             }
76             if (!pHttp->nPort)
77                 return -1;
78         }
79         else                      /* or just a misformed port number */
80             return -1;
81     }
82     else
83         /* Assume default port.  */
84         pHttp->nPort = 80;
85
86     /* skip past the delimiting slash (we'll add it later )  */
87     while (url[i] && url[i] == '/')
88         i++;
89     pHttp->pResource = tmbstrdup (url + i );
90     return 0;
91 }
92
93
94 int fillBuffer( HTTPInputSource *in )
95 {
96     if (0 < in->s)
97     {
98         in->nBufSize = recv( in->s, in->buffer, sizeof( in->buffer ), 0);
99         in->nextBytePos = 0;
100         if (in->nBufSize < sizeof( in->buffer ))
101             in->buffer[in->nBufSize] = '\0';
102     }
103     else
104         in->nBufSize = 0;
105     return in->nBufSize;
106 }
107
108
109 int openURL( HTTPInputSource *in, tmbstr pUrl )
110 {
111     int rc = -1;
112 #ifdef WIN32    
113     WSADATA wsaData;
114
115     rc = WSAStartup( 514, &wsaData );
116 #endif
117
118     in->tis.getByte = (TidyGetByteFunc) HTTPGetByte; 
119     in->tis.ungetByte = (TidyUngetByteFunc) HTTPUngetByte;
120     in->tis.eof = (TidyEOFFunc) HTTPIsEOF;
121     in->tis.sourceData = (uint) in;
122     in->nextBytePos = in->nextUnGotBytePos = in->nBufSize = 0;
123     parseURL( in, pUrl );
124     if (0 == (rc = makeConnection( in )))
125     {
126         char ch, lastCh = '\0';
127         int blanks = 0;
128
129         char *getCmd = MemAlloc( 48 + strlen( in->pResource ));
130         sprintf( getCmd, "GET /%s HTTP/1.0\r\nAccept: text/html\r\n\r\n", in->pResource );
131         send( in->s, getCmd, strlen( getCmd ), 0 );
132         MemFree( getCmd );
133
134         /*  skip past the header information  */
135         while (   in->nextBytePos >= in->nBufSize
136                && 0 < (rc = fillBuffer( in )))
137         {
138             if (1 < blanks)
139                 break;
140             for (; in->nextBytePos < sizeof( in->buffer ) 
141                    && 0 != in->buffer[ in->nextBytePos ]; 
142                  in->nextBytePos++ )
143             {
144                 ch = in->buffer[ in->nextBytePos ];
145                 if (ch == '\r' || ch == '\n')
146                 {
147                     if (ch == lastCh)
148                     {
149                         /*  Two carriage returns or two newlines in a row,
150                             that's good enough */
151                         blanks++;
152                     }
153                     if (lastCh == '\r' || lastCh == '\n')
154                     {
155                         blanks++;
156                     }
157                 }
158                 else
159                     blanks = 0;
160                 lastCh = ch;
161                 if (1 < blanks)
162                 {
163                     /* end of header, scan to first non-white and return */
164                     while ('\0' != ch && isspace( ch ))
165                         ch = in->buffer[ ++in->nextBytePos ];
166                     break;
167                 }
168             }
169         }
170     }
171     return rc;
172 }
173
174
175 void closeURL( HTTPInputSource *source )
176 {
177     if (0 < source->s)
178         closesocket( source->s );
179     source->s = -1;
180     source->tis.sourceData = 0;
181 #ifdef WIN32
182     WSACleanup();
183 #endif
184 }
185
186
187 int HTTPGetByte( HTTPInputSource *source )
188 {
189     if (source->nextUnGotBytePos)
190         return source->unGetBuffer[ --source->nextUnGotBytePos ];
191     if (0 != source->nBufSize && source->nextBytePos >= source->nBufSize)
192     {
193         fillBuffer( source );
194     }
195     if (0 == source->nBufSize)
196         return EndOfStream;
197     return source->buffer[ source->nextBytePos++ ];
198 }
199
200 void HTTPUngetByte( HTTPInputSource *source, uint byteValue )
201 {
202     if (source->nextUnGotBytePos < 16 )  /* Only you can prevent buffer overflows */
203         source->unGetBuffer[ source->nextUnGotBytePos++ ] = (char) byteValue;
204 }
205
206 Bool HTTPIsEOF( HTTPInputSource *source )
207 {
208     if (source->nextUnGotBytePos)
209         /* pending ungot bytes, not done */
210         return no;
211
212     if (   0 != source->nBufSize 
213         && source->nextBytePos >= source->nBufSize)
214         /* We've consumed the existing buffer, get another */
215         fillBuffer( source );
216
217     if (source->nextBytePos < source->nBufSize)
218         /*  we have stuff in the buffer, must not be done. */
219         return no;
220
221     /* Nothing in the buffer, and the last receive failed, must be done.  */
222     return yes;
223 }
224