backport changes from 1.4.3 branch

This commit is contained in:
Marian Krivos
2012-01-07 11:06:14 +00:00
parent cc90b38ae5
commit 6268aa3865
69 changed files with 10381 additions and 5761 deletions

View File

@@ -1,92 +1,96 @@
// //
// Connector.cpp // Connector.cpp
// //
// $Id: //poco/Main/Data/SQLite/src/Connector.cpp#2 $ // $Id: //poco/Main/Data/SQLite/src/Connector.cpp#2 $
// //
// Library: SQLite // Library: SQLite
// Package: SQLite // Package: SQLite
// Module: Connector // Module: Connector
// //
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. // Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors. // and Contributors.
// //
// Permission is hereby granted, free of charge, to any person or organization // Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by // obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute, // this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the // execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to // Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following: // do so, all subject to the following:
// //
// The copyright notices in the Software and this entire statement, including // The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer, // the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and // must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative // all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by // works are solely in the form of machine-executable object code generated by
// a source language processor. // a source language processor.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
// //
#include "Poco/Data/SQLite/Connector.h" #include "Poco/Data/SQLite/Connector.h"
#include "Poco/Data/SQLite/SessionImpl.h" #include "Poco/Data/SQLite/SessionImpl.h"
#include "Poco/Data/SessionFactory.h" #include "Poco/Data/SessionFactory.h"
#include "sqlite3.h" #if defined(POCO_UNBUNDLED)
#include <sqlite3.h>
#else
namespace Poco { #include "sqlite3.h"
namespace Data { #endif
namespace SQLite {
namespace Poco {
namespace Data {
namespace SQLite {
const std::string Connector::KEY("sqlite"); const std::string Connector::KEY("sqlite");
Connector::Connector() Connector::Connector()
{ {
} }
Connector::~Connector() Connector::~Connector()
{ {
} }
Poco::AutoPtr<Poco::Data::SessionImpl> Connector::createSession(const std::string& connectionString, Poco::AutoPtr<Poco::Data::SessionImpl> Connector::createSession(const std::string& connectionString,
std::size_t timeout) std::size_t timeout)
{ {
return Poco::AutoPtr<Poco::Data::SessionImpl>(new SessionImpl(connectionString, timeout)); return Poco::AutoPtr<Poco::Data::SessionImpl>(new SessionImpl(connectionString, timeout));
} }
void Connector::registerConnector() void Connector::registerConnector()
{ {
Poco::Data::SessionFactory::instance().add(new Connector()); Poco::Data::SessionFactory::instance().add(new Connector());
} }
void Connector::unregisterConnector() void Connector::unregisterConnector()
{ {
Poco::Data::SessionFactory::instance().remove(KEY); Poco::Data::SessionFactory::instance().remove(KEY);
} }
void Connector::enableSharedCache(bool flag) void Connector::enableSharedCache(bool flag)
{ {
sqlite3_enable_shared_cache(flag ? 1 : 0); sqlite3_enable_shared_cache(flag ? 1 : 0);
} }
void Connector::enableSoftHeapLimit(int limit) void Connector::enableSoftHeapLimit(int limit)
{ {
sqlite3_soft_heap_limit(limit); sqlite3_soft_heap_limit(limit);
} }
} } } // namespace Poco::Data::SQLite } } } // namespace Poco::Data::SQLite

View File

@@ -1,257 +1,262 @@
// //
// Extractor.cpp // Extractor.cpp
// //
// $Id: //poco/Main/Data/SQLite/src/Extractor.cpp#5 $ // $Id: //poco/Main/Data/SQLite/src/Extractor.cpp#5 $
// //
// Library: SQLite // Library: SQLite
// Package: SQLite // Package: SQLite
// Module: Extractor // Module: Extractor
// //
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. // Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors. // and Contributors.
// //
// Permission is hereby granted, free of charge, to any person or organization // Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by // obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute, // this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the // execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to // Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following: // do so, all subject to the following:
// //
// The copyright notices in the Software and this entire statement, including // The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer, // the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and // must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative // all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by // works are solely in the form of machine-executable object code generated by
// a source language processor. // a source language processor.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
// //
#include "Poco/Data/SQLite/Extractor.h" #include "Poco/Data/SQLite/Extractor.h"
#include "Poco/Data/SQLite/Utility.h" #include "Poco/Data/SQLite/Utility.h"
#include "Poco/Data/Date.h" #include "Poco/Data/Date.h"
#include "Poco/Data/Time.h" #include "Poco/Data/Time.h"
#include "Poco/Data/LOB.h" #include "Poco/Data/LOB.h"
#include "Poco/Data/DataException.h" #include "Poco/Data/DataException.h"
#include "Poco/DateTimeParser.h" #include "Poco/DateTimeParser.h"
#include "Poco/Exception.h" #include "Poco/Exception.h"
#include <cstdlib> #if defined(POCO_UNBUNDLED)
#include <sqlite3.h>
#else
#include "sqlite3.h"
#endif
#include <cstdlib>
using Poco::DateTimeParser; using Poco::DateTimeParser;
namespace Poco { namespace Poco {
namespace Data { namespace Data {
namespace SQLite { namespace SQLite {
Extractor::Extractor(sqlite3_stmt* pStmt): Extractor::Extractor(sqlite3_stmt* pStmt):
_pStmt(pStmt) _pStmt(pStmt)
{ {
} }
Extractor::~Extractor() Extractor::~Extractor()
{ {
} }
bool Extractor::extract(std::size_t pos, Poco::Int32& val) bool Extractor::extract(std::size_t pos, Poco::Int32& val)
{ {
if (isNull(pos)) if (isNull(pos))
return false; return false;
val = sqlite3_column_int(_pStmt, (int) pos); val = sqlite3_column_int(_pStmt, (int) pos);
return true; return true;
} }
bool Extractor::extract(std::size_t pos, Poco::Int64& val) bool Extractor::extract(std::size_t pos, Poco::Int64& val)
{ {
if (isNull(pos)) if (isNull(pos))
return false; return false;
val = sqlite3_column_int64(_pStmt, (int) pos); val = sqlite3_column_int64(_pStmt, (int) pos);
return true; return true;
} }
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
bool Extractor::extract(std::size_t pos, long& val) bool Extractor::extract(std::size_t pos, long& val)
{ {
if (isNull(pos)) if (isNull(pos))
return false; return false;
val = sqlite3_column_int(_pStmt, (int) pos); val = sqlite3_column_int(_pStmt, (int) pos);
return true; return true;
} }
#endif #endif
bool Extractor::extract(std::size_t pos, double& val) bool Extractor::extract(std::size_t pos, double& val)
{ {
if (isNull(pos)) if (isNull(pos))
return false; return false;
val = sqlite3_column_double(_pStmt, (int) pos); val = sqlite3_column_double(_pStmt, (int) pos);
return true; return true;
} }
bool Extractor::extract(std::size_t pos, std::string& val) bool Extractor::extract(std::size_t pos, std::string& val)
{ {
if (isNull(pos)) if (isNull(pos))
return false; return false;
const char *pBuf = reinterpret_cast<const char*>(sqlite3_column_text(_pStmt, (int) pos)); const char *pBuf = reinterpret_cast<const char*>(sqlite3_column_text(_pStmt, (int) pos));
if (!pBuf) if (!pBuf)
val.clear(); val.clear();
else else
val = std::string(pBuf); val = std::string(pBuf);
return true; return true;
} }
bool Extractor::extract(std::size_t pos, Poco::Int8& val) bool Extractor::extract(std::size_t pos, Poco::Int8& val)
{ {
if (isNull(pos)) if (isNull(pos))
return false; return false;
val = sqlite3_column_int(_pStmt, (int) pos); val = sqlite3_column_int(_pStmt, (int) pos);
return true; return true;
} }
bool Extractor::extract(std::size_t pos, Poco::UInt8& val) bool Extractor::extract(std::size_t pos, Poco::UInt8& val)
{ {
if (isNull(pos)) if (isNull(pos))
return false; return false;
val = sqlite3_column_int(_pStmt, (int) pos); val = sqlite3_column_int(_pStmt, (int) pos);
return true; return true;
} }
bool Extractor::extract(std::size_t pos, Poco::Int16& val) bool Extractor::extract(std::size_t pos, Poco::Int16& val)
{ {
if (isNull(pos)) if (isNull(pos))
return false; return false;
val = sqlite3_column_int(_pStmt, (int) pos); val = sqlite3_column_int(_pStmt, (int) pos);
return true; return true;
} }
bool Extractor::extract(std::size_t pos, Poco::UInt16& val) bool Extractor::extract(std::size_t pos, Poco::UInt16& val)
{ {
if (isNull(pos)) if (isNull(pos))
return false; return false;
val = sqlite3_column_int(_pStmt, (int) pos); val = sqlite3_column_int(_pStmt, (int) pos);
return true; return true;
} }
bool Extractor::extract(std::size_t pos, Poco::UInt32& val) bool Extractor::extract(std::size_t pos, Poco::UInt32& val)
{ {
if (isNull(pos)) if (isNull(pos))
return false; return false;
val = sqlite3_column_int(_pStmt, (int) pos); val = sqlite3_column_int(_pStmt, (int) pos);
return true; return true;
} }
bool Extractor::extract(std::size_t pos, Poco::UInt64& val) bool Extractor::extract(std::size_t pos, Poco::UInt64& val)
{ {
if (isNull(pos)) if (isNull(pos))
return false; return false;
val = sqlite3_column_int64(_pStmt, (int) pos); val = sqlite3_column_int64(_pStmt, (int) pos);
return true; return true;
} }
bool Extractor::extract(std::size_t pos, bool& val) bool Extractor::extract(std::size_t pos, bool& val)
{ {
if (isNull(pos)) if (isNull(pos))
return false; return false;
val = (0 != sqlite3_column_int(_pStmt, (int) pos)); val = (0 != sqlite3_column_int(_pStmt, (int) pos));
return true; return true;
} }
bool Extractor::extract(std::size_t pos, float& val) bool Extractor::extract(std::size_t pos, float& val)
{ {
if (isNull(pos)) if (isNull(pos))
return false; return false;
val = static_cast<float>(sqlite3_column_double(_pStmt, (int) pos)); val = static_cast<float>(sqlite3_column_double(_pStmt, (int) pos));
return true; return true;
} }
bool Extractor::extract(std::size_t pos, char& val) bool Extractor::extract(std::size_t pos, char& val)
{ {
if (isNull(pos)) return false; if (isNull(pos)) return false;
val = sqlite3_column_int(_pStmt, (int) pos); val = sqlite3_column_int(_pStmt, (int) pos);
return true; return true;
} }
bool Extractor::extract(std::size_t pos, Date& val) bool Extractor::extract(std::size_t pos, Date& val)
{ {
std::string str; std::string str;
extract(pos, str); extract(pos, str);
int tzd; int tzd;
DateTime dt = DateTimeParser::parse(Utility::SQLITE_DATE_FORMAT, str, tzd); DateTime dt = DateTimeParser::parse(Utility::SQLITE_DATE_FORMAT, str, tzd);
val = dt; val = dt;
return true; return true;
} }
bool Extractor::extract(std::size_t pos, Time& val) bool Extractor::extract(std::size_t pos, Time& val)
{ {
std::string str; std::string str;
extract(pos, str); extract(pos, str);
int tzd; int tzd;
DateTime dt = DateTimeParser::parse(Utility::SQLITE_TIME_FORMAT, str, tzd); DateTime dt = DateTimeParser::parse(Utility::SQLITE_TIME_FORMAT, str, tzd);
val = dt; val = dt;
return true; return true;
} }
bool Extractor::extract(std::size_t pos, DateTime& val) bool Extractor::extract(std::size_t pos, DateTime& val)
{ {
std::string dt; std::string dt;
extract(pos, dt); extract(pos, dt);
int tzd; int tzd;
DateTimeParser::parse(dt, val, tzd); DateTimeParser::parse(dt, val, tzd);
return true; return true;
} }
bool Extractor::extract(std::size_t pos, Poco::Any& val) bool Extractor::extract(std::size_t pos, Poco::Any& val)
{ {
return extractImpl(pos, val); return extractImpl(pos, val);
} }
bool Extractor::extract(std::size_t pos, Poco::DynamicAny& val) bool Extractor::extract(std::size_t pos, Poco::DynamicAny& val)
{ {
return extractImpl(pos, val); return extractImpl(pos, val);
} }
bool Extractor::isNull(std::size_t pos, std::size_t) bool Extractor::isNull(std::size_t pos, std::size_t)
{ {
if (pos >= _nulls.size()) if (pos >= _nulls.size())
_nulls.resize(pos + 1); _nulls.resize(pos + 1);
if (!_nulls[pos].first) if (!_nulls[pos].first)
{ {
_nulls[pos].first = true; _nulls[pos].first = true;
_nulls[pos].second = (SQLITE_NULL == sqlite3_column_type(_pStmt, pos)); _nulls[pos].second = (SQLITE_NULL == sqlite3_column_type(_pStmt, pos));
} }
return _nulls[pos].second; return _nulls[pos].second;
} }
} } } // namespace Poco::Data::SQLite } } } // namespace Poco::Data::SQLite

View File

@@ -1,307 +1,311 @@
// //
// SQLiteStatementImpl.cpp // SQLiteStatementImpl.cpp
// //
// $Id: //poco/Main/Data/SQLite/src/SQLiteStatementImpl.cpp#8 $ // $Id: //poco/Main/Data/SQLite/src/SQLiteStatementImpl.cpp#8 $
// //
// Library: SQLite // Library: SQLite
// Package: SQLite // Package: SQLite
// Module: SQLiteStatementImpl // Module: SQLiteStatementImpl
// //
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. // Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors. // and Contributors.
// //
// Permission is hereby granted, free of charge, to any person or organization // Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by // obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute, // this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the // execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to // Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following: // do so, all subject to the following:
// //
// The copyright notices in the Software and this entire statement, including // The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer, // the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and // must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative // all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by // works are solely in the form of machine-executable object code generated by
// a source language processor. // a source language processor.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
// //
#include "Poco/Data/SQLite/SQLiteStatementImpl.h" #include "Poco/Data/SQLite/SQLiteStatementImpl.h"
#include "Poco/Data/SQLite/Utility.h" #include "Poco/Data/SQLite/Utility.h"
#include "Poco/Data/SQLite/SQLiteException.h" #include "Poco/Data/SQLite/SQLiteException.h"
#include "Poco/String.h" #include "Poco/String.h"
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include "sqlite3.h" #if defined(POCO_UNBUNDLED)
#include <sqlite3.h>
#else
namespace Poco { #include "sqlite3.h"
namespace Data { #endif
namespace SQLite {
namespace Poco {
namespace Data {
namespace SQLite {
SQLiteStatementImpl::SQLiteStatementImpl(Poco::Data::SessionImpl& rSession, sqlite3* pDB): SQLiteStatementImpl::SQLiteStatementImpl(Poco::Data::SessionImpl& rSession, sqlite3* pDB):
StatementImpl(rSession), StatementImpl(rSession),
_pDB(pDB), _pDB(pDB),
_pStmt(0), _pStmt(0),
_stepCalled(false), _stepCalled(false),
_nextResponse(0), _nextResponse(0),
_affectedRowCount(0), _affectedRowCount(0),
_canBind(false), _canBind(false),
_isExtracted(false), _isExtracted(false),
_canCompile(true) _canCompile(true)
{ {
_columns.resize(1); _columns.resize(1);
} }
SQLiteStatementImpl::~SQLiteStatementImpl()
{
clear();
}
void SQLiteStatementImpl::compileImpl()
{
if (!_pLeftover) _bindBegin = bindings().begin();
std::string statement(toString());
sqlite3_stmt* pStmt = 0;
const char* pSql = _pLeftover ? _pLeftover->c_str() : statement.c_str();
if (0 == std::strlen(pSql))
throw InvalidSQLStatementException("Empty statements are illegal");
int rc = SQLITE_OK;
const char* pLeftover = 0;
bool queryFound = false;
do
{
rc = sqlite3_prepare_v2(_pDB, pSql, -1, &pStmt, &pLeftover);
if (rc != SQLITE_OK)
{
if (pStmt) sqlite3_finalize(pStmt);
pStmt = 0;
std::string errMsg = sqlite3_errmsg(_pDB);
Utility::throwException(rc, errMsg);
}
else if (rc == SQLITE_OK && pStmt)
{
queryFound = true;
}
else if (rc == SQLITE_OK && !pStmt) // comment/whitespace ignore
{
pSql = pLeftover;
if (std::strlen(pSql) == 0)
{
// empty statement or an conditional statement! like CREATE IF NOT EXISTS
// this is valid
queryFound = true;
}
}
} while (rc == SQLITE_OK && !pStmt && !queryFound);
//Finalization call in clear() invalidates the pointer, so the value is remembered here.
//For last statement in a batch (or a single statement), pLeftover == "", so the next call
// to compileImpl() shall return false immediately when there are no more statements left.
std::string leftOver(pLeftover);
trimInPlace(leftOver);
clear();
_pStmt = pStmt;
if (!leftOver.empty())
{
_pLeftover = new std::string(leftOver);
_canCompile = true;
}
else _canCompile = false;
_pBinder = new Binder(_pStmt);
_pExtractor = new Extractor(_pStmt);
if (SQLITE_DONE == _nextResponse && _isExtracted)
{
//if this is not the first compile and there has already been extraction
//during previous step, switch to the next set if there is one provided
if (hasMoreDataSets())
{
activateNextDataSet();
_isExtracted = false;
}
}
SQLiteStatementImpl::~SQLiteStatementImpl() int colCount = sqlite3_column_count(_pStmt);
{
clear(); if (colCount)
} {
std::size_t curDataSet = currentDataSet();
if (curDataSet >= _columns.size()) _columns.resize(curDataSet + 1);
for (int i = 0; i < colCount; ++i)
{
MetaColumn mc(i, sqlite3_column_name(_pStmt, i), Utility::getColumnType(_pStmt, i));
_columns[curDataSet].push_back(mc);
}
}
}
void SQLiteStatementImpl::bindImpl()
{
_stepCalled = false;
_nextResponse = 0;
if (_pStmt == 0) return;
sqlite3_reset(_pStmt);
int paramCount = sqlite3_bind_parameter_count(_pStmt);
BindIt bindEnd = bindings().end();
if (0 == paramCount || bindEnd == _bindBegin)
{
_canBind = false;
return;
}
int availableCount = 0;
Bindings::difference_type bindCount = 0;
Bindings::iterator it = _bindBegin;
for (; it != bindEnd; ++it)
{
availableCount += (*it)->numOfColumnsHandled();
if (availableCount <= paramCount) ++bindCount;
else break;
}
Bindings::difference_type remainingBindCount = bindEnd - _bindBegin;
if (bindCount < remainingBindCount)
{
bindEnd = _bindBegin + bindCount;
_canBind = true;
}
else if (bindCount > remainingBindCount)
throw ParameterCountMismatchException();
if (_bindBegin != bindings().end())
{
_affectedRowCount = (*_bindBegin)->numOfRowsHandled();
void SQLiteStatementImpl::compileImpl() Bindings::iterator oldBegin = _bindBegin;
{ for (std::size_t pos = 1; _bindBegin != bindEnd && (*_bindBegin)->canBind(); ++_bindBegin)
if (!_pLeftover) _bindBegin = bindings().begin(); {
if (_affectedRowCount != (*_bindBegin)->numOfRowsHandled())
throw BindingException("Size mismatch in Bindings. All Bindings MUST have the same size");
std::string statement(toString()); (*_bindBegin)->bind(pos);
sqlite3_stmt* pStmt = 0; pos += (*_bindBegin)->numOfColumnsHandled();
const char* pSql = _pLeftover ? _pLeftover->c_str() : statement.c_str(); }
if (0 == std::strlen(pSql))
throw InvalidSQLStatementException("Empty statements are illegal");
int rc = SQLITE_OK;
const char* pLeftover = 0;
bool queryFound = false;
do
{
rc = sqlite3_prepare_v2(_pDB, pSql, -1, &pStmt, &pLeftover);
if (rc != SQLITE_OK)
{
if (pStmt) sqlite3_finalize(pStmt);
pStmt = 0;
std::string errMsg = sqlite3_errmsg(_pDB);
Utility::throwException(rc, errMsg);
}
else if (rc == SQLITE_OK && pStmt)
{
queryFound = true;
}
else if(rc == SQLITE_OK && !pStmt) // comment/whitespace ignore
{
pSql = pLeftover;
if (std::strlen(pSql) == 0)
{
// empty statement or an conditional statement! like CREATE IF NOT EXISTS
// this is valid
queryFound = true;
}
}
} while (rc == SQLITE_OK && !pStmt && !queryFound);
//Finalization call in clear() invalidates the pointer, so the value is remembered here.
//For last statement in a batch (or a single statement), pLeftover == "", so the next call
// to compileImpl() shall return false immediately when there are no more statements left.
std::string leftOver(pLeftover);
trimInPlace(leftOver);
clear();
_pStmt = pStmt;
if (!leftOver.empty())
{
_pLeftover = new std::string(leftOver);
_canCompile = true;
}
else _canCompile = false;
_pBinder = new Binder(_pStmt);
_pExtractor = new Extractor(_pStmt);
if (SQLITE_DONE == _nextResponse && _isExtracted)
{
//if this is not the first compile and there has already been extraction
//during previous step, switch to the next set if there is one provided
if (hasMoreDataSets())
{
activateNextDataSet();
_isExtracted = false;
}
}
int colCount = sqlite3_column_count(_pStmt);
if (colCount)
{
std::size_t curDataSet = currentDataSet();
if (curDataSet >= _columns.size()) _columns.resize(curDataSet + 1);
for (int i = 0; i < colCount; ++i)
{
MetaColumn mc(i, sqlite3_column_name(_pStmt, i), Utility::getColumnType(_pStmt, i));
_columns[curDataSet].push_back(mc);
}
}
}
void SQLiteStatementImpl::bindImpl()
{
_stepCalled = false;
_nextResponse = 0;
if (_pStmt == 0) return;
sqlite3_reset(_pStmt);
int paramCount = sqlite3_bind_parameter_count(_pStmt);
BindIt bindEnd = bindings().end();
if (0 == paramCount || bindEnd == _bindBegin)
{
_canBind = false;
return;
}
int availableCount = 0;
Bindings::difference_type bindCount = 0;
Bindings::iterator it = _bindBegin;
for (; it != bindEnd; ++it)
{
availableCount += (*it)->numOfColumnsHandled();
if (availableCount <= paramCount) ++bindCount;
else break;
}
Bindings::difference_type remainingBindCount = bindEnd - _bindBegin;
if (bindCount < remainingBindCount)
{
bindEnd = _bindBegin + bindCount;
_canBind = true;
}
else if (bindCount > remainingBindCount)
throw ParameterCountMismatchException();
if (_bindBegin != bindings().end())
{
_affectedRowCount = (*_bindBegin)->numOfRowsHandled();
Bindings::iterator oldBegin = _bindBegin;
for (std::size_t pos = 1; _bindBegin != bindEnd && (*_bindBegin)->canBind(); ++_bindBegin)
{
if (_affectedRowCount != (*_bindBegin)->numOfRowsHandled())
throw BindingException("Size mismatch in Bindings. All Bindings MUST have the same size");
(*_bindBegin)->bind(pos);
pos += (*_bindBegin)->numOfColumnsHandled();
}
if ((*oldBegin)->canBind())
{
//container binding will come back for more, so we must rewind
_bindBegin = oldBegin;
_canBind = true;
}
else _canBind = false;
}
}
void SQLiteStatementImpl::clear()
{
_columns[currentDataSet()].clear();
_affectedRowCount = 0;
if (_pStmt)
{
sqlite3_finalize(_pStmt);
_pStmt=0;
}
_pLeftover = 0;
}
bool SQLiteStatementImpl::hasNext()
{
if (_stepCalled)
return (_nextResponse == SQLITE_ROW);
// _pStmt is allowed to be null for conditional SQL statements
if (_pStmt == 0)
{
_stepCalled = true;
_nextResponse = SQLITE_DONE;
return false;
}
_stepCalled = true;
_nextResponse = sqlite3_step(_pStmt);
if (_nextResponse != SQLITE_ROW && _nextResponse != SQLITE_OK && _nextResponse != SQLITE_DONE)
Utility::throwException(_nextResponse);
_pExtractor->reset();//clear the cached null indicators
return (_nextResponse == SQLITE_ROW);
}
if ((*oldBegin)->canBind())
{
//container binding will come back for more, so we must rewind
_bindBegin = oldBegin;
_canBind = true;
}
else _canBind = false;
}
}
void SQLiteStatementImpl::clear()
{
_columns[currentDataSet()].clear();
_affectedRowCount = 0;
if (_pStmt)
{
sqlite3_finalize(_pStmt);
_pStmt=0;
}
_pLeftover = 0;
}
bool SQLiteStatementImpl::hasNext()
{
if (_stepCalled)
return (_nextResponse == SQLITE_ROW);
// _pStmt is allowed to be null for conditional SQL statements
if (_pStmt == 0)
{
_stepCalled = true;
_nextResponse = SQLITE_DONE;
return false;
}
_stepCalled = true;
_nextResponse = sqlite3_step(_pStmt);
if (_nextResponse != SQLITE_ROW && _nextResponse != SQLITE_OK && _nextResponse != SQLITE_DONE)
Utility::throwException(_nextResponse);
_pExtractor->reset();//clear the cached null indicators
return (_nextResponse == SQLITE_ROW);
}
std::size_t SQLiteStatementImpl::next() std::size_t SQLiteStatementImpl::next()
{ {
if (SQLITE_ROW == _nextResponse) if (SQLITE_ROW == _nextResponse)
{ {
poco_assert (columnsReturned() == sqlite3_column_count(_pStmt)); poco_assert (columnsReturned() == sqlite3_column_count(_pStmt));
Extractions& extracts = extractions(); Extractions& extracts = extractions();
Extractions::iterator it = extracts.begin(); Extractions::iterator it = extracts.begin();
Extractions::iterator itEnd = extracts.end(); Extractions::iterator itEnd = extracts.end();
std::size_t pos = 0; // sqlite starts with pos 0 for results! std::size_t pos = 0; // sqlite starts with pos 0 for results!
for (; it != itEnd; ++it) for (; it != itEnd; ++it)
{ {
(*it)->extract(pos); (*it)->extract(pos);
pos += (*it)->numOfColumnsHandled(); pos += (*it)->numOfColumnsHandled();
_isExtracted = true; _isExtracted = true;
} }
_stepCalled = false; _stepCalled = false;
} }
else if (SQLITE_DONE == _nextResponse) else if (SQLITE_DONE == _nextResponse)
{ {
throw Poco::Data::DataException("No data received"); throw Poco::Data::DataException("No data received");
} }
else else
{ {
int rc = _nextResponse; int rc = _nextResponse;
Utility::throwException(rc, std::string("Iterator Error: trying to access the next value")); Utility::throwException(rc, std::string("Iterator Error: trying to access the next value"));
} }
return 1u; return 1u;
} }
std::size_t SQLiteStatementImpl::columnsReturned() const std::size_t SQLiteStatementImpl::columnsReturned() const
{ {
return (std::size_t) _columns[currentDataSet()].size(); return (std::size_t) _columns[currentDataSet()].size();
} }
const MetaColumn& SQLiteStatementImpl::metaColumn(std::size_t pos) const const MetaColumn& SQLiteStatementImpl::metaColumn(std::size_t pos) const
{ {
std::size_t curDataSet = currentDataSet(); std::size_t curDataSet = currentDataSet();
poco_assert (pos >= 0 && pos <= _columns[curDataSet].size()); poco_assert (pos >= 0 && pos <= _columns[curDataSet].size());
return _columns[curDataSet][pos]; return _columns[curDataSet][pos];
} }
std::size_t SQLiteStatementImpl::affectedRowCount() const std::size_t SQLiteStatementImpl::affectedRowCount() const
{ {
return _affectedRowCount ? _affectedRowCount : sqlite3_changes(_pDB); return _affectedRowCount ? _affectedRowCount : sqlite3_changes(_pDB);
} }
} } } // namespace Poco::Data::SQLite } } } // namespace Poco::Data::SQLite

View File

@@ -1,208 +1,212 @@
// //
// Utility.cpp // Utility.cpp
// //
// $Id: //poco/Main/Data/SQLite/src/Utility.cpp#5 $ // $Id: //poco/Main/Data/SQLite/src/Utility.cpp#5 $
// //
// Library: SQLite // Library: SQLite
// Package: SQLite // Package: SQLite
// Module: Utility // Module: Utility
// //
// Implementation of Utility // Implementation of Utility
// //
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. // Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors. // and Contributors.
// //
// Permission is hereby granted, free of charge, to any person or organization // Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by // obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute, // this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the // execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to // Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following: // do so, all subject to the following:
// //
// The copyright notices in the Software and this entire statement, including // The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer, // the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and // must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative // all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by // works are solely in the form of machine-executable object code generated by
// a source language processor. // a source language processor.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
// //
#include "Poco/Data/SQLite/Utility.h" #include "Poco/Data/SQLite/Utility.h"
#include "Poco/Data/SQLite/SQLiteException.h" #include "Poco/Data/SQLite/SQLiteException.h"
#include "Poco/NumberFormatter.h" #include "Poco/NumberFormatter.h"
#include "Poco/String.h" #include "Poco/String.h"
#include "Poco/Exception.h" #include "Poco/Exception.h"
#include "sqlite3.h" #if defined(POCO_UNBUNDLED)
#include <sqlite3.h>
#else
namespace Poco { #include "sqlite3.h"
namespace Data { #endif
namespace SQLite {
namespace Poco {
namespace Data {
namespace SQLite {
const std::string Utility::SQLITE_DATE_FORMAT = "%Y-%m-%d"; const std::string Utility::SQLITE_DATE_FORMAT = "%Y-%m-%d";
const std::string Utility::SQLITE_TIME_FORMAT = "%H:%M:%S"; const std::string Utility::SQLITE_TIME_FORMAT = "%H:%M:%S";
Utility::TypeMap Utility::_types; Utility::TypeMap Utility::_types;
Utility::Utility() Utility::Utility()
{ {
Poco::FastMutex::ScopedLock l(_mutex); Poco::FastMutex::ScopedLock l(_mutex);
if (_types.empty()) if (_types.empty())
{ {
_types.insert(TypeMap::value_type("", MetaColumn::FDT_STRING)); _types.insert(TypeMap::value_type("", MetaColumn::FDT_STRING));
_types.insert(TypeMap::value_type("BOOL", MetaColumn::FDT_BOOL)); _types.insert(TypeMap::value_type("BOOL", MetaColumn::FDT_BOOL));
_types.insert(TypeMap::value_type("BOOLEAN", MetaColumn::FDT_BOOL)); _types.insert(TypeMap::value_type("BOOLEAN", MetaColumn::FDT_BOOL));
_types.insert(TypeMap::value_type("BIT", MetaColumn::FDT_BOOL)); _types.insert(TypeMap::value_type("BIT", MetaColumn::FDT_BOOL));
_types.insert(TypeMap::value_type("UINT8", MetaColumn::FDT_UINT8)); _types.insert(TypeMap::value_type("UINT8", MetaColumn::FDT_UINT8));
_types.insert(TypeMap::value_type("UTINY", MetaColumn::FDT_UINT8)); _types.insert(TypeMap::value_type("UTINY", MetaColumn::FDT_UINT8));
_types.insert(TypeMap::value_type("UINTEGER8", MetaColumn::FDT_UINT8)); _types.insert(TypeMap::value_type("UINTEGER8", MetaColumn::FDT_UINT8));
_types.insert(TypeMap::value_type("INT8", MetaColumn::FDT_INT8)); _types.insert(TypeMap::value_type("INT8", MetaColumn::FDT_INT8));
_types.insert(TypeMap::value_type("TINY", MetaColumn::FDT_INT8)); _types.insert(TypeMap::value_type("TINY", MetaColumn::FDT_INT8));
_types.insert(TypeMap::value_type("INTEGER8", MetaColumn::FDT_INT8)); _types.insert(TypeMap::value_type("INTEGER8", MetaColumn::FDT_INT8));
_types.insert(TypeMap::value_type("UINT16", MetaColumn::FDT_UINT16)); _types.insert(TypeMap::value_type("UINT16", MetaColumn::FDT_UINT16));
_types.insert(TypeMap::value_type("USHORT", MetaColumn::FDT_UINT16)); _types.insert(TypeMap::value_type("USHORT", MetaColumn::FDT_UINT16));
_types.insert(TypeMap::value_type("UINTEGER16", MetaColumn::FDT_UINT16)); _types.insert(TypeMap::value_type("UINTEGER16", MetaColumn::FDT_UINT16));
_types.insert(TypeMap::value_type("INT16", MetaColumn::FDT_INT16)); _types.insert(TypeMap::value_type("INT16", MetaColumn::FDT_INT16));
_types.insert(TypeMap::value_type("SHORT", MetaColumn::FDT_INT16)); _types.insert(TypeMap::value_type("SHORT", MetaColumn::FDT_INT16));
_types.insert(TypeMap::value_type("INTEGER16", MetaColumn::FDT_INT16)); _types.insert(TypeMap::value_type("INTEGER16", MetaColumn::FDT_INT16));
_types.insert(TypeMap::value_type("UINT", MetaColumn::FDT_UINT32)); _types.insert(TypeMap::value_type("UINT", MetaColumn::FDT_UINT32));
_types.insert(TypeMap::value_type("UINT32", MetaColumn::FDT_UINT32)); _types.insert(TypeMap::value_type("UINT32", MetaColumn::FDT_UINT32));
_types.insert(TypeMap::value_type("UINTEGER32", MetaColumn::FDT_UINT32)); _types.insert(TypeMap::value_type("UINTEGER32", MetaColumn::FDT_UINT32));
_types.insert(TypeMap::value_type("INT", MetaColumn::FDT_INT32)); _types.insert(TypeMap::value_type("INT", MetaColumn::FDT_INT32));
_types.insert(TypeMap::value_type("INT32", MetaColumn::FDT_INT32)); _types.insert(TypeMap::value_type("INT32", MetaColumn::FDT_INT32));
_types.insert(TypeMap::value_type("INTEGER", MetaColumn::FDT_INT32)); _types.insert(TypeMap::value_type("INTEGER", MetaColumn::FDT_INT32));
_types.insert(TypeMap::value_type("INTEGER32", MetaColumn::FDT_INT32)); _types.insert(TypeMap::value_type("INTEGER32", MetaColumn::FDT_INT32));
_types.insert(TypeMap::value_type("UINT64", MetaColumn::FDT_UINT64)); _types.insert(TypeMap::value_type("UINT64", MetaColumn::FDT_UINT64));
_types.insert(TypeMap::value_type("ULONG", MetaColumn::FDT_INT64)); _types.insert(TypeMap::value_type("ULONG", MetaColumn::FDT_INT64));
_types.insert(TypeMap::value_type("UINTEGER64", MetaColumn::FDT_UINT64)); _types.insert(TypeMap::value_type("UINTEGER64", MetaColumn::FDT_UINT64));
_types.insert(TypeMap::value_type("INT64", MetaColumn::FDT_INT64)); _types.insert(TypeMap::value_type("INT64", MetaColumn::FDT_INT64));
_types.insert(TypeMap::value_type("LONG", MetaColumn::FDT_INT64)); _types.insert(TypeMap::value_type("LONG", MetaColumn::FDT_INT64));
_types.insert(TypeMap::value_type("INTEGER64", MetaColumn::FDT_INT64)); _types.insert(TypeMap::value_type("INTEGER64", MetaColumn::FDT_INT64));
_types.insert(TypeMap::value_type("COUNTER", MetaColumn::FDT_UINT64)); _types.insert(TypeMap::value_type("COUNTER", MetaColumn::FDT_UINT64));
_types.insert(TypeMap::value_type("AUTOINCREMENT", MetaColumn::FDT_UINT64)); _types.insert(TypeMap::value_type("AUTOINCREMENT", MetaColumn::FDT_UINT64));
_types.insert(TypeMap::value_type("REAL", MetaColumn::FDT_DOUBLE)); _types.insert(TypeMap::value_type("REAL", MetaColumn::FDT_DOUBLE));
_types.insert(TypeMap::value_type("FLOA", MetaColumn::FDT_DOUBLE)); _types.insert(TypeMap::value_type("FLOA", MetaColumn::FDT_DOUBLE));
_types.insert(TypeMap::value_type("FLOAT", MetaColumn::FDT_DOUBLE)); _types.insert(TypeMap::value_type("FLOAT", MetaColumn::FDT_DOUBLE));
_types.insert(TypeMap::value_type("DOUB", MetaColumn::FDT_DOUBLE)); _types.insert(TypeMap::value_type("DOUB", MetaColumn::FDT_DOUBLE));
_types.insert(TypeMap::value_type("DOUBLE", MetaColumn::FDT_DOUBLE)); _types.insert(TypeMap::value_type("DOUBLE", MetaColumn::FDT_DOUBLE));
_types.insert(TypeMap::value_type("CHAR", MetaColumn::FDT_STRING)); _types.insert(TypeMap::value_type("CHAR", MetaColumn::FDT_STRING));
_types.insert(TypeMap::value_type("CLOB", MetaColumn::FDT_STRING)); _types.insert(TypeMap::value_type("CLOB", MetaColumn::FDT_STRING));
_types.insert(TypeMap::value_type("TEXT", MetaColumn::FDT_STRING)); _types.insert(TypeMap::value_type("TEXT", MetaColumn::FDT_STRING));
_types.insert(TypeMap::value_type("VARCHAR", MetaColumn::FDT_STRING)); _types.insert(TypeMap::value_type("VARCHAR", MetaColumn::FDT_STRING));
_types.insert(TypeMap::value_type("NCHAR", MetaColumn::FDT_STRING)); _types.insert(TypeMap::value_type("NCHAR", MetaColumn::FDT_STRING));
_types.insert(TypeMap::value_type("NCLOB", MetaColumn::FDT_STRING)); _types.insert(TypeMap::value_type("NCLOB", MetaColumn::FDT_STRING));
_types.insert(TypeMap::value_type("NTEXT", MetaColumn::FDT_STRING)); _types.insert(TypeMap::value_type("NTEXT", MetaColumn::FDT_STRING));
_types.insert(TypeMap::value_type("NVARCHAR", MetaColumn::FDT_STRING)); _types.insert(TypeMap::value_type("NVARCHAR", MetaColumn::FDT_STRING));
_types.insert(TypeMap::value_type("BLOB", MetaColumn::FDT_BLOB)); _types.insert(TypeMap::value_type("BLOB", MetaColumn::FDT_BLOB));
_types.insert(TypeMap::value_type("DATE", MetaColumn::FDT_DATE)); _types.insert(TypeMap::value_type("DATE", MetaColumn::FDT_DATE));
_types.insert(TypeMap::value_type("TIME", MetaColumn::FDT_TIME)); _types.insert(TypeMap::value_type("TIME", MetaColumn::FDT_TIME));
_types.insert(TypeMap::value_type("DATETIME", MetaColumn::FDT_TIMESTAMP)); _types.insert(TypeMap::value_type("DATETIME", MetaColumn::FDT_TIMESTAMP));
_types.insert(TypeMap::value_type("TIMESTAMP", MetaColumn::FDT_TIMESTAMP)); _types.insert(TypeMap::value_type("TIMESTAMP", MetaColumn::FDT_TIMESTAMP));
} }
} }
std::string Utility::lastError(sqlite3 *pDB) std::string Utility::lastError(sqlite3 *pDB)
{ {
return std::string(sqlite3_errmsg(pDB)); return std::string(sqlite3_errmsg(pDB));
} }
MetaColumn::ColumnDataType Utility::getColumnType(sqlite3_stmt* pStmt, std::size_t pos) MetaColumn::ColumnDataType Utility::getColumnType(sqlite3_stmt* pStmt, std::size_t pos)
{ {
poco_assert_dbg (pStmt); poco_assert_dbg (pStmt);
static Utility u; static Utility u;
const char* pc = sqlite3_column_decltype(pStmt, (int) pos); const char* pc = sqlite3_column_decltype(pStmt, (int) pos);
std::string sqliteType = pc ? pc : ""; std::string sqliteType = pc ? pc : "";
Poco::toUpperInPlace(sqliteType); Poco::toUpperInPlace(sqliteType);
sqliteType = sqliteType.substr(0, sqliteType.find_first_of(" (")); sqliteType = sqliteType.substr(0, sqliteType.find_first_of(" ("));
TypeMap::const_iterator it = _types.find(Poco::trimInPlace(sqliteType)); TypeMap::const_iterator it = _types.find(Poco::trimInPlace(sqliteType));
if (_types.end() == it) throw Poco::NotFoundException(); if (_types.end() == it) throw Poco::NotFoundException();
return it->second; return it->second;
} }
void Utility::throwException(int rc, const std::string& addErrMsg) void Utility::throwException(int rc, const std::string& addErrMsg)
{ {
switch (rc) switch (rc)
{ {
case SQLITE_OK: case SQLITE_OK:
break; break;
case SQLITE_ERROR: case SQLITE_ERROR:
throw InvalidSQLStatementException(std::string("SQL error or missing database"), addErrMsg); throw InvalidSQLStatementException(std::string("SQL error or missing database"), addErrMsg);
case SQLITE_INTERNAL: case SQLITE_INTERNAL:
throw InternalDBErrorException(std::string("An internal logic error in SQLite"), addErrMsg); throw InternalDBErrorException(std::string("An internal logic error in SQLite"), addErrMsg);
case SQLITE_PERM: case SQLITE_PERM:
throw DBAccessDeniedException(std::string("Access permission denied"), addErrMsg); throw DBAccessDeniedException(std::string("Access permission denied"), addErrMsg);
case SQLITE_ABORT: case SQLITE_ABORT:
throw ExecutionAbortedException(std::string("Callback routine requested an abort"), addErrMsg); throw ExecutionAbortedException(std::string("Callback routine requested an abort"), addErrMsg);
case SQLITE_BUSY: case SQLITE_BUSY:
throw DBLockedException(std::string("The database file is locked"), addErrMsg); throw DBLockedException(std::string("The database file is locked"), addErrMsg);
case SQLITE_LOCKED: case SQLITE_LOCKED:
throw TableLockedException(std::string("A table in the database is locked"), addErrMsg); throw TableLockedException(std::string("A table in the database is locked"), addErrMsg);
case SQLITE_NOMEM: case SQLITE_NOMEM:
throw NoMemoryException(std::string("A malloc() failed"), addErrMsg); throw NoMemoryException(std::string("A malloc() failed"), addErrMsg);
case SQLITE_READONLY: case SQLITE_READONLY:
throw ReadOnlyException(std::string("Attempt to write a readonly database"), addErrMsg); throw ReadOnlyException(std::string("Attempt to write a readonly database"), addErrMsg);
case SQLITE_INTERRUPT: case SQLITE_INTERRUPT:
throw InterruptException(std::string("Operation terminated by sqlite_interrupt()"), addErrMsg); throw InterruptException(std::string("Operation terminated by sqlite_interrupt()"), addErrMsg);
case SQLITE_IOERR: case SQLITE_IOERR:
throw IOErrorException(std::string("Some kind of disk I/O error occurred"), addErrMsg); throw IOErrorException(std::string("Some kind of disk I/O error occurred"), addErrMsg);
case SQLITE_CORRUPT: case SQLITE_CORRUPT:
throw CorruptImageException(std::string("The database disk image is malformed"), addErrMsg); throw CorruptImageException(std::string("The database disk image is malformed"), addErrMsg);
case SQLITE_NOTFOUND: case SQLITE_NOTFOUND:
throw TableNotFoundException(std::string("Table or record not found"), addErrMsg); throw TableNotFoundException(std::string("Table or record not found"), addErrMsg);
case SQLITE_FULL: case SQLITE_FULL:
throw DatabaseFullException(std::string("Insertion failed because database is full"), addErrMsg); throw DatabaseFullException(std::string("Insertion failed because database is full"), addErrMsg);
case SQLITE_CANTOPEN: case SQLITE_CANTOPEN:
throw CantOpenDBFileException(std::string("Unable to open the database file"), addErrMsg); throw CantOpenDBFileException(std::string("Unable to open the database file"), addErrMsg);
case SQLITE_PROTOCOL: case SQLITE_PROTOCOL:
throw LockProtocolException(std::string("Database lock protocol error"), addErrMsg); throw LockProtocolException(std::string("Database lock protocol error"), addErrMsg);
case SQLITE_EMPTY: case SQLITE_EMPTY:
throw InternalDBErrorException(std::string("(Internal Only) Database table is empty"), addErrMsg); throw InternalDBErrorException(std::string("(Internal Only) Database table is empty"), addErrMsg);
case SQLITE_SCHEMA: case SQLITE_SCHEMA:
throw SchemaDiffersException(std::string("The database schema changed"), addErrMsg); throw SchemaDiffersException(std::string("The database schema changed"), addErrMsg);
case SQLITE_TOOBIG: case SQLITE_TOOBIG:
throw RowTooBigException(std::string("Too much data for one row of a table"), addErrMsg); throw RowTooBigException(std::string("Too much data for one row of a table"), addErrMsg);
case SQLITE_CONSTRAINT: case SQLITE_CONSTRAINT:
throw ConstraintViolationException(std::string("Abort due to constraint violation"), addErrMsg); throw ConstraintViolationException(std::string("Abort due to constraint violation"), addErrMsg);
case SQLITE_MISMATCH: case SQLITE_MISMATCH:
throw DataTypeMismatchException(std::string("Data type mismatch"), addErrMsg); throw DataTypeMismatchException(std::string("Data type mismatch"), addErrMsg);
case SQLITE_MISUSE: case SQLITE_MISUSE:
throw InvalidLibraryUseException(std::string("Library used incorrectly"), addErrMsg); throw InvalidLibraryUseException(std::string("Library used incorrectly"), addErrMsg);
case SQLITE_NOLFS: case SQLITE_NOLFS:
throw OSFeaturesMissingException(std::string("Uses OS features not supported on host"), addErrMsg); throw OSFeaturesMissingException(std::string("Uses OS features not supported on host"), addErrMsg);
case SQLITE_AUTH: case SQLITE_AUTH:
throw AuthorizationDeniedException(std::string("Authorization denied"), addErrMsg); throw AuthorizationDeniedException(std::string("Authorization denied"), addErrMsg);
case SQLITE_FORMAT: case SQLITE_FORMAT:
throw CorruptImageException(std::string("Auxiliary database format error"), addErrMsg); throw CorruptImageException(std::string("Auxiliary database format error"), addErrMsg);
case SQLITE_NOTADB: case SQLITE_NOTADB:
throw CorruptImageException(std::string("File opened that is not a database file"), addErrMsg); throw CorruptImageException(std::string("File opened that is not a database file"), addErrMsg);
case SQLITE_RANGE: case SQLITE_RANGE:
throw InvalidSQLStatementException(std::string("Bind Parameter out of range (Access of invalid position 0? bind starts with 1!)"), addErrMsg); throw InvalidSQLStatementException(std::string("Bind Parameter out of range (Access of invalid position 0? bind starts with 1!)"), addErrMsg);
case SQLITE_ROW: case SQLITE_ROW:
break; // sqlite_step() has another row ready break; // sqlite_step() has another row ready
case SQLITE_DONE: case SQLITE_DONE:
break; // sqlite_step() has finished executing break; // sqlite_step() has finished executing
default: default:
throw SQLiteException(std::string("Unkown error code: ") + Poco::NumberFormatter::format(rc), addErrMsg); throw SQLiteException(std::string("Unkown error code: ") + Poco::NumberFormatter::format(rc), addErrMsg);
} }
} }
} } } // namespace Poco::Data::SQLite } } } // namespace Poco::Data::SQLite

File diff suppressed because it is too large Load Diff

View File

@@ -107,9 +107,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()]. ** [sqlite_version()] and [sqlite_source_id()].
*/ */
#define SQLITE_VERSION "3.7.7.1" #define SQLITE_VERSION "3.7.9"
#define SQLITE_VERSION_NUMBER 3007007 #define SQLITE_VERSION_NUMBER 3007009
#define SQLITE_SOURCE_ID "2011-06-28 17:39:05 af0d91adf497f5f36ec3813f04235a6e195a605f" #define SQLITE_SOURCE_ID "2011-11-01 00:52:41 c7c6050ef060877ebe77b41d959e9df13f8c9b5e"
/* /*
** CAPI3REF: Run-Time Library Version Numbers ** CAPI3REF: Run-Time Library Version Numbers
@@ -741,6 +741,41 @@ struct sqlite3_io_methods {
** Applications should not call [sqlite3_file_control()] with this ** Applications should not call [sqlite3_file_control()] with this
** opcode as doing so may disrupt the operation of the specialized VFSes ** opcode as doing so may disrupt the operation of the specialized VFSes
** that do require it. ** that do require it.
**
** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
** retry counts and intervals for certain disk I/O operations for the
** windows [VFS] in order to work to provide robustness against
** anti-virus programs. By default, the windows VFS will retry file read,
** file write, and file delete operations up to 10 times, with a delay
** of 25 milliseconds before the first retry and with the delay increasing
** by an additional 25 milliseconds with each subsequent retry. This
** opcode allows those to values (10 retries and 25 milliseconds of delay)
** to be adjusted. The values are changed for all database connections
** within the same process. The argument is a pointer to an array of two
** integers where the first integer i the new retry count and the second
** integer is the delay. If either integer is negative, then the setting
** is not changed but instead the prior value of that setting is written
** into the array entry, allowing the current retry settings to be
** interrogated. The zDbName parameter is ignored.
**
** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
** persistent [WAL | Write AHead Log] setting. By default, the auxiliary
** write ahead log and shared memory files used for transaction control
** are automatically deleted when the latest connection to the database
** closes. Setting persistent WAL mode causes those files to persist after
** close. Persisting the files is useful when other processes that do not
** have write permission on the directory containing the database file want
** to read the database file, as the WAL and shared memory files must exist
** in order for the database to be readable. The fourth parameter to
** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
** That integer is 0 to disable persistent WAL mode or 1 to enable persistent
** WAL mode. If the integer is -1, then it is overwritten with the current
** WAL persistence setting.
**
** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening
** a write transaction to indicate that, unless it is rolled back for some
** reason, the entire database file will be overwritten by the current
** transaction. This is used by VACUUM operations.
*/ */
#define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_FCNTL_LOCKSTATE 1
#define SQLITE_GET_LOCKPROXYFILE 2 #define SQLITE_GET_LOCKPROXYFILE 2
@@ -750,7 +785,9 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_CHUNK_SIZE 6 #define SQLITE_FCNTL_CHUNK_SIZE 6
#define SQLITE_FCNTL_FILE_POINTER 7 #define SQLITE_FCNTL_FILE_POINTER 7
#define SQLITE_FCNTL_SYNC_OMITTED 8 #define SQLITE_FCNTL_SYNC_OMITTED 8
#define SQLITE_FCNTL_WIN32_AV_RETRY 9
#define SQLITE_FCNTL_PERSIST_WAL 10
#define SQLITE_FCNTL_OVERWRITE 11
/* /*
** CAPI3REF: Mutex Handle ** CAPI3REF: Mutex Handle
@@ -1178,16 +1215,10 @@ SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
** order to verify that SQLite recovers gracefully from such ** order to verify that SQLite recovers gracefully from such
** conditions. ** conditions.
** **
** The xMalloc and xFree methods must work like the ** The xMalloc, xRealloc, and xFree methods must work like the
** malloc() and free() functions from the standard C library. ** malloc(), realloc() and free() functions from the standard C library.
** The xRealloc method must work like realloc() from the standard C library ** ^SQLite guarantees that the second argument to
** with the exception that if the second argument to xRealloc is zero,
** xRealloc must be a no-op - it must not perform any allocation or
** deallocation. ^SQLite guarantees that the second argument to
** xRealloc is always a value returned by a prior call to xRoundup. ** xRealloc is always a value returned by a prior call to xRoundup.
** And so in cases where xRoundup always returns a positive number,
** xRealloc can perform exactly as the standard library realloc() and
** still be in compliance with this specification.
** **
** xSize should return the allocated size of a memory allocation ** xSize should return the allocated size of a memory allocation
** previously obtained from xMalloc or xRealloc. The allocated size ** previously obtained from xMalloc or xRealloc. The allocated size
@@ -1373,8 +1404,8 @@ struct sqlite3_mem_methods {
** allocator is engaged to handle all of SQLites memory allocation needs. ** allocator is engaged to handle all of SQLites memory allocation needs.
** The first pointer (the memory pointer) must be aligned to an 8-byte ** The first pointer (the memory pointer) must be aligned to an 8-byte
** boundary or subsequent behavior of SQLite will be undefined. ** boundary or subsequent behavior of SQLite will be undefined.
** The minimum allocation size is capped at 2^12. Reasonable values ** The minimum allocation size is capped at 2**12. Reasonable values
** for the minimum allocation size are 2^5 through 2^8.</dd> ** for the minimum allocation size are 2**5 through 2**8.</dd>
** **
** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt> ** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt>
** <dd> ^(This option takes a single argument which is a pointer to an ** <dd> ^(This option takes a single argument which is a pointer to an
@@ -2773,7 +2804,8 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** that the supplied string is nul-terminated, then there is a small ** that the supplied string is nul-terminated, then there is a small
** performance advantage to be gained by passing an nByte parameter that ** performance advantage to be gained by passing an nByte parameter that
** is equal to the number of bytes in the input string <i>including</i> ** is equal to the number of bytes in the input string <i>including</i>
** the nul-terminator bytes. ** the nul-terminator bytes as this saves SQLite from having to
** make a copy of the input string.
** **
** ^If pzTail is not NULL then *pzTail is made to point to the first byte ** ^If pzTail is not NULL then *pzTail is made to point to the first byte
** past the end of the first SQL statement in zSql. These routines only ** past the end of the first SQL statement in zSql. These routines only
@@ -2824,7 +2856,7 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** ^The specific value of WHERE-clause [parameter] might influence the ** ^The specific value of WHERE-clause [parameter] might influence the
** choice of query plan if the parameter is the left-hand side of a [LIKE] ** choice of query plan if the parameter is the left-hand side of a [LIKE]
** or [GLOB] operator or if the parameter is compared to an indexed column ** or [GLOB] operator or if the parameter is compared to an indexed column
** and the [SQLITE_ENABLE_STAT2] compile-time option is enabled. ** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled.
** the ** the
** </li> ** </li>
** </ol> ** </ol>
@@ -2994,6 +3026,13 @@ typedef struct sqlite3_context sqlite3_context;
** number of <u>bytes</u> in the value, not the number of characters.)^ ** number of <u>bytes</u> in the value, not the number of characters.)^
** ^If the fourth parameter is negative, the length of the string is ** ^If the fourth parameter is negative, the length of the string is
** the number of bytes up to the first zero terminator. ** the number of bytes up to the first zero terminator.
** If a non-negative fourth parameter is provided to sqlite3_bind_text()
** or sqlite3_bind_text16() then that parameter must be the byte offset
** where the NUL terminator would occur assuming the string were NUL
** terminated. If any NUL characters occur at byte offsets less than
** the value of the fourth parameter then the resulting string value will
** contain embedded NULs. The result of expressions involving strings
** with embedded NULs is undefined.
** **
** ^The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and ** ^The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and
** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or ** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or
@@ -3327,6 +3366,12 @@ SQLITE_API int sqlite3_step(sqlite3_stmt*);
** (via calls to the [sqlite3_column_int | sqlite3_column_*()] of ** (via calls to the [sqlite3_column_int | sqlite3_column_*()] of
** interfaces) then sqlite3_data_count(P) returns 0. ** interfaces) then sqlite3_data_count(P) returns 0.
** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer. ** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer.
** ^The sqlite3_data_count(P) routine returns 0 if the previous call to
** [sqlite3_step](P) returned [SQLITE_DONE]. ^The sqlite3_data_count(P)
** will return non-zero if previous call to [sqlite3_step](P) returned
** [SQLITE_ROW], except in the case of the [PRAGMA incremental_vacuum]
** where it always returns zero since each step of that multi-step
** pragma returns 0 columns of data.
** **
** See also: [sqlite3_column_count()] ** See also: [sqlite3_column_count()]
*/ */
@@ -4006,7 +4051,12 @@ typedef void (*sqlite3_destructor_type)(void*);
** ^If the 3rd parameter to the sqlite3_result_text* interfaces ** ^If the 3rd parameter to the sqlite3_result_text* interfaces
** is non-negative, then as many bytes (not characters) of the text ** is non-negative, then as many bytes (not characters) of the text
** pointed to by the 2nd parameter are taken as the application-defined ** pointed to by the 2nd parameter are taken as the application-defined
** function result. ** function result. If the 3rd parameter is non-negative, then it
** must be the byte offset into the string where the NUL terminator would
** appear if the string where NUL terminated. If any NUL characters occur
** in the string at a byte offset that is less than the value of the 3rd
** parameter, then the resulting string will contain embedded NULs and the
** result of expressions operating on strings with embedded NULs is undefined.
** ^If the 4th parameter to the sqlite3_result_text* interfaces ** ^If the 4th parameter to the sqlite3_result_text* interfaces
** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that ** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that
** function as the destructor on the text or BLOB result when it has ** function as the destructor on the text or BLOB result when it has
@@ -5789,6 +5839,18 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** the database connection.)^ ** the database connection.)^
** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0. ** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0.
** </dd> ** </dd>
**
** [[SQLITE_DBSTATUS_CACHE_HIT]] ^(<dt>SQLITE_DBSTATUS_CACHE_HIT</dt>
** <dd>This parameter returns the number of pager cache hits that have
** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT
** is always 0.
** </dd>
**
** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(<dt>SQLITE_DBSTATUS_CACHE_MISS</dt>
** <dd>This parameter returns the number of pager cache misses that have
** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS
** is always 0.
** </dd>
** </dl> ** </dl>
*/ */
#define SQLITE_DBSTATUS_LOOKASIDE_USED 0 #define SQLITE_DBSTATUS_LOOKASIDE_USED 0
@@ -5798,7 +5860,9 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
#define SQLITE_DBSTATUS_LOOKASIDE_HIT 4 #define SQLITE_DBSTATUS_LOOKASIDE_HIT 4
#define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5
#define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6
#define SQLITE_DBSTATUS_MAX 6 /* Largest defined DBSTATUS */ #define SQLITE_DBSTATUS_CACHE_HIT 7
#define SQLITE_DBSTATUS_CACHE_MISS 8
#define SQLITE_DBSTATUS_MAX 8 /* Largest defined DBSTATUS */
/* /*
@@ -5852,7 +5916,6 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
** A non-zero value in this counter may indicate an opportunity to ** A non-zero value in this counter may indicate an opportunity to
** improvement performance by adding permanent indices that do not ** improvement performance by adding permanent indices that do not
** need to be reinitialized each time the statement is run.</dd> ** need to be reinitialized each time the statement is run.</dd>
**
** </dl> ** </dl>
*/ */
#define SQLITE_STMTSTATUS_FULLSCAN_STEP 1 #define SQLITE_STMTSTATUS_FULLSCAN_STEP 1

View File

@@ -1,7 +1,7 @@
// //
// AtomicCounter.h // AtomicCounter.h
// //
// $Id: //poco/1.4/Foundation/include/Poco/AtomicCounter.h#1 $ // $Id: //poco/1.4/Foundation/include/Poco/AtomicCounter.h#4 $
// //
// Library: Foundation // Library: Foundation
// Package: Core // Package: Core
@@ -42,13 +42,15 @@
#include "Poco/Foundation.h" #include "Poco/Foundation.h"
#if POCO_OS == POCO_OS_WINDOWS_NT #if POCO_OS == POCO_OS_WINDOWS_NT
#include "Poco/UnWindows.h" #include "Poco/UnWindows.h"
#elif POCO_OS == POCO_OS_MAC_OS_X #elif POCO_OS == POCO_OS_MAC_OS_X
#include <libkern/OSAtomic.h> #include <libkern/OSAtomic.h>
#elif (POCO_OS == POCO_OS_LINUX) && ((POCO_ARCH == POCO_ARCH_IA32) || (POCO_ARCH == POCO_ARCH_AMD64)) && defined(__GNUC__) #elif ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1) || __GNUC__ > 4) && (defined(__x86_64__) || defined(__i386__))
#define POCO_ARCH_GCC_INTEL_X32_64 1 #if !defined(POCO_HAVE_GCC_ATOMICS)
#define POCO_HAVE_GCC_ATOMICS
#endif
#else #else
#include "Poco/Mutex.h" #include "Poco/Mutex.h"
#endif // POCO_OS #endif // POCO_OS
@@ -70,12 +72,13 @@ class Foundation_API AtomicCounter
/// atomic primitives, operations are guarded by a FastMutex. /// atomic primitives, operations are guarded by a FastMutex.
/// ///
/// The following platforms currently have atomic /// The following platforms currently have atomic
/// primitives: /// primitives:
/// - Windows /// - Windows
/// - Mac OS X /// - Mac OS X
/// - GCC 4.1+ (Intel platforms only)
{ {
public: public:
typedef int ValueType; /// The underlying integer type. typedef int ValueType; /// The underlying integer type.
AtomicCounter(); AtomicCounter();
/// Creates a new AtomicCounter and initializes it to zero. /// Creates a new AtomicCounter and initializes it to zero.
@@ -119,20 +122,20 @@ public:
private: private:
#if POCO_OS == POCO_OS_WINDOWS_NT #if POCO_OS == POCO_OS_WINDOWS_NT
typedef LONG ImplType; typedef volatile LONG ImplType;
#elif POCO_OS == POCO_OS_MAC_OS_X #elif POCO_OS == POCO_OS_MAC_OS_X
typedef int32_t ImplType; typedef int32_t ImplType;
#elif defined(POCO_ARCH_GCC_INTEL_X32_64) #elif defined(POCO_HAVE_GCC_ATOMICS)
typedef int ImplType; typedef int ImplType;
#else // generic implementation based on FastMutex #else // generic implementation based on FastMutex
struct ImplType struct ImplType
{ {
mutable FastMutex mutex; mutable FastMutex mutex;
volatile int value; volatile int value;
}; };
#endif // POCO_OS #endif // POCO_OS
volatile ImplType _counter; volatile ImplType _counter;
}; };
@@ -162,11 +165,11 @@ inline AtomicCounter::ValueType AtomicCounter::operator ++ () // prefix
return InterlockedIncrement(&_counter); return InterlockedIncrement(&_counter);
} }
inline AtomicCounter::ValueType AtomicCounter::operator ++ (int) // postfix inline AtomicCounter::ValueType AtomicCounter::operator ++ (int) // postfix
{ {
ValueType result = InterlockedIncrement(&_counter); ValueType result = InterlockedIncrement(&_counter);
return --result; return --result;
} }
@@ -175,14 +178,14 @@ inline AtomicCounter::ValueType AtomicCounter::operator -- () // prefix
return InterlockedDecrement(&_counter); return InterlockedDecrement(&_counter);
} }
inline AtomicCounter::ValueType AtomicCounter::operator -- (int) // postfix inline AtomicCounter::ValueType AtomicCounter::operator -- (int) // postfix
{ {
ValueType result = InterlockedDecrement(&_counter); ValueType result = InterlockedDecrement(&_counter);
return ++result; return ++result;
} }
inline bool AtomicCounter::operator ! () const inline bool AtomicCounter::operator ! () const
{ {
return _counter == 0; return _counter == 0;
@@ -210,11 +213,11 @@ inline AtomicCounter::ValueType AtomicCounter::operator ++ () // prefix
return OSAtomicIncrement32(&_counter); return OSAtomicIncrement32(&_counter);
} }
inline AtomicCounter::ValueType AtomicCounter::operator ++ (int) // postfix inline AtomicCounter::ValueType AtomicCounter::operator ++ (int) // postfix
{ {
ValueType result = OSAtomicIncrement32(&_counter); ValueType result = OSAtomicIncrement32(&_counter);
return --result; return --result;
} }
@@ -223,11 +226,56 @@ inline AtomicCounter::ValueType AtomicCounter::operator -- () // prefix
return OSAtomicDecrement32(&_counter); return OSAtomicDecrement32(&_counter);
} }
inline AtomicCounter::ValueType AtomicCounter::operator -- (int) // postfix
{
ValueType result = OSAtomicDecrement32(&_counter);
return ++result;
}
inline bool AtomicCounter::operator ! () const
{
return _counter == 0;
}
#elif defined(POCO_HAVE_GCC_ATOMICS)
//
// GCC 4.1+ atomic builtins.
//
inline AtomicCounter::operator AtomicCounter::ValueType () const
{
return _counter;
}
inline AtomicCounter::ValueType AtomicCounter::value() const
{
return _counter;
}
inline AtomicCounter::ValueType AtomicCounter::operator ++ () // prefix
{
return __sync_add_and_fetch(&_counter, 1);
}
inline AtomicCounter::ValueType AtomicCounter::operator ++ (int) // postfix
{
return __sync_fetch_and_add(&_counter, 1);
}
inline AtomicCounter::ValueType AtomicCounter::operator -- () // prefix
{
return __sync_sub_and_fetch(&_counter, 1);
}
inline AtomicCounter::ValueType AtomicCounter::operator -- (int) // postfix inline AtomicCounter::ValueType AtomicCounter::operator -- (int) // postfix
{ {
ValueType result = OSAtomicDecrement32(&_counter); return __sync_fetch_and_sub(&_counter, 1);
return ++result;
} }
@@ -237,72 +285,6 @@ inline bool AtomicCounter::operator ! () const
} }
#elif defined(POCO_ARCH_GCC_INTEL_X32_64)
//
// Generic Intel & GCC
//
//
// From boost atomic_count_gcc_x86
//
inline int poco_atomic_exchange_and_add( volatile int * pw, int dv )
{
int r;
__asm__ __volatile__
(
"lock\n\t"
"xadd %1, %0":
"+m"( *pw ), "=r"( r ): // outputs (%0, %1)
"1"( dv ): // inputs (%2 == %1)
"memory", "cc" // clobbers
);
return r;
}
inline AtomicCounter::operator AtomicCounter::ValueType () const
{
return _counter;
}
inline AtomicCounter::ValueType AtomicCounter::value() const
{
return _counter;
}
inline AtomicCounter::ValueType AtomicCounter::operator ++ () // prefix
{
return poco_atomic_exchange_and_add( &_counter, +1 ) + 1;
}
inline AtomicCounter::ValueType AtomicCounter::operator ++ (int) // postfix
{
return poco_atomic_exchange_and_add( &_counter, +1 );
}
inline AtomicCounter::ValueType AtomicCounter::operator -- () // prefix
{
return poco_atomic_exchange_and_add( &_counter, -1 ) - 1;
}
inline AtomicCounter::ValueType AtomicCounter::operator -- (int) // postfix
{
return poco_atomic_exchange_and_add( &_counter, -1 );
}
inline bool AtomicCounter::operator ! () const
{
return _counter == 0;
}
#else #else
// //
// Generic implementation based on FastMutex // Generic implementation based on FastMutex

View File

@@ -71,12 +71,22 @@ public:
/// Sets the environment variable with the given name /// Sets the environment variable with the given name
/// to the given value. /// to the given value.
static std::string osName(); static std::string osName();
/// Returns the operating system name. /// Returns the operating system name.
static std::string osVersion(); static std::string osDisplayName();
/// Returns the operating system version. /// Returns the operating system name in a
/// "user-friendly" way.
///
/// Currently this is only implemented for
/// Windows. There it will return names like
/// "Windows XP" or "Windows 7/Server 2008 SP2".
/// On other platform, returns the same as
/// osName().
static std::string osVersion();
/// Returns the operating system version.
static std::string osArchitecture(); static std::string osArchitecture();
/// Returns the operating system architecture. /// Returns the operating system architecture.

View File

@@ -54,12 +54,13 @@ public:
typedef UInt8 NodeId[6]; /// Ethernet address. typedef UInt8 NodeId[6]; /// Ethernet address.
static std::string getImpl(const std::string& name); static std::string getImpl(const std::string& name);
static bool hasImpl(const std::string& name); static bool hasImpl(const std::string& name);
static void setImpl(const std::string& name, const std::string& value); static void setImpl(const std::string& name, const std::string& value);
static std::string osNameImpl(); static std::string osNameImpl();
static std::string osVersionImpl(); static std::string osDisplayNameImpl();
static std::string osArchitectureImpl(); static std::string osVersionImpl();
static std::string nodeNameImpl(); static std::string osArchitectureImpl();
static std::string nodeNameImpl();
static void nodeIdImpl(NodeId& id); static void nodeIdImpl(NodeId& id);
static unsigned processorCountImpl(); static unsigned processorCountImpl();

View File

@@ -53,12 +53,13 @@ public:
typedef UInt8 NodeId[6]; /// Ethernet address. typedef UInt8 NodeId[6]; /// Ethernet address.
static std::string getImpl(const std::string& name); static std::string getImpl(const std::string& name);
static bool hasImpl(const std::string& name); static bool hasImpl(const std::string& name);
static void setImpl(const std::string& name, const std::string& value); static void setImpl(const std::string& name, const std::string& value);
static std::string osNameImpl(); static std::string osNameImpl();
static std::string osVersionImpl(); static std::string osDisplayNameImpl();
static std::string osArchitectureImpl(); static std::string osVersionImpl();
static std::string nodeNameImpl(); static std::string osArchitectureImpl();
static std::string nodeNameImpl();
static void nodeIdImpl(NodeId& id); static void nodeIdImpl(NodeId& id);
static unsigned processorCountImpl(); static unsigned processorCountImpl();

View File

@@ -54,12 +54,13 @@ public:
typedef UInt8 NodeId[6]; /// Ethernet address. typedef UInt8 NodeId[6]; /// Ethernet address.
static std::string getImpl(const std::string& name); static std::string getImpl(const std::string& name);
static bool hasImpl(const std::string& name); static bool hasImpl(const std::string& name);
static void setImpl(const std::string& name, const std::string& value); static void setImpl(const std::string& name, const std::string& value);
static std::string osNameImpl(); static std::string osNameImpl();
static std::string osVersionImpl(); static std::string osDisplayNameImpl();
static std::string osArchitectureImpl(); static std::string osVersionImpl();
static std::string nodeNameImpl(); static std::string osArchitectureImpl();
static std::string nodeNameImpl();
static void nodeIdImpl(NodeId& id); static void nodeIdImpl(NodeId& id);
static unsigned processorCountImpl(); static unsigned processorCountImpl();

View File

@@ -52,12 +52,13 @@ public:
typedef UInt8 NodeId[6]; /// Ethernet address. typedef UInt8 NodeId[6]; /// Ethernet address.
static std::string getImpl(const std::string& name); static std::string getImpl(const std::string& name);
static bool hasImpl(const std::string& name); static bool hasImpl(const std::string& name);
static void setImpl(const std::string& name, const std::string& value); static void setImpl(const std::string& name, const std::string& value);
static std::string osNameImpl(); static std::string osNameImpl();
static std::string osVersionImpl(); static std::string osDisplayNameImpl();
static std::string osArchitectureImpl(); static std::string osVersionImpl();
static std::string nodeNameImpl(); static std::string osArchitectureImpl();
static std::string nodeNameImpl();
static void nodeIdImpl(NodeId& id); static void nodeIdImpl(NodeId& id);
static unsigned processorCountImpl(); static unsigned processorCountImpl();
}; };

View File

@@ -52,12 +52,13 @@ public:
typedef UInt8 NodeId[6]; /// Ethernet address. typedef UInt8 NodeId[6]; /// Ethernet address.
static std::string getImpl(const std::string& name); static std::string getImpl(const std::string& name);
static bool hasImpl(const std::string& name); static bool hasImpl(const std::string& name);
static void setImpl(const std::string& name, const std::string& value); static void setImpl(const std::string& name, const std::string& value);
static std::string osNameImpl(); static std::string osNameImpl();
static std::string osVersionImpl(); static std::string osDisplayNameImpl();
static std::string osArchitectureImpl(); static std::string osVersionImpl();
static std::string nodeNameImpl(); static std::string osArchitectureImpl();
static std::string nodeNameImpl();
static void nodeIdImpl(NodeId& id); static void nodeIdImpl(NodeId& id);
static unsigned processorCountImpl(); static unsigned processorCountImpl();
}; };

View File

@@ -110,25 +110,25 @@ public:
Channel* getChannel() const; Channel* getChannel() const;
/// Returns the Channel attached to the logger. /// Returns the Channel attached to the logger.
void setLevel(int level); void setLevel(int level);
/// Sets the Logger's log level. /// Sets the Logger's log level.
/// ///
/// See Message::Priority for valid log levels. /// See Message::Priority for valid log levels.
/// Setting the log level to zero turns off /// Setting the log level to zero turns off
/// logging for that Logger. /// logging for that Logger.
int getLevel() const; int getLevel() const;
/// Returns the Logger's log level. /// Returns the Logger's log level.
void setLevel(const std::string& level); void setLevel(const std::string& level);
/// Sets the Logger's log level using a symbolic value. /// Sets the Logger's log level using a symbolic value.
/// ///
/// Valid values are: /// Valid values are:
/// - none (turns off logging) /// - none (turns off logging)
/// - fatal /// - fatal
/// - critical /// - critical
/// - error /// - error
/// - warning /// - warning
/// - notice /// - notice
/// - information /// - information
@@ -337,12 +337,16 @@ public:
static std::string format(const std::string& fmt, const std::string& arg0, const std::string& arg1, const std::string& arg2, const std::string& arg3); static std::string format(const std::string& fmt, const std::string& arg0, const std::string& arg1, const std::string& arg2, const std::string& arg3);
/// Replaces all occurences of $<n> in fmt with the string given in arg<n> and /// Replaces all occurences of $<n> in fmt with the string given in arg<n> and
/// returns the result. To include a dollar sign in the result string, /// returns the result. To include a dollar sign in the result string,
/// specify two dollar signs ($$) in the format string. /// specify two dollar signs ($$) in the format string.
static void setLevel(const std::string& name, int level); static void formatDump(std::string& message, const void* buffer, std::size_t length);
/// Sets the given log level on all loggers that are /// Creates a hex-dump of the given buffer and appends it to the
/// descendants of the Logger with the given name. /// given message string.
static void setLevel(const std::string& name, int level);
/// Sets the given log level on all loggers that are
/// descendants of the Logger with the given name.
static void setChannel(const std::string& name, Channel* pChannel); static void setChannel(const std::string& name, Channel* pChannel);
/// Attaches the given Channel to all loggers that are /// Attaches the given Channel to all loggers that are
@@ -404,13 +408,12 @@ protected:
~Logger(); ~Logger();
void log(const std::string& text, Message::Priority prio); void log(const std::string& text, Message::Priority prio);
void log(const std::string& text, Message::Priority prio, const char* file, int line); void log(const std::string& text, Message::Priority prio, const char* file, int line);
static std::string format(const std::string& fmt, int argc, std::string argv[]); static std::string format(const std::string& fmt, int argc, std::string argv[]);
static void formatDump(std::string& message, const void* buffer, std::size_t length); static Logger& parent(const std::string& name);
static Logger& parent(const std::string& name); static void add(Logger* pLogger);
static void add(Logger* pLogger); static Logger* find(const std::string& name);
static Logger* find(const std::string& name);
private: private:
Logger(); Logger();

View File

@@ -84,12 +84,12 @@ inline void MutexImpl::lockImpl()
inline bool MutexImpl::tryLockImpl() inline bool MutexImpl::tryLockImpl()
{ {
try try
{ {
return TryEnterCriticalSection(&_cs) == TRUE; return TryEnterCriticalSection(&_cs) != 0;
} }
catch (...) catch (...)
{ {
} }
throw SystemException("cannot lock mutex"); throw SystemException("cannot lock mutex");
} }

View File

@@ -43,6 +43,7 @@
#include "Poco/Foundation.h" #include "Poco/Foundation.h"
#include <istream> #include <istream>
#include <ostream> #include <ostream>
#include <cstddef>
namespace Poco { namespace Poco {
@@ -50,23 +51,53 @@ namespace Poco {
class Foundation_API StreamCopier class Foundation_API StreamCopier
/// This class provides static methods to copy the contents from one stream /// This class provides static methods to copy the contents from one stream
/// into another. /// into another.
{ {
public: public:
static std::streamsize copyStream(std::istream& istr, std::ostream& ostr, unsigned bufferSize = 8192); static std::streamsize copyStream(std::istream& istr, std::ostream& ostr, std::size_t bufferSize = 8192);
/// Writes all bytes readable from istr to ostr, using an internal buffer. /// Writes all bytes readable from istr to ostr, using an internal buffer.
/// ///
/// Returns the number of bytes copied. /// Returns the number of bytes copied.
#if defined(POCO_HAVE_INT64)
static Poco::UInt64 copyStream64(std::istream& istr, std::ostream& ostr, std::size_t bufferSize = 8192);
/// Writes all bytes readable from istr to ostr, using an internal buffer.
///
/// Returns the number of bytes copied as a 64-bit unsigned integer.
///
/// Note: the only difference to copyStream() is that a 64-bit unsigned
/// integer is used to count the number of bytes copied.
#endif
static std::streamsize copyStreamUnbuffered(std::istream& istr, std::ostream& ostr); static std::streamsize copyStreamUnbuffered(std::istream& istr, std::ostream& ostr);
/// Writes all bytes readable from istr to ostr. /// Writes all bytes readable from istr to ostr.
/// ///
/// Returns the number of bytes copied. /// Returns the number of bytes copied.
static std::streamsize copyToString(std::istream& istr, std::string& str, unsigned bufferSize = 8192); #if defined(POCO_HAVE_INT64)
/// Appends all bytes readable from istr to the given string, using an internal buffer. static Poco::UInt64 copyStreamUnbuffered64(std::istream& istr, std::ostream& ostr);
/// /// Writes all bytes readable from istr to ostr.
/// Returns the number of bytes copied. ///
/// Returns the number of bytes copied as a 64-bit unsigned integer.
///
/// Note: the only difference to copyStreamUnbuffered() is that a 64-bit unsigned
/// integer is used to count the number of bytes copied.
#endif
static std::streamsize copyToString(std::istream& istr, std::string& str, std::size_t bufferSize = 8192);
/// Appends all bytes readable from istr to the given string, using an internal buffer.
///
/// Returns the number of bytes copied.
#if defined(POCO_HAVE_INT64)
static Poco::UInt64 copyToString64(std::istream& istr, std::string& str, std::size_t bufferSize = 8192);
/// Appends all bytes readable from istr to the given string, using an internal buffer.
///
/// Returns the number of bytes copied as a 64-bit unsigned integer.
///
/// Note: the only difference to copyToString() is that a 64-bit unsigned
/// integer is used to count the number of bytes copied.
#endif
}; };

View File

@@ -1,9 +1,9 @@
/* zconf.h -- configuration of the zlib compression library /* zconf.h -- configuration of the zlib compression library
* Copyright (C) 1995-2005 Jean-loup Gailly. * Copyright (C) 1995-2010 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
/* @(#) $Id: //poco/svn/Foundation/include/Poco/zconf.h#2 $ */ /* @(#) $Id: //poco/1.4/Foundation/include/Poco/zconf.h#2 $ */
#ifndef ZCONF_H #ifndef ZCONF_H
#define ZCONF_H #define ZCONF_H
@@ -11,52 +11,124 @@
/* /*
* If you *really* need a unique prefix for all types and library functions, * If you *really* need a unique prefix for all types and library functions,
* compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
* Even better than compiling with -DZ_PREFIX would be to use configure to set
* this permanently in zconf.h using "./configure --zprefix".
*/ */
#ifdef Z_PREFIX #ifdef Z_PREFIX /* may be set to #if 1 by ./configure */
# define deflateInit_ z_deflateInit_
# define deflate z_deflate /* all linked symbols */
# define deflateEnd z_deflateEnd # define _dist_code z__dist_code
# define inflateInit_ z_inflateInit_ # define _length_code z__length_code
# define inflate z_inflate # define _tr_align z__tr_align
# define inflateEnd z_inflateEnd # define _tr_flush_block z__tr_flush_block
# define deflateInit2_ z_deflateInit2_ # define _tr_init z__tr_init
# define deflateSetDictionary z_deflateSetDictionary # define _tr_stored_block z__tr_stored_block
# define deflateCopy z_deflateCopy # define _tr_tally z__tr_tally
# define deflateReset z_deflateReset # define adler32 z_adler32
# define deflateParams z_deflateParams # define adler32_combine z_adler32_combine
# define deflateBound z_deflateBound # define adler32_combine64 z_adler32_combine64
# define deflatePrime z_deflatePrime
# define inflateInit2_ z_inflateInit2_
# define inflateSetDictionary z_inflateSetDictionary
# define inflateSync z_inflateSync
# define inflateSyncPoint z_inflateSyncPoint
# define inflateCopy z_inflateCopy
# define inflateReset z_inflateReset
# define inflateBack z_inflateBack
# define inflateBackEnd z_inflateBackEnd
# define compress z_compress # define compress z_compress
# define compress2 z_compress2 # define compress2 z_compress2
# define compressBound z_compressBound # define compressBound z_compressBound
# define uncompress z_uncompress
# define adler32 z_adler32
# define crc32 z_crc32 # define crc32 z_crc32
# define crc32_combine z_crc32_combine
# define crc32_combine64 z_crc32_combine64
# define deflate z_deflate
# define deflateBound z_deflateBound
# define deflateCopy z_deflateCopy
# define deflateEnd z_deflateEnd
# define deflateInit2_ z_deflateInit2_
# define deflateInit_ z_deflateInit_
# define deflateParams z_deflateParams
# define deflatePrime z_deflatePrime
# define deflateReset z_deflateReset
# define deflateSetDictionary z_deflateSetDictionary
# define deflateSetHeader z_deflateSetHeader
# define deflateTune z_deflateTune
# define deflate_copyright z_deflate_copyright
# define get_crc_table z_get_crc_table # define get_crc_table z_get_crc_table
# define gz_error z_gz_error
# define gz_intmax z_gz_intmax
# define gz_strwinerror z_gz_strwinerror
# define gzbuffer z_gzbuffer
# define gzclearerr z_gzclearerr
# define gzclose z_gzclose
# define gzclose_r z_gzclose_r
# define gzclose_w z_gzclose_w
# define gzdirect z_gzdirect
# define gzdopen z_gzdopen
# define gzeof z_gzeof
# define gzerror z_gzerror
# define gzflush z_gzflush
# define gzgetc z_gzgetc
# define gzgets z_gzgets
# define gzoffset z_gzoffset
# define gzoffset64 z_gzoffset64
# define gzopen z_gzopen
# define gzopen64 z_gzopen64
# define gzprintf z_gzprintf
# define gzputc z_gzputc
# define gzputs z_gzputs
# define gzread z_gzread
# define gzrewind z_gzrewind
# define gzseek z_gzseek
# define gzseek64 z_gzseek64
# define gzsetparams z_gzsetparams
# define gztell z_gztell
# define gztell64 z_gztell64
# define gzungetc z_gzungetc
# define gzwrite z_gzwrite
# define inflate z_inflate
# define inflateBack z_inflateBack
# define inflateBackEnd z_inflateBackEnd
# define inflateBackInit_ z_inflateBackInit_
# define inflateCopy z_inflateCopy
# define inflateEnd z_inflateEnd
# define inflateGetHeader z_inflateGetHeader
# define inflateInit2_ z_inflateInit2_
# define inflateInit_ z_inflateInit_
# define inflateMark z_inflateMark
# define inflatePrime z_inflatePrime
# define inflateReset z_inflateReset
# define inflateReset2 z_inflateReset2
# define inflateSetDictionary z_inflateSetDictionary
# define inflateSync z_inflateSync
# define inflateSyncPoint z_inflateSyncPoint
# define inflateUndermine z_inflateUndermine
# define inflate_copyright z_inflate_copyright
# define inflate_fast z_inflate_fast
# define inflate_table z_inflate_table
# define uncompress z_uncompress
# define zError z_zError # define zError z_zError
# define zcalloc z_zcalloc
# define zcfree z_zcfree
# define zlibCompileFlags z_zlibCompileFlags
# define zlibVersion z_zlibVersion
# define alloc_func z_alloc_func /* all zlib typedefs in zlib.h and zconf.h */
# define free_func z_free_func
# define in_func z_in_func
# define out_func z_out_func
# define Byte z_Byte # define Byte z_Byte
# define uInt z_uInt
# define uLong z_uLong
# define Bytef z_Bytef # define Bytef z_Bytef
# define alloc_func z_alloc_func
# define charf z_charf # define charf z_charf
# define free_func z_free_func
# define gzFile z_gzFile
# define gz_header z_gz_header
# define gz_headerp z_gz_headerp
# define in_func z_in_func
# define intf z_intf # define intf z_intf
# define out_func z_out_func
# define uInt z_uInt
# define uIntf z_uIntf # define uIntf z_uIntf
# define uLong z_uLong
# define uLongf z_uLongf # define uLongf z_uLongf
# define voidpf z_voidpf
# define voidp z_voidp # define voidp z_voidp
# define voidpc z_voidpc
# define voidpf z_voidpf
/* all zlib structs in zlib.h and zconf.h */
# define gz_header_s z_gz_header_s
# define internal_state z_internal_state
#endif #endif
#if defined(__MSDOS__) && !defined(MSDOS) #if defined(__MSDOS__) && !defined(MSDOS)
@@ -284,49 +356,73 @@ typedef uLong FAR uLongf;
typedef Byte *voidp; typedef Byte *voidp;
#endif #endif
#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ #ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */
# include <sys/types.h> /* for off_t */ # define Z_HAVE_UNISTD_H
# include <unistd.h> /* for SEEK_* and off_t */
# ifdef VMS
# include <unixio.h> /* for off_t */
# endif
# define z_off_t off_t
#endif #endif
#ifdef STDC
# include <sys/types.h> /* for off_t */
#endif
/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
* "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
* though the former does not conform to the LFS document), but considering
* both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
* equivalently requesting no 64-bit operations
*/
#if -_LARGEFILE64_SOURCE - -1 == 1
# undef _LARGEFILE64_SOURCE
#endif
#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
# include <unistd.h> /* for SEEK_* and off_t */
# ifdef VMS
# include <unixio.h> /* for off_t */
# endif
# ifndef z_off_t
# define z_off_t off_t
# endif
#endif
#ifndef SEEK_SET #ifndef SEEK_SET
# define SEEK_SET 0 /* Seek from beginning of file. */ # define SEEK_SET 0 /* Seek from beginning of file. */
# define SEEK_CUR 1 /* Seek from current position. */ # define SEEK_CUR 1 /* Seek from current position. */
# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ # define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
#endif #endif
#ifndef z_off_t #ifndef z_off_t
# define z_off_t long # define z_off_t long
#endif #endif
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
# define z_off64_t off64_t
#else
# define z_off64_t z_off_t
#endif
#if defined(__OS400__) #if defined(__OS400__)
# define NO_vsnprintf # define NO_vsnprintf
#endif #endif
#if defined(__MVS__) #if defined(__MVS__)
# define NO_vsnprintf # define NO_vsnprintf
# ifdef FAR
# undef FAR
# endif
#endif #endif
/* MVS linker does not support external names larger than 8 bytes */ /* MVS linker does not support external names larger than 8 bytes */
#if defined(__MVS__) #if defined(__MVS__)
# pragma map(deflateInit_,"DEIN") #pragma map(deflateInit_,"DEIN")
# pragma map(deflateInit2_,"DEIN2") #pragma map(deflateInit2_,"DEIN2")
# pragma map(deflateEnd,"DEEND") #pragma map(deflateEnd,"DEEND")
# pragma map(deflateBound,"DEBND") #pragma map(deflateBound,"DEBND")
# pragma map(inflateInit_,"ININ") #pragma map(inflateInit_,"ININ")
# pragma map(inflateInit2_,"ININ2") #pragma map(inflateInit2_,"ININ2")
# pragma map(inflateEnd,"INEND") #pragma map(inflateEnd,"INEND")
# pragma map(inflateSync,"INSY") #pragma map(inflateSync,"INSY")
# pragma map(inflateSetDictionary,"INSEDI") #pragma map(inflateSetDictionary,"INSEDI")
# pragma map(compressBound,"CMBND") #pragma map(compressBound,"CMBND")
# pragma map(inflate_table,"INTABL") #pragma map(inflate_table,"INTABL")
# pragma map(inflate_fast,"INFA") #pragma map(inflate_fast,"INFA")
# pragma map(inflate_copyright,"INCOPY") #pragma map(inflate_copyright,"INCOPY")
#endif #endif
#endif /* ZCONF_H */ #endif /* ZCONF_H */

File diff suppressed because it is too large Load Diff

View File

@@ -122,12 +122,12 @@ AtomicCounter& AtomicCounter::operator = (AtomicCounter::ValueType value)
} }
#elif defined(POCO_ARCH_GCC_INTEL_X32_64) #elif defined(POCO_HAVE_GCC_ATOMICS)
// //
// GCC & Linux // GCC 4.1+ atomic builtins.
// //
AtomicCounter::AtomicCounter(): AtomicCounter::AtomicCounter():
_counter(0) _counter(0)
{ {
} }
@@ -151,15 +151,15 @@ AtomicCounter::~AtomicCounter()
AtomicCounter& AtomicCounter::operator = (const AtomicCounter& counter) AtomicCounter& AtomicCounter::operator = (const AtomicCounter& counter)
{ {
_counter = counter.value(); __sync_lock_test_and_set(&_counter, counter.value());
return *this; return *this;
} }
AtomicCounter& AtomicCounter::operator = (AtomicCounter::ValueType value) AtomicCounter& AtomicCounter::operator = (AtomicCounter::ValueType value)
{ {
_counter = value; __sync_lock_test_and_set(&_counter, value);
return *this; return *this;
} }

View File

@@ -1,7 +1,7 @@
// //
// Environment.cpp // Environment.cpp
// //
// $Id: //poco/1.3/Foundation/src/Environment.cpp#4 $ // $Id: //poco/1.4/Foundation/src/Environment.cpp#3 $
// //
// Library: Foundation // Library: Foundation
// Package: Core // Package: Core
@@ -92,10 +92,16 @@ std::string Environment::osName()
return EnvironmentImpl::osNameImpl(); return EnvironmentImpl::osNameImpl();
} }
std::string Environment::osDisplayName()
{
return EnvironmentImpl::osDisplayNameImpl();
}
std::string Environment::osVersion() std::string Environment::osVersion()
{ {
return EnvironmentImpl::osVersionImpl(); return EnvironmentImpl::osVersionImpl();
} }

View File

@@ -1,7 +1,7 @@
// Environment_UNIX.cpp // Environment_UNIX.cpp
// //
// $Id: //poco/1.3/Foundation/src/Environment_UNIX.cpp#7 $ // $Id: //poco/1.4/Foundation/src/Environment_UNIX.cpp#2 $
// //
// Library: Foundation // Library: Foundation
// Package: Core // Package: Core
@@ -102,9 +102,15 @@ std::string EnvironmentImpl::osNameImpl()
} }
std::string EnvironmentImpl::osDisplayNameImpl()
{
return osNameImpl();
}
std::string EnvironmentImpl::osVersionImpl() std::string EnvironmentImpl::osVersionImpl()
{ {
struct utsname uts; struct utsname uts;
uname(&uts); uname(&uts);
return uts.release; return uts.release;
} }

View File

@@ -1,7 +1,7 @@
// //
// Environment_VMS.cpp // Environment_VMS.cpp
// //
// $Id: //poco/1.3/Foundation/src/Environment_VMS.cpp#3 $ // $Id: //poco/1.4/Foundation/src/Environment_VMS.cpp#2 $
// //
// Library: Foundation // Library: Foundation
// Package: Core // Package: Core
@@ -103,9 +103,15 @@ std::string EnvironmentImpl::osNameImpl()
} }
std::string EnvironmentImpl::osDisplayNameImpl()
{
return osNameImpl();
}
std::string EnvironmentImpl::osVersionImpl() std::string EnvironmentImpl::osVersionImpl()
{ {
return getsyi(SYI$_VERSION); return getsyi(SYI$_VERSION);
} }

View File

@@ -1,7 +1,7 @@
// Environment_VX.cpp // Environment_VX.cpp
// //
// $Id: //poco/1.4/Foundation/src/Environment_VX.cpp#2 $ // $Id: //poco/1.4/Foundation/src/Environment_VX.cpp#3 $
// //
// Library: Foundation // Library: Foundation
// Package: Core // Package: Core
@@ -108,9 +108,15 @@ std::string EnvironmentImpl::osNameImpl()
} }
std::string EnvironmentImpl::osDisplayNameImpl()
{
return osNameImpl();
}
std::string EnvironmentImpl::osVersionImpl() std::string EnvironmentImpl::osVersionImpl()
{ {
return runtimeVersion; return runtimeVersion;
} }
@@ -150,25 +156,25 @@ unsigned EnvironmentImpl::processorCountImpl()
void EnvironmentImpl::nodeIdImpl(NodeId& id) void EnvironmentImpl::nodeIdImpl(NodeId& id)
{ {
std::memset(&id, 0, sizeof(id)); std::memset(&id, 0, sizeof(id));
int ifIndex = 1; int ifIndex = 1;
char ifName[32]; char ifName[32];
for (;;) for (;;)
{ {
if (ifIndexToIfName(ifIndex, ifName) == OK) if (ifIndexToIfName(ifIndex, ifName) == OK)
{ {
struct ifnet* pIf = ifunit(ifName); struct ifnet* pIf = ifunit(ifName);
if (pIf) if (pIf)
{ {
std::memcpy(&id, ((struct arpcom *) pIf)->ac_enaddr, sizeof(id)); std::memcpy(&id, ((struct arpcom *) pIf)->ac_enaddr, sizeof(id));
return; return;
} }
} }
else break; else break;
++ifIndex; ++ifIndex;
} }
throw SystemException("cannot get Ethernet hardware address"); throw SystemException("cannot get Ethernet hardware address");
} }

View File

@@ -1,7 +1,7 @@
// //
// Environment_WIN32.cpp // Environment_WIN32.cpp
// //
// $Id: //poco/1.3/Foundation/src/Environment_WIN32.cpp#6 $ // $Id: //poco/1.4/Foundation/src/Environment_WIN32.cpp#2 $
// //
// Library: Foundation // Library: Foundation
// Package: Core // Package: Core
@@ -88,9 +88,56 @@ std::string EnvironmentImpl::osNameImpl()
return vi.dwMinorVersion == 0 ? "Windows 95" : "Windows 98"; return vi.dwMinorVersion == 0 ? "Windows 95" : "Windows 98";
case VER_PLATFORM_WIN32_NT: case VER_PLATFORM_WIN32_NT:
return "Windows NT"; return "Windows NT";
default: default:
return "Unknown"; return "Unknown";
} }
}
std::string EnvironmentImpl::osDisplayNameImpl()
{
OSVERSIONINFO vi;
vi.dwOSVersionInfoSize = sizeof(vi);
if (GetVersionEx(&vi) == 0) throw SystemException("Cannot get OS version information");
switch(vi.dwMajorVersion)
{
case 6:
switch (vi.dwMinorVersion)
{
case 0:
return "Windows Vista/Server 2008";
case 1:
return "Windows 7/Server 2008 SP2";
default:
return "Unknown";
}
case 5:
switch (vi.dwMinorVersion)
{
case 0:
return "Windows 2000";
case 1:
return "Windows XP";
case 2:
return "Windows Server 2003/Windows Server 2003 R2";
default:
return "Unknown";
}
case 4:
switch (vi.dwMinorVersion)
{
case 0:
return "Windows 95/Windows NT 4.0";
case 10:
return "Windows 98";
case 90:
return "Windows ME";
default:
return "Unknown";
}
default:
return "Unknown";
}
} }

View File

@@ -1,7 +1,7 @@
// //
// Environment_WIN32U.cpp // Environment_WIN32U.cpp
// //
// $Id: //poco/1.3/Foundation/src/Environment_WIN32U.cpp#5 $ // $Id: //poco/1.4/Foundation/src/Environment_WIN32U.cpp#2 $
// //
// Library: Foundation // Library: Foundation
// Package: Core // Package: Core
@@ -98,9 +98,56 @@ std::string EnvironmentImpl::osNameImpl()
return vi.dwMinorVersion == 0 ? "Windows 95" : "Windows 98"; return vi.dwMinorVersion == 0 ? "Windows 95" : "Windows 98";
case VER_PLATFORM_WIN32_NT: case VER_PLATFORM_WIN32_NT:
return "Windows NT"; return "Windows NT";
default: default:
return "Unknown"; return "Unknown";
} }
}
std::string EnvironmentImpl::osDisplayNameImpl()
{
OSVERSIONINFO vi;
vi.dwOSVersionInfoSize = sizeof(vi);
if (GetVersionEx(&vi) == 0) throw SystemException("Cannot get OS version information");
switch(vi.dwMajorVersion)
{
case 6:
switch (vi.dwMinorVersion)
{
case 0:
return "Windows Vista/Server 2008";
case 1:
return "Windows 7/Server 2008 SP2";
default:
return "Unknown";
}
case 5:
switch (vi.dwMinorVersion)
{
case 0:
return "Windows 2000";
case 1:
return "Windows XP";
case 2:
return "Windows Server 2003/Windows Server 2003 R2";
default:
return "Unknown";
}
case 4:
switch (vi.dwMinorVersion)
{
case 0:
return "Windows 95/Windows NT 4.0";
case 10:
return "Windows 98";
case 90:
return "Windows ME";
default:
return "Unknown";
}
default:
return "Unknown";
}
} }

View File

@@ -1,7 +1,7 @@
// //
// Environment_WINCE.cpp // Environment_WINCE.cpp
// //
// $Id: //poco/1.4/Foundation/src/Environment_WINCE.cpp#1 $ // $Id: //poco/1.4/Foundation/src/Environment_WINCE.cpp#2 $
// //
// Library: Foundation // Library: Foundation
// Package: Core // Package: Core
@@ -84,9 +84,15 @@ std::string EnvironmentImpl::osNameImpl()
} }
std::string EnvironmentImpl::osDisplayNameImpl()
{
return osNameImpl();
}
std::string EnvironmentImpl::osVersionImpl() std::string EnvironmentImpl::osVersionImpl()
{ {
OSVERSIONINFOW vi; OSVERSIONINFOW vi;
vi.dwOSVersionInfoSize = sizeof(vi); vi.dwOSVersionInfoSize = sizeof(vi);
if (GetVersionExW(&vi) == 0) throw SystemException("Cannot get OS version information"); if (GetVersionExW(&vi) == 0) throw SystemException("Cannot get OS version information");
std::ostringstream str; std::ostringstream str;

View File

@@ -38,6 +38,7 @@
#include "Poco/Exception.h" #include "Poco/Exception.h"
#include "Poco/Ascii.h" #include "Poco/Ascii.h"
#include <sstream> #include <sstream>
#include <locale>
#include <cstddef> #include <cstddef>
@@ -63,13 +64,13 @@ namespace
} }
void parseWidth(std::ostream& str, std::string::const_iterator& itFmt, const std::string::const_iterator& endFmt) void parseWidth(std::ostream& str, std::string::const_iterator& itFmt, const std::string::const_iterator& endFmt)
{ {
int width = 0; int width = 0;
while (itFmt != endFmt && Ascii::isDigit(*itFmt)) while (itFmt != endFmt && Ascii::isDigit(*itFmt))
{ {
width = 10*width + *itFmt - '0'; width = 10*width + *itFmt - '0';
++itFmt; ++itFmt;
} }
if (width != 0) str.width(width); if (width != 0) str.width(width);
} }
@@ -78,13 +79,13 @@ namespace
void parsePrec(std::ostream& str, std::string::const_iterator& itFmt, const std::string::const_iterator& endFmt) void parsePrec(std::ostream& str, std::string::const_iterator& itFmt, const std::string::const_iterator& endFmt)
{ {
if (itFmt != endFmt && *itFmt == '.') if (itFmt != endFmt && *itFmt == '.')
{ {
++itFmt; ++itFmt;
int prec = 0; int prec = 0;
while (itFmt != endFmt && Ascii::isDigit(*itFmt)) while (itFmt != endFmt && Ascii::isDigit(*itFmt))
{ {
prec = 10*prec + *itFmt - '0'; prec = 10*prec + *itFmt - '0';
++itFmt; ++itFmt;
} }
if (prec >= 0) str.precision(prec); if (prec >= 0) str.precision(prec);
} }
@@ -103,23 +104,23 @@ namespace
case '?': mod = *itFmt++; break; case '?': mod = *itFmt++; break;
} }
} }
return mod; return mod;
} }
std::size_t parseIndex(std::string::const_iterator& itFmt, const std::string::const_iterator& endFmt) std::size_t parseIndex(std::string::const_iterator& itFmt, const std::string::const_iterator& endFmt)
{ {
int index = 0; int index = 0;
while (itFmt != endFmt && Ascii::isDigit(*itFmt)) while (itFmt != endFmt && Ascii::isDigit(*itFmt))
{ {
index = 10*index + *itFmt - '0'; index = 10*index + *itFmt - '0';
++itFmt; ++itFmt;
} }
if (itFmt != endFmt && *itFmt == ']') ++itFmt; if (itFmt != endFmt && *itFmt == ']') ++itFmt;
return index; return index;
} }
void prepareFormat(std::ostream& str, char type) void prepareFormat(std::ostream& str, char type)
{ {
switch (type) switch (type)
{ {
case 'd': case 'd':
@@ -163,12 +164,13 @@ namespace
} }
void formatOne(std::string& result, std::string::const_iterator& itFmt, const std::string::const_iterator& endFmt, std::vector<Any>::const_iterator& itVal) void formatOne(std::string& result, std::string::const_iterator& itFmt, const std::string::const_iterator& endFmt, std::vector<Any>::const_iterator& itVal)
{ {
std::ostringstream str; std::ostringstream str;
parseFlags(str, itFmt, endFmt); str.imbue(std::locale::classic());
parseWidth(str, itFmt, endFmt); parseFlags(str, itFmt, endFmt);
parsePrec(str, itFmt, endFmt); parseWidth(str, itFmt, endFmt);
parsePrec(str, itFmt, endFmt);
char mod = parseMod(itFmt, endFmt); char mod = parseMod(itFmt, endFmt);
if (itFmt != endFmt) if (itFmt != endFmt)
{ {
@@ -355,33 +357,33 @@ void format(std::string& result, const std::string& fmt, const std::vector<Any>&
{ {
switch (*itFmt) switch (*itFmt)
{ {
case '%': case '%':
++itFmt; ++itFmt;
if (itFmt != endFmt && itVal != endVal) if (itFmt != endFmt && itVal != endVal)
{ {
if (*itFmt == '[') if (*itFmt == '[')
{ {
++itFmt; ++itFmt;
std::size_t index = parseIndex(itFmt, endFmt); std::size_t index = parseIndex(itFmt, endFmt);
if (index < values.size()) if (index < values.size())
{ {
std::vector<Any>::const_iterator it = values.begin() + index; std::vector<Any>::const_iterator it = values.begin() + index;
formatOne(result, itFmt, endFmt, it); formatOne(result, itFmt, endFmt, it);
} }
else throw InvalidArgumentException("format argument index out of range", fmt); else throw InvalidArgumentException("format argument index out of range", fmt);
} }
else else
{ {
formatOne(result, itFmt, endFmt, itVal); formatOne(result, itFmt, endFmt, itVal);
} }
} }
else if (itFmt != endFmt) else if (itFmt != endFmt)
{ {
result += *itFmt++; result += *itFmt++;
} }
break; break;
default: default:
result += *itFmt; result += *itFmt;
++itFmt; ++itFmt;
} }
} }

View File

@@ -129,13 +129,13 @@ bool Glob::match(TextIterator& itp, const TextIterator& endp, TextIterator& its,
{ {
bool invert = *itp == '!'; bool invert = *itp == '!';
if (invert) ++itp; if (invert) ++itp;
if (itp != endp) if (itp != endp)
{ {
bool mtch = matchSet(itp, endp, *its++); bool mtch = matchSet(itp, endp, *its++);
if ((invert && mtch) || (!invert && !mtch)) return false; if ((invert && mtch) || (!invert && !mtch)) return false;
break; break;
} }
} }
throw SyntaxException("bad range syntax in glob pattern"); throw SyntaxException("bad range syntax in glob pattern");
case '\\': case '\\':
if (++itp == endp) throw SyntaxException("backslash must be followed by character in glob pattern"); if (++itp == endp) throw SyntaxException("backslash must be followed by character in glob pattern");
@@ -259,11 +259,20 @@ void Glob::collect(const Path& pathPattern, const Path& base, const Path& curren
bool Glob::isDirectory(const Path& path, bool followSymlink) bool Glob::isDirectory(const Path& path, bool followSymlink)
{ {
File f(path); File f(path);
if (f.isDirectory()) bool isDir = false;
{ try
return true; {
} isDir = f.isDirectory();
}
catch (Poco::Exception&)
{
return false;
}
if (isDir)
{
return true;
}
else if (followSymlink && f.isLink()) else if (followSymlink && f.isLink())
{ {
try try

View File

@@ -16,14 +16,14 @@
// execute, and transmit the Software, and to prepare derivative works of the // execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to // Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following: // do so, all subject to the following:
// //
// The copyright notices in the Software and this entire statement, including // The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer, // the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and // must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative // all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by // works are solely in the form of machine-executable object code generated by
// a source language processor. // a source language processor.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
@@ -35,13 +35,16 @@
#include "Poco/NumberFormatter.h" #include "Poco/NumberFormatter.h"
#include "Poco/MemoryStream.h"
#include <iomanip>
#include <locale>
#include <cstdio> #include <cstdio>
#include <cctype> #include <cctype>
#if defined(_MSC_VER) #if defined(_MSC_VER)
#define I64_FMT "I64" #define I64_FMT "I64"
#elif defined(__APPLE__) #elif defined(__APPLE__)
#define I64_FMT "q" #define I64_FMT "q"
#else #else
#define I64_FMT "ll" #define I64_FMT "ll"
@@ -53,28 +56,28 @@ namespace Poco {
std::string NumberFormatter::format(bool value, BoolFormat format) std::string NumberFormatter::format(bool value, BoolFormat format)
{ {
switch(format) switch(format)
{ {
default: default:
case FMT_TRUE_FALSE: case FMT_TRUE_FALSE:
if (value == true) if (value == true)
return "true"; return "true";
return "false"; return "false";
case FMT_YES_NO: case FMT_YES_NO:
if (value == true) if (value == true)
return "yes"; return "yes";
return "no"; return "no";
case FMT_ON_OFF: case FMT_ON_OFF:
if (value == true) if (value == true)
return "on"; return "on";
return "off"; return "off";
} }
} }
void NumberFormatter::append(std::string& str, int value) void NumberFormatter::append(std::string& str, int value)
{ {
char buffer[64]; char buffer[64];
std::sprintf(buffer, "%d", value); std::sprintf(buffer, "%d", value);
str.append(buffer); str.append(buffer);
} }
@@ -356,37 +359,45 @@ void NumberFormatter::appendHex(std::string& str, UInt64 value, int width)
void NumberFormatter::append(std::string& str, float value) void NumberFormatter::append(std::string& str, float value)
{ {
char buffer[64]; char buffer[64];
std::sprintf(buffer, "%.*g", 8, (double) value); Poco::MemoryOutputStream ostr(buffer, sizeof(buffer));
str.append(buffer); ostr.imbue(std::locale::classic());
ostr << std::setprecision(8) << value;
str.append(buffer, ostr.charsWritten());
} }
void NumberFormatter::append(std::string& str, double value) void NumberFormatter::append(std::string& str, double value)
{ {
char buffer[64]; char buffer[64];
std::sprintf(buffer, "%.*g", 16, value); Poco::MemoryOutputStream ostr(buffer, sizeof(buffer));
str.append(buffer); ostr.imbue(std::locale::classic());
ostr << std::setprecision(16) << value;
str.append(buffer, ostr.charsWritten());
} }
void NumberFormatter::append(std::string& str, double value, int precision) void NumberFormatter::append(std::string& str, double value, int precision)
{ {
poco_assert (precision >= 0 && precision < 32); poco_assert (precision >= 0 && precision < 32);
char buffer[64]; char buffer[64];
std::sprintf(buffer, "%.*f", precision, value); Poco::MemoryOutputStream ostr(buffer, sizeof(buffer));
str.append(buffer); ostr.imbue(std::locale::classic());
ostr << std::fixed << std::showpoint << std::setprecision(precision) << value;
str.append(buffer, ostr.charsWritten());
} }
void NumberFormatter::append(std::string& str, double value, int width, int precision) void NumberFormatter::append(std::string& str, double value, int width, int precision)
{ {
poco_assert (width > 0 && width < 64 && precision >= 0 && precision < width); poco_assert (width > 0 && width < 64 && precision >= 0 && precision < width);
char buffer[64]; char buffer[64];
std::sprintf(buffer, "%*.*f", width, precision, value); Poco::MemoryOutputStream ostr(buffer, sizeof(buffer));
str.append(buffer); ostr.imbue(std::locale::classic());
ostr << std::fixed << std::showpoint << std::setw(width) << std::setprecision(precision) << value;
str.append(buffer, ostr.charsWritten());
} }

View File

@@ -36,7 +36,9 @@
#include "Poco/NumberParser.h" #include "Poco/NumberParser.h"
#include "Poco/Exception.h" #include "Poco/Exception.h"
#include "Poco/MemoryStream.h"
#include "Poco/String.h" #include "Poco/String.h"
#include <locale>
#include <cstdio> #include <cstdio>
#include <cctype> #include <cctype>
@@ -170,66 +172,68 @@ double NumberParser::parseFloat(const std::string& s)
throw SyntaxException("Not a valid floating-point number", s); throw SyntaxException("Not a valid floating-point number", s);
} }
bool NumberParser::tryParseFloat(const std::string& s, double& value) bool NumberParser::tryParseFloat(const std::string& s, double& value)
{ {
char temp; Poco::MemoryInputStream istr(s.data(), s.size());
return std::sscanf(s.c_str(), "%lf%c", &value, &temp) == 1; istr.imbue(std::locale::classic());
istr >> value;
return istr.eof() && !istr.fail();
} }
bool NumberParser::parseBool(const std::string& s) bool NumberParser::parseBool(const std::string& s)
{ {
bool result; bool result;
if (tryParseBool(s, result)) if (tryParseBool(s, result))
return result; return result;
else else
throw SyntaxException("Not a valid bool number", s); throw SyntaxException("Not a valid bool number", s);
} }
bool NumberParser::tryParseBool(const std::string& s, bool& value) bool NumberParser::tryParseBool(const std::string& s, bool& value)
{ {
int n; int n;
if (NumberParser::tryParse(s, n)) if (NumberParser::tryParse(s, n))
{ {
value = (n != 0); value = (n != 0);
return true; return true;
} }
if (icompare(s, "true") == 0) if (icompare(s, "true") == 0)
{ {
value = true; value = true;
return true; return true;
} }
else if (icompare(s, "yes") == 0) else if (icompare(s, "yes") == 0)
{ {
value = true; value = true;
return true; return true;
} }
else if (icompare(s, "on") == 0) else if (icompare(s, "on") == 0)
{ {
value = true; value = true;
return true; return true;
} }
if (icompare(s, "false") == 0) if (icompare(s, "false") == 0)
{ {
value = false; value = false;
return true; return true;
} }
else if (icompare(s, "no") == 0) else if (icompare(s, "no") == 0)
{ {
value = false; value = false;
return true; return true;
} }
else if (icompare(s, "off") == 0) else if (icompare(s, "off") == 0)
{ {
value = false; value = false;
return true; return true;
} }
return false; return false;
} }

View File

@@ -456,20 +456,20 @@ Path& Path::resolve(const Path& path)
Path& Path::setNode(const std::string& node) Path& Path::setNode(const std::string& node)
{ {
_node = node; _node = node;
_absolute = _absolute || !node.empty(); _absolute = _absolute || !node.empty();
return *this; return *this;
} }
Path& Path::setDevice(const std::string& device) Path& Path::setDevice(const std::string& device)
{ {
_device = device; _device = device;
_absolute = _absolute || !device.empty(); _absolute = _absolute || !device.empty();
return *this; return *this;
} }
const std::string& Path::directory(int n) const const std::string& Path::directory(int n) const
{ {
poco_assert (0 <= n && n <= _dirs.size()); poco_assert (0 <= n && n <= _dirs.size());
@@ -491,11 +491,11 @@ const std::string& Path::operator [] (int n) const
return _name; return _name;
} }
Path& Path::pushDirectory(const std::string& dir) Path& Path::pushDirectory(const std::string& dir)
{ {
if (!dir.empty() && dir != ".") if (!dir.empty() && dir != ".")
{ {
#if defined(POCO_OS_FAMILY_VMS) #if defined(POCO_OS_FAMILY_VMS)
if (dir == ".." || dir == "-") if (dir == ".." || dir == "-")
{ {
@@ -513,49 +513,49 @@ Path& Path::pushDirectory(const std::string& dir)
else if (!_absolute) else if (!_absolute)
_dirs.push_back(dir); _dirs.push_back(dir);
} }
else _dirs.push_back(dir); else _dirs.push_back(dir);
#endif #endif
} }
return *this; return *this;
} }
Path& Path::popDirectory() Path& Path::popDirectory()
{ {
poco_assert (!_dirs.empty()); poco_assert (!_dirs.empty());
_dirs.pop_back(); _dirs.pop_back();
return *this; return *this;
} }
Path& Path::popFrontDirectory() Path& Path::popFrontDirectory()
{ {
poco_assert (!_dirs.empty()); poco_assert (!_dirs.empty());
StringVec::iterator it = _dirs.begin(); StringVec::iterator it = _dirs.begin();
_dirs.erase(it); _dirs.erase(it);
return *this; return *this;
} }
Path& Path::setFileName(const std::string& name) Path& Path::setFileName(const std::string& name)
{ {
_name = name; _name = name;
return *this; return *this;
} }
Path& Path::setBaseName(const std::string& name) Path& Path::setBaseName(const std::string& name)
{ {
std::string ext = getExtension(); std::string ext = getExtension();
_name = name; _name = name;
if (!ext.empty()) if (!ext.empty())
{ {
_name.append("."); _name.append(".");
_name.append(ext); _name.append(ext);
} }
return *this; return *this;
} }
@@ -571,16 +571,16 @@ std::string Path::getBaseName() const
Path& Path::setExtension(const std::string& extension) Path& Path::setExtension(const std::string& extension)
{ {
_name = getBaseName(); _name = getBaseName();
if (!extension.empty()) if (!extension.empty())
{ {
_name.append("."); _name.append(".");
_name.append(extension); _name.append(extension);
} }
return *this; return *this;
} }
std::string Path::getExtension() const std::string Path::getExtension() const
{ {
std::string::size_type pos = _name.rfind('.'); std::string::size_type pos = _name.rfind('.');
@@ -593,12 +593,12 @@ std::string Path::getExtension() const
Path& Path::clear() Path& Path::clear()
{ {
_node.clear(); _node.clear();
_device.clear(); _device.clear();
_name.clear(); _name.clear();
_dirs.clear(); _dirs.clear();
_version.clear(); _version.clear();
_absolute = false; _absolute = false;
return *this; return *this;
} }
@@ -641,12 +641,21 @@ void Path::listRoots(std::vector<std::string>& roots)
bool Path::find(StringVec::const_iterator it, StringVec::const_iterator end, const std::string& name, Path& path) bool Path::find(StringVec::const_iterator it, StringVec::const_iterator end, const std::string& name, Path& path)
{ {
while (it != end) while (it != end)
{ {
Path p(*it); #if defined(WIN32)
p.makeDirectory(); std::string cleanPath(*it);
p.resolve(Path(name)); if (cleanPath.size() > 1 && cleanPath[0] == '"' && cleanPath[cleanPath.size() - 1] == '"')
File f(p); {
cleanPath = cleanPath.substr(1, cleanPath.size() - 2);
}
Path p(cleanPath);
#else
Path p(*it);
#endif
p.makeDirectory();
p.resolve(Path(name));
File f(p);
if (f.exists()) if (f.exists())
{ {
path = p; path = p;

View File

@@ -1,7 +1,7 @@
// //
// StreamCopier.cpp // StreamCopier.cpp
// //
// $Id: //poco/svn/Foundation/src/StreamCopier.cpp#2 $ // $Id: //poco/1.4/Foundation/src/StreamCopier.cpp#2 $
// //
// Library: Foundation // Library: Foundation
// Package: Streams // Package: Streams
@@ -41,9 +41,9 @@
namespace Poco { namespace Poco {
std::streamsize StreamCopier::copyStream(std::istream& istr, std::ostream& ostr, unsigned bufferSize) std::streamsize StreamCopier::copyStream(std::istream& istr, std::ostream& ostr, std::size_t bufferSize)
{ {
poco_assert (bufferSize > 0); poco_assert (bufferSize > 0);
Buffer<char> buffer(bufferSize); Buffer<char> buffer(bufferSize);
std::streamsize len = 0; std::streamsize len = 0;
@@ -64,9 +64,34 @@ std::streamsize StreamCopier::copyStream(std::istream& istr, std::ostream& ostr,
} }
std::streamsize StreamCopier::copyToString(std::istream& istr, std::string& str, unsigned bufferSize) #if defined(POCO_HAVE_INT64)
Poco::UInt64 StreamCopier::copyStream64(std::istream& istr, std::ostream& ostr, std::size_t bufferSize)
{ {
poco_assert (bufferSize > 0); poco_assert (bufferSize > 0);
Buffer<char> buffer(bufferSize);
Poco::UInt64 len = 0;
istr.read(buffer.begin(), bufferSize);
std::streamsize n = istr.gcount();
while (n > 0)
{
len += n;
ostr.write(buffer.begin(), n);
if (istr && ostr)
{
istr.read(buffer.begin(), bufferSize);
n = istr.gcount();
}
else n = 0;
}
return len;
}
#endif
std::streamsize StreamCopier::copyToString(std::istream& istr, std::string& str, std::size_t bufferSize)
{
poco_assert (bufferSize > 0);
Buffer<char> buffer(bufferSize); Buffer<char> buffer(bufferSize);
std::streamsize len = 0; std::streamsize len = 0;
@@ -87,6 +112,31 @@ std::streamsize StreamCopier::copyToString(std::istream& istr, std::string& str,
} }
#if defined(POCO_HAVE_INT64)
Poco::UInt64 StreamCopier::copyToString64(std::istream& istr, std::string& str, std::size_t bufferSize)
{
poco_assert (bufferSize > 0);
Buffer<char> buffer(bufferSize);
Poco::UInt64 len = 0;
istr.read(buffer.begin(), bufferSize);
std::streamsize n = istr.gcount();
while (n > 0)
{
len += n;
str.append(buffer.begin(), static_cast<std::string::size_type>(n));
if (istr)
{
istr.read(buffer.begin(), bufferSize);
n = istr.gcount();
}
else n = 0;
}
return len;
}
#endif
std::streamsize StreamCopier::copyStreamUnbuffered(std::istream& istr, std::ostream& ostr) std::streamsize StreamCopier::copyStreamUnbuffered(std::istream& istr, std::ostream& ostr)
{ {
char c; char c;
@@ -102,4 +152,21 @@ std::streamsize StreamCopier::copyStreamUnbuffered(std::istream& istr, std::ostr
} }
#if defined(POCO_HAVE_INT64)
Poco::UInt64 StreamCopier::copyStreamUnbuffered64(std::istream& istr, std::ostream& ostr)
{
char c;
Poco::UInt64 len = 0;
istr.get(c);
while (istr && ostr)
{
++len;
ostr.put(c);
istr.get(c);
}
return len;
}
#endif
} // namespace Poco } // namespace Poco

View File

@@ -54,7 +54,7 @@ supporting internal functions that are not used by other modules. */
/* When DEBUG is defined, we need the pcre_printint() function, which is also /* When DEBUG is defined, we need the pcre_printint() function, which is also
used by pcretest. DEBUG is not defined when building a production library. */ used by pcretest. DEBUG is not defined when building a production library. */
#ifdef DEBUG #if defined(DEBUG)
#include "pcre_printint.src" #include "pcre_printint.src"
#endif #endif

View File

@@ -72,12 +72,12 @@ setjmp and stdarg are used is when NO_RECURSE is set. */
#include <ctype.h> #include <ctype.h>
#include <limits.h> #include <limits.h>
#include <setjmp.h>
#include <stdarg.h>
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <setjmp.h>
#include <stdarg.h>
/* When compiling a DLL for Windows, the exported symbols have to be declared /* When compiling a DLL for Windows, the exported symbols have to be declared
using some MS magic. I found some useful information on this web page: using some MS magic. I found some useful information on this web page:
@@ -113,7 +113,7 @@ PCRE_EXP_DATA_DEFN only if they are not already set. */
# define PCRE_EXP_DEFN __declspec(dllexport) # define PCRE_EXP_DEFN __declspec(dllexport)
# define PCRE_EXP_DATA_DEFN __declspec(dllexport) # define PCRE_EXP_DATA_DEFN __declspec(dllexport)
# else # else
# define PCRE_EXP_DECL extern # define PCRE_EXP_DECL extern
# define PCRE_EXP_DEFN # define PCRE_EXP_DEFN
# define PCRE_EXP_DATA_DEFN # define PCRE_EXP_DATA_DEFN
# endif # endif

View File

@@ -1,158 +1,158 @@
// //
// pocomsg.mc[.h] // pocomsg.mc[.h]
// //
// $Id: //poco/svn/Foundation/src/pocomsg.mc#2 $ // $Id: //poco/1.4/Foundation/src/pocomsg.h#1 $
// //
// The Poco message source/header file. // The Poco message source/header file.
// //
// NOTE: pocomsg.h is automatically generated from pocomsg.mc. // NOTE: pocomsg.h is automatically generated from pocomsg.mc.
// Never edit pocomsg.h directly! // Never edit pocomsg.h directly!
// //
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
// and Contributors. // and Contributors.
// //
// Permission is hereby granted, free of charge, to any person or organization // Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by // obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute, // this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the // execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to // Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following: // do so, all subject to the following:
// //
// The copyright notices in the Software and this entire statement, including // The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer, // the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and // must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative // all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by // works are solely in the form of machine-executable object code generated by
// a source language processor. // a source language processor.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
// //
// //
// Categories // Categories
// //
// //
// Values are 32 bit values laid out as follows: // Values are 32 bit values laid out as follows:
// //
// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
// +---+-+-+-----------------------+-------------------------------+ // +---+-+-+-----------------------+-------------------------------+
// |Sev|C|R| Facility | Code | // |Sev|C|R| Facility | Code |
// +---+-+-+-----------------------+-------------------------------+ // +---+-+-+-----------------------+-------------------------------+
// //
// where // where
// //
// Sev - is the severity code // Sev - is the severity code
// //
// 00 - Success // 00 - Success
// 01 - Informational // 01 - Informational
// 10 - Warning // 10 - Warning
// 11 - Error // 11 - Error
// //
// C - is the Customer code flag // C - is the Customer code flag
// //
// R - is a reserved bit // R - is a reserved bit
// //
// Facility - is the facility code // Facility - is the facility code
// //
// Code - is the facility's status code // Code - is the facility's status code
// //
// //
// Define the facility codes // Define the facility codes
// //
// //
// Define the severity codes // Define the severity codes
// //
// //
// MessageId: POCO_CTG_FATAL // MessageId: POCO_CTG_FATAL
// //
// MessageText: // MessageText:
// //
// Fatal // Fatal
// //
#define POCO_CTG_FATAL 0x00000001L #define POCO_CTG_FATAL 0x00000001L
// //
// MessageId: POCO_CTG_CRITICAL // MessageId: POCO_CTG_CRITICAL
// //
// MessageText: // MessageText:
// //
// Critical // Critical
// //
#define POCO_CTG_CRITICAL 0x00000002L #define POCO_CTG_CRITICAL 0x00000002L
// //
// MessageId: POCO_CTG_ERROR // MessageId: POCO_CTG_ERROR
// //
// MessageText: // MessageText:
// //
// Error // Error
// //
#define POCO_CTG_ERROR 0x00000003L #define POCO_CTG_ERROR 0x00000003L
// //
// MessageId: POCO_CTG_WARNING // MessageId: POCO_CTG_WARNING
// //
// MessageText: // MessageText:
// //
// Warning // Warning
// //
#define POCO_CTG_WARNING 0x00000004L #define POCO_CTG_WARNING 0x00000004L
// //
// MessageId: POCO_CTG_NOTICE // MessageId: POCO_CTG_NOTICE
// //
// MessageText: // MessageText:
// //
// Notice // Notice
// //
#define POCO_CTG_NOTICE 0x00000005L #define POCO_CTG_NOTICE 0x00000005L
// //
// MessageId: POCO_CTG_INFORMATION // MessageId: POCO_CTG_INFORMATION
// //
// MessageText: // MessageText:
// //
// Information // Information
// //
#define POCO_CTG_INFORMATION 0x00000006L #define POCO_CTG_INFORMATION 0x00000006L
// //
// MessageId: POCO_CTG_DEBUG // MessageId: POCO_CTG_DEBUG
// //
// MessageText: // MessageText:
// //
// Debug // Debug
// //
#define POCO_CTG_DEBUG 0x00000007L #define POCO_CTG_DEBUG 0x00000007L
// //
// MessageId: POCO_CTG_TRACE // MessageId: POCO_CTG_TRACE
// //
// MessageText: // MessageText:
// //
// Trace // Trace
// //
#define POCO_CTG_TRACE 0x00000008L #define POCO_CTG_TRACE 0x00000008L
// //
// Event Identifiers // Event Identifiers
// //
// //
// MessageId: POCO_MSG_LOG // MessageId: POCO_MSG_LOG
// //
// MessageText: // MessageText:
// //
// %1 // %1
// //
#define POCO_MSG_LOG 0x00001000L #define POCO_MSG_LOG 0x00001000L

View File

@@ -1,7 +1,7 @@
;// ;//
;// pocomsg.mc[.h] ;// pocomsg.mc[.h]
;// ;//
;// $Id: //poco/svn/Foundation/src/pocomsg.mc#2 $ ;// $Id: //poco/1.4/Foundation/src/pocomsg.mc#1 $
;// ;//
;// The Poco message source/header file. ;// The Poco message source/header file.
;// ;//

View File

@@ -291,7 +291,7 @@
# ifdef FAR # ifdef FAR
# undef FAR # undef FAR
# endif # endif
# include "Poco/UnWindows.h" # include <windows.h>
/* No need for _export, use ZLIB.DEF instead. */ /* No need for _export, use ZLIB.DEF instead. */
/* For complete Windows compatibility, use WINAPI, not __stdcall. */ /* For complete Windows compatibility, use WINAPI, not __stdcall. */
# define ZEXPORT WINAPI # define ZEXPORT WINAPI
@@ -356,14 +356,34 @@ typedef uLong FAR uLongf;
typedef Byte *voidp; typedef Byte *voidp;
#endif #endif
#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ #ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */
# define Z_HAVE_UNISTD_H
#endif
#ifdef STDC
# include <sys/types.h> /* for off_t */ # include <sys/types.h> /* for off_t */
#endif
/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
* "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
* though the former does not conform to the LFS document), but considering
* both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
* equivalently requesting no 64-bit operations
*/
#if -_LARGEFILE64_SOURCE - -1 == 1
# undef _LARGEFILE64_SOURCE
#endif
#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
# include <unistd.h> /* for SEEK_* and off_t */ # include <unistd.h> /* for SEEK_* and off_t */
# ifdef VMS # ifdef VMS
# include <unixio.h> /* for off_t */ # include <unixio.h> /* for off_t */
# endif # endif
# ifndef z_off_t
# define z_off_t off_t # define z_off_t off_t
# endif # endif
#endif
#ifndef SEEK_SET #ifndef SEEK_SET
# define SEEK_SET 0 /* Seek from beginning of file. */ # define SEEK_SET 0 /* Seek from beginning of file. */
# define SEEK_CUR 1 /* Seek from current position. */ # define SEEK_CUR 1 /* Seek from current position. */
@@ -386,9 +406,6 @@ typedef uLong FAR uLongf;
#if defined(__MVS__) #if defined(__MVS__)
# define NO_vsnprintf # define NO_vsnprintf
# ifdef FAR
# undef FAR
# endif
#endif #endif
/* MVS linker does not support external names larger than 8 bytes */ /* MVS linker does not support external names larger than 8 bytes */

View File

@@ -1578,7 +1578,7 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
# define gzoffset gzoffset64 # define gzoffset gzoffset64
# define adler32_combine adler32_combine64 # define adler32_combine adler32_combine64
# define crc32_combine crc32_combine64 # define crc32_combine crc32_combine64
# ifndef _LARGEFILE64_SOURCE # ifdef _LARGEFILE64_SOURCE
ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));
ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));

View File

@@ -3,7 +3,7 @@
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
/* @(#) $Id$ */ /* @(#) $Id: //poco/1.4/Foundation/src/zutil.c#2 $ */
#include "zutil.h" #include "zutil.h"

View File

@@ -8,7 +8,7 @@
subject to change. Applications should only use zlib.h. subject to change. Applications should only use zlib.h.
*/ */
/* @(#) $Id$ */ /* @(#) $Id: //poco/1.4/Foundation/src/zutil.h#2 $ */
#ifndef ZUTIL_H #ifndef ZUTIL_H
#define ZUTIL_H #define ZUTIL_H

View File

@@ -82,11 +82,14 @@ public:
DialogSocket(const Socket& socket); DialogSocket(const Socket& socket);
/// Creates the DialogSocket with the SocketImpl /// Creates the DialogSocket with the SocketImpl
/// from another socket. The SocketImpl must be /// from another socket. The SocketImpl must be
/// a StreamSocketImpl, otherwise an InvalidArgumentException /// a StreamSocketImpl, otherwise an InvalidArgumentException
/// will be thrown. /// will be thrown.
~DialogSocket(); DialogSocket(const DialogSocket& socket);
/// Destroys the DialogSocket. /// Creates the DialogSocket as copy of another dialog socket.
~DialogSocket();
/// Destroys the DialogSocket.
DialogSocket& operator = (const Socket& socket); DialogSocket& operator = (const Socket& socket);
/// Assignment operator. /// Assignment operator.

View File

@@ -57,11 +57,18 @@ class PartSource;
class Net_API HTMLForm: public NameValueCollection class Net_API HTMLForm: public NameValueCollection
/// HTMLForm is a helper class for working with HTML forms, /// HTMLForm is a helper class for working with HTML forms,
/// both on the client and on the server side. /// both on the client and on the server side.
///
/// The maximum number of form fields can be restricted
/// by calling setFieldLimit(). This is useful to
/// defend against certain kinds of denial-of-service
/// attacks. The limit is only enforced when parsing
/// form data from a stream or string, not when adding
/// form fields programmatically. The default limit is 100.
{ {
public: public:
HTMLForm(); HTMLForm();
/// Creates an empty HTMLForm and sets the /// Creates an empty HTMLForm and sets the
/// encoding to "application/x-www-form-urlencoded". /// encoding to "application/x-www-form-urlencoded".
@@ -133,12 +140,27 @@ public:
void read(std::istream& istr, PartHandler& handler); void read(std::istream& istr, PartHandler& handler);
/// Reads the form data from the given input stream. /// Reads the form data from the given input stream.
/// ///
/// The form data read from the stream must be /// The form data read from the stream must be
/// in the encoding specified for the form. /// in the encoding specified for the form.
///
void prepareSubmit(HTTPRequest& request); /// Note that read() does not clear the form before
/// Fills out the request object for submitting the form. /// reading the new values.
void read(std::istream& istr);
/// Reads the URL-encoded form data from the given input stream.
///
/// Note that read() does not clear the form before
/// reading the new values.
void read(const std::string& queryString);
/// Reads the form data from the given HTTP query string.
///
/// Note that read() does not clear the form before
/// reading the new values.
void prepareSubmit(HTTPRequest& request);
/// Fills out the request object for submitting the form.
/// ///
/// If the request method is GET, the encoded form is appended to the /// If the request method is GET, the encoded form is appended to the
/// request URI as query string. Otherwise (the method is /// request URI as query string. Otherwise (the method is
@@ -161,11 +183,25 @@ public:
/// using the specified encoding. /// using the specified encoding.
const std::string& boundary() const; const std::string& boundary() const;
/// Returns the MIME boundary used for writing /// Returns the MIME boundary used for writing
/// multipart form data. /// multipart form data.
static const std::string ENCODING_URL; /// "application/x-www-form-urlencoded" int getFieldLimit() const;
static const std::string ENCODING_MULTIPART; /// "multipart/form-data" /// Returns the maximum number of header fields
/// allowed.
///
/// See setFieldLimit() for more information.
void setFieldLimit(int limit);
/// Sets the maximum number of header fields
/// allowed. This limit is used to defend certain
/// kinds of denial-of-service attacks.
/// Specify 0 for unlimited (not recommended).
///
/// The default limit is 100.
static const std::string ENCODING_URL; /// "application/x-www-form-urlencoded"
static const std::string ENCODING_MULTIPART; /// "multipart/form-data"
protected: protected:
void readUrl(std::istream& istr); void readUrl(std::istream& istr);
@@ -174,20 +210,26 @@ protected:
void writeMultipart(std::ostream& ostr); void writeMultipart(std::ostream& ostr);
private: private:
HTMLForm(const HTMLForm&); HTMLForm(const HTMLForm&);
HTMLForm& operator = (const HTMLForm&); HTMLForm& operator = (const HTMLForm&);
struct Part enum Limits
{ {
std::string name; DFL_FIELD_LIMIT = 100
};
struct Part
{
std::string name;
PartSource* pSource; PartSource* pSource;
}; };
typedef std::vector<Part> PartVec; typedef std::vector<Part> PartVec;
std::string _encoding; int _fieldLimit;
std::string _boundary; std::string _encoding;
PartVec _parts; std::string _boundary;
PartVec _parts;
}; };
@@ -206,6 +248,12 @@ inline const std::string& HTMLForm::boundary() const
} }
inline int HTMLForm::getFieldLimit() const
{
return _fieldLimit;
}
} } // namespace Poco::Net } } // namespace Poco::Net

View File

@@ -66,11 +66,16 @@ public:
/// Creates a HTTPBasicCredentials object with the authentication information /// Creates a HTTPBasicCredentials object with the authentication information
/// from the given request. /// from the given request.
/// ///
/// Throws a NotAuthenticatedException if the request does /// Throws a NotAuthenticatedException if the request does
/// not contain basic authentication information. /// not contain basic authentication information.
~HTTPBasicCredentials(); explicit HTTPBasicCredentials(const std::string& authInfo);
/// Destroys the HTTPBasicCredentials. /// Creates a HTTPBasicCredentials object with the authentication information
/// in the given string. The authentication information can be extracted
/// from a HTTPRequest object by calling HTTPRequest::getCredentials().
~HTTPBasicCredentials();
/// Destroys the HTTPBasicCredentials.
void setUsername(const std::string& username); void setUsername(const std::string& username);
/// Sets the username. /// Sets the username.
@@ -87,14 +92,20 @@ public:
void authenticate(HTTPRequest& request); void authenticate(HTTPRequest& request);
/// Adds authentication information to the given HTTPRequest. /// Adds authentication information to the given HTTPRequest.
static const std::string SCHEME; static const std::string SCHEME;
protected:
void parseAuthInfo(const std::string& authInfo);
/// Extracts username and password from Basic authentication info
/// by base64-decoding authInfo and splitting the resulting
/// string at the ':' delimiter.
private: private:
HTTPBasicCredentials(const HTTPBasicCredentials&); HTTPBasicCredentials(const HTTPBasicCredentials&);
HTTPBasicCredentials& operator = (const HTTPBasicCredentials); HTTPBasicCredentials& operator = (const HTTPBasicCredentials&);
std::string _username; std::string _username;
std::string _password; std::string _password;
}; };

View File

@@ -62,23 +62,42 @@ public:
void setVersion(const std::string& version); void setVersion(const std::string& version);
/// Sets the HTTP version for this message. /// Sets the HTTP version for this message.
const std::string& getVersion() const; const std::string& getVersion() const;
/// Returns the HTTP version for this message. /// Returns the HTTP version for this message.
void setContentLength(std::streamsize length); void setContentLength(std::streamsize length);
/// Sets the Content-Length header.
///
/// If length is UNKNOWN_CONTENT_LENGTH, removes
/// the Content-Length header.
std::streamsize getContentLength() const;
/// Returns the content length for this message,
/// which may be UNKNOWN_CONTENT_LENGTH if
/// no Content-Length header is present.
#if defined(POCO_HAVE_INT64)
void setContentLength64(Poco::Int64 length);
/// Sets the Content-Length header. /// Sets the Content-Length header.
/// ///
/// If length is UNKNOWN_CONTENT_LENGTH, removes /// If length is UNKNOWN_CONTENT_LENGTH, removes
/// the Content-Length header. /// the Content-Length header.
///
std::streamsize getContentLength() const; /// In contrast to setContentLength(), this method takes
/// a 64-bit integer as content length.
Poco::Int64 getContentLength64() const;
/// Returns the content length for this message, /// Returns the content length for this message,
/// which may be UNKNOWN_CONTENT_LENGTH if /// which may be UNKNOWN_CONTENT_LENGTH if
/// no Content-Length header is present. /// no Content-Length header is present.
///
/// In contrast to getContentLength(), this method
/// always returns a 64-bit integer for content length.
#endif // defined(POCO_HAVE_INT64)
void setTransferEncoding(const std::string& transferEncoding); void setTransferEncoding(const std::string& transferEncoding);
/// Sets the transfer encoding for this message. /// Sets the transfer encoding for this message.
/// ///
/// The value should be either IDENTITY_TRANSFER_CODING /// The value should be either IDENTITY_TRANSFER_CODING
/// or CHUNKED_TRANSFER_CODING. /// or CHUNKED_TRANSFER_CODING.

View File

@@ -62,15 +62,19 @@ public:
HostEntry(); HostEntry();
/// Creates an empty HostEntry. /// Creates an empty HostEntry.
HostEntry(struct hostent* entry); HostEntry(struct hostent* entry);
/// Creates the HostEntry from the data in a hostent structure. /// Creates the HostEntry from the data in a hostent structure.
#if defined(_WIN32) && defined(POCO_HAVE_IPv6) #if defined(POCO_HAVE_IPv6) || defined(POCO_HAVE_ADDRINFO)
HostEntry(struct addrinfo* info); HostEntry(struct addrinfo* info);
/// Creates the HostEntry from the data in a Windows addrinfo structure. /// Creates the HostEntry from the data in an addrinfo structure.
#endif #endif
HostEntry(const HostEntry& entry); #if defined(POCO_VXWORKS)
HostEntry(const std::string& name, const IPAddress& addr);
#endif
HostEntry(const HostEntry& entry);
/// Creates the HostEntry by copying another one. /// Creates the HostEntry by copying another one.
HostEntry& operator = (const HostEntry& entry); HostEntry& operator = (const HostEntry& entry);

View File

@@ -59,12 +59,19 @@ class Net_API MessageHeader: public NameValueCollection
/// ///
/// There can be more than one name-value pair with the /// There can be more than one name-value pair with the
/// same name. /// same name.
/// ///
/// MessageHeader supports writing and reading the /// MessageHeader supports writing and reading the
/// header data in RFC 2822 format. /// header data in RFC 2822 format.
///
/// The maximum number of fields can be restricted
/// by calling setFieldLimit(). This is useful to
/// defend against certain kinds of denial-of-service
/// attacks. The limit is only enforced when parsing
/// header fields from a stream, not when programmatically
/// adding them. The default limit is 100.
{ {
public: public:
MessageHeader(); MessageHeader();
/// Creates the MessageHeader. /// Creates the MessageHeader.
MessageHeader(const MessageHeader& messageHeader); MessageHeader(const MessageHeader& messageHeader);
@@ -99,12 +106,26 @@ public:
/// Some basic sanity checking of the input stream is /// Some basic sanity checking of the input stream is
/// performed. /// performed.
/// ///
/// Throws a MessageException if the input stream is /// Throws a MessageException if the input stream is
/// malformed. /// malformed.
static void splitElements(const std::string& s, std::vector<std::string>& elements, bool ignoreEmpty = true); int getFieldLimit() const;
/// Splits the given string into separate elements. Elements are expected /// Returns the maximum number of header fields
/// to be separated by commas. /// allowed.
///
/// See setFieldLimit() for more information.
void setFieldLimit(int limit);
/// Sets the maximum number of header fields
/// allowed. This limit is used to defend certain
/// kinds of denial-of-service attacks.
/// Specify 0 for unlimited (not recommended).
///
/// The default limit is 100.
static void splitElements(const std::string& s, std::vector<std::string>& elements, bool ignoreEmpty = true);
/// Splits the given string into separate elements. Elements are expected
/// to be separated by commas.
/// ///
/// For example, the string /// For example, the string
/// text/plain; q=0.5, text/html, text/x-dvi; q=0.8 /// text/plain; q=0.5, text/html, text/x-dvi; q=0.8
@@ -136,18 +157,21 @@ public:
/// ///
/// Enclosing quotes of parameter values are removed. /// Enclosing quotes of parameter values are removed.
static void quote(const std::string& value, std::string& result, bool allowSpace = false); static void quote(const std::string& value, std::string& result, bool allowSpace = false);
/// Checks if the value must be quoted. If so, the value is /// Checks if the value must be quoted. If so, the value is
/// appended to result, enclosed in double-quotes. /// appended to result, enclosed in double-quotes.
/// Otherwise, the value is appended to result as-is. /// Otherwise, the value is appended to result as-is.
private: private:
enum Limits enum Limits
/// Limits for basic sanity checks when reading a header /// Limits for basic sanity checks when reading a header
{ {
MAX_NAME_LENGTH = 256, MAX_NAME_LENGTH = 256,
MAX_VALUE_LENGTH = 4096 MAX_VALUE_LENGTH = 4096,
}; DFL_FIELD_LIMIT = 100
};
int _fieldLimit;
}; };

View File

@@ -69,6 +69,7 @@ POCO_DECLARE_EXCEPTION(Net_API, FTPException, NetException)
POCO_DECLARE_EXCEPTION(Net_API, SMTPException, NetException) POCO_DECLARE_EXCEPTION(Net_API, SMTPException, NetException)
POCO_DECLARE_EXCEPTION(Net_API, POP3Exception, NetException) POCO_DECLARE_EXCEPTION(Net_API, POP3Exception, NetException)
POCO_DECLARE_EXCEPTION(Net_API, ICMPException, NetException) POCO_DECLARE_EXCEPTION(Net_API, ICMPException, NetException)
POCO_DECLARE_EXCEPTION(Net_API, HTMLFormException, NetException)
} } // namespace Poco::Net } } // namespace Poco::Net

View File

@@ -236,11 +236,23 @@
#endif #endif
#if POCO_OS != POCO_OS_VXWORKS
#define POCO_HAVE_ADDRINFO 1
#endif
#if (POCO_OS == POCO_OS_HPUX) || (POCO_OS == POCO_OS_SOLARIS) || (POCO_OS == POCO_OS_WINDOWS_CE) #if (POCO_OS == POCO_OS_HPUX) || (POCO_OS == POCO_OS_SOLARIS) || (POCO_OS == POCO_OS_WINDOWS_CE)
#define POCO_BROKEN_TIMEOUTS 1 #define POCO_BROKEN_TIMEOUTS 1
#endif #endif
#if defined(POCO_HAVE_ADDRINFO)
#if !defined(AI_ADDRCONFIG)
#define AI_ADDRCONFIG 0
#endif
#endif
#if defined(POCO_HAVE_SALEN) #if defined(POCO_HAVE_SALEN)
#define poco_set_sa_len(pSA, len) (pSA)->sa_len = (len) #define poco_set_sa_len(pSA, len) (pSA)->sa_len = (len)
#define poco_set_sin_len(pSA) (pSA)->sin_len = sizeof(struct sockaddr_in) #define poco_set_sin_len(pSA) (pSA)->sin_len = sizeof(struct sockaddr_in)

View File

@@ -51,7 +51,7 @@ using Poco::IOException;
namespace namespace
{ {
class NetworkInitializer class NetworkInitializer
{ {
public: public:
NetworkInitializer() NetworkInitializer()
@@ -61,9 +61,9 @@ namespace
~NetworkInitializer() ~NetworkInitializer()
{ {
Poco::Net::uninitializeNetwork(); Poco::Net::uninitializeNetwork();
} }
}; };
} }
@@ -75,37 +75,37 @@ HostEntry DNS::hostByName(const std::string& hostname)
{ {
NetworkInitializer networkInitializer; NetworkInitializer networkInitializer;
#if defined(POCO_HAVE_IPv6) #if defined(POCO_HAVE_IPv6) || defined(POCO_HAVE_ADDRINFO)
struct addrinfo* pAI; struct addrinfo* pAI;
struct addrinfo hints; struct addrinfo hints;
std::memset(&hints, 0, sizeof(hints)); std::memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
int rc = getaddrinfo(hostname.c_str(), NULL, &hints, &pAI); int rc = getaddrinfo(hostname.c_str(), NULL, &hints, &pAI);
if (rc == 0) if (rc == 0)
{ {
HostEntry result(pAI); HostEntry result(pAI);
freeaddrinfo(pAI); freeaddrinfo(pAI);
return result; return result;
} }
else else
{ {
aierror(rc, hostname); aierror(rc, hostname);
} }
#elif defined(POCO_VXWORKS) #elif defined(POCO_VXWORKS)
int addr = hostGetByName(const_cast<char*>(hostname.c_str())); int addr = hostGetByName(const_cast<char*>(hostname.c_str()));
if (addr != ERROR) if (addr != ERROR)
{ {
return HostEntry(hostname, IPAddress(&addr, sizeof(addr))); return HostEntry(hostname, IPAddress(&addr, sizeof(addr)));
} }
#else #else
struct hostent* he = gethostbyname(hostname.c_str()); struct hostent* he = gethostbyname(hostname.c_str());
if (he) if (he)
{ {
return HostEntry(he); return HostEntry(he);
} }
#endif #endif
error(lastError(), hostname); // will throw an appropriate exception error(lastError(), hostname); // will throw an appropriate exception
throw NetException(); // to silence compiler throw NetException(); // to silence compiler
} }
@@ -113,46 +113,46 @@ HostEntry DNS::hostByAddress(const IPAddress& address)
{ {
NetworkInitializer networkInitializer; NetworkInitializer networkInitializer;
#if defined(POCO_HAVE_IPv6) #if defined(POCO_HAVE_IPv6) || defined(POCO_HAVE_ADDRINFO)
SocketAddress sa(address, 0); SocketAddress sa(address, 0);
static char fqname[1024]; static char fqname[1024];
int rc = getnameinfo(sa.addr(), sa.length(), fqname, sizeof(fqname), NULL, 0, NI_NAMEREQD); int rc = getnameinfo(sa.addr(), sa.length(), fqname, sizeof(fqname), NULL, 0, NI_NAMEREQD);
if (rc == 0) if (rc == 0)
{ {
struct addrinfo* pAI; struct addrinfo* pAI;
struct addrinfo hints; struct addrinfo hints;
std::memset(&hints, 0, sizeof(hints)); std::memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
rc = getaddrinfo(fqname, NULL, &hints, &pAI); rc = getaddrinfo(fqname, NULL, &hints, &pAI);
if (rc == 0) if (rc == 0)
{ {
HostEntry result(pAI); HostEntry result(pAI);
freeaddrinfo(pAI); freeaddrinfo(pAI);
return result; return result;
} }
else else
{ {
aierror(rc, address.toString()); aierror(rc, address.toString());
} }
} }
else else
{ {
aierror(rc, address.toString()); aierror(rc, address.toString());
} }
#elif defined(POCO_VXWORKS) #elif defined(POCO_VXWORKS)
char name[MAXHOSTNAMELEN + 1]; char name[MAXHOSTNAMELEN + 1];
if (hostGetByAddr(*reinterpret_cast<const int*>(address.addr()), name) == OK) if (hostGetByAddr(*reinterpret_cast<const int*>(address.addr()), name) == OK)
{ {
return HostEntry(std::string(name), address); return HostEntry(std::string(name), address);
} }
#else #else
struct hostent* he = gethostbyaddr(reinterpret_cast<const char*>(address.addr()), address.length(), address.af()); struct hostent* he = gethostbyaddr(reinterpret_cast<const char*>(address.addr()), address.length(), address.af());
if (he) if (he)
{ {
return HostEntry(he); return HostEntry(he);
} }
#endif #endif
int err = lastError(); int err = lastError();
error(err, address.toString()); // will throw an appropriate exception error(err, address.toString()); // will throw an appropriate exception
throw NetException(); // to silence compiler throw NetException(); // to silence compiler
} }
@@ -160,11 +160,11 @@ HostEntry DNS::hostByAddress(const IPAddress& address)
HostEntry DNS::resolve(const std::string& address) HostEntry DNS::resolve(const std::string& address)
{ {
NetworkInitializer networkInitializer; NetworkInitializer networkInitializer;
IPAddress ip; IPAddress ip;
if (IPAddress::tryParse(address, ip)) if (IPAddress::tryParse(address, ip))
return hostByAddress(ip); return hostByAddress(ip);
else else
return hostByName(address); return hostByName(address);
} }
@@ -172,11 +172,11 @@ HostEntry DNS::resolve(const std::string& address)
IPAddress DNS::resolveOne(const std::string& address) IPAddress DNS::resolveOne(const std::string& address)
{ {
NetworkInitializer networkInitializer; NetworkInitializer networkInitializer;
const HostEntry& entry = resolve(address); const HostEntry& entry = resolve(address);
if (!entry.addresses().empty()) if (!entry.addresses().empty())
return entry.addresses()[0]; return entry.addresses()[0];
else else
throw NoAddressFoundException(address); throw NoAddressFoundException(address);
} }
@@ -184,7 +184,7 @@ IPAddress DNS::resolveOne(const std::string& address)
HostEntry DNS::thisHost() HostEntry DNS::thisHost()
{ {
return hostByName(hostName()); return hostByName(hostName());
} }
@@ -195,11 +195,11 @@ void DNS::flushCache()
std::string DNS::hostName() std::string DNS::hostName()
{ {
NetworkInitializer networkInitializer; NetworkInitializer networkInitializer;
char buffer[256]; char buffer[256];
int rc = gethostname(buffer, sizeof(buffer)); int rc = gethostname(buffer, sizeof(buffer));
if (rc == 0) if (rc == 0)
return std::string(buffer); return std::string(buffer);
else else
throw NetException("Cannot get host name"); throw NetException("Cannot get host name");
@@ -243,30 +243,30 @@ void DNS::error(int code, const std::string& arg)
void DNS::aierror(int code, const std::string& arg) void DNS::aierror(int code, const std::string& arg)
{ {
#if defined(POCO_HAVE_IPv6) #if defined(POCO_HAVE_IPv6)
switch (code) switch (code)
{ {
case EAI_AGAIN: case EAI_AGAIN:
throw DNSException("Temporary DNS error while resolving", arg); throw DNSException("Temporary DNS error while resolving", arg);
case EAI_FAIL: case EAI_FAIL:
throw DNSException("Non recoverable DNS error while resolving", arg); throw DNSException("Non recoverable DNS error while resolving", arg);
#if !defined(_WIN32) // EAI_NODATA and EAI_NONAME have the same value #if !defined(_WIN32) // EAI_NODATA and EAI_NONAME have the same value
case EAI_NODATA: case EAI_NODATA:
throw NoAddressFoundException(arg); throw NoAddressFoundException(arg);
#endif #endif
case EAI_NONAME: case EAI_NONAME:
throw HostNotFoundException(arg); throw HostNotFoundException(arg);
#if defined(EAI_SYSTEM) #if defined(EAI_SYSTEM)
case EAI_SYSTEM: case EAI_SYSTEM:
error(lastError(), arg); error(lastError(), arg);
break; break;
#endif #endif
#if defined(_WIN32) #if defined(_WIN32)
case WSANO_DATA: // may happen on XP case WSANO_DATA: // may happen on XP
throw HostNotFoundException(arg); throw HostNotFoundException(arg);
#endif #endif
default: default:
throw DNSException("EAI", NumberFormatter::format(code)); throw DNSException("EAI", NumberFormatter::format(code));
} }
#endif // POCO_HAVE_IPv6 #endif // POCO_HAVE_IPv6
} }
@@ -279,24 +279,24 @@ static Poco::AtomicCounter initializeCount;
void initializeNetwork() void initializeNetwork()
{ {
#if defined(_WIN32) #if defined(_WIN32)
if (++initializeCount == 1) if (++initializeCount == 1)
{ {
WORD version = MAKEWORD(2, 2); WORD version = MAKEWORD(2, 2);
WSADATA data; WSADATA data;
if (WSAStartup(version, &data) != 0) if (WSAStartup(version, &data) != 0)
throw NetException("Failed to initialize network subsystem"); throw NetException("Failed to initialize network subsystem");
} }
#endif // _WIN32 #endif // _WIN32
} }
void uninitializeNetwork() void uninitializeNetwork()
{ {
#if defined(_WIN32) #if defined(_WIN32)
if (--initializeCount == 0) if (--initializeCount == 0)
{ {
WSACleanup(); WSACleanup();
} }
#endif // _WIN32 #endif // _WIN32
} }

View File

@@ -63,12 +63,22 @@ DialogSocket::DialogSocket(const SocketAddress& address):
DialogSocket::DialogSocket(const Socket& socket): DialogSocket::DialogSocket(const Socket& socket):
StreamSocket(socket), StreamSocket(socket),
_pBuffer(0), _pBuffer(0),
_pNext(0), _pNext(0),
_pEnd(0) _pEnd(0)
{ {
allocBuffer(); allocBuffer();
}
DialogSocket::DialogSocket(const DialogSocket& socket):
StreamSocket(socket),
_pBuffer(0),
_pNext(0),
_pEnd(0)
{
allocBuffer();
} }

View File

@@ -41,10 +41,10 @@
#include "Poco/Net/MultipartWriter.h" #include "Poco/Net/MultipartWriter.h"
#include "Poco/Net/MultipartReader.h" #include "Poco/Net/MultipartReader.h"
#include "Poco/Net/NullPartHandler.h" #include "Poco/Net/NullPartHandler.h"
#include "Poco/Net/NetException.h"
#include "Poco/NullStream.h" #include "Poco/NullStream.h"
#include "Poco/CountingStream.h" #include "Poco/CountingStream.h"
#include "Poco/StreamCopier.h" #include "Poco/StreamCopier.h"
#include "Poco/Exception.h"
#include "Poco/URI.h" #include "Poco/URI.h"
#include "Poco/String.h" #include "Poco/String.h"
#include <sstream> #include <sstream>
@@ -66,32 +66,37 @@ const std::string HTMLForm::ENCODING_MULTIPART = "multipart/form-data";
HTMLForm::HTMLForm(): HTMLForm::HTMLForm():
_encoding(ENCODING_URL) _fieldLimit(DFL_FIELD_LIMIT),
_encoding(ENCODING_URL)
{ {
} }
HTMLForm::HTMLForm(const std::string& encoding): HTMLForm::HTMLForm(const std::string& encoding):
_encoding(encoding) _fieldLimit(DFL_FIELD_LIMIT),
_encoding(encoding)
{ {
} }
HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& requestBody, PartHandler& handler) HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& requestBody, PartHandler& handler):
_fieldLimit(DFL_FIELD_LIMIT)
{ {
load(request, requestBody, handler); load(request, requestBody, handler);
} }
HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& requestBody) HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& requestBody):
_fieldLimit(DFL_FIELD_LIMIT)
{ {
load(request, requestBody); load(request, requestBody);
} }
HTMLForm::HTMLForm(const HTTPRequest& request) HTMLForm::HTMLForm(const HTTPRequest& request):
_fieldLimit(DFL_FIELD_LIMIT)
{ {
load(request); load(request);
} }
@@ -173,9 +178,22 @@ void HTMLForm::read(std::istream& istr, PartHandler& handler)
} }
void HTMLForm::read(std::istream& istr)
{
readUrl(istr);
}
void HTMLForm::read(const std::string& queryString)
{
std::istringstream istr(queryString);
readUrl(istr);
}
void HTMLForm::prepareSubmit(HTTPRequest& request) void HTMLForm::prepareSubmit(HTTPRequest& request)
{ {
if (request.getMethod() == HTTPRequest::HTTP_POST || request.getMethod() == HTTPRequest::HTTP_PUT) if (request.getMethod() == HTTPRequest::HTTP_POST || request.getMethod() == HTTPRequest::HTTP_PUT)
{ {
if (_encoding == ENCODING_URL) if (_encoding == ENCODING_URL)
{ {
@@ -241,14 +259,17 @@ void HTMLForm::write(std::ostream& ostr)
void HTMLForm::readUrl(std::istream& istr) void HTMLForm::readUrl(std::istream& istr)
{ {
static const int eof = std::char_traits<char>::eof(); static const int eof = std::char_traits<char>::eof();
int ch = istr.get(); int fields = 0;
while (ch != eof) int ch = istr.get();
{ while (ch != eof)
std::string name; {
std::string value; if (_fieldLimit > 0 && fields == _fieldLimit)
while (ch != eof && ch != '=' && ch != '&') throw HTMLFormException("Too many form fields");
std::string name;
std::string value;
while (ch != eof && ch != '=' && ch != '&')
{ {
if (ch == '+') ch = ' '; if (ch == '+') ch = ' ';
name += (char) ch; name += (char) ch;
@@ -266,24 +287,28 @@ void HTMLForm::readUrl(std::istream& istr)
} }
std::string decodedName; std::string decodedName;
std::string decodedValue; std::string decodedValue;
URI::decode(name, decodedName); URI::decode(name, decodedName);
URI::decode(value, decodedValue); URI::decode(value, decodedValue);
add(decodedName, decodedValue); add(decodedName, decodedValue);
if (ch == '&') ch = istr.get(); ++fields;
} if (ch == '&') ch = istr.get();
}
} }
void HTMLForm::readMultipart(std::istream& istr, PartHandler& handler) void HTMLForm::readMultipart(std::istream& istr, PartHandler& handler)
{ {
static const int eof = std::char_traits<char>::eof(); static const int eof = std::char_traits<char>::eof();
MultipartReader reader(istr, _boundary); int fields = 0;
while (reader.hasNextPart()) MultipartReader reader(istr, _boundary);
{ while (reader.hasNextPart())
MessageHeader header; {
reader.nextPart(header); if (_fieldLimit > 0 && fields == _fieldLimit)
std::string disp; throw HTMLFormException("Too many form fields");
MessageHeader header;
reader.nextPart(header);
std::string disp;
NameValueCollection params; NameValueCollection params;
if (header.has("Content-Disposition")) if (header.has("Content-Disposition"))
{ {
@@ -306,10 +331,11 @@ void HTMLForm::readMultipart(std::istream& istr, PartHandler& handler)
{ {
value += (char) ch; value += (char) ch;
ch = istr.get(); ch = istr.get();
} }
add(name, value); add(name, value);
} }
} ++fields;
}
} }
@@ -363,4 +389,12 @@ void HTMLForm::writeMultipart(std::ostream& ostr)
} }
void HTMLForm::setFieldLimit(int limit)
{
poco_assert (limit >= 0);
_fieldLimit = limit;
}
} } // namespace Poco::Net } } // namespace Poco::Net

View File

@@ -69,29 +69,20 @@ HTTPBasicCredentials::HTTPBasicCredentials(const std::string& username, const st
HTTPBasicCredentials::HTTPBasicCredentials(const HTTPRequest& request) HTTPBasicCredentials::HTTPBasicCredentials(const HTTPRequest& request)
{ {
static const int eof = std::char_traits<char>::eof(); std::string scheme;
std::string authInfo;
request.getCredentials(scheme, authInfo);
if (icompare(scheme, SCHEME) == 0)
{
parseAuthInfo(authInfo);
}
else throw NotAuthenticatedException("Basic authentication expected");
}
std::string scheme;
std::string info; HTTPBasicCredentials::HTTPBasicCredentials(const std::string& authInfo)
request.getCredentials(scheme, info); {
if (icompare(scheme, SCHEME) == 0) parseAuthInfo(authInfo);
{
std::istringstream istr(info);
Base64Decoder decoder(istr);
int ch = decoder.get();
while (ch != eof && ch != ':')
{
_username += (char) ch;
ch = decoder.get();
}
if (ch == ':') ch = decoder.get();
while (ch != eof)
{
_password += (char) ch;
ch = decoder.get();
}
}
else throw NotAuthenticatedException("Basic authentication expected");
} }
@@ -123,4 +114,25 @@ void HTTPBasicCredentials::authenticate(HTTPRequest& request)
} }
void HTTPBasicCredentials::parseAuthInfo(const std::string& authInfo)
{
static const int eof = std::char_traits<char>::eof();
std::istringstream istr(authInfo);
Base64Decoder decoder(istr);
int ch = decoder.get();
while (ch != eof && ch != ':')
{
_username += (char) ch;
ch = decoder.get();
}
if (ch == ':') ch = decoder.get();
while (ch != eof)
{
_password += (char) ch;
ch = decoder.get();
}
}
} } // namespace Poco::Net } } // namespace Poco::Net

View File

@@ -90,30 +90,52 @@ void HTTPMessage::setVersion(const std::string& version)
void HTTPMessage::setContentLength(std::streamsize length) void HTTPMessage::setContentLength(std::streamsize length)
{ {
if (length != UNKNOWN_CONTENT_LENGTH) if (length != UNKNOWN_CONTENT_LENGTH)
set(CONTENT_LENGTH, NumberFormatter::format(length)); set(CONTENT_LENGTH, NumberFormatter::format(length));
else else
erase(CONTENT_LENGTH); erase(CONTENT_LENGTH);
} }
std::streamsize HTTPMessage::getContentLength() const std::streamsize HTTPMessage::getContentLength() const
{
const std::string& contentLength = get(CONTENT_LENGTH, EMPTY);
if (!contentLength.empty())
{
if (sizeof(std::streamsize) == sizeof(Poco::Int64))
return static_cast<std::streamsize>(NumberParser::parse64(contentLength));
else
return static_cast<std::streamsize>(NumberParser::parse(contentLength));
}
else return UNKNOWN_CONTENT_LENGTH;
}
#if defined(POCO_HAVE_INT64)
void HTTPMessage::setContentLength64(Poco::Int64 length)
{
if (length != UNKNOWN_CONTENT_LENGTH)
set(CONTENT_LENGTH, NumberFormatter::format(length));
else
erase(CONTENT_LENGTH);
}
Poco::Int64 HTTPMessage::getContentLength64() const
{ {
const std::string& contentLength = get(CONTENT_LENGTH, EMPTY); const std::string& contentLength = get(CONTENT_LENGTH, EMPTY);
if (!contentLength.empty()) if (!contentLength.empty())
{ {
if (sizeof(std::streamsize) == sizeof(Poco::Int64)) return NumberParser::parse64(contentLength);
return static_cast<std::streamsize>(NumberParser::parse64(contentLength));
else
return static_cast<std::streamsize>(NumberParser::parse(contentLength));
} }
else return UNKNOWN_CONTENT_LENGTH; else return UNKNOWN_CONTENT_LENGTH;
} }
#endif // defined(POCO_HAVE_INT64)
void HTTPMessage::setTransferEncoding(const std::string& transferEncoding) void HTTPMessage::setTransferEncoding(const std::string& transferEncoding)
{ {
if (icompare(transferEncoding, IDENTITY_TRANSFER_ENCODING) == 0) if (icompare(transferEncoding, IDENTITY_TRANSFER_ENCODING) == 0)
erase(TRANSFER_ENCODING); erase(TRANSFER_ENCODING);
else else
set(TRANSFER_ENCODING, transferEncoding); set(TRANSFER_ENCODING, transferEncoding);

View File

@@ -39,6 +39,7 @@
#include "Poco/Net/NameValueCollection.h" #include "Poco/Net/NameValueCollection.h"
#include "Poco/NumberFormatter.h" #include "Poco/NumberFormatter.h"
#include "Poco/Ascii.h" #include "Poco/Ascii.h"
#include "Poco/String.h"
using Poco::NumberFormatter; using Poco::NumberFormatter;
@@ -150,11 +151,11 @@ void HTTPRequest::setCookies(const NameValueCollection& cookies)
void HTTPRequest::getCookies(NameValueCollection& cookies) const void HTTPRequest::getCookies(NameValueCollection& cookies) const
{ {
NameValueCollection::ConstIterator it = find(COOKIE); NameValueCollection::ConstIterator it = find(COOKIE);
while (it != end() && it->first == COOKIE) while (it != end() && Poco::icompare(it->first, COOKIE) == 0)
{ {
splitParameters(it->second.begin(), it->second.end(), cookies); splitParameters(it->second.begin(), it->second.end(), cookies);
++it; ++it;
} }
} }

View File

@@ -43,6 +43,7 @@
#include "Poco/DateTimeFormat.h" #include "Poco/DateTimeFormat.h"
#include "Poco/DateTimeParser.h" #include "Poco/DateTimeParser.h"
#include "Poco/Ascii.h" #include "Poco/Ascii.h"
#include "Poco/String.h"
using Poco::DateTime; using Poco::DateTime;
@@ -198,12 +199,12 @@ void HTTPResponse::addCookie(const HTTPCookie& cookie)
void HTTPResponse::getCookies(std::vector<HTTPCookie>& cookies) const void HTTPResponse::getCookies(std::vector<HTTPCookie>& cookies) const
{ {
cookies.clear(); cookies.clear();
NameValueCollection::ConstIterator it = find(SET_COOKIE); NameValueCollection::ConstIterator it = find(SET_COOKIE);
while (it != end() && it->first == SET_COOKIE) while (it != end() && Poco::icompare(it->first, SET_COOKIE) == 0)
{ {
NameValueCollection nvc; NameValueCollection nvc;
splitParameters(it->second.begin(), it->second.end(), nvc); splitParameters(it->second.begin(), it->second.end(), nvc);
cookies.push_back(HTTPCookie(nvc)); cookies.push_back(HTTPCookie(nvc));
++it; ++it;
} }

View File

@@ -116,12 +116,16 @@ void HTTPServerResponseImpl::sendFile(const std::string& path, const std::string
poco_assert (!_pStream); poco_assert (!_pStream);
File f(path); File f(path);
Timestamp dateTime = f.getLastModified(); Timestamp dateTime = f.getLastModified();
File::FileSize length = f.getSize(); File::FileSize length = f.getSize();
set("Last-Modified", DateTimeFormatter::format(dateTime, DateTimeFormat::HTTP_FORMAT)); set("Last-Modified", DateTimeFormatter::format(dateTime, DateTimeFormat::HTTP_FORMAT));
setContentLength(static_cast<int>(length)); #if defined(POCO_HAVE_INT64)
setContentType(mediaType); setContentLength64(length);
setChunkedTransferEncoding(false); #else
setContentLength(static_cast<int>(length));
#endif
setContentType(mediaType);
setChunkedTransferEncoding(false);
Poco::FileInputStream istr(path); Poco::FileInputStream istr(path);
if (istr.good()) if (istr.good())

View File

@@ -1,13 +1,13 @@
// //
// HTTPStreamFactory.cpp // HTTPStreamFactory.cpp
// //
// $Id: //poco/svn/Net/src/HTTPStreamFactory.cpp#3 $ // $Id: //poco/1.4/Net/src/HTTPStreamFactory.cpp#2 $
// //
// Library: Net // Library: Net
// Package: HTTP // Package: HTTP
// Module: HTTPStreamFactory // Module: HTTPStreamFactory
// //
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. // Copyright (c) 2005-2012, Applied Informatics Software Engineering GmbH.
// and Contributors. // and Contributors.
// //
// Permission is hereby granted, free of charge, to any person or organization // Permission is hereby granted, free of charge, to any person or organization
@@ -39,10 +39,13 @@
#include "Poco/Net/HTTPIOStream.h" #include "Poco/Net/HTTPIOStream.h"
#include "Poco/Net/HTTPRequest.h" #include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h" #include "Poco/Net/HTTPResponse.h"
#include "Poco/Net/HTTPCredentials.h"
#include "Poco/Net/NetException.h" #include "Poco/Net/NetException.h"
#include "Poco/URI.h" #include "Poco/URI.h"
#include "Poco/URIStreamOpener.h" #include "Poco/URIStreamOpener.h"
#include "Poco/UnbufferedStreamBuf.h" #include "Poco/UnbufferedStreamBuf.h"
#include "Poco/NullStream.h"
#include "Poco/StreamCopier.h"
using Poco::URIStreamFactory; using Poco::URIStreamFactory;
@@ -86,39 +89,57 @@ std::istream* HTTPStreamFactory::open(const URI& uri)
{ {
poco_assert (uri.getScheme() == "http"); poco_assert (uri.getScheme() == "http");
URI resolvedURI(uri); URI resolvedURI(uri);
URI proxyUri; URI proxyUri;
HTTPClientSession* pSession = 0; HTTPClientSession* pSession = 0;
bool retry = false; HTTPResponse res;
bool retry = false;
bool authorize = false;
std::string username;
std::string password;
try try
{ {
do do
{ {
pSession = new HTTPClientSession(resolvedURI.getHost(), resolvedURI.getPort()); if (!pSession)
{
if (proxyUri.empty()) pSession = new HTTPClientSession(resolvedURI.getHost(), resolvedURI.getPort());
pSession->setProxy(_proxyHost, _proxyPort);
else if (proxyUri.empty())
pSession->setProxy(proxyUri.getHost(), proxyUri.getPort()); pSession->setProxy(_proxyHost, _proxyPort);
pSession->setProxyCredentials(_proxyUsername, _proxyPassword); else
pSession->setProxy(proxyUri.getHost(), proxyUri.getPort());
std::string path = resolvedURI.getPathAndQuery(); pSession->setProxyCredentials(_proxyUsername, _proxyPassword);
if (path.empty()) path = "/"; }
HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1);
pSession->sendRequest(req); std::string path = resolvedURI.getPathAndQuery();
HTTPResponse res; if (path.empty()) path = "/";
std::istream& rs = pSession->receiveResponse(res); HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1);
bool moved = (res.getStatus() == HTTPResponse::HTTP_MOVED_PERMANENTLY ||
res.getStatus() == HTTPResponse::HTTP_FOUND || if (authorize)
{
HTTPCredentials::extractCredentials(uri, username, password);
HTTPCredentials cred(username, password);
cred.authenticate(req, res);
}
pSession->sendRequest(req);
std::istream& rs = pSession->receiveResponse(res);
bool moved = (res.getStatus() == HTTPResponse::HTTP_MOVED_PERMANENTLY ||
res.getStatus() == HTTPResponse::HTTP_FOUND ||
res.getStatus() == HTTPResponse::HTTP_SEE_OTHER || res.getStatus() == HTTPResponse::HTTP_SEE_OTHER ||
res.getStatus() == HTTPResponse::HTTP_TEMPORARY_REDIRECT); res.getStatus() == HTTPResponse::HTTP_TEMPORARY_REDIRECT);
if (moved) if (moved)
{ {
resolvedURI.resolve(res.get("Location")); resolvedURI.resolve(res.get("Location"));
throw URIRedirection(resolvedURI.toString()); if (!username.empty())
} {
else if (res.getStatus() == HTTPResponse::HTTP_OK) resolvedURI.setUserInfo(username + ":" + password);
}
throw URIRedirection(resolvedURI.toString());
}
else if (res.getStatus() == HTTPResponse::HTTP_OK)
{ {
return new HTTPResponseStream(rs, pSession); return new HTTPResponseStream(rs, pSession);
} }
@@ -130,16 +151,20 @@ std::istream* HTTPStreamFactory::open(const URI& uri)
// single request via the proxy. 305 responses MUST only be generated by origin servers. // single request via the proxy. 305 responses MUST only be generated by origin servers.
// only use for one single request! // only use for one single request!
proxyUri.resolve(res.get("Location")); proxyUri.resolve(res.get("Location"));
delete pSession; pSession = 0; delete pSession; pSession = 0;
retry = true; // only allow useproxy once retry = true; // only allow useproxy once
} }
else else if (res.getStatus() == HTTPResponse::HTTP_UNAUTHORIZED && !authorize)
{ {
throw HTTPException(res.getReason(), uri.toString()); authorize = true;
} retry = true;
} Poco::NullOutputStream null;
while(retry); Poco::StreamCopier::copyStream(rs, null);
throw HTTPException("Too many redirects", uri.toString()); }
else throw HTTPException(res.getReason(), uri.toString());
}
while (retry);
throw HTTPException("Too many redirects", uri.toString());
} }
catch (...) catch (...)
{ {

View File

@@ -74,7 +74,7 @@ HostEntry::HostEntry(struct hostent* entry)
} }
#if defined(POCO_HAVE_IPv6) #if defined(POCO_HAVE_IPv6) || defined(POCO_HAVE_ADDRINFO)
HostEntry::HostEntry(struct addrinfo* ainfo) HostEntry::HostEntry(struct addrinfo* ainfo)
@@ -91,15 +91,17 @@ HostEntry::HostEntry(struct addrinfo* ainfo)
{ {
switch (ai->ai_addr->sa_family) switch (ai->ai_addr->sa_family)
{ {
case AF_INET: case AF_INET:
_addresses.push_back(IPAddress(&reinterpret_cast<struct sockaddr_in*>(ai->ai_addr)->sin_addr, sizeof(in_addr))); _addresses.push_back(IPAddress(&reinterpret_cast<struct sockaddr_in*>(ai->ai_addr)->sin_addr, sizeof(in_addr)));
break; break;
#if defined(POCO_HAVE_IPv6)
case AF_INET6: case AF_INET6:
_addresses.push_back(IPAddress(&reinterpret_cast<struct sockaddr_in6*>(ai->ai_addr)->sin6_addr, sizeof(in6_addr), reinterpret_cast<struct sockaddr_in6*>(ai->ai_addr)->sin6_scope_id)); _addresses.push_back(IPAddress(&reinterpret_cast<struct sockaddr_in6*>(ai->ai_addr)->sin6_addr, sizeof(in6_addr), reinterpret_cast<struct sockaddr_in6*>(ai->ai_addr)->sin6_scope_id));
break; break;
#endif
} }
} }
} }
} }
@@ -110,9 +112,9 @@ HostEntry::HostEntry(struct addrinfo* ainfo)
HostEntry::HostEntry(const std::string& name, const IPAddress& addr): HostEntry::HostEntry(const std::string& name, const IPAddress& addr):
_name(name) _name(name)
{ {
_addresses.push_back(addr); _addresses.push_back(addr);
} }

View File

@@ -1,7 +1,7 @@
// //
// MessageHeader.cpp // MessageHeader.cpp
// //
// $Id: //poco/1.4/Net/src/MessageHeader.cpp#3 $ // $Id: //poco/1.4/Net/src/MessageHeader.cpp#4 $
// //
// Library: Net // Library: Net
// Package: Messages // Package: Messages
@@ -44,13 +44,15 @@ namespace Poco {
namespace Net { namespace Net {
MessageHeader::MessageHeader() MessageHeader::MessageHeader():
_fieldLimit(DFL_FIELD_LIMIT)
{ {
} }
MessageHeader::MessageHeader(const MessageHeader& messageHeader): MessageHeader::MessageHeader(const MessageHeader& messageHeader):
NameValueCollection(messageHeader) NameValueCollection(messageHeader),
_fieldLimit(DFL_FIELD_LIMIT)
{ {
} }
@@ -85,14 +87,17 @@ void MessageHeader::read(std::istream& istr)
std::string name; std::string name;
std::string value; std::string value;
name.reserve(32); name.reserve(32);
value.reserve(64); value.reserve(64);
int ch = buf.sbumpc(); int ch = buf.sbumpc();
while (ch != eof && ch != '\r' && ch != '\n') int fields = 0;
{ while (ch != eof && ch != '\r' && ch != '\n')
name.clear(); {
value.clear(); if (_fieldLimit > 0 && fields == _fieldLimit)
while (ch != eof && ch != ':' && ch != '\n' && name.length() < MAX_NAME_LENGTH) { name += ch; ch = buf.sbumpc(); } throw MessageException("Too many header fields");
name.clear();
value.clear();
while (ch != eof && ch != ':' && ch != '\n' && name.length() < MAX_NAME_LENGTH) { name += ch; ch = buf.sbumpc(); }
if (ch == '\n') { ch = buf.sbumpc(); continue; } // ignore invalid header lines if (ch == '\n') { ch = buf.sbumpc(); continue; } // ignore invalid header lines
if (ch != ':') throw MessageException("Field name too long/no colon found"); if (ch != ':') throw MessageException("Field name too long/no colon found");
if (ch != eof) ch = buf.sbumpc(); // ':' if (ch != eof) ch = buf.sbumpc(); // ':'
@@ -111,17 +116,32 @@ void MessageHeader::read(std::istream& istr)
ch = buf.sbumpc(); ch = buf.sbumpc();
else if (ch != eof) else if (ch != eof)
throw MessageException("Folded field value too long/no CRLF found"); throw MessageException("Folded field value too long/no CRLF found");
} }
Poco::trimRightInPlace(value); Poco::trimRightInPlace(value);
add(name, value); add(name, value);
} ++fields;
istr.putback(ch); }
istr.putback(ch);
}
int MessageHeader::getFieldLimit() const
{
return _fieldLimit;
}
void MessageHeader::setFieldLimit(int limit)
{
poco_assert (limit >= 0);
_fieldLimit = limit;
} }
void MessageHeader::splitElements(const std::string& s, std::vector<std::string>& elements, bool ignoreEmpty) void MessageHeader::splitElements(const std::string& s, std::vector<std::string>& elements, bool ignoreEmpty)
{ {
elements.clear(); elements.clear();
std::string::const_iterator it = s.begin(); std::string::const_iterator it = s.begin();
std::string::const_iterator end = s.end(); std::string::const_iterator end = s.end();
std::string elem; std::string elem;

View File

@@ -66,6 +66,7 @@ POCO_IMPLEMENT_EXCEPTION(FTPException, NetException, "FTP Exception")
POCO_IMPLEMENT_EXCEPTION(SMTPException, NetException, "SMTP Exception") POCO_IMPLEMENT_EXCEPTION(SMTPException, NetException, "SMTP Exception")
POCO_IMPLEMENT_EXCEPTION(POP3Exception, NetException, "POP3 Exception") POCO_IMPLEMENT_EXCEPTION(POP3Exception, NetException, "POP3 Exception")
POCO_IMPLEMENT_EXCEPTION(ICMPException, NetException, "ICMP Exception") POCO_IMPLEMENT_EXCEPTION(ICMPException, NetException, "ICMP Exception")
POCO_IMPLEMENT_EXCEPTION(HTMLFormException, NetException, "HTML Form Exception")
} } // namespace Poco::Net } } // namespace Poco::Net

View File

@@ -1,7 +1,7 @@
// //
// NetworkInterface.cpp // NetworkInterface.cpp
// //
// $Id: //poco/1.4/Net/src/NetworkInterface.cpp#3 $ // $Id: //poco/1.4/Net/src/NetworkInterface.cpp#9 $
// //
// Library: Net // Library: Net
// Package: Sockets // Package: Sockets
@@ -292,42 +292,35 @@ bool NetworkInterface::supportsIPv6() const
NetworkInterface NetworkInterface::forName(const std::string& name, bool requireIPv6) NetworkInterface NetworkInterface::forName(const std::string& name, bool requireIPv6)
{ {
#if defined(_WIN32) NetworkInterfaceList ifs = list();
NetworkInterfaceList ifs = list(); for (NetworkInterfaceList::const_iterator it = ifs.begin(); it != ifs.end(); ++it)
for (NetworkInterfaceList::const_iterator it = ifs.begin(); it != ifs.end(); ++it) {
{
if (it->name() == name && ((requireIPv6 && it->supportsIPv6()) || !requireIPv6)) if (it->name() == name && ((requireIPv6 && it->supportsIPv6()) || !requireIPv6))
return *it; return *it;
} }
throw InterfaceNotFoundException(name); throw InterfaceNotFoundException(name);
#else
FastMutex::ScopedLock lock(_mutex);
struct ifreq ifr;
std::strncpy(ifr.ifr_name, name.c_str(), IFNAMSIZ);
DatagramSocket ds(requireIPv6 ? IPAddress::IPv6 : IPAddress::IPv4);
ds.impl()->ioctl(SIOCGIFADDR, &ifr);
IPAddress addr;
#if defined(POCO_HAVE_IPv6)
if (ifr.ifr_addr.sa_family == AF_INET)
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in*>(&ifr.ifr_addr)->sin_addr, sizeof(struct in_addr));
else if (ifr.ifr_addr.sa_family == AF_INET6)
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(&ifr.ifr_addr)->sin6_addr, sizeof(struct in6_addr));
else
throw InterfaceNotFoundException(addr.toString(), "interface has no IP address");
int index = if_nametoindex(name.c_str());
#else
if (ifr.ifr_addr.sa_family == AF_INET)
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in*>(&ifr.ifr_addr)->sin_addr, sizeof(struct in_addr));
else
throw InterfaceNotFoundException(addr.toString(), "interface has no IP address");
int index = 0;
#endif
return NetworkInterface(name, name, addr, index);
#endif
} }
NetworkInterface NetworkInterface::forName(const std::string& name, IPVersion ipVersion)
{
NetworkInterfaceList ifs = list();
for (NetworkInterfaceList::const_iterator it = ifs.begin(); it != ifs.end(); ++it)
{
if (it->name() == name)
{
if (ipVersion == IPv4_ONLY && it->supportsIPv4())
return *it;
else if (ipVersion == IPv6_ONLY && it->supportsIPv6())
return *it;
else if (ipVersion == IPv4_OR_IPv6)
return *it;
}
}
throw InterfaceNotFoundException(name);
}
NetworkInterface NetworkInterface::forAddress(const IPAddress& addr) NetworkInterface NetworkInterface::forAddress(const IPAddress& addr)
{ {
NetworkInterfaceList ifs = list(); NetworkInterfaceList ifs = list();
@@ -374,10 +367,45 @@ NetworkInterface NetworkInterface::forIndex(int i)
namespace Poco { namespace Poco {
namespace Net { namespace Net {
#if defined(POCO_HAVE_IPv6)
IPAddress subnetMaskForInterface(const std::string& name, bool isLoopback)
{
if (isLoopback)
{
return IPAddress::parse("255.0.0.0");
}
else
{
std::string subKey("SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces\\");
subKey += name;
std::wstring usubKey;
Poco::UnicodeConverter::toUTF16(subKey, usubKey);
HKEY hKey;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, usubKey.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS)
return IPAddress();
wchar_t unetmask[16];
DWORD size = sizeof(unetmask);
if (RegQueryValueExW(hKey, L"DhcpSubnetMask", NULL, NULL, (LPBYTE) &unetmask, &size) != ERROR_SUCCESS)
{
if (RegQueryValueExW(hKey, L"SubnetMask", NULL, NULL, (LPBYTE) &unetmask, &size) != ERROR_SUCCESS)
{
RegCloseKey(hKey);
return IPAddress();
}
}
RegCloseKey(hKey);
std::string netmask;
Poco::UnicodeConverter::toUTF8(unetmask, netmask);
return IPAddress::parse(netmask);
}
}
#endif // POCO_HAVE_IPv6
NetworkInterface::NetworkInterfaceList NetworkInterface::list() NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{ {
FastMutex::ScopedLock lock(_mutex); FastMutex::ScopedLock lock(_mutex);
NetworkInterfaceList result; NetworkInterfaceList result;
DWORD rc; DWORD rc;
@@ -403,48 +431,62 @@ NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{ {
if (GetAdaptersAddresses(AF_UNSPEC, 0, 0, pAdapterAddresses, &addrLen) == NO_ERROR) if (GetAdaptersAddresses(AF_UNSPEC, 0, 0, pAdapterAddresses, &addrLen) == NO_ERROR)
{ {
pAddress = pAdapterAddresses; pAddress = pAdapterAddresses;
while (pAddress) while (pAddress)
{ {
if (pAddress->FirstUnicastAddress) if (pAddress->OperStatus == IfOperStatusUp)
{ {
IPAddress addr; PIP_ADAPTER_UNICAST_ADDRESS pUniAddr = pAddress->FirstUnicastAddress;
switch (pAddress->FirstUnicastAddress->Address.lpSockaddr->sa_family) while (pUniAddr)
{ {
case AF_INET: std::string name(pAddress->AdapterName);
addr = IPAddress(&reinterpret_cast<struct sockaddr_in*>(pAddress->FirstUnicastAddress->Address.lpSockaddr)->sin_addr, sizeof(in_addr)); std::string displayName;
break;
case AF_INET6:
addr = IPAddress(&reinterpret_cast<struct sockaddr_in6*>(pAddress->FirstUnicastAddress->Address.lpSockaddr)->sin6_addr, sizeof(in6_addr));
break;
}
std::string name(pAddress->AdapterName);
std::string displayName;
#ifdef POCO_WIN32_UTF8 #ifdef POCO_WIN32_UTF8
Poco::UnicodeConverter::toUTF8(pAddress->Description, displayName); Poco::UnicodeConverter::toUTF8(pAddress->FriendlyName, displayName);
#else #else
char displayNameBuffer[1024]; char displayNameBuffer[1024];
int rc = WideCharToMultiByte(CP_ACP, WC_DEFAULTCHAR, pAddress->Description, -1, displayNameBuffer, sizeof(displayNameBuffer), NULL, NULL); int rc = WideCharToMultiByte(CP_ACP, WC_DEFAULTCHAR, pAddress->FriendlyName, -1, displayNameBuffer, sizeof(displayNameBuffer), NULL, NULL);
if (rc) displayName = displayNameBuffer; if (rc) displayName = displayNameBuffer;
#endif #endif
result.push_back(NetworkInterface(name, displayName, addr, pAddress->Ipv6IfIndex)); IPAddress address;
pAddress = pAddress->Next; IPAddress subnetMask;
} IPAddress broadcastAddress;
} switch (pUniAddr->Address.lpSockaddr->sa_family)
} {
else throw NetException("cannot get network adapter list"); case AF_INET:
} address = IPAddress(&reinterpret_cast<struct sockaddr_in*>(pUniAddr->Address.lpSockaddr)->sin_addr, sizeof(in_addr));
catch (Poco::Exception&) subnetMask = subnetMaskForInterface(name, address.isLoopback());
if (!address.isLoopback())
{
broadcastAddress = address;
broadcastAddress.mask(subnetMask, IPAddress::broadcast());
}
result.push_back(NetworkInterface(name, displayName, address, subnetMask, broadcastAddress));
break;
case AF_INET6:
address = IPAddress(&reinterpret_cast<struct sockaddr_in6*>(pUniAddr->Address.lpSockaddr)->sin6_addr, sizeof(in6_addr), reinterpret_cast<struct sockaddr_in6*>(pUniAddr->Address.lpSockaddr)->sin6_scope_id);
result.push_back(NetworkInterface(name, displayName, address, pAddress->Ipv6IfIndex));
break;
}
pUniAddr = pUniAddr->Next;
}
}
pAddress = pAddress->Next;
}
}
else throw NetException("cannot get network adapter list");
}
catch (Poco::Exception&)
{ {
delete [] reinterpret_cast<char*>(pAdapterAddresses); delete [] reinterpret_cast<char*>(pAdapterAddresses);
throw; throw;
} }
delete [] reinterpret_cast<char*>(pAdapterAddresses); delete [] reinterpret_cast<char*>(pAdapterAddresses);
return result; return result;
#endif #endif // POCO_HAVE_IPv6
// Add IPv4 loopback interface (not returned by GetAdaptersInfo) // Add IPv4 loopback interface (not returned by GetAdaptersInfo)
result.push_back(NetworkInterface("Loopback", "Loopback Interface", IPAddress("127.0.0.1"), IPAddress("255.0.0.0"), IPAddress(), -1)); result.push_back(NetworkInterface("Loopback", "Loopback Interface", IPAddress("127.0.0.1"), IPAddress("255.0.0.0"), IPAddress(), -1));
// On Windows 2000 we use GetAdaptersInfo. // On Windows 2000 we use GetAdaptersInfo.
PIP_ADAPTER_INFO pAdapterInfo; PIP_ADAPTER_INFO pAdapterInfo;
PIP_ADAPTER_INFO pInfo = 0; PIP_ADAPTER_INFO pInfo = 0;
@@ -471,13 +513,13 @@ NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{ {
IPAddress address(std::string(pInfo->IpAddressList.IpAddress.String)); IPAddress address(std::string(pInfo->IpAddressList.IpAddress.String));
if (!address.isWildcard()) // only return interfaces that have an address assigned. if (!address.isWildcard()) // only return interfaces that have an address assigned.
{ {
IPAddress subnetMask(std::string(pInfo->IpAddressList.IpMask.String)); IPAddress subnetMask(std::string(pInfo->IpAddressList.IpMask.String));
IPAddress broadcastAddress(address); IPAddress broadcastAddress(address);
broadcastAddress.mask(subnetMask, IPAddress("255.255.255.255")); broadcastAddress.mask(subnetMask, IPAddress::broadcast());
std::string name(pInfo->AdapterName); std::string name(pInfo->AdapterName);
std::string displayName(pInfo->Description); std::string displayName(pInfo->Description);
result.push_back(NetworkInterface(name, displayName, address, subnetMask, broadcastAddress)); result.push_back(NetworkInterface(name, displayName, address, subnetMask, broadcastAddress));
} }
pInfo = pInfo->Next; pInfo = pInfo->Next;
} }
@@ -498,6 +540,59 @@ NetworkInterface::NetworkInterfaceList NetworkInterface::list()
} } // namespace Poco::Net } } // namespace Poco::Net
#elif defined(POCO_VXWORKS)
//
// VxWorks
//
namespace Poco {
namespace Net {
NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{
FastMutex::ScopedLock lock(_mutex);
NetworkInterfaceList result;
int ifIndex = 1;
char ifName[32];
char ifAddr[INET_ADDR_LEN];
for (;;)
{
if (ifIndexToIfName(ifIndex, ifName) == OK)
{
std::string name(ifName);
IPAddress addr;
IPAddress mask;
IPAddress bcst;
if (ifAddrGet(ifName, ifAddr) == OK)
{
addr = IPAddress(std::string(ifAddr));
}
int ifMask;
if (ifMaskGet(ifName, &ifMask) == OK)
{
mask = IPAddress(&ifMask, sizeof(ifMask));
}
if (ifBroadcastGet(ifName, ifAddr) == OK)
{
bcst = IPAddress(std::string(ifAddr));
}
result.push_back(NetworkInterface(name, name, addr, mask, bcst));
ifIndex++;
}
else break;
}
return result;
}
} } // namespace Poco::Net
#elif defined(POCO_OS_FAMILY_BSD) || POCO_OS == POCO_OS_QNX #elif defined(POCO_OS_FAMILY_BSD) || POCO_OS == POCO_OS_QNX
// //
// BSD variants // BSD variants
@@ -536,14 +631,15 @@ NetworkInterface::NetworkInterfaceList NetworkInterface::list()
result.push_back(NetworkInterface(name, name, addr, subnetMask, broadcastAddr)); result.push_back(NetworkInterface(name, name, addr, subnetMask, broadcastAddr));
} }
#if defined(POCO_HAVE_IPv6) #if defined(POCO_HAVE_IPv6)
else if (ifap->ifa_addr->sa_family == AF_INET6) else if (ifap->ifa_addr->sa_family == AF_INET6)
{ {
IPAddress addr(&reinterpret_cast<struct sockaddr_in6*>(ifap->ifa_addr)->sin6_addr, sizeof(struct in6_addr)); Poco::UInt32 ifIndex = if_nametoindex(ifap->ifa_name);
std::string name(ifap->ifa_name); IPAddress addr(&reinterpret_cast<struct sockaddr_in6*>(ifap->ifa_addr)->sin6_addr, sizeof(struct in6_addr), ifIndex);
result.push_back(NetworkInterface(name, name, addr, if_nametoindex(ifap->ifa_name))); std::string name(ifap->ifa_name);
} result.push_back(NetworkInterface(name, name, addr, ifIndex));
}
#endif #endif
} }
} }
freeifaddrs(ifaphead); freeifaddrs(ifaphead);
return result; return result;
@@ -557,6 +653,68 @@ NetworkInterface::NetworkInterfaceList NetworkInterface::list()
// //
// Linux // Linux
// //
#if defined(POCO_HAVE_IPv6)
#include <sys/types.h>
#include <ifaddrs.h>
namespace Poco {
namespace Net {
NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{
NetworkInterfaceList result;
struct ifaddrs* ifaces = 0;
struct ifaddrs* currIface = 0;
if (getifaddrs(&ifaces) < 0)
throw NetException("cannot get network adapter list");
try
{
for (currIface = ifaces; currIface != 0; currIface = currIface->ifa_next)
{
IPAddress addr;
bool haveAddr = false;
int ifIndex(-1);
switch (currIface->ifa_addr->sa_family)
{
case AF_INET6:
ifIndex = if_nametoindex(currIface->ifa_name);
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(currIface->ifa_addr)->sin6_addr, sizeof(struct in6_addr), ifIndex);
haveAddr = true;
break;
case AF_INET:
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in*>(currIface->ifa_addr)->sin_addr, sizeof(struct in_addr));
haveAddr = true;
break;
default:
break;
}
if (haveAddr)
{
std::string name(currIface->ifa_name);
result.push_back(NetworkInterface(name, name, addr, ifIndex));
}
}
}
catch (...)
{
}
if (ifaces) freeifaddrs(ifaces);
return result;
}
} } // namespace Poco::Net
#else // !POCO_HAVE_IPv6
namespace Poco { namespace Poco {
@@ -599,32 +757,22 @@ NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{ {
const struct ifreq* ifr = reinterpret_cast<const struct ifreq*>(ptr); const struct ifreq* ifr = reinterpret_cast<const struct ifreq*>(ptr);
IPAddress addr; IPAddress addr;
bool haveAddr = false; bool haveAddr = false;
switch (ifr->ifr_addr.sa_family) switch (ifr->ifr_addr.sa_family)
{ {
#if defined(POCO_HAVE_IPv6) case AF_INET:
case AF_INET6: addr = IPAddress(&reinterpret_cast<const struct sockaddr_in*>(&ifr->ifr_addr)->sin_addr, sizeof(struct in_addr));
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(&ifr->ifr_addr)->sin6_addr, sizeof(struct in6_addr)); haveAddr = true;
haveAddr = true;
break;
#endif
case AF_INET:
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in*>(&ifr->ifr_addr)->sin_addr, sizeof(struct in_addr));
haveAddr = true;
break; break;
default: default:
break; break;
} }
if (haveAddr) if (haveAddr)
{ {
#if defined(POCO_HAVE_IPv6) int index = -1;
int index = if_nametoindex(ifr->ifr_name); std::string name(ifr->ifr_name);
#else result.push_back(NetworkInterface(name, name, addr, index));
int index = -1; }
#endif
std::string name(ifr->ifr_name);
result.push_back(NetworkInterface(name, name, addr, index));
}
ptr += sizeof(struct ifreq); ptr += sizeof(struct ifreq);
} }
} }
@@ -641,6 +789,9 @@ NetworkInterface::NetworkInterfaceList NetworkInterface::list()
} } // namespace Poco::Net } } // namespace Poco::Net
#endif // POCO_HAVE_IPv6
#else #else
// //
// Non-BSD Unix variants // Non-BSD Unix variants
@@ -692,16 +843,18 @@ NetworkInterface::NetworkInterfaceList NetworkInterface::list()
#else #else
len = sizeof(struct sockaddr); len = sizeof(struct sockaddr);
#endif #endif
IPAddress addr; IPAddress addr;
bool haveAddr = false; bool haveAddr = false;
switch (ifr->ifr_addr.sa_family) int ifIndex(-1);
{ switch (ifr->ifr_addr.sa_family)
{
#if defined(POCO_HAVE_IPv6) #if defined(POCO_HAVE_IPv6)
case AF_INET6: case AF_INET6:
if (len < sizeof(struct sockaddr_in6)) len = sizeof(struct sockaddr_in6); ifIndex = if_nametoindex(ifr->ifr_name);
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(&ifr->ifr_addr)->sin6_addr, sizeof(struct in6_addr)); if (len < sizeof(struct sockaddr_in6)) len = sizeof(struct sockaddr_in6);
haveAddr = true; addr = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(&ifr->ifr_addr)->sin6_addr, sizeof(struct in6_addr), ifIndex);
break; haveAddr = true;
break;
#endif #endif
case AF_INET: case AF_INET:
if (len < sizeof(struct sockaddr_in)) len = sizeof(struct sockaddr_in); if (len < sizeof(struct sockaddr_in)) len = sizeof(struct sockaddr_in);
@@ -710,19 +863,14 @@ NetworkInterface::NetworkInterfaceList NetworkInterface::list()
break; break;
default: default:
break; break;
} }
if (haveAddr) if (haveAddr)
{ {
#if defined(POCO_HAVE_IPv6) std::string name(ifr->ifr_name);
int index = if_nametoindex(ifr->ifr_name); result.push_back(NetworkInterface(name, name, addr, ifIndex));
#else }
int index = -1; len += sizeof(ifr->ifr_name);
#endif ptr += len;
std::string name(ifr->ifr_name);
result.push_back(NetworkInterface(name, name, addr, index));
}
len += sizeof(ifr->ifr_name);
ptr += len;
} }
} }
catch (...) catch (...)

View File

@@ -257,14 +257,18 @@ public:
void remove(const std::string& key); void remove(const std::string& key);
/// Removes the property with the given key. /// Removes the property with the given key.
/// ///
/// Does nothing if the key does not exist. /// Does nothing if the key does not exist.
void setPropertyEventingMode(bool enabled); void enableEvents(bool enable = true);
/// Enable/Disable property eventing. /// Enables (or disables) events.
bool eventsEnabled() const;
/// Returns true iff events are enabled.
protected: protected:
virtual bool getRaw(const std::string& key, std::string& value) const = 0; virtual bool getRaw(const std::string& key, std::string& value) const = 0;
/// If the property with the given key exists, stores the property's value /// If the property with the given key exists, stores the property's value
/// in value and returns true. Otherwise, returns false. /// in value and returns true. Otherwise, returns false.
/// ///
/// Must be overridden by subclasses. /// Must be overridden by subclasses.
@@ -298,16 +302,15 @@ private:
std::string uncheckedExpand(const std::string& value) const; std::string uncheckedExpand(const std::string& value) const;
AbstractConfiguration(const AbstractConfiguration&); AbstractConfiguration(const AbstractConfiguration&);
AbstractConfiguration& operator = (const AbstractConfiguration&); AbstractConfiguration& operator = (const AbstractConfiguration&);
mutable int _depth; mutable int _depth;
mutable Poco::FastMutex _mutex; bool _eventsEnabled;
mutable Poco::FastMutex _mutex;
bool _propertyEventing;
friend class LayeredConfiguration;
friend class LayeredConfiguration; friend class ConfigurationView;
friend class ConfigurationView; friend class ConfigurationMapper;
friend class ConfigurationMapper;
}; };

View File

@@ -54,19 +54,21 @@ class Util_API WinRegistryConfiguration: public AbstractConfiguration
/// in the Windows registry. /// in the Windows registry.
/// ///
/// Removing key is not supported. An attempt to remove a key results /// Removing key is not supported. An attempt to remove a key results
/// in a NotImplementedException being thrown. /// in a NotImplementedException being thrown.
{ {
public: public:
WinRegistryConfiguration(const std::string& rootPath); WinRegistryConfiguration(const std::string& rootPath, REGSAM extraSam = 0);
/// Creates the WinRegistryConfiguration. /// Creates the WinRegistryConfiguration.
/// The rootPath must start with one of the root key names /// The rootPath must start with one of the root key names
/// like HKEY_CLASSES_ROOT, e.g. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services. /// like HKEY_CLASSES_ROOT, e.g. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services.
/// All further keys are relativ to the root path and can be /// All further keys are relativ to the root path and can be
/// dot seperated, e.g. the path MyService.ServiceName will be converted to /// dot seperated, e.g. the path MyService.ServiceName will be converted to
/// HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MyService\ServiceName. /// HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MyService\ServiceName.
/// The extraSam parameter will be passed along to WinRegistryKey, to control
/// registry virtualization for example.
protected: protected:
~WinRegistryConfiguration(); ~WinRegistryConfiguration();
/// Destroys the WinRegistryConfiguration. /// Destroys the WinRegistryConfiguration.
bool getRaw(const std::string& key, std::string& value) const; bool getRaw(const std::string& key, std::string& value) const;
@@ -79,7 +81,8 @@ protected:
/// registry format A\B\C, the last entry is the keyName, the rest is returned as path /// registry format A\B\C, the last entry is the keyName, the rest is returned as path
private: private:
std::string _rootPath; std::string _rootPath;
REGSAM _extraSam;
}; };

View File

@@ -55,7 +55,9 @@ namespace Poco {
namespace Util { namespace Util {
AbstractConfiguration::AbstractConfiguration(): _depth(0), _propertyEventing(true) AbstractConfiguration::AbstractConfiguration():
_depth(0),
_eventsEnabled(true)
{ {
} }
@@ -292,13 +294,31 @@ std::string AbstractConfiguration::expand(const std::string& value) const
void AbstractConfiguration::remove(const std::string& key) void AbstractConfiguration::remove(const std::string& key)
{ {
if (_propertyEventing) propertyRemoving(this, key); if (_eventsEnabled)
{ {
FastMutex::ScopedLock lock(_mutex); propertyRemoving(this, key);
}
{
FastMutex::ScopedLock lock(_mutex);
removeRaw(key); removeRaw(key);
} }
if (_propertyEventing) propertyRemoved(this, key); if (_eventsEnabled)
{
propertyRemoved(this, key);
}
}
void AbstractConfiguration::enableEvents(bool enable)
{
_eventsEnabled = enable;
}
bool AbstractConfiguration::eventsEnabled() const
{
return _eventsEnabled;
} }
@@ -385,19 +405,21 @@ bool AbstractConfiguration::parseBool(const std::string& value)
void AbstractConfiguration::setRawWithEvent(const std::string& key, std::string value) void AbstractConfiguration::setRawWithEvent(const std::string& key, std::string value)
{ {
KeyValue kv(key, value); KeyValue kv(key, value);
if (_propertyEventing) propertyChanging(this, kv); if (_eventsEnabled)
{ {
FastMutex::ScopedLock lock(_mutex); propertyChanging(this, kv);
}
{
FastMutex::ScopedLock lock(_mutex);
setRaw(key, value); setRaw(key, value);
} }
if (_propertyEventing) propertyChanged(this, kv); if (_eventsEnabled)
{
propertyChanged(this, kv);
}
} }
void AbstractConfiguration::setPropertyEventingMode(bool enabled)
{
_propertyEventing = enabled;
}
} } // namespace Poco::Util } } // namespace Poco::Util

View File

@@ -34,6 +34,9 @@
// //
#if !defined(_WIN32_WCE)
#include "Poco/Util/WinRegistryConfiguration.h" #include "Poco/Util/WinRegistryConfiguration.h"
#include "Poco/Util/WinRegistryKey.h" #include "Poco/Util/WinRegistryKey.h"
#include "Poco/NumberFormatter.h" #include "Poco/NumberFormatter.h"
@@ -45,10 +48,10 @@ namespace Poco {
namespace Util { namespace Util {
WinRegistryConfiguration::WinRegistryConfiguration(const std::string& rootPath): _rootPath(rootPath) WinRegistryConfiguration::WinRegistryConfiguration(const std::string& rootPath, REGSAM extraSam): _rootPath(rootPath), _extraSam(extraSam)
{ {
// rootPath must end with backslash // rootPath must end with backslash
std::string::iterator it = _rootPath.end(); std::string::iterator it = _rootPath.end();
if (*(--it) != '\\') if (*(--it) != '\\')
_rootPath.append("\\"); _rootPath.append("\\");
} }
@@ -61,12 +64,12 @@ WinRegistryConfiguration::~WinRegistryConfiguration()
bool WinRegistryConfiguration::getRaw(const std::string& key, std::string& value) const bool WinRegistryConfiguration::getRaw(const std::string& key, std::string& value) const
{ {
std::string keyName; std::string keyName;
std::string fullPath = _rootPath + ConvertToRegFormat(key, keyName); std::string fullPath = _rootPath + ConvertToRegFormat(key, keyName);
WinRegistryKey aKey(fullPath, true); WinRegistryKey aKey(fullPath, true, _extraSam);
bool exists = aKey.exists(keyName); bool exists = aKey.exists(keyName);
if (exists) if (exists)
{ {
WinRegistryKey::Type type = aKey.type(keyName); WinRegistryKey::Type type = aKey.type(keyName);
switch (type) switch (type)
@@ -90,10 +93,10 @@ bool WinRegistryConfiguration::getRaw(const std::string& key, std::string& value
void WinRegistryConfiguration::setRaw(const std::string& key, const std::string& value) void WinRegistryConfiguration::setRaw(const std::string& key, const std::string& value)
{ {
std::string keyName; std::string keyName;
std::string fullPath = _rootPath+ConvertToRegFormat(key, keyName); std::string fullPath = _rootPath+ConvertToRegFormat(key, keyName);
WinRegistryKey aKey(fullPath); WinRegistryKey aKey(fullPath, false, _extraSam);
aKey.setString(keyName, value); aKey.setString(keyName, value);
} }
@@ -110,13 +113,13 @@ void WinRegistryConfiguration::enumerate(const std::string& key, Keys& range) co
range.push_back("HKEY_USERS"); range.push_back("HKEY_USERS");
} }
else else
{ {
std::string keyName; std::string keyName;
std::string fullPath = _rootPath+ConvertToRegFormat(key, keyName); std::string fullPath = _rootPath+ConvertToRegFormat(key, keyName);
WinRegistryKey aKey(fullPath, true); WinRegistryKey aKey(fullPath, true, _extraSam);
aKey.values(range); aKey.values(range);
aKey.subKeys(range); aKey.subKeys(range);
} }
} }
@@ -142,3 +145,6 @@ std::string WinRegistryConfiguration::ConvertToRegFormat(const std::string& key,
} } // namespace Poco::Util } } // namespace Poco::Util
#endif // !defined(_WIN32_WCE)

View File

@@ -1,7 +1,7 @@
// //
// WinRegistryKey.cpp // WinRegistryKey.cpp
// //
// $Id: //poco/Main/Util/src/WinRegistryKey.cpp#14 $ // $Id: //poco/1.4/Util/src/WinRegistryKey.cpp#3 $
// //
// Library: Util // Library: Util
// Package: Windows // Package: Windows
@@ -34,6 +34,9 @@
// //
#if !defined(_WIN32_WCE)
#include "Poco/Util/WinRegistryKey.h" #include "Poco/Util/WinRegistryKey.h"
#include "Poco/Exception.h" #include "Poco/Exception.h"
#if defined(POCO_WIN32_UTF8) #if defined(POCO_WIN32_UTF8)
@@ -531,3 +534,6 @@ void WinRegistryKey::values(WinRegistryKey::Values& vals)
} } // namespace Poco::Util } } // namespace Poco::Util
#endif // !defined(_WIN32_WCE)

View File

@@ -1,7 +1,7 @@
// //
// WinService.cpp // WinService.cpp
// //
// $Id: //poco/Main/Util/src/WinService.cpp#10 $ // $Id: //poco/1.4/Util/src/WinService.cpp#4 $
// //
// Library: Util // Library: Util
// Package: Windows // Package: Windows
@@ -34,6 +34,9 @@
// //
#if !defined(_WIN32_WCE)
#include "Poco/Util/WinService.h" #include "Poco/Util/WinService.h"
#include "Poco/Util/WinRegistryKey.h" #include "Poco/Util/WinRegistryKey.h"
#include "Poco/Thread.h" #include "Poco/Thread.h"
@@ -261,48 +264,52 @@ WinService::Startup WinService::getStartup() const
void WinService::setDescription(const std::string& description) void WinService::setDescription(const std::string& description)
{ {
std::string key(REGISTRY_KEY); std::string key(REGISTRY_KEY);
key += _name; key += _name;
WinRegistryKey regKey(HKEY_LOCAL_MACHINE, key); WinRegistryKey regKey(HKEY_LOCAL_MACHINE, key);
regKey.setString(REGISTRY_DESCRIPTION, description); regKey.setString(REGISTRY_DESCRIPTION, description);
} }
std::string WinService::getDescription() const std::string WinService::getDescription() const
{ {
std::string key(REGISTRY_KEY); std::string key(REGISTRY_KEY);
key += _name; key += _name;
WinRegistryKey regKey(HKEY_LOCAL_MACHINE, key, true); WinRegistryKey regKey(HKEY_LOCAL_MACHINE, key, true);
return regKey.getString(REGISTRY_DESCRIPTION); return regKey.getString(REGISTRY_DESCRIPTION);
} }
void WinService::open() const void WinService::open() const
{ {
if (!tryOpen()) if (!tryOpen())
throw NotFoundException("service does not exist", _name); throw NotFoundException("service does not exist", _name);
} }
bool WinService::tryOpen() const bool WinService::tryOpen() const
{ {
if (!_svcHandle)
{
#if defined(POCO_WIN32_UTF8) #if defined(POCO_WIN32_UTF8)
std::wstring uname; std::wstring uname;
Poco::UnicodeConverter::toUTF16(_name, uname); Poco::UnicodeConverter::toUTF16(_name, uname);
_svcHandle = OpenServiceW(_scmHandle, uname.c_str(), SERVICE_ALL_ACCESS); _svcHandle = OpenServiceW(_scmHandle, uname.c_str(), SERVICE_ALL_ACCESS);
#else #else
_svcHandle = OpenService(_scmHandle, _name.c_str(), SERVICE_ALL_ACCESS); _svcHandle = OpenService(_scmHandle, _name.c_str(), SERVICE_ALL_ACCESS);
#endif #endif
return _svcHandle != 0; }
return _svcHandle != 0;
} }
void WinService::close() const void WinService::close() const
{ {
if (_svcHandle) if (_svcHandle)
{ {
CloseServiceHandle(_svcHandle); CloseServiceHandle(_svcHandle);
} _svcHandle = 0;
}
} }
@@ -340,3 +347,6 @@ POCO_LPQUERY_SERVICE_CONFIG WinService::config() const
} } // namespace Poco::Util } } // namespace Poco::Util
#endif // !defined(_WIN32_WCE)

View File

@@ -6122,12 +6122,13 @@ poolGrow(STRING_POOL *pool)
} }
if (pool->blocks && pool->start == pool->blocks->s) { if (pool->blocks && pool->start == pool->blocks->s) {
int blockSize = (int)(pool->end - pool->start)*2; int blockSize = (int)(pool->end - pool->start)*2;
pool->blocks = (BLOCK *) BLOCK *temp = (BLOCK *)
pool->mem->realloc_fcn(pool->blocks, pool->mem->realloc_fcn(pool->blocks,
(offsetof(BLOCK, s) (offsetof(BLOCK, s)
+ blockSize * sizeof(XML_Char))); + blockSize * sizeof(XML_Char)));
if (pool->blocks == NULL) if (temp == NULL)
return XML_FALSE; return XML_FALSE;
pool->blocks = temp;
pool->blocks->size = blockSize; pool->blocks->size = blockSize;
pool->ptr = pool->blocks->s + (pool->ptr - pool->start); pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
pool->start = pool->blocks->s; pool->start = pool->blocks->s;

View File

@@ -1,319 +1,318 @@
// //
// ZipStream.cpp // ZipStream.cpp
// //
// $Id: //poco/Main/Zip/src/ZipStream.cpp#14 $ // $Id: //poco/Main/Zip/src/ZipStream.cpp#14 $
// //
// Library: Zip // Library: Zip
// Package: Zip // Package: Zip
// Module: ZipStream // Module: ZipStream
// //
// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. // Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
// and Contributors. // and Contributors.
// //
// Permission is hereby granted, free of charge, to any person or organization // Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by // obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute, // this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the // execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to // Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following: // do so, all subject to the following:
// //
// The copyright notices in the Software and this entire statement, including // The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer, // the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and // must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative // all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by // works are solely in the form of machine-executable object code generated by
// a source language processor. // a source language processor.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
// //
#include "Poco/Zip/ZipStream.h" #include "Poco/Zip/ZipStream.h"
#include "Poco/zlib.h" #include "Poco/zlib.h"
#include "Poco/Zip/ZipArchive.h" #include "Poco/Zip/ZipArchive.h"
#include "Poco/Zip/AutoDetectStream.h" #include "Poco/Zip/AutoDetectStream.h"
#include "Poco/Zip/PartialStream.h" #include "Poco/Zip/PartialStream.h"
#include "Poco/Zip/ZipDataInfo.h" #include "Poco/Zip/ZipDataInfo.h"
#include "Poco/Zip/ZipException.h" #include "Poco/Zip/ZipException.h"
#include "Poco/Exception.h" #include "Poco/Exception.h"
#include "Poco/InflatingStream.h" #include "Poco/InflatingStream.h"
#include "Poco/DeflatingStream.h" #include "Poco/DeflatingStream.h"
namespace Poco { namespace Poco {
namespace Zip { namespace Zip {
ZipStreamBuf::ZipStreamBuf(std::istream& istr, const ZipLocalFileHeader& fileEntry, bool reposition): ZipStreamBuf::ZipStreamBuf(std::istream& istr, const ZipLocalFileHeader& fileEntry, bool reposition):
Poco::BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::in), Poco::BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::in),
_pIstr(&istr), _pIstr(&istr),
_pOstr(0), _pOstr(0),
_ptrBuf(), _ptrBuf(),
_ptrOBuf(), _ptrOBuf(),
_ptrHelper(), _ptrHelper(),
_ptrOHelper(), _ptrOHelper(),
_crc32(Poco::Checksum::TYPE_CRC32), _crc32(Poco::Checksum::TYPE_CRC32),
_expectedCrc32(0), _expectedCrc32(0),
_checkCRC(true), _checkCRC(true),
_bytesWritten(0), _bytesWritten(0),
_pHeader(0) _pHeader(0)
{ {
if (fileEntry.isDirectory()) if (fileEntry.isDirectory())
return; return;
_expectedCrc32 = fileEntry.getCRC(); _expectedCrc32 = fileEntry.getCRC();
std::streamoff start = fileEntry.getDataStartPos(); std::streamoff start = fileEntry.getDataStartPos();
std::streamoff end = fileEntry.getDataEndPos(); std::streamoff end = fileEntry.getDataEndPos();
_checkCRC = !fileEntry.searchCRCAndSizesAfterData(); _checkCRC = !fileEntry.searchCRCAndSizesAfterData();
if (fileEntry.getCompressionMethod() == ZipCommon::CM_DEFLATE) if (fileEntry.getCompressionMethod() == ZipCommon::CM_DEFLATE)
{ {
// Fake init bytes at beginning of stream // Fake init bytes at beginning of stream
std::string init = ZipUtil::fakeZLibInitString(fileEntry.getCompressionLevel()); std::string init = ZipUtil::fakeZLibInitString(fileEntry.getCompressionLevel());
// Fake adler at end of stream: just some dummy value, not checked anway // Fake adler at end of stream: just some dummy value, not checked anway
std::string crc(4, ' '); std::string crc(4, ' ');
if (fileEntry.searchCRCAndSizesAfterData()) if (fileEntry.searchCRCAndSizesAfterData())
{ {
_ptrHelper = new AutoDetectInputStream(istr, init, crc, reposition, start); _ptrHelper = new AutoDetectInputStream(istr, init, crc, reposition, start);
} }
else else
_ptrHelper = new PartialInputStream(istr, start, end, reposition, init, crc); {
_ptrBuf = new Poco::InflatingInputStream(*_ptrHelper, Poco::InflatingStreamBuf::STREAM_ZIP); _ptrHelper = new PartialInputStream(istr, start, end, reposition, init, crc);
} }
else if (fileEntry.getCompressionMethod() == ZipCommon::CM_STORE) _ptrBuf = new Poco::InflatingInputStream(*_ptrHelper, Poco::InflatingStreamBuf::STREAM_ZIP);
{ }
if (fileEntry.searchCRCAndSizesAfterData()) else if (fileEntry.getCompressionMethod() == ZipCommon::CM_STORE)
{ {
_ptrBuf = new AutoDetectInputStream(istr, "", "", reposition, start); if (fileEntry.searchCRCAndSizesAfterData())
} {
else _ptrBuf = new AutoDetectInputStream(istr, "", "", reposition, start);
_ptrBuf = new PartialInputStream(istr, start, end, reposition); }
} else
else {
{ _ptrBuf = new PartialInputStream(istr, start, end, reposition);
throw Poco::NotImplementedException("Unsupported compression method"); }
} }
} else throw Poco::NotImplementedException("Unsupported compression method");
}
ZipStreamBuf::ZipStreamBuf(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bool reposition):
Poco::BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::out), ZipStreamBuf::ZipStreamBuf(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bool reposition):
_pIstr(0), Poco::BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::out),
_pOstr(&ostr), _pIstr(0),
_ptrBuf(), _pOstr(&ostr),
_ptrOBuf(), _ptrBuf(),
_ptrHelper(), _ptrOBuf(),
_ptrOHelper(), _ptrHelper(),
_crc32(Poco::Checksum::TYPE_CRC32), _ptrOHelper(),
_expectedCrc32(0), _crc32(Poco::Checksum::TYPE_CRC32),
_checkCRC(false), _expectedCrc32(0),
_bytesWritten(0), _checkCRC(false),
_pHeader(&fileEntry) _bytesWritten(0),
{ _pHeader(&fileEntry)
if (fileEntry.isEncrypted()) {
throw Poco::NotImplementedException("Encryption not supported"); if (fileEntry.isEncrypted())
throw Poco::NotImplementedException("Encryption not supported");
if (fileEntry.isDirectory())
{ if (fileEntry.isDirectory())
// only header, no payload, zero crc {
fileEntry.setSearchCRCAndSizesAfterData(false); // only header, no payload, zero crc
fileEntry.setCompressedSize(0); fileEntry.setSearchCRCAndSizesAfterData(false);
fileEntry.setUncompressedSize(0); fileEntry.setCompressedSize(0);
fileEntry.setCRC(0); fileEntry.setUncompressedSize(0);
std::string header = fileEntry.createHeader(); fileEntry.setCRC(0);
ostr.write(header.c_str(), static_cast<std::streamsize>(header.size())); std::string header = fileEntry.createHeader();
} ostr.write(header.c_str(), static_cast<std::streamsize>(header.size()));
else }
{ else
fileEntry.setSearchCRCAndSizesAfterData(!reposition); {
if (fileEntry.getCompressionMethod() == ZipCommon::CM_DEFLATE) fileEntry.setSearchCRCAndSizesAfterData(!reposition);
{ if (fileEntry.getCompressionMethod() == ZipCommon::CM_DEFLATE)
int level = Z_DEFAULT_COMPRESSION; {
if (fileEntry.getCompressionLevel() == ZipCommon::CL_FAST || fileEntry.getCompressionLevel() == ZipCommon::CL_SUPERFAST) int level = Z_DEFAULT_COMPRESSION;
level = Z_BEST_SPEED; if (fileEntry.getCompressionLevel() == ZipCommon::CL_FAST || fileEntry.getCompressionLevel() == ZipCommon::CL_SUPERFAST)
else if (fileEntry.getCompressionLevel() == ZipCommon::CL_MAXIMUM) level = Z_BEST_SPEED;
level = Z_BEST_COMPRESSION; else if (fileEntry.getCompressionLevel() == ZipCommon::CL_MAXIMUM)
// ignore the zlib init string which is of size 2 and also ignore the 4 byte adler32 value at the end of the stream! level = Z_BEST_COMPRESSION;
_ptrOHelper = new PartialOutputStream(*_pOstr, 2, 4, false); // ignore the zlib init string which is of size 2 and also ignore the 4 byte adler32 value at the end of the stream!
_ptrOBuf = new Poco::DeflatingOutputStream(*_ptrOHelper, DeflatingStreamBuf::STREAM_ZLIB, level); _ptrOHelper = new PartialOutputStream(*_pOstr, 2, 4, false);
} _ptrOBuf = new Poco::DeflatingOutputStream(*_ptrOHelper, DeflatingStreamBuf::STREAM_ZLIB, level);
else if (fileEntry.getCompressionMethod() == ZipCommon::CM_STORE) }
{ else if (fileEntry.getCompressionMethod() == ZipCommon::CM_STORE)
_ptrOHelper = new PartialOutputStream(*_pOstr, 0, 0, false); {
_ptrOBuf = _ptrOHelper; _ptrOHelper = new PartialOutputStream(*_pOstr, 0, 0, false);
} _ptrOBuf = new PartialOutputStream(*_ptrOHelper, 0, 0, false);
else }
{ else throw Poco::NotImplementedException("Unsupported compression method");
throw Poco::NotImplementedException("Unsupported compression method");
} // now write the header to the ostr!
// now write the header to the ostr! std::string header = fileEntry.createHeader();
std::string header = fileEntry.createHeader(); ostr.write(header.c_str(), static_cast<std::streamsize>(header.size()));
ostr.write(header.c_str(), static_cast<std::streamsize>(header.size())); }
} }
}
ZipStreamBuf::~ZipStreamBuf()
ZipStreamBuf::~ZipStreamBuf() {
{ }
}
int ZipStreamBuf::readFromDevice(char* buffer, std::streamsize length)
int ZipStreamBuf::readFromDevice(char* buffer, std::streamsize length) {
{ if (!_ptrBuf) return 0; // directory entry
if (!_ptrBuf) return 0; // directory entry _ptrBuf->read(buffer, length);
_ptrBuf->read(buffer, length); int cnt = _ptrBuf->gcount();
int cnt = _ptrBuf->gcount(); if (cnt > 0)
if (cnt > 0) {
{ _crc32.update(buffer, cnt);
_crc32.update(buffer, cnt); }
} else
else {
{ if (_crc32.checksum() != _expectedCrc32)
if (_crc32.checksum() != _expectedCrc32) {
{ if (_checkCRC)
if (_checkCRC) throw ZipException("CRC failure");
throw ZipException("CRC failure"); else
else {
{ // the CRC value is written directly after the data block
// the CRC value is written directly after the data block // parse it directly from the input stream
// parse it directly from the input stream ZipDataInfo nfo(*_pIstr, false);
ZipDataInfo nfo(*_pIstr, false); // now push back the header to the stream, so that the ZipLocalFileHeader can read it
// now push back the header to the stream, so that the ZipLocalFileHeader can read it Poco::Int32 size = static_cast<Poco::Int32>(nfo.getFullHeaderSize());
Poco::Int32 size = static_cast<Poco::Int32>(nfo.getFullHeaderSize()); _expectedCrc32 = nfo.getCRC32();
_expectedCrc32 = nfo.getCRC32(); const char* rawHeader = nfo.getRawHeader();
const char* rawHeader = nfo.getRawHeader(); for (Poco::Int32 i = size-1; i >= 0; --i)
for (Poco::Int32 i = size-1; i >= 0; --i) _pIstr->putback(rawHeader[i]);
_pIstr->putback(rawHeader[i]); if (!crcValid())
if (!crcValid()) throw ZipException("CRC failure");
throw ZipException("CRC failure"); }
} }
} }
} return cnt;
return cnt; }
}
int ZipStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
int ZipStreamBuf::writeToDevice(const char* buffer, std::streamsize length) {
{ if (!_ptrOBuf) return 0; // directory entry
if (!_ptrOBuf) return 0; // directory entry if (length == 0)
if (length == 0) return 0;
return 0; _bytesWritten += length;
_bytesWritten += length; _ptrOBuf->write(buffer, length);
_ptrOBuf->write(buffer, length); _crc32.update(buffer, length);
_crc32.update(buffer, length); return length;
return length; }
}
void ZipStreamBuf::close()
void ZipStreamBuf::close() {
{ if (_ptrOBuf && _pHeader)
if (_ptrOBuf && _pHeader) {
{ _ptrOBuf->flush();
_ptrOBuf->flush(); DeflatingOutputStream* pDO = dynamic_cast<DeflatingOutputStream*>(_ptrOBuf.get());
DeflatingOutputStream* pDO = dynamic_cast<DeflatingOutputStream*>(_ptrOBuf.get()); if (pDO)
if (pDO) pDO->close();
pDO->close(); if (_ptrOHelper)
if (_ptrOHelper) {
{ _ptrOHelper->flush();
_ptrOHelper->flush(); _ptrOHelper->close();
_ptrOHelper->close(); }
} _ptrOBuf = 0;
_ptrOBuf = 0; poco_assert (*_pOstr);
poco_assert (*_pOstr); // write an extra datablock if required
// write an extra datablock if required // or fix the crc entries
// or fix the crc entries if (_pHeader->searchCRCAndSizesAfterData())
if (_pHeader->searchCRCAndSizesAfterData()) {
{ ZipDataInfo info;
ZipDataInfo info; info.setCRC32(_crc32.checksum());
info.setCRC32(_crc32.checksum()); info.setUncompressedSize(_bytesWritten);
info.setUncompressedSize(_bytesWritten); info.setCompressedSize(static_cast<Poco::UInt32>(_ptrOHelper->bytesWritten()));
info.setCompressedSize(static_cast<Poco::UInt32>(_ptrOHelper->bytesWritten())); _pOstr->write(info.getRawHeader(), static_cast<std::streamsize>(info.getFullHeaderSize()));
_pOstr->write(info.getRawHeader(), static_cast<std::streamsize>(info.getFullHeaderSize())); }
} else
else {
{ poco_check_ptr (_pHeader);
poco_check_ptr (_pHeader); _pHeader->setCRC(_crc32.checksum());
_pHeader->setCRC(_crc32.checksum()); _pHeader->setUncompressedSize(_bytesWritten);
_pHeader->setUncompressedSize(_bytesWritten); _pHeader->setCompressedSize(static_cast<Poco::UInt32>(_ptrOHelper->bytesWritten()));
_pHeader->setCompressedSize(static_cast<Poco::UInt32>(_ptrOHelper->bytesWritten())); _pOstr->seekp(_pHeader->getStartPos(), std::ios_base::beg);
_pOstr->seekp(_pHeader->getStartPos(), std::ios_base::beg); poco_assert (*_pOstr);
poco_assert (*_pOstr); std::string header = _pHeader->createHeader();
std::string header = _pHeader->createHeader(); _pOstr->write(header.c_str(), static_cast<std::streamsize>(header.size()));
_pOstr->write(header.c_str(), static_cast<std::streamsize>(header.size())); _pOstr->seekp(0, std::ios_base::end);
_pOstr->seekp(0, std::ios_base::end); poco_assert (*_pOstr);
poco_assert (*_pOstr); }
} _pHeader = 0;
_pHeader = 0; }
} }
}
bool ZipStreamBuf::crcValid() const
bool ZipStreamBuf::crcValid() const {
{ if (!_ptrBuf) return true; // directory entry
if (!_ptrBuf) return true; // directory entry return _crc32.checksum() == _expectedCrc32;
return _crc32.checksum() == _expectedCrc32; }
}
ZipIOS::ZipIOS(std::istream& istr, const ZipLocalFileHeader& fileEntry, bool reposition): _buf(istr, fileEntry, reposition)
ZipIOS::ZipIOS(std::istream& istr, const ZipLocalFileHeader& fileEntry, bool reposition): _buf(istr, fileEntry, reposition) {
{ poco_ios_init(&_buf);
poco_ios_init(&_buf); }
}
ZipIOS::ZipIOS(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bool reposition): _buf(ostr, fileEntry, reposition)
ZipIOS::ZipIOS(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bool reposition): _buf(ostr, fileEntry, reposition) {
{ poco_ios_init(&_buf);
poco_ios_init(&_buf); }
}
ZipIOS::~ZipIOS()
ZipIOS::~ZipIOS() {
{ }
}
ZipStreamBuf* ZipIOS::rdbuf()
ZipStreamBuf* ZipIOS::rdbuf() {
{ return &_buf;
return &_buf; }
}
ZipInputStream::ZipInputStream(std::istream& istr, const ZipLocalFileHeader& fileEntry, bool reposition): ZipIOS(istr, fileEntry, reposition), std::istream(&_buf)
ZipInputStream::ZipInputStream(std::istream& istr, const ZipLocalFileHeader& fileEntry, bool reposition): ZipIOS(istr, fileEntry, reposition), std::istream(&_buf) {
{ }
}
ZipInputStream::~ZipInputStream()
ZipInputStream::~ZipInputStream() {
{ }
}
bool ZipInputStream::crcValid() const
bool ZipInputStream::crcValid() const {
{ return _buf.crcValid();
return _buf.crcValid(); }
}
ZipOutputStream::ZipOutputStream(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bool seekableOutput): ZipIOS(ostr, fileEntry, seekableOutput), std::ostream(&_buf)
ZipOutputStream::ZipOutputStream(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bool seekableOutput): ZipIOS(ostr, fileEntry, seekableOutput), std::ostream(&_buf) {
{ }
}
ZipOutputStream::~ZipOutputStream()
ZipOutputStream::~ZipOutputStream() {
{ }
}
void ZipOutputStream::close()
void ZipOutputStream::close() {
{ flush();
flush(); _buf.close();
_buf.close(); }
}
} } // namespace Poco::Zip
} } // namespace Poco::Zip