コード例 #1
0
	bool select(string const &sid,time_t &timeout,string &data)
	{
		sqlite3_stmt *st;
		char const *q="SELECT data,timeout FROM sessions WHERE sid=?";
		if(sqlite3_prepare(db,q,-1,&st,NULL)!=0) {
			throw cppcms_error(string("sqlite prepared statement:")+sqlite3_errmsg(db));
		}
		int res;
		sqlite3_bind_text(st,1, sid.c_str(), sid.size(),SQLITE_STATIC);
		while((res=sqlite3_step(st))==SQLITE_BUSY){
			poll(NULL,0,5);
		}
		if(res==SQLITE_DONE) {
			sqlite3_finalize(st);
			return false;
		}
		else if(res==SQLITE_ROW) {
			int64_t to=sqlite3_column_int64(st,1);
			if(to < time(NULL)) {
				sqlite3_finalize(st);
				del(sid);
				write_ops++;
				return false;
			}
			size_t length=sqlite3_column_bytes(st,0);
			data.assign((const char *)sqlite3_column_blob(st,0),length);
			timeout=to;
			sqlite3_finalize(st);
			return true;
		}
		else {
			throw cppcms_error(string("Insert error:")+sqlite3_errmsg(db));
		}
	
	}
コード例 #2
0
ファイル: process_cache.cpp プロジェクト: klupek/cppcms
process_cache_factory::process_cache_factory(size_t memsize,char const *file)
{
	cache=NULL;
	if(memsize<8*1024) {
		throw cppcms_error("Cache size too small -- need at least 8K");
	}
	if(!mem) {
		mem=new shmem_control(memsize,file);
		owner_pid=getpid();
	}
	else {
		throw cppcms_error("The memory initilized -- can't use more then once cache in same time");
	}
	cache=new process_cache(memsize);
};
コード例 #3
0
session_backend_factory session_sqlite_storage::factory(cppcms_config const  &config)
{
	string db=config.sval("session.sqlite_db");
	int db_count=config.ival("session.sqlite_db_num",4);
	if(db_count>8)
		db_count=8;
	if(db_count<0)
		db_count=0;
	db_count=1<<db_count;
	string def="fork";
	if(config.sval("server.mod","")=="thread")
		def="thread";
	string mod=config.sval("session.sqlite_mod",def);
	bool cache=config.ival("session.server_enable_cache",0);
	if(mod=="fork") {
		bool sync=config.ival("session.sqlite_sync",0);
		return builder_proc(db,db_count,sync,cache);
	}
	else if(mod=="thread") {
		bool sync=config.ival("session.sqlite_sync",1);
		int  dc=config.ival("session.sqlite_commits",1000);
		int  dt=config.ival("session.sqlite_commit_timeout",5);
		return builder_thread(db,db_count,sync,dc,dt,cache);
	}
	else {
		throw cppcms_error("Unknown sqlite mode:"+mod);
	}
}
コード例 #4
0
ファイル: global_config.cpp プロジェクト: klupek/cppcms
void cppcms_config::load(int argc,char *argv[],char const *def)
{
	if(loaded) {
		return;
	}
	char const *def_file=def;
	int i;
	for(i=1;i<argc;i++) {
		if(strncmp(argv[i],"--config=",9)==0) {
			def_file=argv[i]+9;
			break;
		}
		else if(strcmp(argv[i],"-c")==0 && i+1<argc) {
			def_file=argv[i+1];
			break;
		}
	}
	if(def_file==NULL) {
		def_file=getenv("CPPCMS_CONFIG");
	}
	if(def_file==NULL) {
		throw cppcms_error("Configuration file not defined");
	}
	load(def_file);
}
コード例 #5
0
ファイル: http_file.cpp プロジェクト: Kaoschuks/cppcms
void file::move_to_file()
{
	std::string tmp_dir;
	if(temporary_dir_.empty()) {
		char const *tmp=getenv("TEMP");
		if(!tmp)
			tmp=getenv("TMP");
		if(!tmp)
			tmp="/tmp";
		tmp_dir=tmp;
	}
	else {
		tmp_dir = temporary_dir_;
	}

	tmp_file_name_ = tmp_dir + "/cppcms_uploads_";
	urandom_device rnd;
	char buf[16];
	char rand[33]={0};
	rnd.generate(buf,16);
	impl::tohex(buf,sizeof(buf),rand);
	tmp_file_name_.append(rand);
	tmp_file_name_+=".tmp";
	file_.open(tmp_file_name_.c_str(),
		std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::trunc);
	if(!file_)
		throw cppcms_error("Failed to create temporary file");
	file_data_.seekg(0);
	copy_stream(file_data_,file_);
	file_data_.str("");
	saved_in_file_ = 1;
}
コード例 #6
0
void session_file_storage::gc()
{
	std::auto_ptr<_WIN32_FIND_DATAW> entry(new _WIN32_FIND_DATAW);
	HANDLE d=INVALID_HANDLE_VALUE;
	std::string search_path = path_ + "/*";
	try{
		if((d=::FindFirstFileW(booster::nowide::convert(search_path).c_str(),entry.get()))==INVALID_HANDLE_VALUE) {
			if(GetLastError() == ERROR_FILE_NOT_FOUND)
				return;
			throw cppcms_error("Failed to open directory :"+path_);
		}
		do {
			if(entry->cFileName[32]!=0)
				continue;
			int i;
			std::string filename=booster::nowide::convert(entry->cFileName);
			for(i=0;i<32;i++) {
				if(!isxdigit(filename[i]))
					break;
			}
			if(i!=32) 
				continue;
			{
				locked_file file(this,filename);
				if(!read_timestamp(file.handle()))
					::DeleteFileW(booster::nowide::convert(file.name()).c_str());
			}
		} while(::FindNextFileW(d,entry.get()));
		::FindClose(d);
	}
	catch(...) {
		if(d!=INVALID_HANDLE_VALUE) ::FindClose(d);
		throw;
	}
}
コード例 #7
0
ファイル: http_file.cpp プロジェクト: Kaoschuks/cppcms
void file::save_to(std::string const &filename)
{
	if(!saved_in_file_) {
		file_data_.clear();
		file_data_.seekg(0);
		save_by_copy(filename,file_data_);
		return;
	}
	file_.clear();
	file_.seekg(0);
	file_.sync();
	#ifdef CPPCMS_WIN32
		file_.close();
		/// we can't move opened file on windows as it would be locked 
		if(booster::nowide::rename(tmp_file_name_.c_str(),filename.c_str())!=0) {
			file_.open(tmp_file_name_.c_str(),std::ios_base::binary | std::ios_base::in | std::ios_base::out);
			if(!file_) {
				throw cppcms_error("Failed to reopen file");
			}
			save_by_copy(filename,file_);
			file_.close();
			booster::nowide::remove(tmp_file_name_.c_str());
		}
	#else
		if(booster::nowide::rename(tmp_file_name_.c_str(),filename.c_str())!=0) {
			save_by_copy(filename,file_);
			booster::nowide::remove(tmp_file_name_.c_str());
		}
		file_.close();
	#endif
	removed_ = 1;
}
コード例 #8
0
ファイル: fcgi.cpp プロジェクト: klupek/cppcms
cgicc_connection &fcgi_session::get_connection()
{
	if(!connection) {
		throw cppcms_error("Connection was not prepared");
	}
	return *connection;
}
コード例 #9
0
	sqlite (string db_name,
		bool sync_,
		int deferred_commit_count_,
		int deferred_commit_time_) :
		db(0),
			deferred_commit_count(deferred_commit_count_),
			deferred_commit_time (deferred_commit_time_)
	{
		pthread_mutex_init(&mutex,NULL);
		try {
			if(sqlite3_open(db_name.c_str(),&db)) {
				string error=sqlite3_errmsg(db);
				throw cppcms_error(error);
			}
			exec(	"CREATE TABLE IF NOT EXISTS sessions ( "
				" sid varchar(32) primary key not null, "
				" data varchar(1)  not null, "
				" timeout integer not null "
				")");
			exec(	"CREATE INDEX IF NOT EXISTS sessions_timeout "
				" ON sessions(timeout)");
			if(!sync_) {
				exec(	"PRAGMA synchronous=OFF");
			}
			write_ops=0;
			last_commit=time(NULL);
			exec("begin");
		}
		catch(...) {
			if(db) sqlite3_close(db);
			pthread_mutex_destroy(&mutex);
			throw;
		}
	}
コード例 #10
0
ファイル: session_interface.cpp プロジェクト: klupek/cppcms
std::string session_interface::get(std::string const &key)
{
	check();
	data_type::const_iterator p=data_.find(key);
	if(p==data_.end()) 
		throw cppcms_error("Undefined session key "+key);
	return p->second.value;
}
コード例 #11
0
ファイル: urandom.cpp プロジェクト: Kaoschuks/cppcms
		void generate(void *ptr,unsigned len)
		{
			if(CryptGenRandom(provider_,len,static_cast<BYTE *>(ptr)))
				return;
			std::ostringstream ss;
			ss<<"CryptGenRandom failed with code 0x"<<std::hex<<GetLastError();
			throw cppcms_error(ss.str());
		}
コード例 #12
0
hmac_cipher::hmac_cipher(std::string const &hash_name,crypto::key const &k) :
	key_(k),
	hash_(hash_name)
{
	if(key_.size() < 16) {
		throw cppcms_error("The key legth is too small, use at leaset the key of 16 bytes/32 hexadecimal digits");
	}
}
コード例 #13
0
ファイル: rpc_json.cpp プロジェクト: klupek/cppcms
	void json_rpc_server::smd_from_file(std::string const &file)
	{
		booster::nowide::ifstream smd(file.c_str());
		if(!smd)
			throw cppcms_error("Failed to open:" + file);
		smd_.reserve(1024);
		smd_.assign(	std::istreambuf_iterator<char>(smd),
				std::istreambuf_iterator<char>());
	}
コード例 #14
0
ファイル: http_context.cpp プロジェクト: klupek/cppcms
void context::async_flush_output(context::handler const &h)
{
	if(response().io_mode() != http::response::asynchronous) {
		throw cppcms_error("Can't use asynchronouse operations when I/O mode is synchronous");
	}
	conn_->async_write_response(
		response(),
		false,
		boost::bind(wrapper,h,_1));
}
コード例 #15
0
	void exec(char const *s,string const &sid,string const &data,int64_t timeout)
	{
		sqlite3_stmt *st;
		if(sqlite3_prepare(db,s,-1,&st,NULL)!=0) {
			throw cppcms_error(string("sqlite prepared statement:")+sqlite3_errmsg(db));
		}
		sqlite3_bind_text(st,1, sid.c_str(), sid.size(),SQLITE_STATIC);
		sqlite3_bind_blob(st,2,data.c_str(),data.size(),SQLITE_STATIC);
		sqlite3_bind_int64(st,3,timeout);
		int res;
		while((res=sqlite3_step(st))==SQLITE_BUSY){
			poll(NULL,0,5);
		}
		if(res==SQLITE_DONE) {
			sqlite3_finalize(st);
		}
		else {
			throw cppcms_error(string("Insert error:")+sqlite3_errmsg(db));
		}
	}
コード例 #16
0
ファイル: http_file.cpp プロジェクト: Kaoschuks/cppcms
void file::save_by_copy(std::string const &file_name,std::istream &in)
{
	booster::nowide::ofstream f(file_name.c_str(),std::ios_base::binary | std::ios_base::out);
	if(!f) {
		throw cppcms_error("Failed to save open file:"+file_name);
	}
	copy_stream(in,f);
	f << std::flush;
	f.close();

}
コード例 #17
0
ファイル: base_encryptor.cpp プロジェクト: klupek/cppcms
std::string base_encryptor::to_binary(std::string const &k)
{
	if(k.size() % 2 != 0) {
		throw cppcms_error("Cipher should be encoded as hexadecimal number with even number of digits");
	}
	std::string key(k.size()/2,0);
	for(unsigned i=0;i<k.size();i+=2) {
		char buf[3];
		if(!isxdigit(k[i]) || !isxdigit(k[i+1])) {
			throw cppcms_error("Cipher should be encoded as hexadecimal 32 digits number");
		}
		buf[0]=k[i];
		buf[1]=k[i+1];
		buf[2]=0;
		unsigned v;
		sscanf(buf,"%x",&v);
		key[i/2]=v;
	}
	return key;
}
コード例 #18
0
ファイル: urandom.cpp プロジェクト: Kaoschuks/cppcms
	void urandom_device::generate(void *ptr,unsigned len)
	{
		if(len == 0)
			return;
		int n = 0;
		#ifndef CPPCMS_WIN32
		if(impl::daemonizer::global_urandom_fd!=-1) {
			n = read(impl::daemonizer::global_urandom_fd,ptr,len);
		}
		else 
		#endif
		{
			int fd = open("/dev/urandom",O_RDONLY);
			if(!fd) 
				throw cppcms_error("Failed to open /dev/urandom");
			n = read(fd,ptr,len);
			close(fd);
		}
		if(n!=int(len))
			throw cppcms_error("Failed to read /dev/urandom");
	}
コード例 #19
0
ファイル: urandom.cpp プロジェクト: Kaoschuks/cppcms
		urandom_device_impl() {
			if(CryptAcquireContext(&provider_,0,0,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT)) 
				return;
			if(GetLastError() == (DWORD)(NTE_BAD_KEYSET)) {
				if(CryptAcquireContext(&provider_,0,0,PROV_RSA_FULL,CRYPT_NEWKEYSET))
					return;
			}
			
			std::ostringstream ss;
			ss<<"CryptAcquireContext failed with code 0x"<<std::hex<<GetLastError();
			throw cppcms_error(ss.str());
		}
コード例 #20
0
	locked_file(session_file_storage *object,std::string sid) :
		h_(INVALID_HANDLE_VALUE)
	{
		name_=object->file_name(sid);
		int sleep_time=0;
		
		for(;;) {
			h_=::CreateFileW(booster::nowide::convert(name_).c_str(),
					GENERIC_READ | GENERIC_WRITE,
					FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
					NULL,
					OPEN_ALWAYS,
					FILE_ATTRIBUTE_NORMAL,
					NULL);
			if(h_==INVALID_HANDLE_VALUE) {
				if(GetLastError()==ERROR_ACCESS_DENIED && sleep_time<1000 ) {
					::Sleep(sleep_time);
					sleep_time = sleep_time == 0 ? 1 : sleep_time * 2;				
					continue;
				}
				else {
					std::ostringstream tmp;
					tmp << "Failed to open file:" + name_ + "error code " <<std::hex << ::GetLastError();
					throw cppcms_error(tmp.str());
				}
			}
			else
				break;
		}
		
		OVERLAPPED ov = OVERLAPPED();
		
		if(!::LockFileEx(h_,LOCKFILE_EXCLUSIVE_LOCK,0,0,16,&ov)) {
			::CloseHandle(h_);
			h_=INVALID_HANDLE_VALUE;
			throw cppcms_error("Failed to lock file:"+name_);
		}

	}
コード例 #21
0
void session_file_storage::save_to_file(HANDLE h,time_t timeout,std::string const &in)
{
	struct {
		int64_t timeout;
		uint32_t crc;
		uint32_t size;
	} tmp = { timeout, 0, in.size() };
	boost::crc_32_type crc_calc;
	crc_calc.process_bytes(in.data(),in.size());
	tmp.crc=crc_calc.checksum();
	if(!write_all(h,&tmp,sizeof(tmp)) || !write_all(h,in.data(),in.size()))
		throw cppcms_error("Failed to write to file");
}
コード例 #22
0
ファイル: fcgi.cpp プロジェクト: klupek/cppcms
fcgi_api::fcgi_api(char const *socket,int backlog)
{
	pthread_once(&init_fcgi,fcgi_api::init);
	if(socket && socket[0]!='\0') {
		fd=FCGX_OpenSocket(socket,backlog);
	}
	else {
		fd=0; // STDIN
	}
	if(fd<0) {
		throw cppcms_error(errno,"FCGX_OpenSocket");
	}
}
コード例 #23
0
	void exec(char const *s)
	{
		char *err=NULL;
		int res;
		while((res=sqlite3_exec(db,s,NULL,NULL,&err))!=0) {
			if(res==SQLITE_BUSY) {
				sqlite3_free(err);
				poll(NULL,0,5);
				continue;
			}
			string err_msg=err;
			sqlite3_free(err);
			throw cppcms_error(err_msg);
		}
	}
コード例 #24
0
session_file_storage::session_file_storage(std::string path)
{
	if(path.empty()){
		if(::getenv("TEMP"))
			path_=std::string(::getenv("TEMP")) + "/cppcms_sessions";
		else if(::getenv("TMP"))
			path_=std::string(::getenv("TMP")) + "/cppcms_sessions";
		else
			path_ = "C:/TEMP";
	}
	else
		path_=path;

	if(!::CreateDirectory(path_.c_str(),NULL)) {
		if(GetLastError()!=ERROR_ALREADY_EXISTS) {
			throw cppcms_error("Failed to create a directory for session storage " + path_);
		}
	}
}
コード例 #25
0
ファイル: process_cache.cpp プロジェクト: klupek/cppcms
process_cache::process_cache(size_t m) :
			memsize(m)
{
	pthread_mutexattr_t a;
	pthread_rwlockattr_t al;

	if(
		pthread_mutexattr_init(&a)
		|| pthread_mutexattr_setpshared(&a,PTHREAD_PROCESS_SHARED)
		|| pthread_mutex_init(&lru_mutex,&a)
		|| pthread_mutexattr_destroy(&a)
		|| pthread_rwlockattr_init(&al)
		|| pthread_rwlockattr_setpshared(&al,PTHREAD_PROCESS_SHARED)
		|| pthread_rwlock_init(&access_lock,&al)
		|| pthread_rwlockattr_destroy(&al))
	{
		throw cppcms_error(errno,"Failed setup mutexes --- is this system "
					 "supports process shared mutex/rwlock?");
	}
};
コード例 #26
0
ファイル: http_cookie.cpp プロジェクト: Kaoschuks/cppcms
void cookie::write(std::ostream &out) const
{
	if(name_.empty())
		throw cppcms_error("Cookie's name is not defined");
	out<<"Set-Cookie:"<<name_<<'=';
	if(value_.empty()) {
		// Nothing to do write
	}
	if(protocol::tocken(value_.begin(),value_.end())==value_.end())
		out<<value_;
	else
		out<<protocol::quote(value_);
	
	if(!comment_.empty())
		out<<"; Comment="<<protocol::quote(comment_);
	if(!domain_.empty())
		out<<"; Domain="<<domain_;
	if(has_age_ || has_expiration_) {
		std::locale l=std::locale::classic();
		std::stringstream ss;
		ss.imbue(l);
		if(has_age_)
			ss<<"; Max-Age="<<max_age_;

		if(has_expiration_ && d.get()) {
			ss<<"; Expires=";
			
			std::tm splitted = booster::ptime::universal_time(booster::ptime(d->expires));
			static char const format[]="%a, %d %b %Y %H:%M:%S GMT";
			char const *b=format;
			char const *e=b+sizeof(format)-1;
			std::use_facet<std::time_put<char> >(l).put(ss,ss,' ',&splitted,b,e);
		}
		out << ss.rdbuf();
	}
	if(!path_.empty())
		out<<"; Path="<<path_;
	if(secure_)
		out<<"; Secure";
	out<<"; Version=1";
}
コード例 #27
0
session_interface::session_interface(worker_thread &w) :
    worker(w)
{
    timeout_val_def=w.app.config.ival("session.timeout",24*3600);
    string s_how=w.app.config.sval("session.expire","browser");
    if(s_how=="fixed") {
        how_def=fixed;
    }
    else if(s_how=="renew") {
        how_def=renew;
    }
    else if(s_how=="browser") {
        how_def=browser;
    }
    else {
        throw cppcms_error("Unsupported `session.expire' type `"+s_how+"'");
    }


    storage=w.app.sessions(w);
}
コード例 #28
0
ファイル: session_interface.cpp プロジェクト: klupek/cppcms
session_interface::session_interface(http::context &context) :
	context_(&context),
	loaded_(0)
{
	timeout_val_def_=context.service().cached_settings().session.timeout;
	string s_how=context.service().cached_settings().session.expire;
	if(s_how=="fixed") {
		how_def_=fixed;
	}
	else if(s_how=="renew") {
		how_def_=renew;
	}
	else if(s_how=="browser") {
		how_def_=browser;
	}
	else {
		throw cppcms_error("Unsupported `session.expire' type `"+s_how+"'");
	}

	storage_=context_->service().session_pool().get();
}
コード例 #29
0
ファイル: session_cookies.cpp プロジェクト: abhijat/cppcms
session_cookies::session_cookies(worker_thread &w) :
	worker(w)
{
#ifdef EN_ENCR_SESSIONS
	string default_type="aes";
#else
	string default_type="hmac";
#endif
	string type=w.app.config.sval("session.cookies_encryptor",default_type);
	string key=w.app.config.sval("session.cookies_key");
	if(type=="hmac") {
		encr.reset(new hmac::cipher(key));
		return;
	}
#ifdef EN_ENCR_SESSIONS
	if(type=="aes") {
		encr.reset(new aes::cipher(key));
		return;
	}
#endif
	throw cppcms_error("Unknown encryptor "+type);
}
コード例 #30
0
ファイル: cache_pool.cpp プロジェクト: klupek/cppcms
cache_pool::cache_pool(json::value const &settings) :
	d(new _data())
{
	std::string type = settings.get("cache.backend","none");
#ifndef CPPCMS_NO_CACHE
	if(type=="thread_shared") {
		if(settings.get("service.worker_processes",0)>1)
			throw cppcms_error(
				"Can't use `thread_shared' backend with more then one process ether set "
				"service.worker_processes to 0 or 1 or use cache.backend=\"process_shared\"");
		unsigned items = settings.get("cache.limit",64);
		d->module=impl::thread_cache_factory(items);
	}
	else if(type=="process_shared") {
#if defined(CPPCMS_WIN32)
		throw cppcms_error("The 'process_shared' backend is not supported under MS Windows and Cygwin platforms");
#elif defined(CPPCMS_NO_PREFOK_CACHE)
		throw cppcms_error("The 'process_shared' backend is disabled during build procedure");
#else // has prefork cache
		size_t memory = settings.get("cache.memory",16384);
		if(memory < 64)
			throw cppcms_error("'process_shared' cache backend requires at least 64 KB of cache memory: cache.memory >= 64");
		unsigned items = settings.get("cache.limit",memory);
		d->module=impl::process_cache_factory(memory*1024,items);
#endif // prefork cache
	}	
	else
#endif // no cache
	if(type != "none" ) {
		throw cppcms_error("Unsupported cache backend `" + type + "'");
	}
#ifndef CPPCMS_NO_TCP_CACHE	
	if(settings.find("cache.tcp").type()==json::is_object) {

		std::vector<std::string> ips=settings.get<std::vector<std::string> >("cache.tcp.ips");
		std::vector<int> ports = settings.get<std::vector<int> >("cache.tcp.ports");

		if(ips.empty() || ports.empty() || ips.size()!=ports.size()) {
			throw cppcms_error("Invalid settings in cache.tcp.ports or cache.tcp.ips");
		}

		booster::intrusive_ptr<impl::base_cache> l1=d->module;
		d->module=impl::tcp_cache_factory(ips,ports,l1);
	}
#endif // no tcp cace
}