diff --git a/.vscode/settings.json b/.vscode/settings.json index b602fd6..883eafe 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -57,6 +57,7 @@ "typeindex": "cpp", "typeinfo": "cpp", "valarray": "cpp", - "string": "cpp" + "string": "cpp", + "future": "cpp" } } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index b8bceb1..84edd5a 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,8 +2,11 @@ if(" ${CMAKE_SOURCE_DIR}" STREQUAL " ${CMAKE_BINARY_DIR}") message(FATAL_ERROR "Please create a separate directory for build files.") endif() + cmake_minimum_required(VERSION 3.6) +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + project(ISNS C CXX) set(CMAKE_VERBOSE_MAKEFILE OFF) @@ -15,6 +18,8 @@ if(build_modules) add_subdirectory(modules) endif() +set(ENABLE_MYSQL ON CACHE BOOL "enable mysql") + ##OpenCV if(WITH_OPENCV) if(CMAKE_TOOLCHAIN_FILE) @@ -69,6 +74,8 @@ endif() include_directories(${PROJECT_SOURCE_DIR}/3rdparty/rapidjson/include/) include_directories(/usr/local/include/hv) include_directories(${PROJECT_SOURCE_DIR}/modules/UserApp/include/) +include_directories(${PROJECT_SOURCE_DIR}/modules/dataType/include/) +include_directories(${PROJECT_SOURCE_DIR}/modules/Disposition/include/) include_directories(${PROJECT_SOURCE_DIR}/modules/TcpProxySession/include/) diff --git a/README.md b/README.md index 4e53b47..42f3159 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## Satellite *** -> Satellite +> satellite diff --git a/cmake/FindMYSQL.cmake b/cmake/FindMYSQL.cmake index b82e6e1..3828ed3 100644 --- a/cmake/FindMYSQL.cmake +++ b/cmake/FindMYSQL.cmake @@ -31,6 +31,7 @@ else(WIN32) $ENV{MYSQL_INCLUDE_DIR} $ENV{MYSQL_DIR}/include /usr/local/mysql/include + /opt/mysql/mysql/include PATH_SUFFIXES mysql ) diff --git a/docker/3rdparty/ZLToolKit.tar.gz b/docker/3rdparty/ZLToolKit.tar.gz new file mode 100644 index 0000000..6ffce13 Binary files /dev/null and b/docker/3rdparty/ZLToolKit.tar.gz differ diff --git a/docker/Dockerfile b/docker/Dockerfile deleted file mode 100644 index e69de29..0000000 diff --git a/docker/Dockerfile.satellite b/docker/Dockerfile.satellite new file mode 100644 index 0000000..3ea10ed --- /dev/null +++ b/docker/Dockerfile.satellite @@ -0,0 +1,34 @@ +FROM ubuntu:16.04 + +MAINTAINER + + +ARG with_satellite_code=yes + +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + cmake \ + libmysqlclient-dev \ + libssl-dev \ + libgoogle-glog-dev \ + libsqlite3-dev \ + sqlite3 \ + uuid-dev + +# 拷贝文件 +COPY ./3rdparty/ZLToolKit.tar.gz /root +COPY ./3rdparty/opencv.tar.gz /root +COPY ./3rdparty/kafka.tar.gz /root + +# install zltoolkit +RUN cd /root/ && tar -zxvf ZLToolKit.tar.gz +RUN cp -rf /root/ZLToolKit/lib/* /usr/lib/ +RUN cp -rf /root/ZLToolKit/include/* /usr/include/ + +RUN if [ "$with_cnstream_code" = "yes" ]; then \ + cd /root && git clone http://120.79.157.137:80/lishengyin/Satellite.git Satellite && \ + cd /root/Satellite && mkdir build && cd build &&\ + cmake ..&& make -j; \ + fi + +WORKDIR /root \ No newline at end of file diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000..0e33258 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,20 @@ +version: '2' + +services: + satellite: + build: + context: $PWD/ + dockerfile: Dockerfile.satellite + volumes: + - /tmp/.X11-unix:/tmp/.X11-unix + - /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime + network_mode: "host" + privileged: true + ports: + - "7400:7400" + tty: true + environment: + - DISPLAY:$DISPLAY + ipc: "host" + pid: "host" + command: /bin/bash -c "cd /root/Satellite/build && ./main" \ No newline at end of file diff --git a/lib/libmodels.so b/lib/libmodels.so index 239bdff..70f235f 100755 Binary files a/lib/libmodels.so and b/lib/libmodels.so differ diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index 6807db5..86fca27 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.6) set(INS_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/..) set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib/) +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + include(CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) if(NOT COMPILER_SUPPORTS_CXX11) @@ -23,6 +25,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -D_REENTRANT -fPIC -Wall -Wer option(build_UserApp "build module UserApp " ON) option(build_TcpProxySession "build module TcpProxySession" ON) option(build_dataType "build module dataType" ON) +option(build_Disposition "build module Disposition" ON) +option(build_md5 "build module md5" ON) # ---[ 3rdparty set(3RDPARTY_LIBS "") @@ -74,6 +78,16 @@ if(build_dataType) include_directories(${PROJECT_SOURCE_DIR}/modules/dataType/src) install(DIRECTORY dataType/include/ DESTINATION include) endif() +if(build_Disposition) + list(APPEND module_list Disposition) + include_directories(${PROJECT_SOURCE_DIR}/modules/Disposition/src) + install(DIRECTORY Disposition/include/ DESTINATION include) +endif() +if(build_md5) + list(APPEND module_list md5) + include_directories(${PROJECT_SOURCE_DIR}/modules/md5/src) + install(DIRECTORY md5/include/ DESTINATION include) +endif() include_directories(${CMAKE_CURRENT_SOURCE_DIR}) include_directories(/usr/local/include/hv) diff --git a/modules/Disposition/include/Disposition.hpp b/modules/Disposition/include/Disposition.hpp new file mode 100644 index 0000000..d8df9bd --- /dev/null +++ b/modules/Disposition/include/Disposition.hpp @@ -0,0 +1,76 @@ +/* + * @Description: + * @Version: 1.0 + * @Autor: lishengyin + * @Date: 2022-04-12 08:37:45 + * @LastEditors: lishengyin + * @LastEditTime: 2022-04-12 10:16:08 + */ +#ifndef __DISPOSITION_HPP_ +#define __DISPOSITION_HPP_ + +#include +#include "NonCopyable.hpp" +#include +#include "login.hpp" + +#include "Util/logger.h" +#include "Util/NoticeCenter.h" +#include "Poller/EventPoller.h" +#include "Util/SqlPool.h" +#include "Network/TcpClient.h" +#include "Poller/Timer.h" +#include + +using namespace std; +using namespace toolkit; + + +class Disposition:private NonCopyable +{ +private: + Disposition(){} + +public: + using Ptr = std::shared_ptr; + + ~Disposition(){} + + /** + * @description: 获取ptr + * @param {*} + * @return {*} + */ + static std::shared_ptr getPtr(); + + /** + * @description: 初始化 + * @param {*} + * @return {*} + */ + bool Init(); + + /** + * @description: 获取用户合法 + * @param {*} + * @return {*} + */ + bool getUserValidity(Login& login); + + /** + * @description: 获取用户数据 + * @param {*} + * @return {*} + */ + bool getUserInfos(); + +protected: + std::string mysqlIP = "101.35.200.152"; + int port = 13306; + map LoginInfos; +}; + + + + +#endif \ No newline at end of file diff --git a/modules/Disposition/src/Disposition.cpp b/modules/Disposition/src/Disposition.cpp new file mode 100644 index 0000000..0c9e2bd --- /dev/null +++ b/modules/Disposition/src/Disposition.cpp @@ -0,0 +1,74 @@ +/* + * @Description: + * @Version: 1.0 + * @Autor: lishengyin + * @Date: 2022-04-12 08:37:49 + * @LastEditors: lishengyin + * @LastEditTime: 2022-04-12 10:02:49 + */ +#include "Disposition.hpp" +#include "md5.hpp" + + +/** + * @description: 获取ptr + * @param {*} + * @return {*} + */ +std::shared_ptr Disposition::getPtr(){ + static std::shared_ptr m_Disposition = nullptr; + if(m_Disposition == nullptr) m_Disposition = std::shared_ptr(new Disposition); + return m_Disposition; +} + + +/** + * @description: 初始化 + * @param {*} + * @return {*} + */ +bool Disposition::Init(){ + // 链接Mysql + #if defined(SUPPORT_DYNAMIC_TEMPLATE) + //初始化数据 + SqlPool::Instance().Init(this->mysqlIP,this->port,"","root",""/*,character*/); + #else + //由于需要编译器对可变参数模板的支持,所以gcc5.0以下一般都不支持,否则编译报错 + ErrorL << "your compiler does not support variable parameter templates!" << endl; + return false; + #endif //defined(SUPPORT_DYNAMIC_TEMPLATE) + // 初始化数据库连接池 + SqlPool::Instance().setSize(2 + thread::hardware_concurrency()); + + return true; +} + +/** + * @description: 用户合法性 + * @param {Login&} login + * @return {*} + */ +bool Disposition::getUserValidity(Login& login){ + // 查询表列表 + this->getUserInfos(); + auto iter = LoginInfos.find(login.usr); + if(iter == LoginInfos.end()) return false; + // md5加密后与数据库的密码做比较 + if(md5(login.usr+login.pwd) == iter->second) return true; + return false; +} + +/** + * @description: 获取用户数据 + * @param {*} + * @return {*} + */ +bool Disposition::getUserInfos(){ + vector> sqlRet; + SqlWriter sqlSelect("SELECT usr,pwd FROM SatelliteConfigDB.`UserInfos`"); + sqlSelect << sqlRet; + for(auto& line : sqlRet){ + LoginInfos[line[0]] = line[1]; + } + return true; +} \ No newline at end of file diff --git a/modules/TcpProxySession/include/TcpProxySession.hpp b/modules/TcpProxySession/include/TcpProxySession.hpp index b3548f8..e0dec66 100644 --- a/modules/TcpProxySession/include/TcpProxySession.hpp +++ b/modules/TcpProxySession/include/TcpProxySession.hpp @@ -3,8 +3,8 @@ * @Version: 1.0 * @Autor: lishengyin * @Date: 2022-04-11 17:30:58 - * @LastEditors: Please set LastEditors - * @LastEditTime: 2022-04-12 00:07:32 + * @LastEditors: lishengyin + * @LastEditTime: 2022-04-12 10:09:31 */ #ifndef __TCPPROXYSESSION_HPP_ #define __TCPPROXYSESSION_HPP_ @@ -24,8 +24,6 @@ using namespace toolkit; class TcpProxySession; - - class TcpProxySession: public TcpSession { public: TcpProxySession(const Socket::Ptr &sock) : diff --git a/modules/TcpProxySession/src/TcpProxySession.cpp b/modules/TcpProxySession/src/TcpProxySession.cpp index dbc17ff..4d9192b 100644 --- a/modules/TcpProxySession/src/TcpProxySession.cpp +++ b/modules/TcpProxySession/src/TcpProxySession.cpp @@ -3,29 +3,35 @@ * @Version: 1.0 * @Autor: lishengyin * @Date: 2022-04-11 17:31:02 - * @LastEditors: Please set LastEditors - * @LastEditTime: 2022-04-12 00:25:04 + * @LastEditors: lishengyin + * @LastEditTime: 2022-04-12 10:36:29 */ #include "TcpProxySession.hpp" #include "login.hpp" #include +#include "Disposition.hpp" static map> m_ProxySessions; void TcpProxySession::onRecv(const Buffer::Ptr &buf) { //处理客户端发送过来的数据 - TraceL << buf->data() << " from port:" << getIdentifier(); + // TraceL << buf->data() << " from port:" << getIdentifier(); if(this->alive == false){ Login login; std::string json = buf->data(); if(buf->size() > 10 && this->alive == false){ auto sendBuf = BufferRaw::create(); if(login.jsonToObject(json)){ - sendBuf->assign("login successfully"); + if(!Disposition::getPtr()->getUserValidity(login)){ + this->alive = false; + sendBuf->assign("The account or password is incorrect"); + }else{ + this->usr = login.usr; + this->alive = true; + m_ProxySessions[this->usr].push_back(this); + sendBuf->assign("login successfully"); + } send((Buffer::Ptr &)sendBuf); - this->alive = true; - this->usr = login.usr; - m_ProxySessions[this->usr].push_back(this); }else { sendBuf->assign("Not logged in. Please log in"); send((Buffer::Ptr &)sendBuf); diff --git a/modules/UserApp/include/UserApp.hpp b/modules/UserApp/include/UserApp.hpp index 2505e73..ff16db6 100644 --- a/modules/UserApp/include/UserApp.hpp +++ b/modules/UserApp/include/UserApp.hpp @@ -3,8 +3,8 @@ * @Version: 1.0 * @Autor: lishengyin * @Date: 2022-04-11 17:12:05 - * @LastEditors: Please set LastEditors - * @LastEditTime: 2022-04-11 23:12:33 + * @LastEditors: lishengyin + * @LastEditTime: 2022-04-12 10:13:25 */ #ifndef __USERAPP_HPP_ #define __USERAPP_HPP_ @@ -27,6 +27,8 @@ #include "Network/TcpServer.h" #include "Network/TcpSession.h" #include "TcpProxySession.hpp" +#include "Disposition.hpp" +#include "Poller/Timer.h" using namespace std; using namespace toolkit; @@ -34,29 +36,6 @@ using namespace toolkit; #define OK 0 #define ERR -1 -// NonCopyAble -class NonCopyable { - protected: - NonCopyable() {}; - ~NonCopyable() {}; - - public: - NonCopyable(const NonCopyable&) = delete; - NonCopyable(NonCopyable&&) = delete; - NonCopyable& operator=(const NonCopyable&) = delete; - NonCopyable& operator=(NonCopyable&&) = delete; - - static std::string getDataTime(){ - char ctime[80]; - time_t rawtime; - struct tm *info; - time(&rawtime); - info = localtime(&rawtime); - strftime(ctime, 80, "%Y-%m-%d %H:%M:%S", info); - std::string DataTime = ctime; - return DataTime; - } -}; class UserApp:private NonCopyable { @@ -91,8 +70,8 @@ public: private: std::string appName_; int port = 7400; - TcpServer::Ptr m_tcpServer = nullptr; + Timer::Ptr m_timer; }; diff --git a/modules/UserApp/src/UserApp.cpp b/modules/UserApp/src/UserApp.cpp index 1a7f90a..ab9f485 100644 --- a/modules/UserApp/src/UserApp.cpp +++ b/modules/UserApp/src/UserApp.cpp @@ -3,8 +3,8 @@ * @Version: 1.0 * @Autor: lishengyin * @Date: 2022-04-11 17:12:10 - * @LastEditors: Please set LastEditors - * @LastEditTime: 2022-04-11 23:58:52 + * @LastEditors: lishengyin + * @LastEditTime: 2022-04-12 10:16:29 */ #include "UserApp.hpp" @@ -23,7 +23,16 @@ std::shared_ptr UserApp::CreateNew(std::string appName){ * @return {*} */ int8_t UserApp::Init(){ + if(!Disposition::getPtr()->Init()){ + ErrorL << "Disposition Module initialization failed. Procedure" << endl; + return ERR; + } if(m_tcpServer == nullptr) m_tcpServer = std::shared_ptr(new TcpServer()); + // 定时表中数据 + this->m_timer = std::make_shared(3.0f, [&](){ + Disposition::getPtr()->getUserInfos(); + return true; + }, nullptr); return OK; } @@ -34,7 +43,6 @@ int8_t UserApp::Init(){ */ int8_t UserApp::StartTask(){ this->m_tcpServer->start(this->port); - return OK; } diff --git a/modules/dataType/include/NonCopyable.hpp b/modules/dataType/include/NonCopyable.hpp new file mode 100644 index 0000000..2d1e675 --- /dev/null +++ b/modules/dataType/include/NonCopyable.hpp @@ -0,0 +1,39 @@ +/* + * @Description: + * @Version: 1.0 + * @Autor: lishengyin + * @Date: 2022-04-12 10:07:55 + * @LastEditors: lishengyin + * @LastEditTime: 2022-04-12 10:08:56 + */ +#ifndef __NONCOPYABLE_HPP_ +#define __NONCOPYABLE_HPP_ + +#include +using namespace std; + +// NonCopyAble +class NonCopyable { + protected: + NonCopyable() {}; + ~NonCopyable() {}; + + public: + NonCopyable(const NonCopyable&) = delete; + NonCopyable(NonCopyable&&) = delete; + NonCopyable& operator=(const NonCopyable&) = delete; + NonCopyable& operator=(NonCopyable&&) = delete; + + static std::string getDataTime(){ + char ctime[80]; + time_t rawtime; + struct tm *info; + time(&rawtime); + info = localtime(&rawtime); + strftime(ctime, 80, "%Y-%m-%d %H:%M:%S", info); + std::string DataTime = ctime; + return DataTime; + } +}; + +#endif \ No newline at end of file diff --git a/modules/md5/include/md5.hpp b/modules/md5/include/md5.hpp new file mode 100644 index 0000000..620b43e --- /dev/null +++ b/modules/md5/include/md5.hpp @@ -0,0 +1,61 @@ +#ifndef BZF_MD5_H +#define BZF_MD5_H + +#include +#include + + +// a small class for calculating MD5 hashes of strings or byte arrays +// it is not meant to be fast or secure +// +// usage: 1) feed it blocks of uchars with update() +// 2) finalize() +// 3) get hexdigest() string +// or +// MD5(std::string).hexdigest() +// +// assumes that char is 8 bit and int is 32 bit +class MD5 +{ +public: + typedef unsigned int size_type; // must be 32bit + + MD5(); + MD5(const std::string& text); + void update(const unsigned char *buf, size_type length); + void update(const char *buf, size_type length); + MD5& finalize(); + std::string hexdigest() const; + friend std::ostream& operator<<(std::ostream&, MD5 md5); + +private: + void init(); + typedef unsigned char uint1; // 8bit + typedef unsigned int uint4; // 32bit + enum {blocksize = 64}; // VC6 won't eat a const static int here + + void transform(const uint1 block[blocksize]); + static void decode(uint4 output[], const uint1 input[], size_type len); + static void encode(uint1 output[], const uint4 input[], size_type len); + + bool finalized; + uint1 buffer[blocksize]; // bytes that didn't fit in last 64 byte chunk + uint4 count[2]; // 64bit counter for number of bits (lo, hi) + uint4 state[4]; // digest so far + uint1 digest[16]; // the result + + // low level logic operations + static inline uint4 F(uint4 x, uint4 y, uint4 z); + static inline uint4 G(uint4 x, uint4 y, uint4 z); + static inline uint4 H(uint4 x, uint4 y, uint4 z); + static inline uint4 I(uint4 x, uint4 y, uint4 z); + static inline uint4 rotate_left(uint4 x, int n); + static inline void FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); + static inline void GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); + static inline void HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); + static inline void II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); +}; + +std::string md5(const std::string str); + +#endif \ No newline at end of file diff --git a/modules/md5/src/md5.cpp b/modules/md5/src/md5.cpp new file mode 100644 index 0000000..06f6efe --- /dev/null +++ b/modules/md5/src/md5.cpp @@ -0,0 +1,330 @@ +/* interface header */ +#include "md5.hpp" + +/* system implementation headers */ +#include + + +// Constants for MD5Transform routine. +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +/////////////////////////////////////////////// + +// F, G, H and I are basic MD5 functions. +inline MD5::uint4 MD5::F(uint4 x, uint4 y, uint4 z) { + return (x&y) | (~x&z); +} + +inline MD5::uint4 MD5::G(uint4 x, uint4 y, uint4 z) { + return (x&z) | (y&~z); +} + +inline MD5::uint4 MD5::H(uint4 x, uint4 y, uint4 z) { + return x^y^z; +} + +inline MD5::uint4 MD5::I(uint4 x, uint4 y, uint4 z) { + return y ^ (x | ~z); +} + +// rotate_left rotates x left n bits. +inline MD5::uint4 MD5::rotate_left(uint4 x, int n) { + return (x << n) | (x >> (32-n)); +} + +// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. +// Rotation is separate from addition to prevent recomputation. +inline void MD5::FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a+ F(b,c,d) + x + ac, s) + b; +} + +inline void MD5::GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a + G(b,c,d) + x + ac, s) + b; +} + +inline void MD5::HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a + H(b,c,d) + x + ac, s) + b; +} + +inline void MD5::II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a + I(b,c,d) + x + ac, s) + b; +} + +////////////////////////////////////////////// + +// default ctor, just initailize +MD5::MD5() +{ + init(); +} + +////////////////////////////////////////////// + +// nifty shortcut ctor, compute MD5 for string and finalize it right away +MD5::MD5(const std::string &text) +{ + init(); + update(text.c_str(), text.length()); + finalize(); +} + +////////////////////////////// + +void MD5::init() +{ + finalized=false; + + count[0] = 0; + count[1] = 0; + + // load magic initialization constants. + state[0] = 0x67452301; + state[1] = 0xefcdab89; + state[2] = 0x98badcfe; + state[3] = 0x10325476; +} + +////////////////////////////// + +// decodes input (unsigned char) into output (uint4). Assumes len is a multiple of 4. +void MD5::decode(uint4 output[], const uint1 input[], size_type len) +{ + for (unsigned int i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) | + (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24); +} + +////////////////////////////// + +// encodes input (uint4) into output (unsigned char). Assumes len is +// a multiple of 4. +void MD5::encode(uint1 output[], const uint4 input[], size_type len) +{ + for (size_type i = 0, j = 0; j < len; i++, j += 4) { + output[j] = input[i] & 0xff; + output[j+1] = (input[i] >> 8) & 0xff; + output[j+2] = (input[i] >> 16) & 0xff; + output[j+3] = (input[i] >> 24) & 0xff; + } +} + +////////////////////////////// + +// apply MD5 algo on a block +void MD5::transform(const uint1 block[blocksize]) +{ + uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + decode (x, block, blocksize); + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + // Zeroize sensitive information. + memset(x, 0, sizeof x); +} + +////////////////////////////// + +// MD5 block update operation. Continues an MD5 message-digest +// operation, processing another message block +void MD5::update(const unsigned char input[], size_type length) +{ + // compute number of bytes mod 64 + size_type index = count[0] / 8 % blocksize; + + // Update number of bits + if ((count[0] += (length << 3)) < (length << 3)) + count[1]++; + count[1] += (length >> 29); + + // number of bytes we need to fill in buffer + size_type firstpart = 64 - index; + + size_type i; + + // transform as many times as possible. + if (length >= firstpart) + { + // fill buffer first, transform + memcpy(&buffer[index], input, firstpart); + transform(buffer); + + // transform chunks of blocksize (64 bytes) + for (i = firstpart; i + blocksize <= length; i += blocksize) + transform(&input[i]); + + index = 0; + } + else + i = 0; + + // buffer remaining input + memcpy(&buffer[index], &input[i], length-i); +} + +////////////////////////////// + +// for convenience provide a verson with signed char +void MD5::update(const char input[], size_type length) +{ + update((const unsigned char*)input, length); +} + +////////////////////////////// + +// MD5 finalization. Ends an MD5 message-digest operation, writing the +// the message digest and zeroizing the context. +MD5& MD5::finalize() +{ + static unsigned char padding[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + if (!finalized) { + // Save number of bits + unsigned char bits[8]; + encode(bits, count, 8); + + // pad out to 56 mod 64. + size_type index = count[0] / 8 % 64; + size_type padLen = (index < 56) ? (56 - index) : (120 - index); + update(padding, padLen); + + // Append length (before padding) + update(bits, 8); + + // Store state in digest + encode(digest, state, 16); + + // Zeroize sensitive information. + memset(buffer, 0, sizeof buffer); + memset(count, 0, sizeof count); + + finalized=true; + } + + return *this; +} + +////////////////////////////// + +// return hex representation of digest as string +std::string MD5::hexdigest() const +{ + if (!finalized) + return ""; + + char buf[33]; + for (int i=0; i<16; i++) + sprintf(buf+i*2, "%02x", digest[i]); + buf[32]=0; + + return std::string(buf); +} + +////////////////////////////// + +std::ostream& operator<<(std::ostream& out, MD5 md5) +{ + return out << md5.hexdigest(); +} + +////////////////////////////// + +std::string md5(const std::string str) +{ + MD5 md5 = MD5(str); + + return md5.hexdigest(); +} \ No newline at end of file