Browse Source

Fixed file size handling now http::file::size() returns correct size on 32 bit systems as well.

master
Artyom Beilis 8 years ago
parent
commit
8624564cd4
4 changed files with 60 additions and 26 deletions
  1. +11
    -1
      cppcms/http_file.h
  2. +10
    -0
      private/multipart_parser.h
  3. +10
    -13
      src/http_file.cpp
  4. +29
    -12
      tests/multipart_parser_test.cpp

+ 11
- 1
cppcms/http_file.h View File

@@ -16,7 +16,13 @@
#include <sstream>
#include <fstream>

namespace cppcms { namespace http {
namespace cppcms {

/// \cond INTERNAL
namespace impl { class multipart_parser; }
/// \endcond

namespace http {

class request;

@@ -82,6 +88,10 @@ namespace cppcms { namespace http {
/// \endcond

private:

void add_bytes_to_size(size_t n);

friend class impl::multipart_parser;
std::string name_;
std::string mime_;
std::string filename_;


+ 10
- 0
private/multipart_parser.h View File

@@ -31,6 +31,7 @@ namespace cppcms {
result.swap(files_);
return result;
}

bool set_content_type(std::string const &ct)
{
http::content_type t(ct);
@@ -139,9 +140,11 @@ namespace cppcms {
break;
case expecting_separator_boundary:
{
content_in_ = true;
std::streambuf *out=file_->write_data().rdbuf();
char const *this_boundary = boundary_.c_str();
size_t boundary_size = boundary_.size();
size_t added = 0;
while(size > 0) {
char c=*buffer;
if(c == this_boundary[position_])
@@ -149,6 +152,7 @@ namespace cppcms {
else if(position_ > 0) {
std::streamsize expected = position_;
std::streamsize s=out->sputn(this_boundary,position_);
added += position_;
position_ = 0;
if(c == boundary_[0])
position_=1;
@@ -156,15 +160,19 @@ namespace cppcms {
return no_room_left;
}
if(position_ == 0) {
added++;
if(out->sputc(c)==EOF)
return no_room_left;
}
else if(position_ == boundary_size) {
state_ = expecting_one_crlf_or_eof;
position_ = 0;
file_->add_bytes_to_size(added);
added = 0;
file_->data().seekg(0);
files_.push_back(file_);
file_.reset(new http::file());
content_in_ = false;
file_->set_temporary_directory(temp_dir_);
if(memory_limit_ != -1) {
file_->set_memory_limit(memory_limit_);
@@ -174,6 +182,8 @@ namespace cppcms {
buffer++;
size--;
} // end while
file_->add_bytes_to_size(added);
added = 0;
}
break;
}


+ 10
- 13
src/http_file.cpp View File

@@ -13,13 +13,14 @@
#include <booster/nowide/fstream.h>
#include <stdlib.h>

#include <iostream>
#include "tohex.h"

namespace cppcms {
namespace http {


struct file::impl_data {};
struct file::impl_data { long long size; };

std::string file::name() const
{
@@ -37,16 +38,7 @@ std::string file::filename() const
}
long long file::size()
{
if(saved_in_file_) {
std::streampos now=file_.tellp();
file_.seekp(0,std::ios_base::end);
long long size = file_.tellp();
file_.seekp(now);
return size;
}
else {
return file_data_.tellp();
}
return d->size;
}

std::istream &file::data()
@@ -168,13 +160,18 @@ void file::move_to_file()
}



void file::add_bytes_to_size(size_t n)
{
d->size += n;
}

file::file() :
size_limit_(1024*128),
saved_in_file_(0),
removed_(0)
removed_(0),
d(new impl_data())
{
d->size = 0;
}

file::~file()


+ 29
- 12
tests/multipart_parser_test.cpp View File

@@ -6,6 +6,7 @@
//
///////////////////////////////////////////////////////////////////////////////
//#define DEBUG_MULTIPART_PARSER
#include <iostream>
#include "multipart_parser.h"
#include <iostream>
#include "test.h"
@@ -63,11 +64,23 @@ std::string getcontent(std::istream &in)
char c;
in.get(c);
if(in.gcount() == 1)
res+=c;
res+=c;
}
return res;
}

std::string getcontent(cppcms::http::file &file)
{
long long len = file.size();
std::string res = getcontent(file.data());
TEST(int(res.size()) == len);
return res;
}
std::string getcontent(booster::shared_ptr<cppcms::http::file> const &p)
{
return getcontent(*p);
}

struct random_consumer {
random_consumer(int bs,cppcms::impl::multipart_parser &p,cppcms::impl::multipart_parser::files_type &f) :
block_size(bs),
@@ -89,7 +102,11 @@ struct random_consumer {

if(block > size)
block=size;
cppcms::impl::multipart_parser::parsing_result_type res = parser->consume(buffer,block);
#ifdef DEBUG_MULTIPART_PARSER
std::cerr << "Got " << int(res) << " Consumed " << block << std::endl;
#endif
buffer+=block;
size-=block;
if(res==cppcms::impl::multipart_parser::eof) {
@@ -137,17 +154,17 @@ int main(int argc,char **argv)
TEST(files[0]->name()=="test1");
TEST(files[0]->filename()=="foo.txt");
TEST(files[0]->mime()=="text/plain");
std::string content = getcontent(files[0]->data());
std::string content = getcontent(files[0]);
TEST(content=="hello\r\n");
TEST(files[1]->name()=="test2");
TEST(files[1]->filename()=="");
TEST(files[1]->mime()=="");
TEST(getcontent(files[1]->data())=="שלום");
TEST(getcontent(files[2]->data())=="x\r");
TEST(getcontent(files[3]->data())=="x\r\n-");
TEST(getcontent(files[4]->data())=="x\r\n--");
TEST(getcontent(files[5]->data())=="x\r\n--x");
TEST(getcontent(files[6]->data())=="x\r\n--x-");
TEST(getcontent(files[1])=="שלום");
TEST(getcontent(files[2])=="x\r");
TEST(getcontent(files[3])=="x\r\n-");
TEST(getcontent(files[4])=="x\r\n--");
TEST(getcontent(files[5])=="x\r\n--x");
TEST(getcontent(files[6])=="x\r\n--x-");
}
{
cppcms::impl::multipart_parser parser("",max_mem_size[j]);
@@ -159,7 +176,7 @@ int main(int argc,char **argv)
TEST(files[0]->name()=="test1");
TEST(files[0]->filename()=="");
TEST(files[0]->mime()=="");
std::string content = getcontent(files[0]->data());
std::string content = getcontent(files[0]);
TEST(content=="hello");
}
std::string boundaries[4]= {
@@ -197,7 +214,7 @@ int main(int argc,char **argv)
TEST(files.size()==3);
TEST(files[0]->name()=="submit-name");
TEST(files[0]->mime()=="" && files[0]->filename().empty());
TEST(getcontent(files[0]->data())=="שלום");
TEST(getcontent(files[0])=="שלום");
TEST(files[1]->name()=="file");
TEST(files[1]->mime()=="text/plain");
if(i==3) // IE
@@ -205,7 +222,7 @@ int main(int argc,char **argv)
else
TEST(files[1]->filename()=="שלום.txt");
TEST(getcontent(files[1]->data())=="שלום עולם!\n");
TEST(getcontent(files[1])=="שלום עולם!\n");
files[1]->save_to("test.txt");
{
std::ifstream tmp("test.txt");
@@ -218,7 +235,7 @@ int main(int argc,char **argv)
TEST(files[2]->name()=="submit");
TEST(files[2]->mime().empty());
TEST(files[2]->filename().empty());
TEST(getcontent(files[2]->data())=="Send");
TEST(getcontent(files[2])=="Send");
}
}
}


Loading…
Cancel
Save