From 74cd43ec44fc5dc9e64ec768f3cbf2f028773086 Mon Sep 17 00:00:00 2001 From: Tyler Dauwalder Date: Tue, 6 Aug 2002 08:25:41 +0000 Subject: [PATCH] New mime sniffer support classes git-svn-id: file:///srv/svn/repos/haiku/trunk/current@601 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/storage/sniffer/Err.h | 43 ++++++ headers/private/storage/sniffer/Pattern.h | 49 +++++++ headers/private/storage/sniffer/PatternList.h | 40 ++++++ headers/private/storage/sniffer/RPattern.h | 38 +++++ .../private/storage/sniffer/RPatternList.h | 38 +++++ src/kits/storage/sniffer/Err.cpp | 94 +++++++++++++ src/kits/storage/sniffer/Pattern.cpp | 133 ++++++++++++++++++ src/kits/storage/sniffer/PatternList.cpp | 59 ++++++++ src/kits/storage/sniffer/RPattern.cpp | 60 ++++++++ src/kits/storage/sniffer/RPatternList.cpp | 58 ++++++++ 10 files changed, 612 insertions(+) create mode 100644 headers/private/storage/sniffer/Err.h create mode 100644 headers/private/storage/sniffer/Pattern.h create mode 100644 headers/private/storage/sniffer/PatternList.h create mode 100644 headers/private/storage/sniffer/RPattern.h create mode 100644 headers/private/storage/sniffer/RPatternList.h create mode 100644 src/kits/storage/sniffer/Err.cpp create mode 100644 src/kits/storage/sniffer/Pattern.cpp create mode 100644 src/kits/storage/sniffer/PatternList.cpp create mode 100644 src/kits/storage/sniffer/RPattern.cpp create mode 100644 src/kits/storage/sniffer/RPatternList.cpp diff --git a/headers/private/storage/sniffer/Err.h b/headers/private/storage/sniffer/Err.h new file mode 100644 index 0000000000..8dec660a48 --- /dev/null +++ b/headers/private/storage/sniffer/Err.h @@ -0,0 +1,43 @@ +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- +/*! + \file sniffer/Err.h + Mime Sniffer Error class declarations +*/ +#ifndef _sk_sniffer_err_h_ +#define _sk_sniffer_err_h_ + +#include +#include + +namespace Sniffer { + +//! Exception class used by the MIME Sniffer +class Err { +public: + Err(const char *msg, const ssize_t pos); + Err(const std::string &msg, const ssize_t pos); + Err(const Err &ref); + virtual ~Err(); + Err& operator=(const Err &ref); + + status_t SetTo(const char *msg, const ssize_t pos); + status_t SetTo(const std::string &msg, const ssize_t pos); + void Unset(); + + const char* Msg() const; + ssize_t Pos() const; + +private: + friend class Parser; // So it can update the pos of its out of mem object + void SetMsg(const char *msg); + void SetPos(ssize_t pos); + char *fMsg; + ssize_t fPos; +}; + +} + +#endif // _sk_sniffer_err_h_ \ No newline at end of file diff --git a/headers/private/storage/sniffer/Pattern.h b/headers/private/storage/sniffer/Pattern.h new file mode 100644 index 0000000000..31dde16cd3 --- /dev/null +++ b/headers/private/storage/sniffer/Pattern.h @@ -0,0 +1,49 @@ +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- +/*! + \file sniffer/Pattern.h + Mime Sniffer Pattern declarations +*/ +#ifndef _sk_sniffer_pattern_h_ +#define _sk_sniffer_pattern_h_ + +#include +#include +#include + +class BPositionIO; + +namespace Sniffer { + +class Err; + +//! Abstract class definining an interface for sniffing BPositionIO objects +class Pattern { +public: + Pattern(const char *string, const char *mask = NULL); + ~Pattern(); + + status_t InitCheck() const; + Err* GetErr() const; + + bool Sniff(Range range, BPositionIO *data) const; + + status_t SetTo(const char *string, const char *mask = NULL); +private: + bool Sniff(off_t start, off_t size, BPositionIO *data) const; + + void SetStatus(status_t status, const char *msg = NULL); + void SetErrorMessage(const char *msg); + + std::string fString; + std::string fMask; + + status_t fCStatus; + Err *fErrorMessage; +}; + +} + +#endif // _sk_sniffer_pattern_h_ \ No newline at end of file diff --git a/headers/private/storage/sniffer/PatternList.h b/headers/private/storage/sniffer/PatternList.h new file mode 100644 index 0000000000..cd7365f2c1 --- /dev/null +++ b/headers/private/storage/sniffer/PatternList.h @@ -0,0 +1,40 @@ +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- +/*! + \file sniffer/PatternList.h + MIME sniffer pattern list declarations +*/ +#ifndef _sk_sniffer_pattern_list_h_ +#define _sk_sniffer_pattern_list_h_ + +#include +#include +#include + +class BPositionIO; + +namespace Sniffer { + +class Err; +class Pattern; + +class PatternList : public Expr { +public: + PatternList(Range range); + virtual ~PatternList(); + + status_t InitCheck() const; + Err* GetErr() const; + + virtual bool Sniff(BPositionIO *data) const; + void Add(Pattern *pattern); +private: + std::vector fList; + Range fRange; +}; + +} + +#endif // _sk_sniffer_pattern_list_h_ \ No newline at end of file diff --git a/headers/private/storage/sniffer/RPattern.h b/headers/private/storage/sniffer/RPattern.h new file mode 100644 index 0000000000..f02cf4785d --- /dev/null +++ b/headers/private/storage/sniffer/RPattern.h @@ -0,0 +1,38 @@ +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- +/*! + \file sniffer/RPattern.h + Mime Sniffer RPattern declarations +*/ +#ifndef _sk_sniffer_r_pattern_h_ +#define _sk_sniffer_r_pattern_h_ + +#include + +class BPositionIO; + +namespace Sniffer { + +class Err; +class Pattern; + +//! Abstract class definining an interface for sniffing BFile objects +class RPattern { +public: + RPattern(Range range, Pattern *pattern); + ~RPattern(); + + status_t InitCheck() const; + Err* GetErr() const; + + bool Sniff(BPositionIO *data) const; +private: + Range fRange; + Pattern *fPattern; +}; + +} + +#endif // _sk_sniffer_r_pattern_h_ \ No newline at end of file diff --git a/headers/private/storage/sniffer/RPatternList.h b/headers/private/storage/sniffer/RPatternList.h new file mode 100644 index 0000000000..572daa1347 --- /dev/null +++ b/headers/private/storage/sniffer/RPatternList.h @@ -0,0 +1,38 @@ +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- +/*! + \file sniffer/RPatternList.h + MIME sniffer rpattern list declarations +*/ +#ifndef _sk_sniffer_r_pattern_list_h_ +#define _sk_sniffer_r_pattern_list_h_ + +#include +#include + +class BPositionIO; + +namespace Sniffer { + +class Err; +class RPattern; + +class RPatternList : public Expr { +public: + RPatternList(); + virtual ~RPatternList(); + + status_t InitCheck() const; + Err* GetErr() const; + + virtual bool Sniff(BPositionIO *data) const; + void Add(RPattern *rpattern); +private: + std::vector fList; +}; + +} + +#endif // _sk_sniffer_r_pattern_list_h_ \ No newline at end of file diff --git a/src/kits/storage/sniffer/Err.cpp b/src/kits/storage/sniffer/Err.cpp new file mode 100644 index 0000000000..5678bfbd9c --- /dev/null +++ b/src/kits/storage/sniffer/Err.cpp @@ -0,0 +1,94 @@ +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- +/*! + \file Err.cpp + MIME sniffer Error class implementation +*/ + +#include +#include + +using namespace Sniffer; + +//------------------------------------------------------------------------------ +// Err +//------------------------------------------------------------------------------ + +Err::Err(const char *msg, const ssize_t pos) + : fMsg(NULL) + , fPos(-1) +{ + SetTo(msg, pos); +} + +Err::Err(const std::string &msg, const ssize_t pos) + : fMsg(NULL) + , fPos(-1) +{ + SetTo(msg, pos); +} + +Err::Err(const Err &ref) + : fMsg(NULL) + , fPos(-1) +{ + *this = ref; +} + +Err::~Err() { + Unset(); +} + +Err& +Err::operator=(const Err &ref) { + SetTo(ref.Msg(), ref.Pos()); + return *this; +} + +status_t +Err::SetTo(const char *msg, const ssize_t pos) { + SetMsg(msg); + SetPos(pos); +} + +status_t +Err::SetTo(const std::string &msg, const ssize_t pos) { + SetTo(msg.c_str(), pos); +} + +void +Err::Unset() { + delete fMsg; + fMsg = NULL; + fPos = -1; +} + +const char* +Err::Msg() const { + return fMsg; +} + +ssize_t +Err::Pos() const { + return fPos; +} + +void +Err::SetMsg(const char *msg) { + if (fMsg) { + delete fMsg; + fMsg = NULL; + } + if (msg) { + fMsg = new(nothrow) char[strlen(msg)+1]; + if (fMsg) + strcpy(fMsg, msg); + } +} + +void +Err::SetPos(ssize_t pos) { + fPos = pos; +} diff --git a/src/kits/storage/sniffer/Pattern.cpp b/src/kits/storage/sniffer/Pattern.cpp new file mode 100644 index 0000000000..d475d5454d --- /dev/null +++ b/src/kits/storage/sniffer/Pattern.cpp @@ -0,0 +1,133 @@ +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- +/*! + \file Pattern.cpp + MIME sniffer pattern implementation +*/ + +#include +#include +#include +#include // for SEEK_* defines + +using namespace Sniffer; + +Pattern::Pattern(const char *string, const char *mask = NULL) + : fCStatus(B_NO_INIT) + , fErrorMessage(NULL) +{ + SetTo(string, mask); +} + +Pattern::~Pattern() { + delete fErrorMessage; +} + +status_t +Pattern::InitCheck() const { + return fCStatus; +} + +Err* +Pattern::GetErr() const { + if (fCStatus == B_OK) + return NULL; + else + return new(nothrow) Err(*fErrorMessage); +// return fErrorMessage ? NULL : new Err(*fErrorMessage); +// return new Err("HEY, FIX THIS CRAP!", -1); +} + +status_t +Pattern::SetTo(const char *string, const char *mask) { + if (string) { + fString = string; + if (fString.length() == 0) { + SetStatus(B_BAD_VALUE, "Sniffer pattern error: illegal empty pattern"); + } else { + if (mask) { + fMask = mask; + if (fString.length() != fMask.length()) { + SetStatus(B_BAD_VALUE, "Sniffer pattern error: pattern and mask lengths do not match"); + } else { + SetStatus(B_OK); + } + } else { + fMask = ""; + for (int i = 0; i < fString.length(); i++) + fMask += (char)0xFF; + SetStatus(B_OK); + } + } + } else { + SetStatus(B_BAD_VALUE, "Sniffer parser error: NULL string parameter passed to Pattern::SetTo()"); + } +} + +bool +Pattern::Sniff(Range range, BPositionIO *data) const { + // If our range contains negative values relative to the end of + // the file, convert them to positive values relative to the + // beginning of the file. + int32 start = range.Start(); + int32 end = range.End(); + off_t size = data->Seek(0, SEEK_END); + if (end >= size) + end = size-1; + for (int i = start; i <= end; i++) { + if (Sniff(i, size, data)) + return true; + } +} + +// Assumes the BPositionIO object is in the correct +// position from which to sniff +bool +Pattern::Sniff(off_t start, off_t size, BPositionIO *data) const { + off_t len = fString.length(); + char *buffer = new(nothrow) char[len+1]; + if (buffer) { + ssize_t bytesRead = data->ReadAt(start, buffer, len); + // /todo If there are fewer bytes left in the data stream + // from the given position than the length of our data + // string, should we just return false (which is what we're + // doing now), or should we compare as many bytes as we + // can and return true if those match? + if (bytesRead < len) + return false; + else { + bool result = true; + for (int i = 0; i < len; i++) { + if ((fString[i] & fMask[i]) != (buffer[i] & fMask[i])) { + result = false; + break; + } + } + return result; + } + } else + return false; +} + +void +Pattern::SetStatus(status_t status, const char *msg) { + fCStatus = status; + if (status == B_OK) + SetErrorMessage(NULL); + else { + if (msg) + SetErrorMessage(msg); + else { + SetErrorMessage("Sniffer parser error: Pattern::SetStatus() -- NULL msg with non-B_OK status.\n" + "(This is officially the most helpful error message you will ever receive ;-)"); + } + } +} + +void +Pattern::SetErrorMessage(const char *msg) { + delete fErrorMessage; + fErrorMessage = (msg) ? (new(nothrow) Err(msg, -1)) : (NULL); +} diff --git a/src/kits/storage/sniffer/PatternList.cpp b/src/kits/storage/sniffer/PatternList.cpp new file mode 100644 index 0000000000..0df8ce9d65 --- /dev/null +++ b/src/kits/storage/sniffer/PatternList.cpp @@ -0,0 +1,59 @@ +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- +/*! + \file PatternList.cpp + MIME sniffer pattern list implementation +*/ + +#include +#include +#include +#include +#include + +using namespace Sniffer; + +PatternList::PatternList(Range range) + : fRange(range) +{ +} + +PatternList::~PatternList() { + // Clean up + std::vector::iterator i; + for (i = fList.begin(); i != fList.end(); i++) + delete *i; +} + +status_t +PatternList::InitCheck() const { + return fRange.InitCheck(); +} + +Err* +PatternList::GetErr() const { + return fRange.GetErr(); +} + +bool +PatternList::Sniff(BPositionIO *data) const { + if (InitCheck() != B_OK) + return false; + else { + bool result = false; + std::vector::const_iterator i; + for (i = fList.begin(); i != fList.end(); i++) { + if (*i) + result |= (*i)->Sniff(fRange, data); + } + return result; + } +} + +void +PatternList::Add(Pattern *pattern) { + if (pattern) + fList.push_back(pattern); +} diff --git a/src/kits/storage/sniffer/RPattern.cpp b/src/kits/storage/sniffer/RPattern.cpp new file mode 100644 index 0000000000..00a409ce7d --- /dev/null +++ b/src/kits/storage/sniffer/RPattern.cpp @@ -0,0 +1,60 @@ +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- +/*! + \file RPattern.cpp + MIME sniffer rpattern implementation +*/ + +#include +#include +#include +#include +#include + +using namespace Sniffer; + +RPattern::RPattern(Range range, Pattern *pattern) + : fRange(range) + , fPattern(pattern) +{ +} + +status_t +RPattern::InitCheck() const { + if (fRange.InitCheck() != B_OK) + return fRange.InitCheck(); + else if (fPattern) { + if (fPattern->InitCheck() != B_OK) + return fPattern->InitCheck(); + else + return B_OK; + } else + return B_BAD_VALUE; +} + +Err* +RPattern::GetErr() const { + if (fRange.InitCheck() != B_OK) + return fRange.GetErr(); + else if (fPattern) { + if (fPattern->InitCheck() != B_OK) + return fPattern->GetErr(); + else + return NULL; + } else + return new Err("Sniffer parser error: RPattern::RPattern() -- NULL pattern parameter", -1); +} + +RPattern::~RPattern() { + delete fPattern; +} + +bool +RPattern::Sniff(BPositionIO *data) const { + if (!data || InitCheck() != B_OK) + return false; + else + return fPattern->Sniff(fRange, data); +} diff --git a/src/kits/storage/sniffer/RPatternList.cpp b/src/kits/storage/sniffer/RPatternList.cpp new file mode 100644 index 0000000000..5803b27002 --- /dev/null +++ b/src/kits/storage/sniffer/RPatternList.cpp @@ -0,0 +1,58 @@ +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- +/*! + \file RPatternList.cpp + MIME sniffer rpattern list implementation +*/ + +#include +#include +#include +#include +#include + +using namespace Sniffer; + +RPatternList::RPatternList() +{ +} + +RPatternList::~RPatternList() { + // Clear our rpattern list + std::vector::iterator i; + for (i = fList.begin(); i != fList.end(); i++) + delete *i; +} + +status_t +RPatternList::InitCheck() const { + return B_OK; +} + +Err* +RPatternList::GetErr() const { + return NULL; +} + +bool +RPatternList::Sniff(BPositionIO *data) const { + if (InitCheck() != B_OK) + return false; + else { + bool result = false; + std::vector::const_iterator i; + for (i = fList.begin(); i != fList.end(); i++) { + if (*i) + result |= (*i)->Sniff(data); + } + return result; + } +} + +void +RPatternList::Add(RPattern *rpattern) { + if (rpattern) + fList.push_back(rpattern); +}