📄 warpath.h
字号:
/** */#ifndef WAR_PATH_H#define WAR_PATH_H/* SYSTEM INCLUDES */#ifndef WAR_IOSTREAM_INCLUDED# define WAR_IOSTREAM_INCLUDED# include <iostream>#endif#ifndef WAR_ASSERT_H_INCLUDED# define WAR_ASSERT_H_INCLUDED# include <assert.h>#endif/* PROJECT INCLUDES */#ifndef WAR_COLLECTOR_H# include "WarCollector.h"#endif#ifndef WAR_EXCEPTION_H# include "WarException.h"#endif#ifndef WAR_FILE_ENUMS_H# include "WarFileEnums.h"#endif/* LOCAL INCLUDES *//* FORWARD REFERENCES */#ifdef __cplusplusextern "C" {#endif/****************** BEGIN OLD STYLE C spesific ********//****************** END OLD STYLE C spesific **********/#ifdef __cplusplus }#endif/****************** BEGIN C++ spesific ****************/#ifdef __cplusplusenum WarPathE{ WAR_SYSSLASH, /// SLASH OR BACKSLASH WAR_DSYSSLASH, /// DOUBLE SLASH OR BACKSLASH WAR_SLASH, /// '/' WAR_DSLASH, /// '//' WAR_CDIR /// './'};class WarSlash{public: enum SlashE { SYS_SLASH = '/' };};class WarSysSlash : public WarSlash{public: enum SlashE {#ifdef WIN32 SYS_SLASH = '\\'#else SYS_SLASH = '/'#endif }; static bool IsSlash(const char ch) { if (SYS_SLASH != '/') { if (SYS_SLASH == ch) return true; } return '/' == ch; } static bool IsSlash(const wchar_t ch) { if (SYS_SLASH != '/') { if (SYS_SLASH == ch) return true; } return '/' == ch; }};template <class charT, class slashT = WarSysSlash>class WarPath : public WarCollector<charT>, public WarFileEnums{public: typedef std::basic_string<charT> path_string_t; typedef charT const * path_ccstring_t; typedef charT path_char_t; typedef slashT sys_slash_t; typedef WarPath<charT, slashT> path_t; WarPath<charT, slashT>() {} template <class fcT, class fsT> WarPath<charT, slashT>(const WarPath<fcT, fsT>& from) { *this << (WarCollector<fcT>)from; } template <class fcT> WarPath<charT, slashT>(const WarCollector<fcT>& from) { *this << (WarCollector<fcT>)from; } template <class fcT> WarPath<charT, slashT>(const std::basic_string<fcT>& from) { *this << from; } WarPath<charT, slashT>(war_ccstr_t from) { *this << from; } WarPath<charT, slashT>(war_cwstr_t from) { *this << from; } // LIFECYCLE // OPERATORS path_char_t operator [] (int offset) const { return mString[offset]; } template <class T> WarPath<charT, slashT>& operator = (const T& from) { mString.erase(); *this << from; return *this; } bool operator == (const WarPath<charT, slashT>& from) { return mString == from.mString; } // OPERATIONS bool CutAtLastCh (path_char_t ch) { path_string_t::size_type len = mString.find_last_of(ch); if (len != mString.npos) mString.resize(len); return 0 < len; } bool CutAtFirstCh(path_char_t ch) { path_string_t::size_type len = mString.find_first_of(ch); if (len != mString.npos) mString.resize (len); return 0 < len; } void ClipAfterLevel(size_t level) throw(WarException) { path_ccstring_t p = mString.c_str(), p_start = p; int i; for(i = 0; i < level; i++) { while(*p && ('\\' != *p)) ++p; if ('\\' == *p) ++p; } if (i != level) WarThrow(WarError(WAR_ERR_OUT_OF_RANGE), NULL); mString.resize(p - p_start); } /// Prepere for use. Set slashes the right way etc. void Normalize() { if (sys_slash_t::SYS_SLASH != '/') { for(path_string_t::iterator P = mString.begin() ; P != mString.end() ; P++) { if (*P == '/') *P = (path_char_t)sys_slash_t::SYS_SLASH; } } } /// Convert any backslashes to posix slashes (/) void MakePosixPath() { for(path_string_t::iterator P = mString.begin() ; P != mString.end() ; P++) { if (*P == '\\') *P = '/'; } } void RemovePaddingSlash() { while(IsSlash(GetLastCh())) mString.erase(mString.length() -1); } void RemovePaddingCdir() { for(size_t len = mString.size() ; (len > 2) && (mString[len -1] == '/') && (mString[len -2] == '.') && ((len == 2) || (mString[len -3] == '/')) ; len = mString.size()) { mString.erase(mString.length() -2); } } /** Deparses a path by interperating and removing * "./" and "../" * Known exploits, like "..." under Win32 throws an * exception. So does paths that tries to CD up beoynd * the root. */ void Deparse() throw(WarException) { std::vector<path_char_t> buffer(mString.size() + 1); const path_char_t *p = mString.c_str(); path_char_t *pp = &buffer[0]; int cnt = 0; while (*p) { if (IsSlash(*p)) { // /C/.. /C/./any /C/any/. /C/any/../.any /C/any\.. if (p[1] == '.') { if (!p[2] || IsSlash(p[2])) { // /C/any/. style. Just ignore p += 2; continue; } if (p[2] == '.') { if (!p[3] || IsSlash(p[3])) { // /C/any/.. /C/any/../test style. Move back one if (cnt == 0) WarThrow(WarError(WAR_ERR_INVALID_PATH), NULL); while (--cnt && !IsSlash(pp[cnt])) { assert(cnt >= 0); } p += 3; continue; } else { const path_char_t *ppp = p; while(*ppp == '.') ++ppp; // Deny /......[/] if (!*ppp || IsSlash(*ppp) // We deny some common characters with special meanings as well! // /..*../ || (*ppp == '*') || (*ppp == '?') || (*ppp == '~')) { // Possible exploit WarThrow(WarError(WAR_ERR_INVALID_PATH), NULL); } } } } } // Default pp[cnt++] = *p++; } pp[cnt++] = 0; mString = &buffer[0]; } // ACCESS // INQUIRY /** Return the number of letters in the path */ size_t GetLength() const {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -