%PDF- %PDF-
Direktori : /data/old/usr/local/include/znc/ |
Current File : //data/old/usr/local/include/znc/Utils.h |
/* * Copyright (C) 2004-2018 ZNC, see the NOTICE file for details. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ZNC_UTILS_H #define ZNC_UTILS_H #include <znc/zncconfig.h> #include <znc/ZNCString.h> #include <assert.h> #include <cstdio> #include <fcntl.h> #include <map> #include <sys/file.h> #include <sys/time.h> #include <unistd.h> #include <vector> static inline void SetFdCloseOnExec(int fd) { int flags = fcntl(fd, F_GETFD, 0); if (flags < 0) return; // Ignore errors // When we execve() a new process this fd is now automatically closed. fcntl(fd, F_SETFD, flags | FD_CLOEXEC); } static const char g_HexDigits[] = "0123456789abcdef"; class CUtils { public: CUtils(); ~CUtils(); static CString GetIP(unsigned long addr); static unsigned long GetLongIP(const CString& sIP); static void PrintError(const CString& sMessage); static void PrintMessage(const CString& sMessage, bool bStrong = false); static void PrintPrompt(const CString& sMessage); static void PrintAction(const CString& sMessage); static void PrintStatus(bool bSuccess, const CString& sMessage = ""); #ifndef SWIGPERL // TODO refactor this static const CString sDefaultHash; #endif static CString GetSaltedHashPass(CString& sSalt); static CString GetSalt(); static CString SaltedMD5Hash(const CString& sPass, const CString& sSalt); static CString SaltedSHA256Hash(const CString& sPass, const CString& sSalt); static CString GetPass(const CString& sPrompt); static bool GetInput(const CString& sPrompt, CString& sRet, const CString& sDefault = "", const CString& sHint = ""); static bool GetBoolInput(const CString& sPrompt, bool bDefault); static bool GetBoolInput(const CString& sPrompt, bool* pbDefault = nullptr); static bool GetNumInput(const CString& sPrompt, unsigned int& uRet, unsigned int uMin = 0, unsigned int uMax = ~0, unsigned int uDefault = ~0); static timeval GetTime(); static unsigned long long GetMillTime(); #ifdef HAVE_LIBSSL static void GenerateCert(FILE* pOut, const CString& sHost = ""); #endif /* HAVE_LIBSSL */ static CString CTime(time_t t, const CString& sTZ); static CString FormatTime(time_t t, const CString& sFormat, const CString& sTZ); /** Supports an additional format specifier for formatting sub-second values: * * - %f - sub-second fraction * - %3f - millisecond (default, if no width is specified) * - %6f - microsecond * * However, note that timeval only supports microsecond precision * (thus, formatting with higher-than-microsecond precision will * always result in trailing zeroes), and IRC server-time is specified * in millisecond precision (thus formatting received timestamps with * higher-than-millisecond precision will always result in trailing * zeroes). */ static CString FormatTime(const timeval& tv, const CString& sFormat, const CString& sTZ); static CString FormatServerTime(const timeval& tv); static timeval ParseServerTime(const CString& sTime); static SCString GetTimezones(); static SCString GetEncodings(); /** CIDR notation checker, e.g. "192.0.2.0/24" or "2001:db8::/32" * * For historical reasons also allows wildcards, e.g. "192.168.*" */ static bool CheckCIDR(const CString& sIP, const CString& sRange); /// @deprecated Use CMessage instead static MCString GetMessageTags(const CString& sLine); /// @deprecated Use CMessage instead static void SetMessageTags(CString& sLine, const MCString& mssTags); private: protected: }; class CException { public: typedef enum { EX_Shutdown, EX_Restart } EType; CException(EType e) : m_eType(e) {} virtual ~CException() {} EType GetType() const { return m_eType; } private: protected: EType m_eType; }; /** Generate a grid-like output from a given input. * * @code * CTable table; * table.AddColumn("a"); * table.AddColumn("b"); * table.AddRow(); * table.SetCell("a", "hello"); * table.SetCell("b", "world"); * * unsigned int idx = 0; * CString tmp; * while (table.GetLine(idx++, tmp)) { * // Output tmp somehow * } * @endcode * * The above code would generate the following output: * @verbatim +-------+-------+ | a | b | +-------+-------+ | hello | world | +-------+-------+@endverbatim */ class CTable : protected std::vector<std::vector<CString>> { public: CTable() {} virtual ~CTable() {} /** Adds a new column to the table. * Please note that you should add all columns before starting to fill * the table! * @param sName The name of the column. * @return false if a column by that name already existed. */ bool AddColumn(const CString& sName); /** Adds a new row to the table. * After calling this you can fill the row with content. * @return The index of this row */ size_type AddRow(); /** Sets a given cell in the table to a value. * @param sColumn The name of the column you want to fill. * @param sValue The value to write into that column. * @param uRowIdx The index of the row to use as returned by AddRow(). * If this is not given, the last row will be used. * @return True if setting the cell was successful. */ bool SetCell(const CString& sColumn, const CString& sValue, size_type uRowIdx = ~0); /** Get a line of the table's output * @param uIdx The index of the line you want. * @param sLine This string will receive the output. * @return True unless uIdx is past the end of the table. */ bool GetLine(unsigned int uIdx, CString& sLine) const; /** Return the width of the given column. * Please note that adding and filling new rows might change the * result of this function! * @param uIdx The index of the column you are interested in. * @return The width of the column. */ CString::size_type GetColumnWidth(unsigned int uIdx) const; /// Completely clear the table. void Clear(); /// @return The number of rows in this table, not counting the header. using std::vector<std::vector<CString>>::size; /// @return True if this table doesn't contain any rows. using std::vector<std::vector<CString>>::empty; private: unsigned int GetColumnIndex(const CString& sName) const; protected: std::vector<CString> m_vsHeaders; // Used to cache the width of a column std::map<CString, CString::size_type> m_msuWidths; }; #ifdef HAVE_LIBSSL #include <openssl/aes.h> #include <openssl/blowfish.h> #include <openssl/md5.h> //! does Blowfish w/64 bit feedback, no padding class CBlowfish { public: /** * @param sPassword key to encrypt with * @param iEncrypt encrypt method (BF_DECRYPT or BF_ENCRYPT) * @param sIvec what to set the ivector to start with, default sets it all 0's */ CBlowfish(const CString& sPassword, int iEncrypt, const CString& sIvec = ""); ~CBlowfish(); CBlowfish(const CBlowfish&) = default; CBlowfish& operator=(const CBlowfish&) = default; //! output must be freed static unsigned char* MD5(const unsigned char* input, unsigned int ilen); //! returns an md5 of the CString (not hex encoded) static CString MD5(const CString& sInput, bool bHexEncode = false); //! output must be the same size as input void Crypt(unsigned char* input, unsigned char* output, unsigned int ibytes); //! must free result unsigned char* Crypt(unsigned char* input, unsigned int ibytes); CString Crypt(const CString& sData); private: unsigned char* m_ivec; BF_KEY m_bkey; int m_iEncrypt, m_num; }; #endif /* HAVE_LIBSSL */ /** * @class TCacheMap * @author prozac <prozac@rottenboy.com> * @brief Insert an object with a time-to-live and check later if it still exists */ template <typename K, typename V = bool> class TCacheMap { public: TCacheMap(unsigned int uTTL = 5000) : m_mItems(), m_uTTL(uTTL) {} virtual ~TCacheMap() {} /** * @brief This function adds an item to the cache using the default time-to-live value * @param Item the item to add to the cache */ void AddItem(const K& Item) { AddItem(Item, m_uTTL); } /** * @brief This function adds an item to the cache using a custom time-to-live value * @param Item the item to add to the cache * @param uTTL the time-to-live for this specific item */ void AddItem(const K& Item, unsigned int uTTL) { AddItem(Item, V(), uTTL); } /** * @brief This function adds an item to the cache using the default time-to-live value * @param Item the item to add to the cache * @param Val The value associated with the key Item */ void AddItem(const K& Item, const V& Val) { AddItem(Item, Val, m_uTTL); } /** * @brief This function adds an item to the cache using a custom time-to-live value * @param Item the item to add to the cache * @param Val The value associated with the key Item * @param uTTL the time-to-live for this specific item */ void AddItem(const K& Item, const V& Val, unsigned int uTTL) { if (!uTTL) { // If time-to-live is zero we don't want to waste our time adding // it RemItem(Item); // Remove the item incase it already exists return; } m_mItems[Item] = value(CUtils::GetMillTime() + uTTL, Val); } /** * @brief Performs a Cleanup() and then checks to see if your item exists * @param Item The item to check for * @return true if item exists */ bool HasItem(const K& Item) { Cleanup(); return (m_mItems.find(Item) != m_mItems.end()); } /** * @brief Performs a Cleanup() and returns a pointer to the object, or nullptr * @param Item The item to check for * @return Pointer to the item or nullptr if there is no suitable one */ V* GetItem(const K& Item) { Cleanup(); iterator it = m_mItems.find(Item); if (it == m_mItems.end()) return nullptr; return &it->second.second; } /** * @brief Removes a specific item from the cache * @param Item The item to be removed * @return true if item existed and was removed, false if it never existed */ bool RemItem(const K& Item) { return (m_mItems.erase(Item) != 0); } /** * @brief Cycles through the queue removing all of the stale entries */ void Cleanup() { iterator it = m_mItems.begin(); while (it != m_mItems.end()) { if (CUtils::GetMillTime() > (it->second.first)) { m_mItems.erase(it++); } else { ++it; } } } /** * @brief Clear all entries */ void Clear() { m_mItems.clear(); } /** * @brief Returns all entries */ std::map<K, V> GetItems() { Cleanup(); std::map<K, V> mItems; for (const auto& it : m_mItems) { mItems[it.first] = it.second.second; } return mItems; } // Setters void SetTTL(unsigned int u) { m_uTTL = u; } // !Setters // Getters unsigned int GetTTL() const { return m_uTTL; } // !Getters protected: typedef std::pair<unsigned long long, V> value; typedef typename std::map<K, value>::iterator iterator; std::map<K, value> m_mItems; //!< Map of cached items. The value portion of the map is for the expire time unsigned int m_uTTL; //!< Default time-to-live duration }; #endif // !ZNC_UTILS_H