00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifdef _WIN32
00031 #pragma warning(disable:4786)
00032 #pragma warning(disable:4503)
00033 #else
00034 #include <errno.h>
00035 #include <ctype.h>
00036 #endif
00037 #include "ISocketHandler.h"
00038 #include <sys/types.h>
00039 #include <sys/stat.h>
00040 #include "Parse.h"
00041 #include "Utility.h"
00042 #include "Lock.h"
00043
00044 #include "HttpPostSocket.h"
00045
00046
00047 #ifdef SOCKETS_NAMESPACE
00048 namespace SOCKETS_NAMESPACE {
00049 #endif
00050
00051
00052 int HttpPostSocket::m_boundary_count = 0;
00053 Mutex HttpPostSocket::m_boundary_mutex;
00054
00055
00056 HttpPostSocket::HttpPostSocket(ISocketHandler& h) : HttpClientSocket(h)
00057 ,m_bMultipart(false)
00058 {
00059 }
00060
00061
00062 HttpPostSocket::HttpPostSocket(ISocketHandler& h,const std::string& url_in) : HttpClientSocket(h, url_in)
00063 ,m_bMultipart(false)
00064 {
00065 Lock lock(m_boundary_mutex);
00066
00067 m_boundary = "----";
00068 for (int i = 0; i < 12; i++)
00069 {
00070 char c = m_boundary_count++ % 128;
00071 while (!isalnum(c))
00072 c = m_boundary_count++ % 128;
00073 m_boundary += c;
00074 }
00075 m_boundary += "__" + Utility::l2string(m_boundary_count++);
00076 }
00077
00078
00079 HttpPostSocket::~HttpPostSocket()
00080 {
00081 }
00082
00083
00084 void HttpPostSocket::AddField(const std::string& name,const std::string& value)
00085 {
00086 std::list<std::string> vec;
00087 vec.push_back(value);
00088 AddMultilineField(name, vec);
00089 }
00090
00091
00092 void HttpPostSocket::AddMultilineField(const std::string& name,std::list<std::string>& values)
00093 {
00094 m_fields[name] = values;
00095 }
00096
00097
00098 void HttpPostSocket::AddFile(const std::string& name,const std::string& filename,const std::string& type)
00099 {
00100 struct stat st;
00101 if (!stat(filename.c_str(), &st))
00102 {
00103 m_files[name] = filename;
00104 m_content_length[filename] = st.st_size;
00105 m_content_type[filename] = type;
00106 m_bMultipart = true;
00107 }
00108 else
00109 {
00110 Handler().LogError(this, "AddFile", Errno, StrError(Errno), LOG_LEVEL_FATAL);
00111 SetCloseAndDelete();
00112 }
00113 }
00114
00115
00116 void HttpPostSocket::Open()
00117 {
00118
00119 TcpSocket::Open(GetUrlHost(), GetUrlPort());
00120 }
00121
00122
00123 void HttpPostSocket::OnConnect()
00124 {
00125 if (m_bMultipart)
00126 {
00127 DoMultipartPost();
00128 }
00129 else
00130 {
00131 std::string body;
00132
00133
00134 for (std::map<std::string,std::list<std::string> >::iterator it = m_fields.begin(); it != m_fields.end(); it++)
00135 {
00136 std::string name = (*it).first;
00137 std::list<std::string>& ref = (*it).second;
00138 if (body.size())
00139 {
00140 body += '&';
00141 }
00142 body += name + "=";
00143 bool first = true;
00144 for (std::list<std::string>::iterator it = ref.begin(); it != ref.end(); it++)
00145 {
00146 std::string value = *it;
00147 if (!first)
00148 {
00149 body += "%0d%0a";
00150 }
00151 body += Utility::rfc1738_encode(value);
00152 first = false;
00153 }
00154 }
00155
00156
00157 SetMethod("POST");
00158 SetHttpVersion( "HTTP/1.1" );
00159 AddResponseHeader( "Host", GetUrlHost() );
00160 AddResponseHeader( "User-agent", MyUseragent());
00161 AddResponseHeader( "Accept", "text/html, text/plain, */*;q=0.01" );
00162 AddResponseHeader( "Connection", "close" );
00163 AddResponseHeader( "Content-type", "application/x-www-form-urlencoded" );
00164 AddResponseHeader( "Content-length", Utility::l2string((long)body.size()) );
00165 SendRequest();
00166
00167
00168 Send( body );
00169 }
00170 }
00171
00172
00173 void HttpPostSocket::DoMultipartPost()
00174 {
00175 long length = 0;
00176 std::string tmp;
00177
00178
00179 {
00180 for (std::map<std::string,std::list<std::string> >::iterator it = m_fields.begin(); it != m_fields.end(); it++)
00181 {
00182 std::string name = (*it).first;
00183 std::list<std::string>& ref = (*it).second;
00184 tmp = "--" + m_boundary + "\r\n"
00185 "content-disposition: form-data; name=\"" + name + "\"\r\n"
00186 "\r\n";
00187 for (std::list<std::string>::iterator it = ref.begin(); it != ref.end(); it++)
00188 {
00189 std::string value = *it;
00190 tmp += value + "\r\n";
00191 }
00192 length += (long)tmp.size();
00193 }
00194 }
00195
00196
00197 {
00198 for (std::map<std::string,std::string>::iterator it = m_files.begin(); it != m_files.end(); it++)
00199 {
00200 std::string name = (*it).first;
00201 std::string filename = (*it).second;
00202 long content_length = m_content_length[filename];
00203 std::string content_type = m_content_type[filename];
00204 tmp = "--" + m_boundary + "\r\n"
00205 "content-disposition: form-data; name=\"" + name + "\"; filename=\"" + filename + "\"\r\n"
00206 "content-type: " + content_type + "\r\n"
00207 "\r\n";
00208 length += (long)tmp.size();
00209 length += content_length;
00210 length += 2;
00211 }
00212 }
00213
00214
00215 tmp = "--" + m_boundary + "--\r\n";
00216 length += (long)tmp.size();
00217
00218
00219 SetMethod("POST");
00220 SetHttpVersion( "HTTP/1.1" );
00221 AddResponseHeader( "Host", GetUrlHost() );
00222 AddResponseHeader( "User-agent", MyUseragent());
00223 AddResponseHeader( "Accept", "text/html, text/plain, */*;q=0.01" );
00224 AddResponseHeader( "Connection", "close" );
00225 AddResponseHeader( "Content-type", "multipart/form-data; boundary=" + m_boundary );
00226 AddResponseHeader( "Content-length", Utility::l2string(length) );
00227
00228 SendRequest();
00229
00230
00231 {
00232 for (std::map<std::string,std::list<std::string> >::iterator it = m_fields.begin(); it != m_fields.end(); it++)
00233 {
00234 std::string name = (*it).first;
00235 std::list<std::string>& ref = (*it).second;
00236 tmp = "--" + m_boundary + "\r\n"
00237 "content-disposition: form-data; name=\"" + name + "\"\r\n"
00238 "\r\n";
00239 for (std::list<std::string>::iterator it = ref.begin(); it != ref.end(); it++)
00240 {
00241 std::string value = *it;
00242 tmp += value + "\r\n";
00243 }
00244 Send( tmp );
00245 }
00246 }
00247
00248
00249 {
00250 for (std::map<std::string,std::string>::iterator it = m_files.begin(); it != m_files.end(); it++)
00251 {
00252 std::string name = (*it).first;
00253 std::string filename = (*it).second;
00254 std::string content_type = m_content_type[filename];
00255 tmp = "--" + m_boundary + "\r\n"
00256 "content-disposition: form-data; name=\"" + name + "\"; filename=\"" + filename + "\"\r\n"
00257 "content-type: " + content_type + "\r\n"
00258 "\r\n";
00259 Send( tmp );
00260 {
00261 FILE *fil = fopen(filename.c_str(),"rb");
00262 if (fil)
00263 {
00264 char slask[2000];
00265 size_t n;
00266 while ((n = fread(slask, 1, 2000, fil)) > 0)
00267 {
00268 SendBuf(slask, n);
00269 }
00270 fclose(fil);
00271 }
00272 }
00273 Send("\r\n");
00274 }
00275 }
00276
00277
00278 Send("--" + m_boundary + "--\r\n");
00279 }
00280
00281
00282 void HttpPostSocket::SetMultipart()
00283 {
00284 m_bMultipart = true;
00285 }
00286
00287
00288 #ifdef SOCKETS_NAMESPACE
00289 }
00290 #endif
00291