1+ #include <time.h>
2+ #include <stdio.h>
3+ #include <string.h>
4+ #include <WinSock2.h>
5+ // #pragma comment(lib, "ws2_32.lib") //加载 ws2_32.dll
6+
7+ typedef void Fun (char * , int );
8+
9+ #define MAXLINE 100
10+ #define MAXRECV 0xfff
11+ #define PROXY_IP "192.168.10.1"
12+ #define PROXY_PORT 1088
13+ #define PROXY_FLAG 1
14+
15+ FILE * fp = NULL ;
16+ _Bool dowm_flag = 0 ;
17+
18+ const char * format_headers = (
19+ "GET %s HTTP/1.1\r\n"
20+ "Host: %s\r\n"
21+ "Connection: keep-alive\r\n"
22+ "Accept: */*\r\n"
23+ "%s"
24+ "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.47\r\n\r\n"
25+ );
26+
27+ void get_admin (const char * url , char * admin )
28+ {
29+ int start = 7 ;
30+ if (strstr (url , "https" ))
31+ start ++ ;
32+ char * r1 = strchr (url + start , ':' );
33+ char * r2 = strchr (url + start , '/' );
34+ int admin_len = r1 ? r1 - url - start : r2 ? r2 - url - start : strlen (url )- start ;
35+
36+ strncpy (admin , url + start , admin_len );
37+ }
38+
39+ void get_admin_ip (const char * url , char * ip )
40+ {
41+ char admin [30 ] = {0 };
42+ get_admin (url , admin );
43+
44+ struct hostent * phst = gethostbyname (admin );
45+ struct in_addr * iddr = (struct in_addr * )phst -> h_addr ;
46+ inet_ntoa (* iddr );
47+ strcpy (ip , inet_ntoa (* iddr ));
48+ }
49+
50+ int get_url_port (const char * url )
51+ {
52+ int port ;
53+ char * p ;
54+
55+ if (p = strchr (url + 7 , ':' ))
56+ {
57+ sscanf (p + 1 , "%d" , & port );
58+ return port ;
59+ }
60+
61+ char * ret = strstr (url , "https" );
62+ return ret ? 443 : 80 ;
63+ }
64+
65+ _Bool get_file_name (char * header , char * filename )
66+ {
67+ char str [200 ];
68+ char * p ;
69+ p = strstr (header , "Content-Disposition" );
70+ if (p == NULL ) return 0 ;
71+ sscanf (p , "%*s %[^\n]" , str );
72+ p = strchr (str , '\'' );
73+ if (p == NULL ) return 0 ;
74+ p += 2 ;
75+ strncpy (filename , p , strlen (p )- 1 );
76+ filename [strlen (p )- 1 ] = '\0' ;
77+
78+ return 1 ;
79+ }
80+
81+ void check_type (const char * url , char * type , char * filename , int nameflag )
82+ {
83+ char type_list [][15 ] = {"json" , "text" , "html" , "x-javascript" };
84+
85+ if (type == NULL )
86+ return ;
87+
88+ for (int i = 0 ; i < 4 ; i ++ )
89+ {
90+ if (strstr (type , type_list [i ]))
91+ return ;
92+ }
93+
94+ if (!nameflag )
95+ {
96+ char * p = strrchr (url , '/' ) + 1 ;
97+ char * q = strrchr (p , '?' );
98+ if (q )
99+ {
100+ strncpy (filename , p , q - p );
101+ filename [q - p ] = '\0' ;
102+ }
103+ else
104+ {
105+ strncpy (filename , p , strlen (p ));
106+ filename [strlen (p )] = '\0' ;
107+ }
108+ if (strchr (p , '.' ) == NULL )
109+ {
110+ char ext [10 ] = {0 };
111+ ext [0 ] = '.' ;
112+
113+ sscanf (type , "%*[^/]/%[a-zA-Z]" , ext + 1 );
114+ strcat (filename , ext );
115+ }
116+ }
117+ fp = fopen (filename , "wb" );
118+ dowm_flag = 1 ;
119+ }
120+
121+ void request (const char * sUrl , Fun * fun )
122+ {
123+ struct sockaddr_in servaddr ;
124+ clock_t start , end ;
125+ SOCKET sockfd ;
126+
127+ char buf [MAXRECV + 1 ] = {0 };
128+ char send_msg [strlen (format_headers ) + strlen (sUrl )* 2 ];
129+ char data_type [10 ] = "text/plain" ;
130+ char header [2500 ] = {0 };
131+ char admin [30 ] = {0 };
132+ char filename [100 ];
133+ char ip [20 ] = {0 };
134+ _Bool chunked = 1 ;
135+ int header_len = 0 ;
136+ int cont_len = 0 ;
137+ int data_len = 0 ;
138+ int status = 0 ;
139+ int r_len ;
140+ int port ;
141+ char * p ;
142+ char * q ;
143+
144+ WSADATA wsaData ;
145+ WSAStartup (MAKEWORD (2 , 2 ), & wsaData );
146+
147+ port = get_url_port (sUrl );
148+ get_admin (sUrl , admin );
149+ get_admin_ip (sUrl , ip );
150+ sprintf (send_msg , format_headers , sUrl , admin , \
151+ strstr (admin , "i.pximg.net" )?"referer: http://www.pixiv.net/\r\n" :""
152+ );
153+
154+ sockfd = socket (AF_INET , SOCK_STREAM , 0 );
155+
156+ memset (& servaddr , 0 , sizeof (servaddr ));
157+
158+ servaddr .sin_family = AF_INET ;
159+ servaddr .sin_addr .s_addr = inet_addr (PROXY_FLAG ?PROXY_IP :ip );
160+ servaddr .sin_port = htons (PROXY_FLAG ?PROXY_PORT :port );
161+
162+ connect (sockfd , (struct sockaddr * )& servaddr , sizeof (servaddr ));
163+ send (sockfd , send_msg , strlen (send_msg ), 0 );
164+
165+ start = clock ();
166+
167+ while (1 )
168+ {
169+ memset (buf , 0 , sizeof (buf ));
170+ r_len = recv (sockfd , buf , MAXBYTE , 0 );
171+ memmove (header + header_len , buf , r_len );
172+ header_len += r_len ;
173+ p = strstr (header , "\r\n\r\n" );
174+ if (p )
175+ {
176+ p [0 ] = '\0' ;
177+ p += 4 ;
178+ data_len = header_len - (p - header );
179+ break ;
180+ }
181+ }
182+
183+ sscanf (header , "%*s %d" , & status );
184+ if (q = strstr (header , "Content-Type" ))
185+ sscanf (q , "%*s %s" , data_type );
186+ check_type (sUrl , data_type , filename , get_file_name (header , filename ));
187+
188+ // 打印 response
189+ if (status != 200 )
190+ printf ("\n%s\n\n" , header );
191+ fun (p , data_len );
192+
193+ if (strstr (header , "Transfer-Encoding: chunked" ) == NULL )
194+ {
195+ chunked = 0 ;
196+ p = strstr (header , "Content-Length" );
197+ sscanf (p , "%*s %d" , & cont_len );
198+ }
199+
200+ while (1 )
201+ {
202+ if (!chunked )
203+ {
204+ if (data_len >= cont_len ) break ;
205+ }
206+ else
207+ {
208+ if (strstr (buf , "\r\n0\r\n\r\n" )) break ;
209+ }
210+ r_len = recv (sockfd , buf , MAXRECV , 0 );
211+ buf [r_len ] = '\0' ;
212+ data_len += r_len ;
213+ fun (buf , r_len );
214+ if (dowm_flag )
215+ {
216+ end = clock ();
217+ printf ("\r" );
218+ printf ("downloading %d/%d bytes %.0f%% - %.1fs" ,\
219+ data_len , cont_len , (data_len /(float )cont_len )* 100 , (end - start )/1000.0
220+ );
221+ }
222+ }
223+
224+ fclose (fp );
225+ closesocket (sockfd );
226+ WSACleanup ();
227+
228+ return ;
229+ }
230+
231+ void process_data (char * str , int len )
232+ {
233+ if (!dowm_flag )
234+ {
235+ printf ("%s" , str );
236+ }
237+ else
238+ {
239+ fwrite (str , sizeof (char ), len , fp );
240+ }
241+ }
242+
243+ void https_to_http (char * * url )
244+ {
245+ if (url [1 ][4 ] == 's' )
246+ {
247+ memmove (url [1 ]+ 1 , "http" , 4 );
248+ url [1 ]++ ;
249+ }
250+ }
251+
252+ int main (int argc , char * argv [])
253+ {
254+ clock_t start , end ;
255+ // char *url = "http://tva1.sinaimg.cn/large/ec43126fgy1h1753rj0z3j20k00zk7b7.jpg";
256+ // char *url = "http://api.lolicon.app/setu/v2";
257+
258+ if (argc < 2 )
259+ {
260+ printf ("usage: ./request url\n" );
261+ exit (0 );
262+ }
263+
264+ if (argc < 3 || !strstr (argv [2 ], "-b" ))
265+ system ("chcp 65001" );
266+
267+ https_to_http (argv );
268+ printf ("\n" );
269+ start = clock ();
270+ request (argv [1 ], process_data );
271+ // request(url, process_data);
272+ end = clock ();
273+
274+ printf ("\n\nexecution time %f seconds\n" , (end - start )/1000.0 );
275+
276+ return 0 ;
277+ }
0 commit comments