1 /*
2  * lftp - file transfer program
3  *
4  * Copyright (c) 1996-2016 by Alexander V. Lukyanov (lav@yars.free.net)
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef HTTP_H
21 #define HTTP_H
22 
23 #include "NetAccess.h"
24 #include "buffer.h"
25 #include "lftp_ssl.h"
26 #include "HttpHeader.h"
27 #include "HttpAuth.h"
28 
29 class Http : public NetAccess
30 {
31    enum state_t
32    {
33       DISCONNECTED,
34       CONNECTING,
35       CONNECTED,
36       RECEIVING_HEADER,
37       RECEIVING_BODY,
38       DONE
39    };
40 
41    enum tunnel_state_t {
42       NO_TUNNEL,
43       TUNNEL_WAITING,
44       TUNNEL_ESTABLISHED
45    };
46 
47    state_t state;
48    tunnel_state_t tunnel_state;
49 
50    void Init();
51 
52    void Send(const xstring& str);
53    void	Send(const char *format,...) PRINTF_LIKE(2,3);
54    void Send(const HttpHeader *hdr);
55 
56    class Connection
57    {
58       xstring_c closure;
59    public:
60       int sock;
61       SMTaskRef<IOBuffer> send_buf;
62       SMTaskRef<IOBuffer> recv_buf;
63       void MakeBuffers();
64 #if USE_SSL
65       Ref<lftp_ssl> ssl;
66       void MakeSSLBuffers();
67 #endif
68 
SuspendInternal()69       void SuspendInternal()
70       {
71 	 if(send_buf) send_buf->SuspendSlave();
72 	 if(recv_buf) recv_buf->SuspendSlave();
73       }
ResumeInternal()74       void ResumeInternal()
75       {
76 	 if(send_buf) send_buf->ResumeSlave();
77 	 if(recv_buf) recv_buf->ResumeSlave();
78       }
79 
80       Connection(int s,const char *c);
81       ~Connection();
82    };
83 
84    Ref<Connection> conn;
85 
86    static void AppendHostEncoded(xstring&,const char *);
87    void SendMethod(const char *,const char *);
88    const char *last_method;
89    xstring_c last_uri;
90    xstring_c last_url; // for proxy requests
91 
92    enum { HTTP_NONE=0, HTTP_POST, HTTP_MOVE, HTTP_COPY, HTTP_PROPFIND } special;
93    xstring special_data;
94 
95    void DirFile(xstring& path,const xstring& ecwd,const xstring& efile) const;
96    void SendAuth();
97    void SendProxyAuth();
98    void SendCacheControl();
99    void SendBasicAuth(const char *tag,const char *auth);
100    void SendBasicAuth(const char *tag,const char *u,const char *p);
101    void SendRequest(const char *connection,const char *f);
102    void SendRequest(const char *connection=0)
103       {
104 	 SendRequest(connection,file);
105       }
106    int SendArrayInfoRequest(); // returns count of sent requests
107    void ProceedArrayInfo();
108    void SendPropfind(const xstring& efile,int depth);
109    void SendPropfindBody();
110    static const xstring& FormatLastModified(time_t);
111    void SendProppatch(const xstring& efile);
112 
113    int status_code;
114    void HandleHeaderLine(const char *name,const char *value);
115    static const xstring& extract_quoted_header_value(const char *value,const char **end=0);
116    void HandleRedirection();
117    void GetBetterConnection(int level);
118    void SetCookie(const char *val);
119    void MakeCookie(xstring &cookie,const char *host,const char *path);
120    void CookieMerge(xstring &c,const char *add);
121    bool CookieClosureMatch(const char *closure,const char *host,const char *path);
122 
123    void DisconnectLL();
124    void ResetRequestData();
125    void MoveConnectionHere(Http *o);
IsConnected()126    int IsConnected() const
127       {
128 	 if(!conn)
129 	    return 0;
130 	 if(state==CONNECTING || tunnel_state==TUNNEL_WAITING)
131 	    return 1;
132 	 return 2;
133       }
134    void LogErrorText();
135 
136    xstring status;
137    int status_consumed;
138    int proto_version;
139    xstring line;
140    off_t body_size;
141    off_t bytes_received;
142    bool sent_eot;
143 
144    bool ModeSupported();
ModeIs(open_mode m)145    bool ModeIs(open_mode m) const {
146       if(m==STORE)
147 	 return mode==m && !sending_proppatch;
148       return mode==m;
149    }
150 
151    int  keep_alive_max;
152    bool keep_alive;
153 
154    int array_send;
155 
156    bool chunked;
157    bool chunked_trailer;
158    long chunk_size;
159    off_t chunk_pos;
160 
161    off_t request_pos;
162 
163    Ref<DirectedBuffer> inflate;
164    SMTaskRef<IOBuffer> propfind;
165    xstring_c content_encoding;
166    static bool IsCompressed(const char *s);
167    bool CompressedContentEncoding() const;
168    bool CompressedContentType() const;
169 
170    bool no_ranges;
171    bool seen_ranges_bytes;
172    bool entity_date_set;
173    bool sending_proppatch;
174 
175    bool no_cache;
176    bool no_cache_this;
177 
178    // for WWW[0] and PROXY[1]
179    int  auth_sent[2];
180    HttpAuth::scheme_t auth_scheme[2];
181    void NewAuth(const char *hdr,HttpAuth::target_t target,const char *user,const char *pass);
182    void SendAuth(HttpAuth::target_t target,const char *user,const char *uri);
183 
184    xstring_c auth_user;
185    xstring_c auth_pass;
186 
187    bool use_propfind_now;
188    xstring allprop;
189 
190    long retry_after;
191 
192    const char *user_agent;
193 
194    int _Read(Buffer *,int);  // does not update pos, rate_limit, retries, does not check state.
195    void _Skip(int to_skip); // skip in recv_buf or inflate (unless moved), update real_pos
196    void _UpdatePos(int to_skip); // update real_pos, chunk_pos etc.
197 
198 protected:
199    bool hftp;  // ftp over http proxy.
200    bool https; // secure http
201    bool use_head;
202 
203 public:
204    static void ClassInit();
205 
206    Http();
207    Http(const Http *);
208    ~Http();
209 
GetProto()210    const char *GetProto() const { return "http"; }
211 
Clone()212    FileAccess *Clone() const { return new Http(this); }
213    static FileAccess *New();
214    FileSet *ParseLongList(const char *buf,int len,int *err=0) const;
215 
216    int Do();
217    int Done();
218    int Read(Buffer *,int);
219    int Write(const void *,int);
220    int StoreStatus();
221    int SendEOT();
222    int Buffered();
223 
224    void	ResetLocationData();
225 
226    void Close();
227    const char *CurrentStatus();
228 
229    void Reconfig(const char *name=0);
230 
231    bool SameSiteAs(const FileAccess *fa) const;
232    bool SameLocationAs(const FileAccess *fa) const;
233 
234    DirList *MakeDirList(ArgV *a);
235    Glob *MakeGlob(const char *pattern);
236    ListInfo *MakeListInfo(const char *path);
237 
UseCache(bool use)238    void UseCache(bool use) { no_cache_this=!use; }
239 
NeedSizeDateBeforehand()240    bool NeedSizeDateBeforehand() { return true; }
241 
242    void SuspendInternal();
243    void ResumeInternal();
244 
245    static const time_t ATOTM_ERROR = -1;
246    static time_t atotm (const char *time_string);
247 };
248 
249 class HFtp : public Http
250 {
251 public:
252    HFtp();
253    HFtp(const HFtp *);
254    ~HFtp();
255 
GetProto()256    const char *GetProto() const { return "hftp"; }
257 
Clone()258    FileAccess *Clone() const { return new HFtp(this); }
259    static FileAccess *New();
260 
261    virtual void Login(const char *,const char *);
262    virtual void Reconfig(const char *);
263 };
264 
265 class Https : public Http
266 {
267 public:
268    Https();
269    Https(const Https *);
270    ~Https();
271 
GetProto()272    const char *GetProto() const { return "https"; }
273 
Clone()274    FileAccess *Clone() const { return new Https(this); }
275    static FileAccess *New();
276 };
277 
278 #endif//HTTP_H
279