add FileUpload,not complete yet

This commit is contained in:
an-tao 2018-06-11 15:31:34 +08:00
parent 9ddd79b194
commit 10a6d39a32
4 changed files with 514 additions and 0 deletions

51
lib/inc/drogon/FileUpload.h Executable file
View File

@ -0,0 +1,51 @@
/**
*
* @file
* @author An Tao
* @section LICENSE
*
* Copyright 2018, An Tao. All rights reserved.
* Use of this source code is governed by a MIT license
* that can be found in the License file.
*
* @section DESCRIPTION
*
*/
#pragma
#include "HttpRequest.h"
#include <string>
#include <map>
#include <vector>
namespace drogon
{
class HttpFile
{
public:
const std::string& getFileName() const {return fileName_;};
void setFileName(const std::string& filename){fileName_=filename;};
void setFile(const std::string& file){fileContent_=file;};
int save(const std::string& path);
int saveAs(const std::string& filename);
int64_t fileLength() const {return fileContent_.length();};
const std::string getMd5()const;
protected:
std::string fileName_;
std::string fileContent_;
};
class FileUpload
{
public:
FileUpload(){};
~FileUpload(){};
const std::vector<HttpFile> getFiles();
const std::map<std::string,std::string>& getPremeter() const;
int parse(const HttpRequest& req);
protected:
std::vector<HttpFile> files_;
std::map<std::string,std::string> premeter_;
int parseEntity(const std::string& str);
};
}

141
lib/src/FileUpload.cc Executable file
View File

@ -0,0 +1,141 @@
#include <drogon/FileUpload.h>
#include "Funcs.h"
#include <openssl/md5.h>
#include <iostream>
#include <fstream>
using namespace drogon;
const std::vector<HttpFile> FileUpload::getFiles()
{
return files_;
}
const std::map<std::string, std::string> &FileUpload::getPremeter() const
{
return premeter_;
};
int FileUpload::parse(const HttpRequest &req)
{
if (req.method() != HttpRequest::kPost)
return -1;
std::map<std::string, std::string> headers = req.headers();
if (headers.find("Content-Type") == headers.end())
return -1;
std::string &contentType = headers["Content-Type"];
std::string::size_type pos = contentType.find(";");
if (pos == std::string::npos)
return -1;
std::string type = contentType.substr(0, pos);
if (type != "multipart/form-data")
return -1;
pos = contentType.find("boundary=");
if (pos == std::string::npos)
return -1;
std::string boundary = contentType.substr(pos + 9);
std::cout << "boundary[" << boundary << "]" << std::endl;
std::string content = req.query();
std::string::size_type pos1, pos2;
pos1 = pos2 = 0;
pos2 = content.find(boundary);
while (1)
{
pos1 = pos2;
if (pos1 == std::string::npos)
break;
pos1 += boundary.length();
if (content[pos1] == '\r' && content[pos1 + 1] == '\n')
pos1 += 2;
pos2 = content.find(boundary, pos1);
if (pos2 == std::string::npos)
break;
// std::cout<<"pos1="<<pos1<<" pos2="<<pos2<<std::endl;
if (content[pos2 - 4] == '\r' && content[pos2 - 3] == '\n' && content[pos2 - 2] == '-' && content[pos2 - 1] == '-')
pos2 -= 4;
if (parseEntity(content.substr(pos1, pos2 - pos1)) != 0)
return -1;
//pos2+=boundary.length();
}
return 0;
}
int FileUpload::parseEntity(const std::string &str)
{
// parseEntity:[Content-Disposition: form-data; name="userfile1"; filename="appID.txt"
// Content-Type: text/plain
//
// AA004MV7QI]
// pos1=190 pos2=251
// parseEntity:[YvBu
// Content-Disposition: form-data; name="text"
//
// text]
// std::cout<<"parseEntity:["<<str<<"]"<<std::endl;
std::string::size_type pos = str.find("name=\"");
if (pos == std::string::npos)
return -1;
pos += 6;
std::string::size_type pos1 = str.find("\"", pos);
if (pos1 == std::string::npos)
return -1;
std::string name = str.substr(pos, pos1 - pos);
// std::cout<<"name=["<<name<<"]\n";
pos = str.find("filename=\"");
if (pos == std::string::npos)
{
pos1 = str.find("\r\n\r\n");
if (pos1 == std::string::npos)
return -1;
premeter_[name] = str.substr(pos1 + 4);
return 0;
}
else
{
pos += 10;
std::string::size_type pos1 = str.find("\"", pos);
if (pos1 == std::string::npos)
return -1;
HttpFile file;
file.setFileName(str.substr(pos, pos1 - pos));
pos1 = str.find("\r\n\r\n");
if (pos1 == std::string::npos)
return -1;
file.setFile(str.substr(pos1 + 4));
files_.push_back(file);
return 0;
}
}
int HttpFile::save(const std::string &path)
{
if (fileName_ == "")
return -1;
std::string filename;
if (path[path.length()] != '/')
{
filename = path + "/" + fileName_;
}
else
filename = path + fileName_;
return saveAs(filename);
}
int HttpFile::saveAs(const std::string &filename)
{
std::ofstream file(filename);
if (file.is_open())
{
file << fileContent_;
file.close();
return 0;
}
else
return -1;
}
const std::string HttpFile::getMd5() const
{
MD5_CTX c;
unsigned char md5[16] = {0};
MD5_Init(&c);
MD5_Update(&c, fileContent_.c_str(), fileContent_.size());
MD5_Final(md5, &c);
return StringToHex(md5, 16);
}

257
lib/src/Funcs.cc Executable file
View File

@ -0,0 +1,257 @@
#include "Funcs.h"
#include <openssl/sha.h>
static const std::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
static inline bool is_base64(unsigned char c) {
return (isalnum(c) || (c == '+') || (c == '/'));
}
bool isInteger(const std::string &str)
{
for(auto c:str)
{
if(c>'9'||c<'0')
return false;
}
return true;
}
std::string genRandomString(int length)
{
int flag, i;
char str[length + 1];
timespec tp;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp);
//LOG_INFO<<"time: "<<tp.tv_nsec;
srand(static_cast<unsigned int>(tp.tv_nsec));
std::string char_space = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (i = 0; i < length; i++)
{
str[i] = char_space[rand() % char_space.length()];
}
return std::string(str);
}
std::string StringToHex(unsigned char* ptr, long long length)
{
std::string idString;
for (long long i = 0; i < length; i++)
{
int value = (ptr[i] & 0xf0)>>4;
if (value < 10)
{
idString.append(1, char(value + 48));
} else
{
idString.append(1, char(value + 55));
}
value = (ptr[i] & 0x0f);
if (value < 10)
{
idString.append(1, char(value + 48));
} else
{
idString.append(1, char(value + 55));
}
}
return idString;
}
std::vector<std::string> splitString(const std::string &str, const std::string &separator)
{
std::vector<std::string> ret;
std::string::size_type pos1, pos2;
pos1 = pos2 = 0;
pos1 = str.find(separator);
while (pos1 != std::string::npos)
{
if (pos1 != 0)
{
std::string item = str.substr(pos2, pos1 - pos2);
ret.push_back(item);
}
pos2 = pos1 + separator.length();
while (pos2 < str.length() && str.substr(pos2, separator.length()) == separator)
pos2 += separator.length();
pos1 = str.find(separator, pos2);
}
if (pos2 < str.length())
ret.push_back(str.substr(pos2));
return ret;
}
std::string getuuid()
{
uuid_t uu;
uuid_generate(uu);
return StringToHex(uu, 16);
}
std::string stringPreProcess(const std::string& str)
{
std::string ret;
for(int i = 0; i < str.length(); i++)
{
if(str[i] == '\'')
{
ret += "\'\'";
}
else
{
ret += str[i];
}
}
return ret;
}
std::string encryptPassword(const std::string& plainPasswd,const std::string& salt)
{
unsigned char psd[SHA256_DIGEST_LENGTH];
SHA256(reinterpret_cast<const unsigned char *>(plainPasswd.c_str()), plainPasswd.length(), psd);
std::string encryptPasswd = std::string((char *)psd, SHA256_DIGEST_LENGTH);
encryptPasswd +=salt;
SHA256(reinterpret_cast<const unsigned char *>(encryptPasswd.c_str()), encryptPasswd.length(), psd);
encryptPasswd = StringToHex(psd, SHA256_DIGEST_LENGTH);
return encryptPasswd;
}
std::string encryptHashPassword(const std::string& hashPasswd,const std::string& salt)
{
unsigned char psd[SHA256_DIGEST_LENGTH];
std::string encryptPasswd = hashPasswd+salt;
SHA256(reinterpret_cast<const unsigned char *>(encryptPasswd.c_str()), encryptPasswd.length(), psd);
encryptPasswd = StringToHex(psd, SHA256_DIGEST_LENGTH);
return encryptPasswd;
}
std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) {
std::string ret;
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];
while (in_len--) {
char_array_3[i++] = *(bytes_to_encode++);
if (i == 3) {
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for(i = 0; (i <4) ; i++)
ret += base64_chars[char_array_4[i]];
i = 0;
}
}
if (i)
{
for(j = i; j < 3; j++)
char_array_3[j] = '\0';
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (j = 0; (j < i + 1); j++)
ret += base64_chars[char_array_4[j]];
while((i++ < 3))
ret += '=';
}
return ret;
}
std::string base64_decode(std::string const& encoded_string) {
int in_len = encoded_string.size();
int i = 0;
int j = 0;
int in_ = 0;
unsigned char char_array_4[4], char_array_3[3];
std::string ret;
while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
char_array_4[i++] = encoded_string[in_]; in_++;
if (i ==4) {
for (i = 0; i <4; i++)
char_array_4[i] = base64_chars.find(char_array_4[i]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (i = 0; (i < 3); i++)
ret += char_array_3[i];
i = 0;
}
}
if (i) {
for (j = i; j <4; j++)
char_array_4[j] = 0;
for (j = 0; j <4; j++)
char_array_4[j] = base64_chars.find(char_array_4[j]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
}
return ret;
}
std::string UrlDecode(const std::string& szToDecode)
{
std::string result;
int hex = 0;
for (size_t i = 0; i < szToDecode.length(); ++i)
{
switch (szToDecode[i])
{
case '+':
result += ' ';
break;
case '%':
if (isxdigit(szToDecode[i + 1]) && isxdigit(szToDecode[i + 2]))
{
std::string hexStr = szToDecode.substr(i + 1, 2);
hex = strtol(hexStr.c_str(), 0, 16);
//字母和数字[0-9a-zA-Z]、一些特殊符号[$-_.+!*'(),] 、以及某些保留字[$&+,/:;=?@]
//可以不经过编码直接用于URL
if (!((hex >= 48 && hex <= 57) || //0-9
(hex >=97 && hex <= 122) || //a-z
(hex >=65 && hex <= 90) || //A-Z
//一些特殊符号及保留字[$-_.+!*'(),] [$&+,/:;=?@]
hex == 0x21 || hex == 0x24 || hex == 0x26 || hex == 0x27 || hex == 0x28 || hex == 0x29
|| hex == 0x2a || hex == 0x2b|| hex == 0x2c || hex == 0x2d || hex == 0x2e || hex == 0x2f
|| hex == 0x3A || hex == 0x3B|| hex == 0x3D || hex == 0x3f || hex == 0x40 || hex == 0x5f
))
{
result += char(hex);
i += 2;
}
else result += '%';
}else {
result += '%';
}
break;
default:
result += szToDecode[i];
break;
}
}
return result;
}

65
lib/src/Funcs.h Executable file
View File

@ -0,0 +1,65 @@
#ifndef FUNCS_H_
#define FUNCS_H_
#include <uuid/uuid.h>
#include <string>
#include <vector>
#include <pqxx/pqxx>
#define USING_PQXX_TO_STRING
using namespace pqxx;
bool isInteger(const std::string &str);
std::string genRandomString(int length);
std::string StringToHex(unsigned char* ptr, long long length);
std::vector<std::string> splitString(const std::string &str,const std::string &separator);
std::string getuuid();
std::string stringPreProcess(const std::string& str);
std::string encryptPassword(const std::string& plainPasswd,const std::string& salt);
std::string encryptHashPassword(const std::string& hashPasswd,const std::string& salt);
template <typename T>
std::string toString(const T &obj)
{
#ifdef USING_PQXX_TO_STRING
return pqxx::to_string(obj);
#else
char str[32];
if(typeid(obj).name() == typeid(long).name())
{
sprintf(str, "%ld", obj);
return std::string(str);
}
else if(typeid(obj).name() == typeid(int).name())
{
sprintf(str, "%d", obj);
return std::string(str);
}
else if(typeid(obj).name() == typeid(std::string).name())
{
return obj;
}
else if(typeid(obj).name() == typeid(bool).name())
{
return obj ? "true" : "false";
}
else
{
LOG_ERROR<<"no way to transfer to string"
}
#endif
}
template <typename T>
void fromString(const std::string& str, T &obj)
{
#ifdef USING_PQXX_TO_STRING
pqxx::from_string(str, obj);
#endif
}
std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len);
std::string base64_decode(std::string const& encoded_string);
std::string UrlDecode(const std::string& szToDecode);
#endif