1
0

Merge remote-tracking branch 'upstream/master' into Enchanting

This commit is contained in:
daniel0916 2014-04-07 20:12:17 +02:00
commit 2e9754ac1c
710 changed files with 39009 additions and 62353 deletions

65
.gitignore vendored
View File

@ -1,4 +1,5 @@
build/
nbproject/
ipch/
Win32/
MCServer/MCServer
@ -22,6 +23,9 @@ cloc.xsl
*.*~
*~
*.orig
## Eclipse
.cproject
.project
# world inside source
ChunkWorx.ini
@ -57,6 +61,7 @@ install_mainfest.txt
src/MCServer
lib/tolua++/tolua
src/Bindings/Bindings.*
src/Bindings/BindingDependecies.txt
MCServer.dir/
#win32 cmake stuff
@ -70,58 +75,8 @@ MCServer.dir/
#cmake output folders
ZERO_CHECK.dir/
lib/cryptopp/Debug/
lib/cryptopp/DebugProfile/
lib/cryptopp/Release/
lib/cryptopp/ReleaseProfile/
lib/cryptopp/cryptopp.dir/
lib/expat/Debug/
lib/expat/DebugProfile/
lib/expat/Release/
lib/expat/ReleaseProfile/
lib/expat/expat.dir/
lib/inifile/Debug/
lib/inifile/DebugProfile/
lib/inifile/Release/
lib/inifile/ReleaseProfile/
lib/inifile/inifile.dir/
lib/jsoncpp/Debug/
lib/jsoncpp/DebugProfile/
lib/jsoncpp/Release/
lib/jsoncpp/ReleaseProfile/
lib/jsoncpp/jsoncpp.dir/
lib/lua/Debug/
lib/lua/DebugProfile/
lib/lua/Release/
lib/lua/ReleaseProfile/
lib/lua/lua.dir/
lib/luaexpat/Debug/
lib/luaexpat/DebugProfile/
lib/luaexpat/Release/
lib/luaexpat/ReleaseProfile/
lib/luaexpat/luaexpat.dir/
lib/md5/Debug/
lib/md5/DebugProfile/
lib/md5/Release/
lib/md5/ReleaseProfile/
lib/md5/md5.dir/
lib/sqlite/Debug/
lib/sqlite/DebugProfile/
lib/sqlite/Release/
lib/sqlite/ReleaseProfile/
lib/sqlite/sqlite.dir/
lib/tolua++/Debug/
lib/tolua++/DebugProfile/
lib/tolua++/Release/
lib/tolua++/ReleaseProfile/
lib/tolua++/tolua.dir/
lib/tolua++/tolualib.dir/
lib/zlib/Debug/
lib/zlib/DebugProfile/
lib/zlib/Release/
lib/zlib/ReleaseProfile/
lib/zlib/zlib.dir/
src/Debug/
src/DebugProfile/
src/Release/
src/ReleaseProfile/
Debug/
DebugProfile/
Release/
ReleaseProfile/
*.dir/

3
.gitmodules vendored
View File

@ -7,3 +7,6 @@
[submodule "MCServer/Plugins/TransAPI"]
path = MCServer/Plugins/TransAPI
url = https://github.com/bearbin/transapi.git
[submodule "lib/polarssl"]
path = lib/polarssl
url = https://github.com/polarssl/polarssl

View File

@ -3,7 +3,13 @@ compiler:
- gcc
- clang
# Build MCServer
script: cmake . -DCMAKE_BUILD_TYPE=RELEASE && make -j 2
script: cmake . -DBUILD_TOOLS=1 -DSELF_TEST=1 && make -j 2 && cd MCServer/ && (echo stop | $MCSERVER_PATH)
env:
- TRAVIS_MCSERVER_BUILD_TYPE=RELEASE MCSERVER_PATH=./MCServer
- TRAVIS_MCSERVER_BUILD_TYPE=DEBUG MCSERVER_PATH=./MCServer_debug
- TRAVIS_MCSERVER_BUILD_TYPE=RELEASE TRAVIS_MCSERVER_FORCE32=1 MCSERVER_PATH=./MCServer
- TRAVIS_MCSERVER_BUILD_TYPE=DEBUG TRAVIS_MCSERVER_FORCE32=1 MCSERVER_PATH=./MCServer_debug
# Notification Settings
notifications:

View File

@ -5,7 +5,7 @@ LOCAL_MODULE := mcserver
LOCAL_SRC_FILES := $(shell find ../CryptoPP ../lua ../jsoncpp ../zlib ../src ../tolua++ ../iniFile ../expat ../md5 ../sqlite ../luaexpat '(' -name '*.cpp' -o -name '*.c' ')')
LOCAL_SRC_FILES := $(shell find ../lib/polarssl ../lib/lua ../lib/jsoncpp ../lib/zlib ../src ../lib/tolua++ ../lib/iniFile ../lib/expat ../lib/md5 ../lib/sqlite ../lib/luaexpat '(' -name '*.cpp' -o -name '*.c' ')')
LOCAL_SRC_FILES := $(filter-out %SquirrelFunctions.cpp %SquirrelBindings.cpp %cPlugin_Squirrel.cpp %cSquirrelCommandBinder.cpp %minigzip.c %lua.c %tolua.c %toluabind.c %LeakFinder.cpp %StackWalker.cpp %example.c,$(LOCAL_SRC_FILES))
LOCAL_SRC_FILES := $(patsubst %.cpp,../%.cpp,$(LOCAL_SRC_FILES))
LOCAL_SRC_FILES := $(patsubst %.c,../%.c,$(LOCAL_SRC_FILES))
@ -24,17 +24,17 @@ LOCAL_C_INCLUDES := ../src \
../src/packets \
../src/items \
../src/blocks \
../tolua++/src/lib \
../lua/src \
../zlib-1.2.7 \
../iniFile \
../tolua++/include \
../jsoncpp/include \
../jsoncpp/src/lib_json \
../expat/ \
../md5/ \
../sqlite/ \
../luaexpat/ \
../lib/tolua++/src/lib \
../lib/lua/src \
../lib/zlib-1.2.7 \
../lib/iniFile \
../lib/tolua++/include \
../lib/jsoncpp/include \
../lib/jsoncpp/src/lib_json \
../lib/expat/ \
../lib/md5/ \
../lib/sqlite/ \
../lib/luaexpat/ \
.. \

View File

@ -1,102 +1,33 @@
cmake_minimum_required (VERSION 2.6)
# Without this, the MSVC variable isn't defined for MSVC builds ( http://www.cmake.org/pipermail/cmake/2011-November/047130.html )
enable_language(CXX C)
macro (add_flags_lnk FLAGS)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG} ${FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} ${FLAGS}")
endmacro()
macro(add_flags_cxx FLAGS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAGS}")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FLAGS}")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${FLAGS}")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${FLAGS}")
endmacro()
# Add the preprocessor macros used for distinguishing between debug and release builds (CMake does this automatically for MSVC):
if (NOT MSVC)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNDEBUG")
# These env variables are used for configuring Travis CI builds.
# See https://github.com/mc-server/MCServer/pull/767
if(DEFINED ENV{TRAVIS_MCSERVER_BUILD_TYPE})
message("Setting build type to $ENV{TRAVIS_MCSERVER_BUILD_TYPE}")
set(CMAKE_BUILD_TYPE $ENV{TRAVIS_MCSERVER_BUILD_TYPE})
endif()
if(MSVC)
# Make build use multiple threads under MSVC:
add_flags_cxx("/MP")
# Make release builds use link-time code generation:
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /GL")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG")
set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} /LTCG")
elseif(APPLE)
#on os x clang adds pthread for us but we need to add it for gcc
if (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
add_flags_cxx("-pthread")
add_flags_cxx("-std=c++11")
endif()
else()
# Let gcc / clang know that we're compiling a multi-threaded app:
add_flags_cxx("-pthread")
if(DEFINED ENV{TRAVIS_MCSERVER_FORCE32})
set(FORCE32 $ENV{TRAVIS_MCSERVER_FORCE32})
endif()
# Allow for a forced 32-bit build under 64-bit OS:
if (FORCE_32)
add_flags_cxx("-m32")
add_flags_lnk("-m32")
# This has to be done before any flags have been set up.
if(${BUILD_TOOLS})
add_subdirectory(Tools/MCADefrag/)
add_subdirectory(Tools/ProtoProxy/)
endif()
# Have the compiler generate code specifically targeted at the current machine on Linux
if(LINUX AND NOT CROSSCOMPILE)
add_flags_cxx("-march=native")
endif()
# Use static CRT in MSVC builds:
if (MSVC)
string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
string(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
string(REPLACE "/MDd" "/MTd" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
endif()
# Set lower warnings-level for the libraries:
if (MSVC)
# Remove /W3 from command line -- cannot just cancel it later with /w like in unix, MSVC produces a D9025 warning (option1 overriden by option2)
string(REPLACE "/W3" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
string(REPLACE "/W3" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
string(REPLACE "/W3" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
string(REPLACE "/W3" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
else()
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -w")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -w")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -w")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -w")
endif()
# Under clang, we need to disable ASM support in CryptoPP:
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
add_definitions(-DCRYPTOPP_DISABLE_ASM)
if(${BUILD_UNSTABLE_TOOLS})
add_subdirectory(Tools/GeneratorPerformanceTest/)
endif()
include(SetFlags.cmake)
set_flags()
set_lib_flags()
enable_profile()
# Under Windows, we need Lua as DLL; on *nix we need it linked statically:
if (WIN32)
@ -104,86 +35,23 @@ if (WIN32)
endif()
# On Unix we use two dynamic loading libraries dl and ltdl.
# Preference is for dl on unknown systems as it is specified in POSIX
# the dynamic loader is used by lua and sqllite.
if (UNIX)
if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
set(DYNAMIC_LOADER ltdl)
else()
set(DYNAMIC_LOADER dl)
endif()
endif()
# The Expat library is linked in statically, make the source files aware of that:
add_definitions(-DXML_STATIC)
# Declare the flags used for profiling builds:
if (MSVC)
set (CXX_PROFILING "")
set (LNK_PROFILING "/PROFILE")
else()
set (CXX_PROFILING "-pg")
set (LNK_PROFILING "-pg")
# Self Test Mode enables extra checks at startup
if(${SELF_TEST})
add_definitions(-DSELF_TEST)
endif()
# Declare the profiling configurations:
SET(CMAKE_CXX_FLAGS_DEBUGPROFILE
"${CMAKE_CXX_FLAGS_DEBUG} ${PCXX_ROFILING}"
CACHE STRING "Flags used by the C++ compiler during profile builds."
FORCE )
SET(CMAKE_C_FLAGS_DEBUGPROFILE
"${CMAKE_C_FLAGS_DEBUG} ${CXX_PROFILING}"
CACHE STRING "Flags used by the C compiler during profile builds."
FORCE )
SET(CMAKE_EXE_LINKER_FLAGS_DEBUGPROFILE
"${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${LNK_PROFILING}"
CACHE STRING "Flags used for linking binaries during profile builds."
FORCE )
SET(CMAKE_SHARED_LINKER_FLAGS_DEBUGPROFILE
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${LNK_PROFILING}"
CACHE STRING "Flags used by the shared libraries linker during profile builds."
FORCE )
MARK_AS_ADVANCED(
CMAKE_CXX_FLAGS_DEBUGPROFILE
CMAKE_C_FLAGS_DEBUGPROFILE
CMAKE_EXE_LINKER_FLAGS_DEBUGPROFILE
CMAKE_SHARED_LINKER_FLAGS_DEBUGPROFILE )
SET(CMAKE_CXX_FLAGS_RELEASEPROFILE
"${CMAKE_CXX_FLAGS_RELEASE} ${CXX_PROFILING}"
CACHE STRING "Flags used by the C++ compiler during profile builds."
FORCE )
SET(CMAKE_C_FLAGS_RELEASEPROFILE
"${CMAKE_C_FLAGS_RELEASE} ${CXX_PROFILING}"
CACHE STRING "Flags used by the C compiler during profile builds."
FORCE )
SET(CMAKE_EXE_LINKER_FLAGS_RELEASEPROFILE
"${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${LNK_PROFILING}"
CACHE STRING "Flags used for linking binaries during profile builds."
FORCE )
SET(CMAKE_SHARED_LINKER_FLAGS_RELEASEPROFILE
"${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${LNK_PROFILING}"
CACHE STRING "Flags used by the shared libraries linker during profile builds."
FORCE )
MARK_AS_ADVANCED(
CMAKE_CXX_FLAGS_RELEASEPROFILE
CMAKE_C_FLAGS_RELEASEPROFILE
CMAKE_EXE_LINKER_FLAGS_RELEASEPROFILE
CMAKE_SHARED_LINKER_FLAGS_RELEASEPROFILE )
# The configuration types need to be set after their respective c/cxx/linker flags and before the project directive
set(CMAKE_CONFIGURATION_TYPES "Debug;Release;DebugProfile;ReleaseProfile" CACHE STRING "" FORCE)
project (MCServer)
# Include all the libraries:
add_subdirectory(lib/inifile/)
add_subdirectory(lib/jsoncpp/)
add_subdirectory(lib/cryptopp/)
add_subdirectory(lib/zlib/)
add_subdirectory(lib/lua/)
add_subdirectory(lib/tolua++/)
@ -192,16 +60,12 @@ add_subdirectory(lib/expat/)
add_subdirectory(lib/luaexpat/)
add_subdirectory(lib/md5/)
# Remove disabling the maximum warning level:
# clang does not like a command line that reads -Wall -Wextra -w -Wall -Wextra and does not output any warnings
# We do not do that for MSVC since MSVC produces an awful lot of warnings for its own STL headers;
# the important warnings are turned on using #pragma in Globals.h
if (NOT MSVC)
string(REPLACE "-w" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
string(REPLACE "-w" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
string(REPLACE "-w" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
string(REPLACE "-w" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
endif()
# We use EXCLUDE_FROM_ALL so that only the explicit dependencies are used
# (PolarSSL also has test and example programs in their CMakeLists.txt, we don't want those)
include(lib/polarssl.cmake)
set_exe_flags()
add_subdirectory (src)

View File

@ -49,7 +49,7 @@ There's a script file, `MCServer/profile_run.cmd` that encapsulates most of the
Install git, cmake and gcc or clang, using your platform's package manager:
```
sudo apt-get install git cmake gcc
sudo apt-get install git cmake gcc g++
```
### Getting the sources ###
@ -65,17 +65,29 @@ git submodule update
Release mode is preferred for almost all cases, it has much better speed and less console spam. However, if you are developing MCServer actively, debug mode might be better.
cmake . -DCMAKE_BUILD_TYPE=RELEASE && make
Assuming you are in the MCServer folder created in the initial setup step, you need to run these commands:
```
mkdir Release
cd Release
cmake -DCMAKE_BUILD_TYPE=RELEASE .. && make
```
The executable will be built in the `MCServer/MCServer` folder and will be named `MCServer`.
### Debug Mode ###
Debug mode is useful if you want more debugging information about MCServer as it's running or if you want to use a debugger like GDB to debug issues and crashes.
Debug mode is useful if you want more debugging information about MCServer while it's running or if you want to use a debugger like GDB to debug issues and crashes.
cmake . -DCMAKE_BUILD_TYPE=DEBUG && make
Assuming you are in the MCServer folder created in the Getting the sources step, you need to run these commands:
```
mkdir Debug
cd Debug
cmake -DCMAKE_BUILD_TYPE=DEBUG .. && make
```
The executable will be built in the `MCServer/MCServer` folder and will be named `MCServer_debug`.
### 32 Bit Mode ###
### 32 Bit Mode switch ###
This is useful if you want to compile MCServer to use on another 32-bit machine. It can be used with debug or release mode. To use 32 bit mode, simply add:
This is useful if you want to compile MCServer on an x64 (64-bit Intel) machine but want to use on an x86 (32-bit Intel) machine. This switch can be used with debug or release mode. Simply add:
-DFORCE_32=1
@ -84,8 +96,10 @@ to your cmake command and 32 bit will be forced.
### Compiling for another computer ###
When compiling for another computer it is important to set cross compiling mode. This tells the compiler not to optimise for your machine. It can be used with debug or release mode. To enable simply add:
When cross-compiling for another computer it is important to set cross compiling mode. This tells the compiler not to optimise for your machine. This switch can be used with debug or release mode. To enable, simply add:
-DCROSSCOMPILE=1
to your cmake command.
Note that cross-compilation is probably broken at this moment, since the build requires running an executable that it has built, as part of the build process.

View File

@ -1,35 +1,41 @@
Code Stuff
----------
* Because some devs use MSVC2008, we use C++03 - no C++11 magic for now at least :(
* We use C++03 with some C++11 extensions (ask if you think that something would be useful)
* Use the provided wrappers for OS stuff:
- Threading is done by inheriting from cIsThread, thread synchronization through cCriticalSection, cSemaphore and cEvent, file access and filesystem operations through the cFile class, high-precision timers through cTimer, high-precision sleep through cSleep
- Threading is done by inheriting from `cIsThread`, thread synchronization through `cCriticalSection`, `cSemaphore` and `cEvent`, file access and filesystem operations through the `cFile` class, high-precision timers through `cTimer`, high-precision sleep through `cSleep`
* No magic numbers, use named constants:
- E_ITEM_XXX, E_BLOCK_XXX and E_META_XXX for items and blocks
- E_ENTITY_TYPE_XXX for mob types
- dimNether, dimOverworld and dimEnd for world dimension
- gmSurvival, gmCreative, gmAdventure for game modes
- wSunny, wRain, wThunderstorm for weather
- cChunkDef::Width, cChunkDef::Height for chunk dimensions (C++)
- `E_ITEM_XXX`, `E_BLOCK_XXX` and `E_META_XXX` for items and blocks
- `cEntity::etXXX` for entity types, `cMonster::mtXXX` for mob types
- `dimNether`, `dimOverworld` and `dimEnd` for world dimension
- `gmSurvival`, `gmCreative`, `gmAdventure` for game modes
- `wSunny`, `wRain`, `wThunderstorm` for weather
- `cChunkDef::Width`, `cChunkDef::Height` for chunk dimensions (C++)
- etc.
* Instead of checking for specific value, use Is functions, if available:
- cPlayer:IsGameModeCreative() instead of (cPlayer:GetGameMode() == gmCreative)
* Please use tabs for indentation and spaces for alignment. This means that if it's at line start, it's a tab; if it's in the middle of a line, it's a space
* Instead of checking for a specific value, use an `IsXXX` function, if available:
- `cPlayer:IsGameModeCreative()` instead of` (cPlayer:GetGameMode() == gmCreative)` (the player can also inherit the gamemode from the world, which the value-d condition doesn't catch)
* Please use **tabs for indentation and spaces for alignment**. This means that if it's at line start, it's a tab; if it's in the middle of a line, it's a space
* Alpha-sort stuff that makes sense alpha-sorting - long lists of similar items etc.
* Keep individual functions spaced out by 5 empty lines, this enhances readability and makes navigation in the source file easier.
* Add those extra parentheses to conditions, especially in C++
- "if ((a == 1) && ((b == 2) || (c == 3)))" instead of ambiguous "if (a == 1 && b == 2 || c == 3)"
- This helps prevent mistakes such as "if (a & 1 == 0)"
- `if ((a == 1) && ((b == 2) || (c == 3)))` instead of ambiguous `if (a == 1 && b == 2 || c == 3)`
- This helps prevent mistakes such as `if (a & 1 == 0)`
* White space is free, so use it freely
- "freely" as in "plentifully", not "arbitrarily"
* All `case` statements inside a `switch` need an extra indent.
* Each and every control statement deserves its braces. This helps maintainability later on when the file is edited, lines added or removed - the control logic doesn't break so easily.
* Please leave the first line of all source files blank, to get around an IDE bug.
* Also leave the last line of all source files blank (GCC and GIT can complain otherwise)
- The only exception: a `switch` statement with all `case` statements being a single short statement is allowed to use the short brace-less form.
- These two rules really mean that indent is governed by braces
* Add an empty last line in all source files (GCC and GIT can complain otherwise)
* Use doxy-comments for functions in the header file, format as `/** Description */`
* Use spaces after the comment markers: `// Comment` instead of `//Comment`
Copyright
---------
Your work should be licensed under the Apache license, and you should add yourself to the CONTRIBUTORS file.
Your work must be licensed at least under the Apache license.
If your work is not licensed under the Apache license, then it must be compatible and marked as such. Note that only plugins may choose a different license; MC-server's internals need to be single-license.
You can add yourself to the CONTRIBUTORS file if you wish.
**PLUGINS ONLY**: If your plugin is not licensed under the Apache license, then it must be compatible and marked as such. This is only valid for the plugins included within the MCServer source; plugins developed on separate repositories can use whatever license they want.

View File

@ -1,25 +1,31 @@
Many people have contributed to MCServer, and this list attempts to broadcast at least some of them.
faketruth (founder)
xoft
keyboard
STR_Warrior
mgueydan
tigerw
bearbin (Alexander Harkness)
Lapayo
rs2k
derouinw
Diusrex
Duralex
mtilden
FakeTruth (founder)
keyboard
Lapayo
Luksor
marmot21
Sofapriester
mborland
mgueydan
MikeHunsinger
mtilden
nesco
rs2k
SamJBarney
worktycho
Sxw1212
tonibm19
Diusrex
Sofapriester
STR_Warrior
structinf (xdot)
Sxw1212
Taugeshtu
tigerw (Tiger Wang)
tonibm19
UltraCoderRU
worktycho
xoft
Please add yourself to this list if you contribute to MCServer.

View File

@ -665,9 +665,7 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = source \
iniFile \
WebServer
INPUT = src
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is

View File

@ -1,8 +1,2 @@
MCServer\*.pdb
VC2008\Release\*.pdb
VC2008\Release\JsonCpp\*.pdb
VC2008\Release\Lua\*.pdb
VC2008\Release\ToLua\*.pdb
VC2008\Release\webserver\*.pdb
VC2008\Release\zlib\*.pdb
src\Bindings.*
src\Bindings\Bindings.*

197
LICENSE
View File

@ -1,4 +1,199 @@
Copyright MCServer Contributors
MCServer: A performant C++ Minecraft Server
www: http://mc-server.org/
Copyright 2014 MCServer Team
------
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

11
MCServer/.gitignore vendored
View File

@ -4,6 +4,9 @@
*.lib
*.ini
MCServer
MCServer_debug
CommLogs/
GalExports/
logs
players
world*
@ -17,13 +20,13 @@ schematics
*.pdb
memdump*
*.grab
Galleries.cfg
Galleries.example.cfg
Galleries.sqlite
ProtectionAreas.sqlite
*.cfg
*.sqlite
helgrind.log
valgrind.log
motd.txt
*.deuser
*.dmp
*.xml
mcserver_api.lua

3
MCServer/Plugins/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.txt
*.md
*/

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,9 @@
<file>
<filename>Classes\BlockEntities.lua</filename>
</file>
<file>
<filename>Classes\Geometry.lua</filename>
</file>
<file>
<filename>Hooks\OnBlockToPickups.lua</filename>
</file>

View File

@ -196,9 +196,11 @@ World:ForEachChestInChunk(Player:GetChunkX(), Player:GetChunkZ(),
Inherits = "cBlockEntity",
Functions =
{
EjectRecord = { Params = "", Return = "", Notes = "Ejects the current record as a {{cPickup|pickup}}. No action if there's no current record. To remove record without generating the pickup, use SetRecord(0)" },
EjectRecord = { Params = "", Return = "bool", Notes = "Ejects the current record as a {{cPickup|pickup}}. No action if there's no current record. To remove record without generating the pickup, use SetRecord(0). Returns true if pickup ejected." },
GetRecord = { Params = "", Return = "number", Notes = "Returns the record currently present. Zero for no record, E_ITEM_*_DISC for records." },
PlayRecord = { Params = "", Return = "", Notes = "Plays the currently present record. No action if there's no current record." },
IsPlayingRecord = { Params = "", Return = "bool", Notes = "Returns true if the jukebox is playing a record." },
IsRecordItem = { Params = "ItemType", Return = "bool", Notes = "Returns true if the specified item is a record that can be played." },
PlayRecord = { Params = "RecordItemType", Return = "bool", Notes = "Plays the specified Record. Return false if the parameter isn't a playable Record (E_ITEM_XXX_DISC). If there is a record already playing, ejects it first." },
SetRecord = { Params = "number", Return = "", Notes = "Sets the currently present record. Use zero for no record, or E_ITEM_*_DISC for records." },
},
}, -- cJukeboxEntity
@ -236,6 +238,20 @@ World:ForEachChestInChunk(Player:GetChunkX(), Player:GetChunkZ(),
},
Inherits = "cBlockEntity";
}, -- cSignEntity
cFlowerPotEntity =
{
Desc = [[
This class represents a flower pot entity in the world.
]],
Functions =
{
IsItemInPot = { Params = "", Return = "bool", Notes = "Is a flower in the pot?" },
GetItem = { Params = "", Return = "{{cItem|Item}}", Notes = "Returns the item in the flower pot." },
SetItem = { Params = "{{cItem|Item}}", Return = "", Notes = "Set the item in the flower pot" },
},
Inherits = "cBlockEntity";
}, -- cFlowerPotEntity
}

View File

@ -0,0 +1,332 @@
-- Geometry.lua
-- Defines the documentation for geometry-related classes:
-- cBoundingBox, cCuboid, cLineBlockTracer, cTracer, Vector3X
return
{
cBoundingBox =
{
Desc = [[
Represents two sets of coordinates, minimum and maximum for each direction; thus defining an
axis-aligned cuboid with floating-point boundaries. It supports operations changing the size and
position of the box, as well as querying whether a point or another BoundingBox is inside the box.</p>
<p>
All the points within the coordinate limits (inclusive the edges) are considered "inside" the box.
However, for intersection purposes, if the intersection is "sharp" in any coord (min1 == max2, i. e.
zero volume), the boxes are considered non-intersecting.</p>
]],
Functions =
{
constructor =
{
{ Params = "MinX, MaxX, MinY, MaxY, MinZ, MaxZ", Return = "cBoundingBox", Notes = "Creates a new bounding box with the specified edges" },
{ Params = "{{Vector3d|Min}}, {{Vector3d|Max}}", Return = "cBoundingBox", Notes = "Creates a new bounding box with the coords specified as two vectors" },
{ Params = "{{Vector3d|Pos}}, Radius, Height", Return = "cBoundingBox", Notes = "Creates a new bounding box from the position given and radius (X/Z) and height. Radius is added from X/Z to calculate the maximum coords and subtracted from X/Z to get the minimum; minimum Y is set to Pos.y and maxumim Y to Pos.y plus Height. This corresponds with how {{cEntity|entities}} are represented in Minecraft." },
{ Params = "OtherBoundingBox", Return = "cBoundingBox", Notes = "Creates a new copy of the given bounding box. Same result can be achieved by using a simple assignment." },
},
CalcLineIntersection = { Params = "{{Vector3d|LineStart}}, {{Vector3d|LinePt2}}", Return = "DoesIntersect, LineCoeff, Face", Notes = "Calculates the intersection of a ray (half-line), given by two of its points, with the bounding box. Returns false if the line doesn't intersect the bounding box, or true, together with coefficient of the intersection (how much of the difference between the two ray points is needed to reach the intersection), and the face of the box which is intersected.<br /><b>TODO</b>: Lua binding for this function is wrong atm." },
DoesIntersect = { Params = "OtherBoundingBox", Return = "bool", Notes = "Returns true if the two bounding boxes have an intersection of nonzero volume." },
Expand = { Params = "ExpandX, ExpandY, ExpandZ", Return = "", Notes = "Expands this bounding box by the specified amount in each direction (so the box becomes larger by 2 * Expand in each axis)." },
IsInside =
{
{ Params = "{{Vector3d|Point}}", Return = "bool", Notes = "Returns true if the specified point is inside (including on the edge) of the box." },
{ Params = "PointX, PointY, PointZ", Return = "bool", Notes = "Returns true if the specified point is inside (including on the edge) of the box." },
{ Params = "OtherBoundingBox", Return = "bool", Notes = "Returns true if OtherBoundingBox is inside of this box." },
{ Params = "{{Vector3d|OtherBoxMin}}, {{Vector3d|OtherBoxMax}}", Return = "bool", Notes = "Returns true if the other bounding box, specified by its 2 corners, is inside of this box." },
},
Move =
{
{ Params = "OffsetX, OffsetY, OffsetZ", Return = "", Notes = "Moves the bounding box by the specified offset in each axis" },
{ Params = "{{Vector3d|Offset}}", Return = "", Notes = "Moves the bounding box by the specified offset in each axis" },
},
Union = { Params = "OtherBoundingBox", Return = "cBoundingBox", Notes = "Returns the smallest bounding box that contains both OtherBoundingBox and this bounding box. Note that unlike the strict geometrical meaning of \"union\", this operation actually returns a cBoundingBox." },
},
}, -- cBoundingBox
cCuboid =
{
Desc = [[
cCuboid offers some native support for integral-boundary cuboids. A cuboid internally consists of
two {{Vector3i}}-s. By default the cuboid doesn't make any assumptions about the defining points,
but for most of the operations in the cCuboid class, the p1 member variable is expected to be the
minima and the p2 variable the maxima. The Sort() function guarantees this condition.</p>
<p>
The Cuboid considers both its edges inclusive.</p>
]],
Functions =
{
constructor =
{
{ Params = "", Return = "cCuboid", Notes = "Creates a new Cuboid object with all-zero coords" },
{ Params = "OtherCuboid", Return = "cCuboid", Notes = "Creates a new Cuboid object as a copy of OtherCuboid" },
{ Params = "{{Vector3i|Point1}}, {{Vector3i|Point2}}", Return = "cCuboid", Notes = "Creates a new Cuboid object with the specified points as its corners." },
{ Params = "X, Y, Z", Return = "cCuboid", Notes = "Creates a new Cuboid object with the specified point as both its corners (the cuboid has a size of 1 in each direction)." },
{ Params = "X1, Y1, Z1, X2, Y2, Z2", Return = "cCuboid", Notes = "Creates a new Cuboid object with the specified points as its corners." },
},
Assign =
{
{ Params = "SrcCuboid", Return = "", Notes = "Copies all the coords from the src cuboid to this cuboid. Sort-state is ignored." },
{ Params = "X1, Y1, Z1, X2, Y2, Z2", Return = "", Notes = "Assigns all the coords to the specified values. Sort-state is ignored." },
},
ClampX = { Params = "MinX, MaxX", Return = "", Notes = "Clamps both X coords into the range provided. Sortedness-agnostic." },
ClampY = { Params = "MinY, MaxY", Return = "", Notes = "Clamps both Y coords into the range provided. Sortedness-agnostic." },
ClampZ = { Params = "MinZ, MaxZ", Return = "", Notes = "Clamps both Z coords into the range provided. Sortedness-agnostic." },
DifX = { Params = "", Return = "number", Notes = "Returns the difference between the two X coords (X-size minus 1). Assumes sorted." },
DifY = { Params = "", Return = "number", Notes = "Returns the difference between the two Y coords (Y-size minus 1). Assumes sorted." },
DifZ = { Params = "", Return = "number", Notes = "Returns the difference between the two Z coords (Z-size minus 1). Assumes sorted." },
DoesIntersect = { Params = "OtherCuboid", Return = "bool", Notes = "Returns true if this cuboid has at least one voxel in common with OtherCuboid. Note that edges are considered inclusive. Assumes both sorted." },
Engulf = { Params = "{{Vector3i|Point}}", Return = "", Notes = "If needed, expands the cuboid to include the specified point. Doesn't shrink. Assumes sorted. " },
Expand = { Params = "SubMinX, AddMaxX, SubMinY, AddMaxY, SubMinZ, AddMaxZ", Return = "", Notes = "Expands the cuboid by the specified amount in each direction. Works on unsorted cuboids as well. NOTE: this function doesn't check for underflows." },
GetVolume = { Params = "", Return = "number", Notes = "Returns the volume of the cuboid, in blocks. Note that the volume considers both coords inclusive. Works on unsorted cuboids, too." },
IsCompletelyInside = { Params = "OuterCuboid", Return = "bool", Notes = "Returns true if this cuboid is completely inside (in all directions) in OuterCuboid. Assumes both sorted." },
IsInside =
{
{ Params = "X, Y, Z", Return = "bool", Notes = "Returns true if the specified point (integral coords) is inside this cuboid. Assumes sorted." },
{ Params = "{{Vector3i|Point}}", Return = "bool", Notes = "Returns true if the specified point (integral coords) is inside this cuboid. Assumes sorted." },
{ Params = "{{Vector3d|Point}}", Return = "bool", Notes = "Returns true if the specified point (floating-point coords) is inside this cuboid. Assumes sorted." },
},
IsSorted = { Params = "", Return = "bool", Notes = "Returns true if this cuboid is sorted" },
Move = { Params = "OffsetX, OffsetY, OffsetZ", Return = "", Notes = "Adds the specified offsets to each respective coord, effectively moving the Cuboid. Sort-state is ignored and preserved." },
Sort = { Params = "", Return = "" , Notes = "Sorts the internal representation so that p1 contains the lesser coords and p2 contains the greater coords." },
},
Variables =
{
p1 = { Type = "{{Vector3i}}", Notes = "The first corner. Usually the lesser of the two coords in each set" },
p2 = { Type = "{{Vector3i}}", Notes = "The second corner. Usually the larger of the two coords in each set" },
},
}, -- cCuboid
cLineBlockTracer =
{
Desc = [[This class provides an easy-to-use interface for tracing lines through individual
blocks in the world. It will call the provided callbacks according to what events it encounters along the
way.</p>
<p>
For the Lua API, there's only one static function exported that takes all the parameters necessary to do
the tracing. The Callbacks parameter is a table containing all the functions that will be called upon the
various events. See below for further information.
]],
Functions =
{
Trace = { Params = "{{cWorld}}, Callbacks, StartX, StartY, StartZ, EndX, EndY, EndZ", Return = "bool", Notes = "(STATIC) Performs the trace on the specified line. Returns true if the entire trace was processed (no callback returned true)" },
},
AdditionalInfo =
{
{
Header = "Callbacks",
Contents = [[
The Callbacks in the Trace() function is a table that contains named functions. MCServer will call
individual functions from that table for the events that occur on the line - hitting a block, going out of
valid world data etc. The following table lists all the available callbacks. If the callback function is
not defined, MCServer skips it. Each function can return a bool value, if it returns true, the tracing is
aborted and Trace() returns false.</p>
<p>
<table><tr><th>Name</th><th>Parameters</th><th>Notes</th></tr>
<tr><td>OnNextBlock</td><td>BlockX, BlockY, BlockZ, BlockType, BlockMeta, EntryFace</td>
<td>Called when the ray hits a new valid block. The block type and meta is given. EntryFace is one of the
BLOCK_FACE_ constants indicating which "side" of the block got hit by the ray.</td></tr>
<tr><td>OnNextBlockNoData</td><td>BlockX, BlockY, BlockZ, EntryFace</td>
<td>Called when the ray hits a new block, but the block is in an unloaded chunk - no valid data is
available. Only the coords and the entry face are given.</td></tr>
<tr><td>OnOutOfWorld</td><td>X, Y, Z</td>
<td>Called when the ray goes outside of the world (Y-wise); the coords specify the exact exit point. Note
that for other paths than lines (considered for future implementations) the path may leave the world and
go back in again later, in such a case this callback is followed by OnIntoWorld() and further
OnNextBlock() calls.</td></tr>
<tr><td>OnIntoWorld</td><td>X, Y, Z</td>
<td>Called when the ray enters the world (Y-wise); the coords specify the exact entry point.</td></tr>
<tr><td>OnNoMoreHits</td><td>&nbsp;</td>
<td>Called when the path is sure not to hit any more blocks. This is the final callback, no more
callbacks are called after this function. Unlike the other callbacks, this function doesn't have a return
value.</td></tr>
<tr><td>OnNoChunk</td><td>&nbsp;</td>
<td>Called when the ray enters a chunk that is not loaded. This usually means that the tracing is aborted.
Unlike the other callbacks, this function doesn't have a return value.</td></tr>
</table>
]],
},
{
Header = "Example",
Contents = [[
<p>The following example is taken from the Debuggers plugin. It is a command handler function for the
"/spidey" command that creates a line of cobweb blocks from the player's eyes up to 50 blocks away in
the direction they're looking, but only through the air.
<pre class="prettyprint lang-lua">
function HandleSpideyCmd(a_Split, a_Player)
local World = a_Player:GetWorld();
local Callbacks = {
OnNextBlock = function(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta)
if (a_BlockType ~= E_BLOCK_AIR) then
-- abort the trace
return true;
end
World:SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_COBWEB, 0);
end
};
local EyePos = a_Player:GetEyePosition();
local LookVector = a_Player:GetLookVector();
LookVector:Normalize(); -- Make the vector 1 m long
-- Start cca 2 blocks away from the eyes
local Start = EyePos + LookVector + LookVector;
local End = EyePos + LookVector * 50;
cLineBlockTracer.Trace(World, Callbacks, Start.x, Start.y, Start.z, End.x, End.y, End.z);
return true;
end
</pre>
</p>
]],
},
}, -- AdditionalInfo
}, -- cLineBlockTracer
cTracer =
{
Desc = [[
A cTracer object is used to trace lines in the world. One thing you can use the cTracer for, is
tracing what block a player is looking at, but you can do more with it if you want.</p>
<p>
The cTracer is still a work in progress.</p>
<p>
See also the {{cLineBlockTracer}} class for an alternative approach using callbacks.
]],
Functions =
{
},
}, -- cTracer
Vector3d =
{
Desc = [[
A Vector3d object uses double precision floating point values to describe a point in 3D space.</p>
<p>
See also {{Vector3f}} for single-precision floating point 3D coords and {{Vector3i}} for integer
3D coords.
]],
Functions =
{
constructor =
{
{ Params = "{{Vector3f}}", Return = "Vector3d", Notes = "Creates a new Vector3d object by copying the coords from the given Vector3f." },
{ Params = "", Return = "Vector3d", Notes = "Creates a new Vector3d object with all its coords set to 0." },
{ Params = "X, Y, Z", Return = "Vector3d", Notes = "Creates a new Vector3d object with its coords set to the specified values." },
},
operator_div = { Params = "number", Return = "Vector3d", Notes = "Returns a new Vector3d with each coord divided by the specified number." },
operator_mul = { Params = "number", Return = "Vector3d", Notes = "Returns a new Vector3d with each coord multiplied." },
operator_sub = { Params = "Vector3d", Return = "Vector3d", Notes = "Returns a new Vector3d containing the difference between this object and the specified vector." },
operator_plus = {Params = "Vector3d", Return = "Vector3d", Notes = "Returns a new Vector3d containing the sum of this vector and the specified vector" },
Cross = { Params = "Vector3d", Return = "Vector3d", Notes = "Returns a new Vector3d that is a {{http://en.wikipedia.org/wiki/Cross_product|cross product}} of this vector and the specified vector." },
Dot = { Params = "Vector3d", Return = "number", Notes = "Returns the dot product of this vector and the specified vector." },
Equals = { Params = "Vector3d", Return = "bool", Notes = "Returns true if this vector is exactly equal to the specified vector." },
Length = { Params = "", Return = "number", Notes = "Returns the (euclidean) length of the vector." },
LineCoeffToXYPlane = { Params = "Vector3d, Z", Return = "number", Notes = "Returns the coefficient for the line from the specified vector through this vector to reach the specified Z coord. The result satisfies the following equation: (this + Result * (Param - this)).z = Z. Returns the NO_INTERSECTION constant if there's no intersection." },
LineCoeffToXZPlane = { Params = "Vector3d, Y", Return = "number", Notes = "Returns the coefficient for the line from the specified vector through this vector to reach the specified Y coord. The result satisfies the following equation: (this + Result * (Param - this)).y = Y. Returns the NO_INTERSECTION constant if there's no intersection." },
LineCoeffToYZPlane = { Params = "Vector3d, X", Return = "number", Notes = "Returns the coefficient for the line from the specified vector through this vector to reach the specified X coord. The result satisfies the following equation: (this + Result * (Param - this)).x = X. Returns the NO_INTERSECTION constant if there's no intersection." },
Normalize = { Params = "", Return = "", Notes = "Changes this vector so that it keeps current direction but is exactly 1 unit long. FIXME: Fails for a zero vector." },
NormalizeCopy = { Params = "", Return = "Vector3d", Notes = "Returns a new vector that has the same directino as this but is exactly 1 unit long. FIXME: Fails for a zero vector." },
Set = { Params = "X, Y, Z", Return = "", Notes = "Sets all the coords in this object." },
SqrLength = { Params = "", Return = "number", Notes = "Returns the (euclidean) length of this vector, squared. This operation is slightly less computationally expensive than Length(), while it conserves some properties of Length(), such as comparison. " },
},
Constants =
{
EPS = { Notes = "The max difference between two coords for which the coords are assumed equal (in LineCoeffToXYPlane() et al)." },
NO_INTERSECTION = { Notes = "Special return value for the LineCoeffToXYPlane() et al meaning that there's no intersectino with the plane." },
},
Variables =
{
x = { Type = "number", Notes = "The X coord of the vector." },
y = { Type = "number", Notes = "The Y coord of the vector." },
z = { Type = "number", Notes = "The Z coord of the vector." },
},
}, -- Vector3d
Vector3f =
{
Desc = [[
A Vector3f object uses floating point values to describe a point in space.</p>
<p>
See also {{Vector3d}} for double-precision floating point 3D coords and {{Vector3i}} for integer
3D coords.
]],
Functions =
{
constructor =
{
{ Params = "", Return = "Vector3f", Notes = "Creates a new Vector3f object with zero coords" },
{ Params = "x, y, z", Return = "Vector3f", Notes = "Creates a new Vector3f object with the specified coords" },
{ Params = "Vector3f", Return = "Vector3f", Notes = "Creates a new Vector3f object as a copy of the specified vector" },
{ Params = "{{Vector3d}}", Return = "Vector3f", Notes = "Creates a new Vector3f object as a copy of the specified {{Vector3d}}" },
{ Params = "{{Vector3i}}", Return = "Vector3f", Notes = "Creates a new Vector3f object as a copy of the specified {{Vector3i}}" },
},
operator_mul =
{
{ Params = "number", Return = "Vector3f", Notes = "Returns a new Vector3f object that has each of its coords multiplied by the specified number" },
{ Params = "Vector3f", Return = "Vector3f", Notes = "Returns a new Vector3f object that has each of its coords multiplied by the respective coord of the specified vector." },
},
operator_plus = { Params = "Vector3f", Return = "Vector3f", Notes = "Returns a new Vector3f object that holds the vector sum of this vector and the specified vector." },
operator_sub = { Params = "Vector3f", Return = "Vector3f", Notes = "Returns a new Vector3f object that holds the vector differrence between this vector and the specified vector." },
Cross = { Params = "Vector3f", Return = "Vector3f", Notes = "Returns a new Vector3f object that holds the cross product of this vector and the specified vector." },
Dot = { Params = "Vector3f", Return = "number", Notes = "Returns the dot product of this vector and the specified vector." },
Equals = { Params = "Vector3f", Return = "bool", Notes = "Returns true if the specified vector is exactly equal to this vector." },
Length = { Params = "", Return = "number", Notes = "Returns the (euclidean) length of this vector" },
Normalize = { Params = "", Return = "", Notes = "Normalizes this vector (makes it 1 unit long while keeping the direction). FIXME: Fails for zero vectors." },
NormalizeCopy = { Params = "", Return = "Vector3f", Notes = "Returns a copy of this vector that is normalized (1 unit long while keeping the same direction). FIXME: Fails for zero vectors." },
Set = { Params = "x, y, z", Return = "", Notes = "Sets all the coords of the vector at once." },
SqrLength = { Params = "", Return = "number", Notes = "Returns the (euclidean) length of this vector, squared. This operation is slightly less computationally expensive than Length(), while it conserves some properties of Length(), such as comparison." },
},
Variables =
{
x = { Type = "number", Notes = "The X coord of the vector." },
y = { Type = "number", Notes = "The Y coord of the vector." },
z = { Type = "number", Notes = "The Z coord of the vector." },
},
}, -- Vector3f
Vector3i =
{
Desc = [[
A Vector3i object uses integer values to describe a point in space.</p>
<p>
See also {{Vector3d}} for double-precision floating point 3D coords and {{Vector3f}} for
single-precision floating point 3D coords.
]],
Functions =
{
constructor =
{
{ Params = "", Return = "Vector3i", Notes = "Creates a new Vector3i object with zero coords." },
{ Params = "x, y, z", Return = "Vector3i", Notes = "Creates a new Vector3i object with the specified coords." },
{ Params = "{{Vector3d}}", Return = "Vector3i", Notes = "Creates a new Vector3i object with coords copied and floor()-ed from the specified {{Vector3d}}." },
},
Equals = { Params = "Vector3i", Return = "bool", Notes = "Returns true if this vector is exactly the same as the specified vector." },
Length = { Params = "", Return = "number", Notes = "Returns the (euclidean) length of this vector." },
Move = { Params = "X, Y, Z", Return = "", Notes = "Moves the vector by the specified amount in each axis direction." },
Set = { Params = "x, y, z", Return = "", Notes = "Sets all the coords of the vector at once" },
SqrLength = { Params = "", Return = "number", Notes = "Returns the (euclidean) length of this vector, squared. This operation is slightly less computationally expensive than Length(), while it conserves some properties of Length(), such as comparison." },
},
Variables =
{
x = { Type = "number", Notes = "The X coord of the vector." },
y = { Type = "number", Notes = "The Y coord of the vector." },
z = { Type = "number", Notes = "The Z coord of the vector." },
},
}, -- Vector3i
}

View File

@ -0,0 +1,40 @@
return
{
HOOK_BLOCK_SPREAD =
{
CalledWhen = "Called when a block spreads based on world conditions",
DefaultFnName = "OnBlockSpread", -- also used as pagename
Desc = [[
This hook is called when a block spreads.</p>
<p>
The spread carries with it the type of its source - whether it's a block spreads.
It also carries the identification of the actual source. The exact type of the identification
depends on the source kind:
<table>
<tr><th>Source</th><th>Notes</th></tr>
<tr><td>ssFireSpread</td><td>Fire spreading</td></tr>
<tr><td>ssGrassSpread</td><td>Grass spreading</td></tr>
<tr><td>ssMushroomSpread</td><td>Mushroom spreading</td></tr>
<tr><td>ssMycelSpread</td><td>Mycel spreading</td></tr>
<tr><td>ssVineSpread</td><td>Vine spreading</td></tr>
</table></p>
]],
Params =
{
{ Name = "World", Type = "{{cWorld}}", Notes = "The world in which the block resides" },
{ Name = "BlockX", Type = "number", Notes = "X-coord of the block" },
{ Name = "BlockY", Type = "number", Notes = "Y-coord of the block" },
{ Name = "BlockZ", Type = "number", Notes = "Z-coord of the block" },
{ Name = "Source", Type = "eSpreadSource", Notes = "Source of the spread. See the table above." },
},
Returns = [[
If the function returns false or no value, the next plugin's callback is called, and finally
MCServer will process the spread. If the function
returns true, no other callback is called for this event and the spread will not occur.
]],
}, -- HOOK_BLOCK_SPREAD
}

View File

@ -5,13 +5,10 @@ return
CalledWhen = "A player has explicitly disconnected.",
DefaultFnName = "OnDisconnect", -- also used as pagename
Desc = [[
This hook is called when a client sends the disconnect packet and is about to be disconnected from
the server.</p>
<p>
Note that this callback is not called if the client drops the connection or is kicked by the
server.</p>
<p>
FIXME: There is no callback for "client destroying" that would be called in all circumstances.</p>
This hook is called when a client is about to be disconnected from the server, for whatever reason.
<p><b>Note that this hook will be removed after <1.7 protocol support is removed, as it was originally a hook for
the client sending the server a disconnect packet, which no longer happens.</b></p>
]],
Params =
{
@ -19,9 +16,8 @@ return
{ Name = "Reason", Type = "string", Notes = "The reason that the client has sent in the disconnect packet" },
},
Returns = [[
If the function returns false or no value, MCServer calls other plugins' callbacks for this event
and finally broadcasts a disconnect message to the player's world. If the function returns true, no
other plugins are called for this event and the disconnect message is not broadcast. In either case,
If the function returns false or no value, MCServer calls other plugins' callbacks for this event.
If the function returns true, no other plugins are called for this event. In either case,
the player is disconnected.
]],
}, -- HOOK_DISCONNECT

View File

@ -0,0 +1,27 @@
return
{
HOOK_PLAYER_DESTROYED =
{
CalledWhen = "A player object is about to be destroyed.",
DefaultFnName = "OnPlayerDestroyed", -- also used as pagename
Desc = [[
This function is called before a {{cPlayer|player}} is about to be destroyed.
The player has disconnected for whatever reason and is no longer in the server.
If a plugin returns true, a leave message is not broadcast, and vice versa.
However, whatever the return value, the player object is removed from memory.
]],
Params =
{
{ Name = "Player", Type = "{{cPlayer}}", Notes = "The destroyed player" },
},
Returns = [[
If the function returns false or no value, other plugins' callbacks are called and a leave message is broadcast.
If the function returns true, no other callbacks are called for this event and no leave message appears. Either way the player is removed internally.
]],
}, -- HOOK_PLAYER_DESTROYED
}

View File

@ -9,16 +9,16 @@ return
enabled, this function is called after their name has been authenticated. It is called after
{{OnLogin|HOOK_LOGIN}} and before {{OnPlayerSpawned|HOOK_PLAYER_SPAWNED}}, right after the player's
entity is created, but not added to the world yet. The player is not yet visible to other players.
This is a notification-only event, plugins wishing to refuse player's entry should kick the player
using the {{cPlayer}}:Kick() function.
Returning true will block a join message from being broadcast, but otherwise, the player is still allowed to join.
Plugins wishing to refuse player's entry should kick the player using the {{cPlayer}}:Kick() function.
]],
Params =
{
{ Name = "Player", Type = "{{cPlayer}}", Notes = "The player who has joined the game" },
},
Returns = [[
If the function returns false or no value, other plugins' callbacks are called. If the function
returns true, no other callbacks are called for this event. Either way the player is let in.
If the function returns false or no value, other plugins' callbacks are called and a join message is broadcast. If the function
returns true, no other callbacks are called for this event and a join message is not sent. Either way the player is let in.
]],
}, -- HOOK_PLAYER_JOINED
}

View File

@ -5,7 +5,7 @@ return
CalledWhen = "A player is tossing an item. Plugin may override / refuse.",
DefaultFnName = "OnPlayerTossingItem", -- also used as pagename
Desc = [[
This hook is called when a {{cPlayer|player}} has tossed an item (Q keypress). The
This hook is called when a {{cPlayer|player}} has tossed an item. The
{{cPickup|pickup}} has not been spawned yet. Plugins may disallow the tossing, but in that case they
need to clean up - the player's client already thinks the item has been tossed so the
{{cInventory|inventory}} needs to be re-sent to the player.</p>
@ -18,8 +18,9 @@ return
},
Returns = [[
If the function returns false or no value, other plugins' callbacks are called and finally MCServer
creates the pickup for the item and tosses it, using {{cPlayer}}:TossItem. If the function returns
true, no other callbacks are called for this event and MCServer doesn't toss the item.
creates the pickup for the item and tosses it, using {{cPlayer}}:TossHeldItem, {{cPlayer}}:TossEquippedItem,
or {{cPlayer}}:TossPickup. If the function returns true, no other callbacks are called for this event
and MCServer doesn't toss the item.
]],
}, -- HOOK_PLAYER_TOSSING_ITEM
}

View File

@ -0,0 +1,24 @@
return
{
HOOK_PROJECTILE_HIT_BLOCK =
{
CalledWhen = "A projectile hits a solid block.",
DefaultFnName = "OnProjectileHitBlock", -- also used as pagename
Desc = [[
This hook is called when a {{cProjectileEntity|projectile}} hits a solid block..
]],
Params =
{
{ Name = "ProjectileEntity", Type = "{{cProjectileEntity}}", Notes = "The projectile that hit an entity." },
},
Returns = [[
If the function returns false or no value, the next plugin's callback is called. If the function
returns true, no other callback is called for this event and the projectile flies through block..
]],
}, -- HOOK_PROJECTILE_HIT_BLOCK
}

View File

@ -0,0 +1,25 @@
return
{
HOOK_PROJECTILE_HIT_ENTITY =
{
CalledWhen = "A projectile hits another entity.",
DefaultFnName = "OnProjectileHitEntity", -- also used as pagename
Desc = [[
This hook is called when a {{cProjectileEntity|projectile}} hits another entity.
]],
Params =
{
{ Name = "ProjectileEntity", Type = "{{cProjectileEntity}}", Notes = "The projectile that hit an entity." },
{ Name = "Entity", Type = "{{cEntity}}", Notes = "The entity wich was hit." },
},
Returns = [[
If the function returns false or no value, the next plugin's callback is called. If the function
returns true, no other callback is called for this event and the projectile flies through the entity.
]],
}, -- HOOK_PROJECTILE_HIT_ENTITY
}

View File

@ -0,0 +1,46 @@
<!DOCTYPE html>
<html>
<head>
<title>MCServer - Setting up ZeroBrane Studio</title>
<link rel="stylesheet" type="text/css" href="main.css" />
<link rel="stylesheet" type="text/css" href="prettify.css" />
<script src="prettify.js"></script>
<script src="lang-lua.js"></script>
<meta charset="UTF-8">
</head>
<body>
<div id="content">
<h1>Setting up the ZeroBrane Studio IDE</h1>
<p>
This article will explain how to set up ZeroBrane Studio, an IDE for writing Lua code, so that you can develop MCServer plugins with the comfort of an IDE.</p>
<h2><img src="Static/zbs_logo.png" /> About ZeroBrane Studio</h2>
<p>To quickly introduce ZeroBrane Studio, it is an IDE for writing Lua code. It has the basic features expected of an IDE - it allows you to manage groups of files as a project, you can edit multiple files in a tabbed editor, the code is syntax-highlighted. Code completion, symbol browsing, and more. It also features a Lua debugger that allows you to debug your Lua code within any application that uses Lua and can load Lua packages. It is written using the multiplatform WxWidgets toolkit, and runs on multiple platforms, including Windows, Linux and MacOS.</p>
<p>Here's a screenshot of a default ZBS window with the debugger stepping through the code (scaled down):<br />
<img src="Static/zbs_workspace.png" /></p>
<p>As you can see, you can set breakpoints in the code, inspect variables' values, view the Lua call-stacks.</p>
<p>ZBS is open-source, the sources are on GitHub: <a href="https://github.com/pkulchenko/ZeroBraneStudio">https://github.com/pkulchenko/ZeroBraneStudio</a>. The project's homepage is at <a href="http://studio.zerobrane.com/">http://studio.zerobrane.com/</a>.
<h2><img src="Static/zbs_logo.png" /> First-time setup</h2>
<p>Since ZBS is a universal Lua IDE, you need to first set it up so that it is ready for MCS plugin development. For that, you need to download one file, <a href="https://raw.githubusercontent.com/pkulchenko/ZeroBranePackage/master/mcserver.lua">mcserver.lua</a> from the <a href="https://github.com/pkulchenko/ZeroBranePackage">ZBS's plugin repository</a>. Place that file in the "packages" folder inside your ZBS's folder. Note that there are other useful plugins in the repository and you may want to have a look there later on to further customize your ZBS. To install them, simply save them into the same folder.</p>
<p>Next you should install the code-completion support specific for MCServer. You should repeat this step from time to time, because the API evolves in time so new functions and classes are added to it quite often. You should have an APIDump plugin in your MCServer installation. Enable the APIDump plugin in the server settings, it's very cheap to keep it enabled and it doesn't cost any performance during normal gameplay. To generate the code-completion support file, enter the <code style="background: #ddd; border: 1px solid #aaa">api</code> command into the server console. This will create a new file, "mcserver_api.lua", next to the MCS executable. Move that file into the "api/lua" subfolder inside your ZBS's folder.</p>
<p>After you download the mcserver.lua file and install the completion support, you need to restart ZBS in order for the plugin to load. If there are no errors, you should see two new items in the Project -> Lua Interpreter submenu: "MCServer - debug mode" and "MCServer - release mode". The only difference between the two is which filename they use to launch MCServer - mcserver_debug(.exe) for the debug option and "mcserver(.exe)" for the release option. If you built your own MCServer executable and you built it in debug mode, you should select the debug mode option. In all other cases, including if you downloaded the already-compiled MCServer executable from the internet, you should select the release mode option.</p>
<p>For a first time user, it might be a bit overwhelming that there are no GUI settings in the ZBS, yet the IDE is very configurable. There are two files that you edit in order to change settings, either system-wide (all users of the computer share those settings) or user-wide (the settings are only for a specific user of the computer). Those files are regular Lua sources and you can quickly locate them and edit them from within the IDE itself, select Edit -> Preferences -> Settings: XYZ from the menu, with XYZ being either System or User.</p>
<p>There is a documentation on most of the settings on ZBS's webpage, have a look at <a href="http://studio.zerobrane.com/documentation.html">http://studio.zerobrane.com/documentation.html</a>, especially the Preferences section. Personally I recommend setting editor.usetabs to true and possibly adjusting the editor.tabwidth, turn off the editor.smartindent feature and for debugging the option debugger.alloweditting should be set to true unless you feel like punishing yourself.</p>
<h2><img src="Static/zbs_logo.png" /> Project management</h2>
<p>ZBS works with projects, it considers all files and subfolder in a specific folder to be a project. There's no need for a special project file nor for adding individual files to the workspace, all files are added automatically. To open a MCS plugin as the project, click the triple-dot button in the Project pane, or select Project -> Project directory -> Choose... from the menu. Browse and select the MCS plugin's folder. ZBS will load all the files in the plugin's folder and you can start editting code.</p>
<p>Note that although ZBS allows you to work with subfolders in your plugins (and you should, especially with larger plugins), the current mcserver ZBS plugin will not be able to start debugging unless you have a file open in the editor that is at the root level of the MCS plugin's folder.</p>
<h2><img src="Static/zbs_logo.png" /> Debugging</h2>
<p>You are now ready to debug your code. Before doing that, though, don't forget to save your project files. If you haven't done so already, enable your plugin in the settings.ini file. If you want the program to break at a certain line, it is best to set the breakpoint before starting the program. Set the cursor on the line and hit F9 (or use menu Project -> Toggle Breakpoint) to toggle a breakpoint on that line. Finally, hit F5, or select menu Project -> Start Debugging to launch MCServer under the debugger. The MCServer window comes up and loads your plugin. If the window doesn't come up, inspect the Output pane in ZBS, there are usually two reasons for failure:<ul>
<li>Your code in the currently open file has a hard syntax error. These are reported as "Compilation error" in the Output pane, double-click the line to go to the error</li>
<li>ZBS cannot find the MCServer executable. Make sure you are editting a file two levels down the folder hierarchy from the MCS executable and that the MCS executable is named properly (mcserver[.exe] or mcserver_debug[.exe]). Also make sure you have selected the right Interpreter (menu Project -> Lua Interpreter).</li>
</ul></p>
<p>Once running, if the execution hits a breakpoint, the ZBS window will come up and a green arrow is displayed next to the breakpoint line. You can step through the code using F10 (Step Into) and Shift+F10 (Step Over). You can also use the Watch window to inspect variable values, or simply hover your mouse over a variable to display its value in the tooltip. Use the Remote console pane to execute commands directly *inside* the MCServer's plugin context.</p>
<p>You can also use the Project -> Break menu item to break into the debugger as soon as possible. You can also set breakpoints while the MCS plugin is running. Note that due to the way in which the debugger is implemented, MCS may execute some more Lua code before the break / breakpoint comes into effect. If MCS is not executing any Lua code in your plugin, it will not break until the plugin code kicks in again. This may result in missed breakpoints and delays before the Break command becomes effective. Therefore it's best to set breakpoints before running the program, or while the program is waiting in another breakpoint.</p>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

View File

@ -20,13 +20,7 @@
<p>
Let us begin. In order to begin development, we must firstly obtain a compiled copy
of MCServer, and make sure that the Core plugin is within the Plugins folder, and activated.
Core handles much of the MCServer end-user experience and is a necessary component of
plugin development, as necessary plugin components depend on sone of its functions.
</p>
<p>
Next, we must obtain a copy of CoreMessaging.lua. This can be found
<a href="https://raw.github.com/mc-server/MCServer/master/MCServer/Plugins/MagicCarpet/coremessaging.lua">here.</a>
This is used to provide messaging support that is compliant with MCServer standards.
Core handles much of the MCServer end-user experience and gameplay will be very bland without it.
</p>
<h2>Creating the basic template</h2>
<p>
@ -35,18 +29,17 @@
Format it like so:
</p>
<pre class="prettyprint lang-lua">
local PLUGIN
PLUGIN = nil
function Initialize(Plugin)
Plugin:SetName("DerpyPlugin")
Plugin:SetName("NewPlugin")
Plugin:SetVersion(1)
PLUGIN = Plugin
-- Hooks
local PluginManager = cPluginManager:Get()
-- Command bindings
PLUGIN = Plugin -- NOTE: only needed if you want OnDisable() to use GetName() or something like that
-- Command Bindings
LOG("Initialised " .. Plugin:GetName() .. " v." .. Plugin:GetVersion())
return true
@ -63,7 +56,8 @@ end
<li><b>Plugin:SetName</b> sets the name of the plugin.</li>
<li><b>Plugin:SetVersion</b> sets the revision number of the plugin. This must be an integer.</li>
<li><b>LOG</b> logs to console a message, in this case, it prints that the plugin was initialised.</li>
<li>The <b>PLUGIN</b> variable just stores this plugin's object, so GetName() can be called in OnDisable (as no Plugin parameter is passed there, contrary to Initialize).</li>
<li>The <b>PLUGIN</b> variable just stores this plugin's object, so GetName() can be called in OnDisable (as no Plugin parameter is passed there, contrary to Initialize).
This global variable is only needed if you want to know the plugin details (name, etc.) when shutting down.</li>
<li><b>function OnDisable</b> is called when the plugin is disabled, commonly when the server is shutting down. Perform cleanup and logging here.</li>
</ul>
Be sure to return true for this function, else MCS thinks you plugin had failed to initialise and prints a stacktrace with an error message.
@ -84,7 +78,7 @@ end
To register a hook, insert the following code template into the "-- Hooks" area in the previous code example.
</p>
<pre class="prettyprint lang-lua">
cPluginManager:AddHook(cPluginManager.HOOK_NAME_HERE, FunctionNameToBeCalled)
cPluginManager.AddHook(cPluginManager.HOOK_NAME_HERE, FunctionNameToBeCalled)
</pre>
<p>
What does this code do?
@ -102,10 +96,7 @@ function Initialize(Plugin)
Plugin:SetName("DerpyPlugin")
Plugin:SetVersion(1)
cPluginManager:AddHook(cPluginManager.HOOK_PLAYER_MOVING, OnPlayerMoving)
local PluginManager = cPluginManager:Get()
-- Command bindings
cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_MOVING, OnPlayerMoving)
LOG("Initialised " .. Plugin:GetName() .. " v." .. Plugin:GetVersion())
return true
@ -127,10 +118,10 @@ end
</p>
<pre class="prettyprint lang-lua">
-- ADD THIS IF COMMAND DOES NOT REQUIRE A PARAMETER (/explode)
PluginManager:BindCommand("/commandname", "permissionnode", FunctionToCall, " - Description of command")
cPluginManager.BindCommand("/commandname", "permissionnode", FunctionToCall, " - Description of command")
-- ADD THIS IF COMMAND DOES REQUIRE A PARAMETER (/explode Notch)
PluginManager:BindCommand("/commandname", "permissionnode", FunctionToCall, " ~ Description of command and parameter(s)")
cPluginManager.BindCommand("/commandname", "permissionnode", FunctionToCall, " ~ Description of command and parameter(s)")
</pre>
<p>
What does it do, and why are there two?
@ -167,21 +158,23 @@ PluginManager:BindCommand("/commandname", "permissionnode", FunctionToCall, " ~
a message. Again, see the API documentation for fuller details. But, you ask, how <i>do</i> we send a message to the client?
</p>
<p>
Remember that copy of CoreMessaging.lua that we downloaded earlier? Make sure that file is in your plugin folder, along with the main.lua file you are typing
your code in. Since MCS brings all the files together on JIT compile, we don't need to worry about requiring any files or such. Simply follow the below examples:
There are dedicated functions used for sending a player formatted messages. By format, I refer to coloured prefixes/coloured text (depending on configuration)
that clearly categorise what type of message a player is being sent. For example, an informational message has a yellow coloured [INFO] prefix, and a warning message
has a rose coloured [WARNING] prefix. A few of the most used functions are listed here, but see the API docs for more details. Look in the cRoot, cWorld, and cPlayer sections
for functions that broadcast to the entire server, the whole world, and a single player, respectively.
</p>
<pre class="prettyprint lang-lua">
-- Format: §yellow[INFO] §white%text% (yellow [INFO], white text following it)
-- Use: Informational message, such as instructions for usage of a command
SendMessage(Player, "Usage: /explode [player]")
Player:SendMessageInfo("Usage: /explode [player]")
-- Format: §green[INFO] §white%text% (green [INFO] etc.)
-- Use: Success message, like when a command executes successfully
SendMessageSuccess(Player, "Notch was blown up!")
Player:SendMessageSuccess("Notch was blown up!")
-- Format: §rose[INFO] §white%text% (rose coloured [INFO] etc.)
-- Use: Failure message, like when a command was entered correctly but failed to run, such as when the destination player wasn't found in a /tp command
SendMessageFailure(Player, "Player Salted was not found")
Player:SendMessageFailure("Player Salted was not found")
</pre>
<p>
Those are the basics. If you want to output text to the player for a reason other than the three listed above, and you want to colour the text, simply concatenate
@ -197,8 +190,7 @@ function Initialize(Plugin)
Plugin:SetName("DerpyPluginThatBlowsPeopleUp")
Plugin:SetVersion(9001)
local PluginManager = cPluginManager:Get()
PluginManager:BindCommand("/explode", "derpyplugin.explode", Explode, " ~ Explode a player");
cPluginManager.BindCommand("/explode", "derpyplugin.explode", Explode, " ~ Explode a player");
cPluginManager:AddHook(cPluginManager.HOOK_COLLECTING_PICKUP, OnCollectingPickup)

File diff suppressed because it is too large Load Diff

View File

@ -122,7 +122,7 @@ function OnTick( DeltaTime )
end
end
WW_instance:QueueSaveAllChunks()
WW_instance:UnloadUnusedChunks()
WW_instance:QueueUnloadUnusedChunks()
end
end
end

View File

@ -44,7 +44,7 @@ function HandleRequest_Generation( Request )
if (Request.PostParams["AGHRRRR"] ~= nil) then
GENERATION_STATE = 0
WW_instance:SaveAllChunks()
WW_instance:UnloadUnusedChunks()
WW_instance:QueueUnloadUnusedChunks()
LOGERROR("" .. PLUGIN:GetName() .. " v" .. PLUGIN:GetVersion() .. ": works ABORTED by admin")
end
--Content = Content .. "<head><meta http-equiv=\"refresh\" content=\"2;\"></head>"

@ -1 +1 @@
Subproject commit 759cf48ba3f1409e6d7b60cb821ee17e589bdef8
Subproject commit 013a32a7fb3c8a6cfe0aef892d4c7394d4e1be59

View File

@ -19,18 +19,21 @@ function Initialize(Plugin)
cPluginManager.AddHook(cPluginManager.HOOK_TICK, OnTick2);
--]]
cPluginManager:AddHook(cPluginManager.HOOK_PLAYER_USING_BLOCK, OnPlayerUsingBlock);
cPluginManager:AddHook(cPluginManager.HOOK_PLAYER_USING_ITEM, OnPlayerUsingItem);
cPluginManager:AddHook(cPluginManager.HOOK_TAKE_DAMAGE, OnTakeDamage);
cPluginManager:AddHook(cPluginManager.HOOK_TICK, OnTick);
cPluginManager:AddHook(cPluginManager.HOOK_CHAT, OnChat);
cPluginManager:AddHook(cPluginManager.HOOK_PLAYER_RIGHT_CLICKING_ENTITY, OnPlayerRightClickingEntity);
cPluginManager:AddHook(cPluginManager.HOOK_WORLD_TICK, OnWorldTick);
cPluginManager:AddHook(cPluginManager.HOOK_CHUNK_GENERATED, OnChunkGenerated);
cPluginManager:AddHook(cPluginManager.HOOK_PLUGINS_LOADED, OnPluginsLoaded);
cPluginManager:AddHook(cPluginManager.HOOK_PLUGIN_MESSAGE, OnPluginMessage);
local PM = cPluginManager;
PM:AddHook(cPluginManager.HOOK_PLAYER_USING_BLOCK, OnPlayerUsingBlock);
PM:AddHook(cPluginManager.HOOK_PLAYER_USING_ITEM, OnPlayerUsingItem);
PM:AddHook(cPluginManager.HOOK_TAKE_DAMAGE, OnTakeDamage);
PM:AddHook(cPluginManager.HOOK_TICK, OnTick);
PM:AddHook(cPluginManager.HOOK_CHAT, OnChat);
PM:AddHook(cPluginManager.HOOK_PLAYER_RIGHT_CLICKING_ENTITY, OnPlayerRightClickingEntity);
PM:AddHook(cPluginManager.HOOK_WORLD_TICK, OnWorldTick);
PM:AddHook(cPluginManager.HOOK_PLUGINS_LOADED, OnPluginsLoaded);
PM:AddHook(cPluginManager.HOOK_PLUGIN_MESSAGE, OnPluginMessage);
PM:AddHook(cPluginManager.HOOK_PLAYER_JOINED, OnPlayerJoined)
-- _X: Disabled so that the normal operation doesn't interfere with anything
-- PM:AddHook(cPluginManager.HOOK_CHUNK_GENERATED, OnChunkGenerated);
PM = cRoot:Get():GetPluginManager();
PM:BindCommand("/le", "debuggers", HandleListEntitiesCmd, "- Shows a list of all the loaded entities");
PM:BindCommand("/ke", "debuggers", HandleKillEntitiesCmd, "- Kills all the loaded entities");
PM:BindCommand("/wool", "debuggers", HandleWoolCmd, "- Sets all your armor to blue wool");
@ -53,18 +56,36 @@ function Initialize(Plugin)
PM:BindCommand("/fr", "debuggers", HandleFurnaceRecipe, "- Shows the furnace recipe for the currently held item");
PM:BindCommand("/ff", "debuggers", HandleFurnaceFuel, "- Shows how long the currently held item would burn in a furnace");
PM:BindCommand("/sched", "debuggers", HandleSched, "- Schedules a simple countdown using cWorld:ScheduleTask()");
PM:BindCommand("/cs", "debuggers", HandleChunkStay, "- Tests the ChunkStay Lua integration for the specified chunk coords");
PM:BindCommand("/compo", "debuggers", HandleCompo, "- Tests the cCompositeChat bindings")
PM:BindCommand("/sb", "debuggers", HandleSetBiome, "- Sets the biome around you to the specified one")
PM:BindCommand("/wesel", "debuggers", HandleWESel, "- Expands the current WE selection by 1 block in X/Z")
Plugin:AddWebTab("Debuggers", HandleRequest_Debuggers);
Plugin:AddWebTab("Debuggers", HandleRequest_Debuggers)
Plugin:AddWebTab("StressTest", HandleRequest_StressTest)
-- Enable the following line for BlockArea / Generator interface testing:
-- PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_GENERATED);
LOG("Initialized " .. Plugin:GetName() .. " v." .. Plugin:GetVersion())
-- TestBlockAreas();
-- TestSQLiteBindings();
-- TestExpatBindings();
-- TestBlockAreas()
-- TestSQLiteBindings()
-- TestExpatBindings()
-- TestPluginCalls()
TestBlockAreasString()
TestStringBase64()
--[[
-- Test cCompositeChat usage in console-logging:
LOGINFO(cCompositeChat("This is a simple message with some @2 color formatting @4 and http://links.to .")
:AddSuggestCommandPart("(Suggested command)", "cmd")
:AddRunCommandPart("(Run command)", "cmd")
:SetMessageType(mtInfo)
)
--]]
return true
end;
@ -72,6 +93,38 @@ end;
function TestPluginCalls()
-- In order to test the inter-plugin communication, we're going to call Core's ReturnColorFromChar() function
-- It is a rather simple function that doesn't need any tables as its params and returns a value, too
-- Note the signature: function ReturnColorFromChar( Split, char ) ... return cChatColog.Gray ... end
-- The Split parameter should be a table, but it is not used in that function anyway,
-- so we can get away with passing nil to it.
-- Use the old, deprecated and unsafe method:
local Core = cPluginManager:Get():GetPlugin("Core")
if (Core ~= nil) then
LOGINFO("Calling Core::ReturnColorFromChar() the old-fashioned way...")
local Gray = Core:Call("ReturnColorFromChar", nil, "8")
if (Gray ~= cChatColor.Gray) then
LOGWARNING("Call failed, exp " .. cChatColor.Gray .. ", got " .. (Gray or "<nil>"))
else
LOGINFO("Call succeeded")
end
end
-- Use the new method:
LOGINFO("Calling Core::ReturnColorFromChar() the recommended way...")
local Gray = cPluginManager:CallPlugin("Core", "ReturnColorFromChar", nil, "8")
if (Gray ~= cChatColor.Gray) then
LOGWARNING("Call failed, exp " .. cChatColor.Gray .. ", got " .. (Gray or "<nil>"))
else
LOGINFO("Call succeeded")
end
end
function TestBlockAreas()
LOG("Testing block areas...");
@ -164,6 +217,60 @@ end
function TestBlockAreasString()
-- Write one area to string, then to file:
local BA1 = cBlockArea()
BA1:Create(5, 5, 5, cBlockArea.baTypes + cBlockArea.baMetas)
BA1:Fill(cBlockArea.baTypes, E_BLOCK_DIAMOND_BLOCK)
BA1:FillRelCuboid(1, 3, 1, 3, 1, 3, cBlockArea.baTypes, E_BLOCK_GOLD_BLOCK)
local Data = BA1:SaveToSchematicString()
if ((type(Data) ~= "string") or (Data == "")) then
LOG("Cannot save schematic to string")
return
end
cFile:CreateFolder("schematics")
local f = io.open("schematics/StringTest.schematic", "wb")
f:write(Data)
f:close()
-- Load a second area from that file:
local BA2 = cBlockArea()
if not(BA2:LoadFromSchematicFile("schematics/StringTest.schematic")) then
LOG("Cannot read schematic from string test file")
return
end
BA2:Clear()
-- Load another area from a string in that file:
f = io.open("schematics/StringTest.schematic", "rb")
Data = f:read("*all")
if not(BA2:LoadFromSchematicString(Data)) then
LOG("Cannot load schematic from string")
end
end
function TestStringBase64()
-- Create a binary string:
local s = ""
for i = 0, 255 do
s = s .. string.char(i)
end
-- Roundtrip through Base64:
local Base64 = Base64Encode(s)
local UnBase64 = Base64Decode(Base64)
assert(UnBase64 == s)
end
function TestSQLiteBindings()
LOG("Testing SQLite bindings...");
@ -1004,6 +1111,68 @@ end
local g_Counter = 0
local g_JavaScript =
[[
<script>
function createXHR()
{
var request = false;
try {
request = new ActiveXObject('Msxml2.XMLHTTP');
}
catch (err2)
{
try
{
request = new ActiveXObject('Microsoft.XMLHTTP');
}
catch (err3)
{
try
{
request = new XMLHttpRequest();
}
catch (err1)
{
request = false;
}
}
}
return request;
}
function RefreshCounter()
{
var xhr = createXHR();
xhr.onreadystatechange = function()
{
if (xhr.readyState == 4)
{
document.getElementById("cnt").innerHTML = xhr.responseText;
}
};
xhr.open("POST", "/~webadmin/Debuggers/StressTest", true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send("counter=true");
}
setInterval(RefreshCounter, 10)
</script>
]]
function HandleRequest_StressTest(a_Request)
if (a_Request.PostParams["counter"]) then
g_Counter = g_Counter + 1
return tostring(g_Counter)
end
return g_JavaScript .. "<p>The counter below should be reloading as fast as possible</p><div id='cnt'>0</div>"
end
function OnPluginMessage(a_Client, a_Channel, a_Message)
LOGINFO("Received a plugin message from client " .. a_Client:GetUsername() .. ": channel '" .. a_Channel .. "', message '" .. a_Message .. "'");
@ -1028,3 +1197,185 @@ end
function HandleChunkStay(a_Split, a_Player)
-- As an example of using ChunkStay, this call will load 3x3 chunks around the specified chunk coords,
-- then build an obsidian pillar in the middle of each one.
-- Once complete, the player will be teleported to the middle pillar
if (#a_Split ~= 3) then
a_Player:SendMessageInfo("Usage: /cs <ChunkX> <ChunkZ>")
return true
end
local ChunkX = tonumber(a_Split[2])
local ChunkZ = tonumber(a_Split[3])
if ((ChunkX == nil) or (ChunkZ == nil)) then
a_Player:SendMessageFailure("Invalid chunk coords.")
return true
end
local World = a_Player:GetWorld()
local PlayerID = a_Player:GetUniqueID()
a_Player:SendMessageInfo("Loading chunks, stand by...");
-- Set the wanted chunks:
local Chunks = {}
for z = -1, 1 do for x = -1, 1 do
table.insert(Chunks, {ChunkX + x, ChunkZ + z})
end end
-- The function that is called when all chunks are available
-- Will perform the actual action with all those chunks
-- Note that the player needs to be referenced using their EntityID - in case they disconnect before the chunks load
local OnAllChunksAvailable = function()
LOGINFO("ChunkStay all chunks now available")
-- Build something on the neighboring chunks, to verify:
for z = -1, 1 do for x = -1, 1 do
local BlockX = (ChunkX + x) * 16 + 8
local BlockZ = (ChunkZ + z) * 16 + 8
for y = 20, 80 do
World:SetBlock(BlockX, y, BlockZ, E_BLOCK_OBSIDIAN, 0)
end
end end
-- Teleport the player there for visual inspection:
World:DoWithEntityByID(PlayerID,
function (a_CallbackPlayer)
a_CallbackPlayer:TeleportToCoords(ChunkX * 16 + 8, 85, ChunkZ * 16 + 8)
a_CallbackPlayer:SendMessageSuccess("ChunkStay fully available")
end
)
end
-- This function will be called for each chunk that is made available
-- Note that the player needs to be referenced using their EntityID - in case they disconnect before the chunks load
local OnChunkAvailable = function(a_ChunkX, a_ChunkZ)
LOGINFO("ChunkStay now has chunk [" .. a_ChunkX .. ", " .. a_ChunkZ .. "]")
World:DoWithEntityByID(PlayerID,
function (a_CallbackPlayer)
a_CallbackPlayer:SendMessageInfo("ChunkStay now has chunk [" .. a_ChunkX .. ", " .. a_ChunkZ .. "]")
end
)
end
-- Process the ChunkStay:
World:ChunkStay(Chunks, OnChunkAvailable, OnAllChunksAvailable)
return true
end
function HandleCompo(a_Split, a_Player)
-- Send one composite message to self:
local msg = cCompositeChat()
msg:AddTextPart("Hello! ", "b@e") -- bold yellow
msg:AddUrlPart("MCServer", "http://mc-server.org")
msg:AddTextPart(" rules! ")
msg:AddRunCommandPart("Set morning", "/time set 0")
a_Player:SendMessage(msg)
-- Broadcast another one to the world:
local msg2 = cCompositeChat()
msg2:AddSuggestCommandPart(a_Player:GetName(), "/tell " .. a_Player:GetName() .. " ")
msg2:AddTextPart(" knows how to use cCompositeChat!");
a_Player:GetWorld():BroadcastChat(msg2)
return true
end
function HandleSetBiome(a_Split, a_Player)
local Biome = biJungle
local Size = 20
local SplitSize = #a_Split
if (SplitSize > 3) then
a_Player:SendMessage("Too many parameters. Usage: " .. a_Split[1] .. " <BiomeType>")
return true
end
if (SplitSize >= 2) then
Biome = StringToBiome(a_Split[2])
if (Biome == biInvalidBiome) then
a_Player:SendMessage("Unknown biome: '" .. a_Split[2] .. "'. Command ignored.")
return true
end
end
if (SplitSize >= 3) then
Size = tostring(a_Split[3])
if (Size == nil) then
a_Player:SendMessage("Unknown size: '" .. a_Split[3] .. "'. Command ignored.")
return true
end
end
local BlockX = math.floor(a_Player:GetPosX())
local BlockZ = math.floor(a_Player:GetPosZ())
a_Player:GetWorld():SetAreaBiome(BlockX - Size, BlockX + Size, BlockZ - Size, BlockZ + Size, Biome)
a_Player:SendMessage(
"Blocks {" .. (BlockX - Size) .. ", " .. (BlockZ - Size) ..
"} - {" .. (BlockX + Size) .. ", " .. (BlockZ + Size) ..
"} set to biome #" .. tostring(Biome) .. "."
)
return true
end
function HandleWESel(a_Split, a_Player)
-- Check if the selection is a cuboid:
local IsCuboid = cPluginManager:CallPlugin("WorldEdit", "IsPlayerSelectionCuboid")
if (IsCuboid == nil) then
a_Player:SendMessage(cCompositeChat():SetMessageType(mtFailure):AddTextPart("Cannot adjust selection, WorldEdit is not loaded"))
return true
elseif (IsCuboid == false) then
a_Player:SendMessage(cCompositeChat():SetMessageType(mtFailure):AddTextPart("Cannot adjust selection, the selection is not a cuboid"))
return true
end
-- Get the selection:
local SelCuboid = cCuboid()
local IsSuccess = cPluginManager:CallPlugin("WorldEdit", "GetPlayerCuboidSelection", a_Player, SelCuboid)
if not(IsSuccess) then
a_Player:SendMessage(cCompositeChat():SetMessageType(mtFailure):AddTextPart("Cannot adjust selection, WorldEdit reported failure while getting current selection"))
return true
end
-- Adjust the selection:
local NumBlocks = tonumber(a_Split[2] or "1") or 1
SelCuboid:Expand(NumBlocks, NumBlocks, 0, 0, NumBlocks, NumBlocks)
-- Set the selection:
local IsSuccess = cPluginManager:CallPlugin("WorldEdit", "SetPlayerCuboidSelection", a_Player, SelCuboid)
if not(IsSuccess) then
a_Player:SendMessage(cCompositeChat():SetMessageType(mtFailure):AddTextPart("Cannot adjust selection, WorldEdit reported failure while setting new selection"))
return true
end
a_Player:SendMessage(cCompositeChat():SetMessageType(mtInformation):AddTextPart("Successfully adjusted the selection by " .. NumBlocks .. " block(s)"))
return true
end
function OnPlayerJoined(a_Player)
-- Test composite chat chaining:
a_Player:SendMessage(cCompositeChat()
:AddTextPart("Hello, ")
:AddUrlPart(a_Player:GetName(), "www.mc-server.org", "u@2")
:AddSuggestCommandPart(", and welcome.", "/help", "u")
:AddRunCommandPart(" SetDay", "/time set 0")
)
end

View File

@ -0,0 +1,49 @@
function Initialize(a_Plugin)
a_Plugin:SetName("DumpInfo")
a_Plugin:SetVersion(1)
-- Check if the infodump file exists.
if (not cFile:Exists("Plugins/InfoDump.lua")) then
LOGWARN("[DumpInfo] InfoDump.lua was not found.")
return false
end
-- Add the webtab.
a_Plugin:AddWebTab("DumpPlugin", HandleDumpPluginRequest)
return true
end
function HandleDumpPluginRequest(a_Request)
local Content = ""
-- Check if it already was requested to dump a plugin.
if (a_Request.PostParams["DumpInfo"] ~= nil) then
local F = loadfile("Plugins/InfoDump.lua")
F("Plugins/" .. a_Request.PostParams["DumpInfo"])
end
Content = Content .. [[
<table>
<th colspan="2">DumpInfo</th>]]
-- Loop through each plugin that is found.
for PluginName, k in pairs(cPluginManager:Get():GetAllPlugins()) do
-- Check if there is a file called 'Info.lua' or 'info.lua'
if (cFile:Exists("Plugins/" .. PluginName .. "/Info.lua")) then
Content = Content .. "<tr>"
Content = Content .. "<td>" .. PluginName .. "</td>"
Content = Content .. "<td> <form method='POST'> <input type='hidden' value='" .. PluginName .. "' name='DumpInfo'> <input type='submit' value='DumpInfo'> </form>"
Content = Content .. "</td>"
end
end
Content = Content .. [[
</table>]]
return Content
end

View File

@ -2,10 +2,17 @@
-- InfoDump.lua
-- Goes through all subfolders, loads Info.lua and dumps its g_PluginInfo into various text formats
-- This is used for generating plugin documentation for the forum and for GitHub's INFO.md files
--[[
Loads plugins' Info.lua and dumps its g_PluginInfo into various text formats
This is used for generating plugin documentation for the forum and for GitHub's INFO.md files
-- This script requires LuaRocks with LFS installed, instructions are printed when this is not present.
This script can be used in two ways:
Executing "lua InfoDump.lua" will go through all subfolders and dump each Info.lua file it can find
Note that this mode of operation requires LuaRocks with LFS installed; instructions are printed
when the prerequisites are not met.
Executing "lua InfoDump.lua PluginName" will load the Info.lua file from PluginName's folder and dump
only that one plugin's documentation. This mode of operation doesn't require LuaRocks
--]]
@ -17,33 +24,6 @@ if (_VERSION ~= "Lua 5.1") then
return;
end
-- Try to load lfs, do not abort if not found
local lfs, err = pcall(
function()
return require("lfs")
end
);
-- Rather, print a nice message with instructions:
if not(lfs) then
print([[
Cannot load LuaFileSystem
Install it through luarocks by executing the following command:
sudo luarocks install luafilesystem
If you don't have luarocks installed, you need to install them using your OS's package manager, usually:
sudo apt-get install luarocks
On windows, a binary distribution can be downloaded from the LuaRocks homepage, http://luarocks.org/en/Download
]]);
print("Original error text: ", err);
return;
end
-- We now know that LFS is present, get it normally:
lfs = require("lfs");
@ -89,6 +69,47 @@ end
--- Replaces generic formatting with forum-specific formatting
-- Also removes the single line-ends
local function GithubizeString(a_Str)
assert(type(a_Str) == "string");
-- Remove the indentation, unless in the code tag:
-- Only one code or /code tag per line is supported!
local IsInCode = false;
local function RemoveIndentIfNotInCode(s)
if (IsInCode) then
-- we're in code section, check if this line terminates it
IsInCode = (s:find("{%%/code}") ~= nil);
return s .. "\n";
else
-- we're not in code section, check if this line starts it
IsInCode = (s:find("{%%code}") ~= nil);
return s:gsub("^%s*", "") .. "\n";
end
end
a_Str = a_Str:gsub("(.-)\n", RemoveIndentIfNotInCode);
-- Replace multiple line ends with {%p} and single line ends with a space,
-- so that manual word-wrap in the Info.lua file doesn't wrap in the forum.
a_Str = a_Str:gsub("\n\n", "{%%p}");
a_Str = a_Str:gsub("\n", " ");
-- Replace the generic formatting:
a_Str = a_Str:gsub("{%%p}", "\n\n");
a_Str = a_Str:gsub("{%%b}", "**"):gsub("{%%/b}", "**");
a_Str = a_Str:gsub("{%%i}", "*"):gsub("{%%/i}", "*");
a_Str = a_Str:gsub("{%%list}", ""):gsub("{%%/list}", "");
a_Str = a_Str:gsub("{%%li}", " - "):gsub("{%%/li}", "");
-- TODO: Other formatting
return a_Str;
end
--- Builds an array of categories, each containing all the commands belonging to the category,
-- and the category description, if available.
-- Returns the array table, each item has the following format:
@ -161,6 +182,43 @@ end
--- Returns a string specifying the command.
-- If a_Command is a simple string, returns a_Command colorized to blue
-- If a_Command is a table, expects members Name (full command name) and Params (command parameters),
-- colorizes command name blue and params green
local function GetCommandRefForum(a_Command)
if (type(a_Command) == "string") then
return "[color=blue]" .. a_Command .. "[/color]";
end
return "[color=blue]" .. a_Command.Name .. "[/color] [color=green]" .. (a_Command.Params or "") .. "[/color]";
end
--- Returns a string specifying the command.
-- If a_CommandParams is nil, returns a_CommandName apostrophed
-- If a_CommandParams is a string, apostrophes a_CommandName with a_CommandParams
local function GetCommandRefGithub(a_CommandName, a_CommandParams)
assert(type(a_CommandName) == "string");
if (a_CommandParams == nil) then
return "`" .. a_CommandName .. "`";
end
assert(type(a_CommandParams) == "table");
if ((a_CommandParams.Params == nil) or (a_CommandParams.Params == "")) then
return "`" .. a_CommandName .. "`";
end
assert(type(a_CommandParams.Params) == "string");
return "`" .. a_CommandName .. " " .. a_CommandParams.Params .. "`";
end
--- Writes the specified command detailed help array to the output file, in the forum dump format
local function WriteCommandParameterCombinationsForum(a_CmdString, a_ParameterCombinations, f)
assert(type(a_CmdString) == "string");
@ -174,7 +232,7 @@ local function WriteCommandParameterCombinationsForum(a_CmdString, a_ParameterCo
f:write("The following parameter combinations are recognized:\n");
for idx, combination in ipairs(a_ParameterCombinations) do
f:write("[color=blue]", a_CmdString, "[/color] [color=green]", combination.Params, "[/color]");
f:write("[color=blue]", a_CmdString, "[/color] [color=green]", combination.Params or "", "[/color]");
if (combination.Help ~= nil) then
f:write(" - ", ForumizeString(combination.Help));
end
@ -189,6 +247,34 @@ end
--- Writes the specified command detailed help array to the output file, in the forum dump format
local function WriteCommandParameterCombinationsGithub(a_CmdString, a_ParameterCombinations, f)
assert(type(a_CmdString) == "string");
assert(type(a_ParameterCombinations) == "table");
assert(f ~= nil);
if (#a_ParameterCombinations == 0) then
-- No explicit parameter combinations to write
return;
end
f:write("The following parameter combinations are recognized:\n\n");
for idx, combination in ipairs(a_ParameterCombinations) do
f:write(GetCommandRefGithub(a_CmdString, combination));
if (combination.Help ~= nil) then
f:write(" - ", GithubizeString(combination.Help));
end
if (combination.Permission ~= nil) then
f:write(" (Requires permission '**", combination.Permission, "**')");
end
f:write("\n");
end
end
--- Writes all commands in the specified category to the output file, in the forum dump format
local function WriteCommandsCategoryForum(a_Category, f)
-- Write category name:
@ -211,7 +297,7 @@ local function WriteCommandsCategoryForum(a_Category, f)
f:write("Permission required: [color=red]", cmd.Info.Permission, "[/color]\n");
end
if (cmd.Info.DetailedDescription ~= nil) then
f:write(cmd.Info.DetailedDescription);
f:write(ForumizeString(cmd.Info.DetailedDescription));
end
if (cmd.Info.ParameterCombinations ~= nil) then
WriteCommandParameterCombinationsForum(cmd.CommandString, cmd.Info.ParameterCombinations, f);
@ -224,6 +310,34 @@ end
--- Writes all commands in the specified category to the output file, in the Github dump format
local function WriteCommandsCategoryGithub(a_Category, f)
-- Write category name:
local CategoryName = a_Category.Name;
if (CategoryName == "") then
CategoryName = "General";
end
f:write("\n### ", GithubizeString(a_Category.DisplayName or CategoryName), "\n");
-- Write description:
if (a_Category.Description ~= "") then
f:write(GithubizeString(a_Category.Description), "\n\n");
end
f:write("| Command | Permission | Description | \n")
f:write("| ------- | ---------- | ----------- | \n")
-- Write commands:
for idx2, cmd in ipairs(a_Category.Commands) do
f:write("|", cmd.CommandString, " | ", cmd.Info.Permission or "", " | ", GithubizeString(cmd.Info.HelpString or "UNDOCUMENTED"), "| \n")
end
f:write("\n\n")
end
local function DumpCommandsForum(a_PluginInfo, f)
-- Copy all Categories from a dictionary into an array:
local Categories = BuildCategories(a_PluginInfo);
@ -251,9 +365,36 @@ end
local function DumpCommandsGithub(a_PluginInfo, f)
-- Copy all Categories from a dictionary into an array:
local Categories = BuildCategories(a_PluginInfo);
-- Sort the categories by name:
table.sort(Categories,
function(cat1, cat2)
return (string.lower(cat1.Name) < string.lower(cat2.Name));
end
);
if (#Categories == 0) then
return;
end
f:write("\n# Commands\n");
-- Dump per-category commands:
for idx, cat in ipairs(Categories) do
WriteCommandsCategoryGithub(cat, f);
end
end
local function DumpAdditionalInfoForum(a_PluginInfo, f)
local AInfo = a_PluginInfo.AdditionalInfo;
if ((AInfo == nil) or (type(AInfo) ~= "table")) then
if (type(AInfo) ~= "table") then
-- There is no AdditionalInfo in a_PluginInfo
return;
end
@ -270,6 +411,153 @@ end
local function DumpAdditionalInfoGithub(a_PluginInfo, f)
local AInfo = a_PluginInfo.AdditionalInfo;
if (type(AInfo) ~= "table") then
-- There is no AdditionalInfo in a_PluginInfo
return;
end
for idx, info in ipairs(a_PluginInfo.AdditionalInfo) do
if ((info.Title ~= nil) and (info.Contents ~= nil)) then
f:write("\n# ", GithubizeString(info.Title), "\n");
f:write(GithubizeString(info.Contents), "\n");
end
end
end
--- Collects all permissions mentioned in the info, returns them as a sorted array
-- Each array item is {Name = "PermissionName", Info = { PermissionInfo }}
local function BuildPermissions(a_PluginInfo)
-- Collect all used permissions from Commands, reference the commands that use the permission:
local Permissions = a_PluginInfo.Permissions or {};
local function CollectPermissions(a_CmdPrefix, a_Commands)
for cmd, info in pairs(a_Commands) do
CommandString = a_CmdPrefix .. cmd;
if ((info.Permission ~= nil) and (info.Permission ~= "")) then
-- Add the permission to the list of permissions:
local Permission = Permissions[info.Permission] or {};
Permissions[info.Permission] = Permission;
-- Add the command to the list of commands using this permission:
Permission.CommandsAffected = Permission.CommandsAffected or {};
table.insert(Permission.CommandsAffected, CommandString);
end
-- Process the command param combinations for permissions:
local ParamCombinations = info.ParameterCombinations or {};
for idx, comb in ipairs(ParamCombinations) do
if ((comb.Permission ~= nil) and (comb.Permission ~= "")) then
-- Add the permission to the list of permissions:
local Permission = Permissions[comb.Permission] or {};
Permissions[info.Permission] = Permission;
-- Add the command to the list of commands using this permission:
Permission.CommandsAffected = Permission.CommandsAffected or {};
table.insert(Permission.CommandsAffected, {Name = CommandString, Params = comb.Params});
end
end
-- Process subcommands:
if (info.Subcommands ~= nil) then
CollectPermissions(CommandString .. " ", info.Subcommands);
end
end
end
CollectPermissions("", a_PluginInfo.Commands);
-- Copy the list of permissions to an array:
local PermArray = {};
for name, perm in pairs(Permissions) do
table.insert(PermArray, {Name = name, Info = perm});
end
-- Sort the permissions array:
table.sort(PermArray,
function(p1, p2)
return (p1.Name < p2.Name);
end
);
return PermArray;
end
local function DumpPermissionsForum(a_PluginInfo, f)
-- Get the processed sorted array of permissions:
local Permissions = BuildPermissions(a_PluginInfo);
if ((Permissions == nil) or (#Permissions <= 0)) then
return;
end
-- Dump the permissions:
f:write("\n[size=X-Large]Permissions[/size]\n[list]\n");
for idx, perm in ipairs(Permissions) do
f:write(" - [color=red]", perm.Name, "[/color] - ");
f:write(ForumizeString(perm.Info.Description or ""));
local CommandsAffected = perm.Info.CommandsAffected or {};
if (#CommandsAffected > 0) then
f:write("\n[list] Commands affected:\n- ");
local Affects = {};
for idx2, cmd in ipairs(CommandsAffected) do
table.insert(Affects, GetCommandRefForum(cmd));
end
f:write(table.concat(Affects, "\n - "));
f:write("\n[/list]");
end
if (perm.Info.RecommendedGroups ~= nil) then
f:write("\n[list] Recommended groups: ", perm.Info.RecommendedGroups, "[/list]");
end
f:write("\n");
end
f:write("[/list]");
end
local function DumpPermissionsGithub(a_PluginInfo, f)
-- Get the processed sorted array of permissions:
local Permissions = BuildPermissions(a_PluginInfo);
if ((Permissions == nil) or (#Permissions <= 0)) then
return;
end
-- Dump the permissions:
f:write("\n# Permissions\n");
f:write("| Permissions | Description | Commands | Recommended groups |\n")
f:write("| ----------- | ----------- | -------- | ------------------ |\n")
for idx, perm in ipairs(Permissions) do
f:write(perm.Name, " | ");
f:write(GithubizeString(perm.Info.Description or ""), " | ");
local CommandsAffected = perm.Info.CommandsAffected or {};
if (#CommandsAffected > 0) then
local Affects = {};
for idx2, cmd in ipairs(CommandsAffected) do
if (type(cmd) == "string") then
table.insert(Affects, GetCommandRefGithub(cmd));
else
table.insert(Affects, GetCommandRefGithub(cmd.Name, cmd));
end
end
f:write(table.concat(Affects, ", "), " | ");
end
if (perm.Info.RecommendedGroups ~= nil) then
f:write(perm.Info.RecommendedGroups, " |");
end
f:write("\n");
end
end
local function DumpPluginInfoForum(a_PluginFolder, a_PluginInfo)
-- Open the output file:
local f, msg = io.open(a_PluginInfo.Name .. "_forum.txt", "w");
@ -282,7 +570,11 @@ local function DumpPluginInfoForum(a_PluginFolder, a_PluginInfo)
f:write(ForumizeString(a_PluginInfo.Description), "\n");
DumpAdditionalInfoForum(a_PluginInfo, f);
DumpCommandsForum(a_PluginInfo, f);
DumpPermissionsForum(a_PluginInfo, f);
if (a_PluginInfo.SourceLocation ~= nil) then
f:write("[b][color=blue]Source:[/color] [url=", a_PluginInfo.SourceLocation, "]Link[/url][/b]");
end
f:close();
end
@ -290,8 +582,21 @@ end
local function DumpPluginInfoGitHub()
-- TODO
local function DumpPluginInfoGithub(a_PluginFolder, a_PluginInfo)
-- Open the output file:
local f, msg = io.open(a_PluginInfo.Name .. ".md", "w"); -- TODO: Save to a_PluginFolder .. "/Readme.md" instead
if (f == nil) then
print("\tCannot dump github info for plugin " .. a_PluginFolder .. ": " .. msg);
return;
end
-- Write the description:
f:write(GithubizeString(a_PluginInfo.Description), "\n");
DumpAdditionalInfoGithub(a_PluginInfo, f);
DumpCommandsGithub(a_PluginInfo, f);
DumpPermissionsGithub(a_PluginInfo, f);
f:close();
end
@ -301,12 +606,6 @@ end
--- Tries to load the g_PluginInfo from the plugin's Info.lua file
-- Returns the g_PluginInfo table on success, or nil and error message on failure
local function LoadPluginInfo(a_FolderName)
-- Check if the Info file is present at all:
local Attribs = lfs.attributes(a_FolderName .. "/Info.lua");
if ((Attribs == nil) or (Attribs.mode ~= "file")) then
return nil;
end
-- Load and compile the Info file:
local cfg, err = loadfile(a_FolderName .. "/Info.lua");
if (cfg == nil) then
@ -332,30 +631,76 @@ local function ProcessPluginFolder(a_FolderName)
local PluginInfo, Msg = LoadPluginInfo(a_FolderName);
if (PluginInfo == nil) then
if (Msg ~= nil) then
print("\tCannot load Info.lua: " .. Msg);
print("\t" .. Msg);
end
return;
end
DumpPluginInfoForum(a_FolderName, PluginInfo);
DumpPluginInfoGithub(a_FolderName, PluginInfo);
end
print("Processing plugin subfolders:");
for fnam in lfs.dir(".") do
if ((fnam ~= ".") and (fnam ~= "..")) then
local Attributes = lfs.attributes(fnam);
if (Attributes ~= nil) then
if (Attributes.mode == "directory") then
print(fnam);
ProcessPluginFolder(fnam);
--- Tries to load LFS through LuaRocks, returns the LFS instance, or nil on error
local function LoadLFS()
-- Try to load lfs, do not abort if not found ...
local lfs, err = pcall(
function()
return require("lfs")
end
);
-- ... rather, print a nice message with instructions:
if not(lfs) then
print([[
Cannot load LuaFileSystem
Install it through luarocks by executing the following command:
luarocks install luafilesystem (Windows)
sudo luarocks install luafilesystem (*nix)
If you don't have luarocks installed, you need to install them using your OS's package manager, usually:
sudo apt-get install luarocks (Ubuntu / Debian)
On windows, a binary distribution can be downloaded from the LuaRocks homepage, http://luarocks.org/en/Download
]]);
print("Original error text: ", err);
return nil;
end
-- We now know that LFS is present, get it normally:
return require("lfs");
end
local Arg1 = ...;
if ((Arg1 ~= nil) and (Arg1 ~= "")) then
-- Called with a plugin folder name, export only that one
ProcessPluginFolder(Arg1)
else
-- Called without any arguments, process all subfolders:
local lfs = LoadLFS();
if (lfs == nil) then
-- LFS not loaded, error has already been printed, just bail out
return;
end
print("Processing plugin subfolders:");
for fnam in lfs.dir(".") do
if ((fnam ~= ".") and (fnam ~= "..")) then
local Attributes = lfs.attributes(fnam);
if (Attributes ~= nil) then
if (Attributes.mode == "directory") then
print(fnam);
ProcessPluginFolder(fnam);
end
end
end
end
end
print("Done.");

View File

@ -0,0 +1,198 @@
-- InfoReg.lua
-- Implements registration functions that process g_PluginInfo
--- Lists all the subcommands that the player has permissions for
local function ListSubcommands(a_Player, a_Subcommands, a_CmdString)
if (a_Player == nil) then
LOGINFO("The " .. a_CmdString .. " command requires another verb:")
else
a_Player:SendMessage("The " .. a_CmdString .. " command requires another verb:")
end
-- Enum all the subcommands:
local Verbs = {};
for cmd, info in pairs(a_Subcommands) do
if (a_Player:HasPermission(info.Permission or "")) then
table.insert(Verbs, " " .. a_CmdString .. " " .. cmd);
end
end
table.sort(Verbs);
-- Send the list:
if (a_Player == nil) then
for idx, verb in ipairs(Verbs) do
LOGINFO(verb);
end
else
for idx, verb in ipairs(Verbs) do
a_Player:SendMessage(verb);
end
end
end
--- This is a generic command callback used for handling multicommands' parent commands
-- For example, if there are "/gal save" and "/gal load" commands, this callback handles the "/gal" command
-- It is used for both console and in-game commands; the console version has a_Player set to nil
local function MultiCommandHandler(a_Split, a_Player, a_CmdString, a_CmdInfo, a_Level)
local Verb = a_Split[a_Level + 1];
if (Verb == nil) then
-- No verb was specified. If there is a handler for the upper level command, call it:
if (a_CmdInfo.Handler ~= nil) then
return a_CmdInfo.Handler(a_Split, a_Player);
end
-- Let the player know they need to give a subcommand:
ListSubcommands(a_Player, a_CmdInfo.Subcommands, a_CmdString);
return true;
end
-- A verb was specified, look it up in the subcommands table:
local Subcommand = a_CmdInfo.Subcommands[Verb];
if (Subcommand == nil) then
if (a_Level > 1) then
-- This is a true subcommand, display the message and make MCS think the command was handled
-- Otherwise we get weird behavior: for "/cmd verb" we get "unknown command /cmd" although "/cmd" is valid
if (a_Player == nil) then
LOGWARNING("The " .. a_CmdString .. " command doesn't support verb " .. Verb)
else
a_Player:SendMessage("The " .. a_CmdString .. " command doesn't support verb " .. Verb)
end
return true;
end
-- This is a top-level command, let MCS handle the unknown message
return false;
end
-- Check the permission:
if (a_Player ~= nil) then
if not(a_Player:HasPermission(Subcommand.Permission or "")) then
a_Player:SendMessage("You don't have permission to execute this command");
return true;
end
end
-- If the handler is not valid, check the next sublevel:
if (Subcommand.Handler == nil) then
if (Subcommand.Subcommands == nil) then
LOG("Cannot find handler for command " .. a_CmdString .. " " .. Verb);
return false;
end
MultiCommandHandler(a_Split, a_Player, a_CmdString .. " " .. Verb, Subcommand, a_Level + 1);
return true;
end
-- Execute:
return Subcommand.Handler(a_Split, a_Player);
end
--- Registers all commands specified in the g_PluginInfo.Commands
function RegisterPluginInfoCommands()
-- A sub-function that registers all subcommands of a single command, using the command's Subcommands table
-- The a_Prefix param already contains the space after the previous command
-- a_Level is the depth of the subcommands being registered, with 1 being the top level command
local function RegisterSubcommands(a_Prefix, a_Subcommands, a_Level)
assert(a_Subcommands ~= nil);
-- A table that will hold aliases to subcommands temporarily, during subcommand iteration
local AliasTable = {}
-- Iterate through the subcommands, register them, and accumulate aliases:
for cmd, info in pairs(a_Subcommands) do
local CmdName = a_Prefix .. cmd;
local Handler = info.Handler;
-- Provide a special handler for multicommands:
if (info.Subcommands ~= nil) then
Handler = function(a_Split, a_Player)
return MultiCommandHandler(a_Split, a_Player, CmdName, info, a_Level);
end
end
if (Handler == nil) then
LOGWARNING(g_PluginInfo.Name .. ": Invalid handler for command " .. CmdName .. ", command will not be registered.");
else
local HelpString;
if (info.HelpString ~= nil) then
HelpString = " - " .. info.HelpString;
else
HelpString = "";
end
cPluginManager.BindCommand(CmdName, info.Permission or "", Handler, HelpString);
-- Register all aliases for the command:
if (info.Alias ~= nil) then
if (type(info.Alias) == "string") then
info.Alias = {info.Alias};
end
for idx, alias in ipairs(info.Alias) do
cPluginManager.BindCommand(a_Prefix .. alias, info.Permission or "", Handler, HelpString);
-- Also copy the alias's info table as a separate subcommand,
-- so that MultiCommandHandler() handles it properly. Need to off-load into a separate table
-- than the one we're currently iterating and join after the iterating.
AliasTable[alias] = info
end
end
end -- else (if Handler == nil)
-- Recursively register any subcommands:
if (info.Subcommands ~= nil) then
RegisterSubcommands(a_Prefix .. cmd .. " ", info.Subcommands, a_Level + 1);
end
end -- for cmd, info - a_Subcommands[]
-- Add the subcommand aliases that were off-loaded during registration:
for alias, info in pairs(AliasTable) do
a_Subcommands[alias] = info
end
AliasTable = {}
end
-- Loop through all commands in the plugin info, register each:
RegisterSubcommands("", g_PluginInfo.Commands, 1);
end
--- Registers all console commands specified in the g_PluginInfo.ConsoleCommands
function RegisterPluginInfoConsoleCommands()
-- A sub-function that registers all subcommands of a single command, using the command's Subcommands table
-- The a_Prefix param already contains the space after the previous command
local function RegisterSubcommands(a_Prefix, a_Subcommands, a_Level)
assert(a_Subcommands ~= nil);
for cmd, info in pairs(a_Subcommands) do
local CmdName = a_Prefix .. cmd;
local Handler = info.Handler
if (Handler == nil) then
Handler = function(a_Split)
return MultiCommandHandler(a_Split, nil, CmdName, info, a_Level);
end
end
cPluginManager.BindConsoleCommand(CmdName, Handler, info.HelpString or "");
-- Recursively register any subcommands:
if (info.Subcommands ~= nil) then
RegisterSubcommands(a_Prefix .. cmd .. " ", info.Subcommands, a_Level + 1);
end
end
end
-- Loop through all commands in the plugin info, register each:
RegisterSubcommands("", g_PluginInfo.ConsoleCommands, 1);
end

View File

@ -1,19 +0,0 @@
Core = cPluginManager:Get():GetPlugin("Core")
function SendMessage(a_Player, a_Message)
if (Core ~= nil) then
Core:Call("SendMessage", a_Player, a_Message)
end
end
function SendMessageSuccess(a_Player, a_Message)
if (Core ~= nil) then
Core:Call("SendMessageSuccess", a_Player, a_Message)
end
end
function SendMessageFailure(a_Player, a_Message)
if (Core ~= nil) then
Core:Call("SendMessageFailure", a_Player, a_Message)
end
end

View File

@ -6,7 +6,7 @@ function Initialize( Plugin )
Plugin:SetVersion( 2 )
cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_MOVING, OnPlayerMoving)
cPluginManager.AddHook(cPluginManager.HOOK_DISCONNECT, OnDisconnect)
cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_DESTROYED, OnDisconnect)
local PluginManager = cPluginManager:Get()
PluginManager:BindCommand("/mc", "magiccarpet", HandleCarpetCommand, " - Spawns a magical carpet");
@ -37,12 +37,12 @@ function HandleCarpetCommand( Split, Player )
if( Carpet == nil ) then
Carpets[ Player ] = cCarpet:new()
SendMessageSuccess(Player, "You're on a magic carpet!")
SendMessage(Player, "Look straight down to descend. Jump to ascend.")
Player:SendMessageSuccess("You're on a magic carpet!")
Player:SendMessageInfo("Look straight down to descend. Jump to ascend.")
else
Carpet:remove()
Carpets[ Player ] = nil
SendMessageSuccess(Player, "The carpet vanished!")
Player:SendMessageSuccess("The carpet vanished!")
end
return true

View File

@ -39,6 +39,7 @@
#
# Need to list each of the four log types, otherwise all logs would get converted into apple planks (^0)
ApplePlanks, 4 = AppleLog, *
ConiferPlanks, 4 = ConiferLog, *
BirchPlanks, 4 = BirchLog, *
@ -156,7 +157,7 @@ Lighter = IronIngot, 1:1 | Flint, 2:2
Lighter = IronIngot, 2:1 | Flint, 1:2
Bucket = IronIngot, 1:1, 2:2, 3:1
Compass = IronIngot, 2:1, 1:2, 3:2, 2:3 | RedstoneDust, 2:2
Map = Paper, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | Compass, 2:2
EmptyMap = Paper, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | Compass, 2:2
Watch = GoldIngot, 2:1, 1:2, 3:2, 2:3 | RedstoneDust, 2:2
FishingRod = Stick, 1:3, 2:2, 3:1 | String, 3:2, 3:3
FishingRod = Stick, 3:3, 2:2, 1:1 | String, 1:2, 1:3
@ -434,6 +435,55 @@ GoldNugget, 9 = GoldIngot, *
EnchantmentTable = Obsidian, 1:3, 2:3, 3:3, 2:2 | Diamond, 1:2, 3:2 | Book, 2:1
#******************************************************#
# Fireworks & Co.
# (Best not to add non-vanilla items to this as it will cause internal firework data handling code to log warnings)
# Ballistic firework rockets - plain and with firework star, all with 1 - 3 gunpowder
FireworkRocket = Paper, * | Gunpowder, *
FireworkRocket = Paper, * | Gunpowder, * | Gunpowder, *
FireworkRocket = Paper, * | Gunpowder, * | Gunpowder, * | Gunpowder, *
FireworkRocket = FireworkStar, * | Paper, * | Gunpowder, *
FireworkRocket = FireworkStar, * | Paper, * | Gunpowder, * | Gunpowder, *
FireworkRocket = FireworkStar, * | Paper, * | Gunpowder, * | Gunpowder, * | Gunpowder, *
# Radioactive firework stars
# Plain powder and dye
FireworkStar = Gunpowder, * | Dye ^-1, *
# Powder and effect, with effect combining
FireworkStar = Gunpowder, * | Dye ^-1, * | Diamond, *
FireworkStar = Gunpowder, * | Dye ^-1, * | Glowdust, *
FireworkStar = Gunpowder, * | Dye ^-1, * | Glowdust, * | Diamond, *
# Powder and shape (no shape combining possible)
FireworkStar = Gunpowder, * | Dye ^-1, * | Firecharge, *
FireworkStar = Gunpowder, * | Dye ^-1, * | Goldnugget, *
FireworkStar = Gunpowder, * | Dye ^-1, * | Feather, *
FireworkStar = Gunpowder, * | Dye ^-1, * | SkeletonHead ^-1, *
# Power and shape (no shape combining possible), combined with effect
FireworkStar = Gunpowder, * | Dye ^-1, * | Firecharge, * | Diamond, *
FireworkStar = Gunpowder, * | Dye ^-1, * | Firecharge, * | Glowdust, *
FireworkStar = Gunpowder, * | Dye ^-1, * | Goldnugget, * | Diamond, *
FireworkStar = Gunpowder, * | Dye ^-1, * | Goldnugget, * | Glowdust, *
FireworkStar = Gunpowder, * | Dye ^-1, * | Feather, * | Diamond, *
FireworkStar = Gunpowder, * | Dye ^-1, * | Feather, * | Glowdust, *
FireworkStar = Gunpowder, * | Dye ^-1, * | SkeletonHead ^-1, * | Diamond, *
FireworkStar = Gunpowder, * | Dye ^-1, * | SkeletonHead ^-1, * | Glowdust, *
# Power and shape (no shape combining possible), combined with effect (with effect combining)
FireworkStar = Gunpowder, * | Dye ^-1, * | Firecharge, * | Glowdust, * | Diamond, *
FireworkStar = Gunpowder, * | Dye ^-1, * | Goldnugget, * | Glowdust, * | Diamond, *
FireworkStar = Gunpowder, * | Dye ^-1, * | Feather, * | Glowdust, * | Diamond, *
FireworkStar = Gunpowder, * | Dye ^-1, * | SkeletonHead ^-1, * | Glowdust, * | Diamond, *
# Star fade colour-change
FireworkStar = FireworkStar, * | Dye ^-1, *
FireworkStar = FireworkStar, * | Dye ^-1, * | Dye ^-1, *
FireworkStar = FireworkStar, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, *
FireworkStar = FireworkStar, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, *
FireworkStar = FireworkStar, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, *
FireworkStar = FireworkStar, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, *
FireworkStar = FireworkStar, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, *
FireworkStar = FireworkStar, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, *

0
MCServer/hg Normal file → Executable file
View File

View File

@ -1,4 +1,5 @@
[Items]
air=0
rock=1
stone=1
grass=2
@ -177,6 +178,8 @@ workbench=58
crop=59
crops=59
soil=60
farmland=60
tilleddirt=60
furnace=61
litfurnace=62
signblock=63

BIN
MCServer/lua5.1.dll Normal file

Binary file not shown.

View File

@ -1,68 +1,68 @@
[Spider]
AttackRange=5.0
AttackRange=2.0
AttackRate=1
AttackDamage=2.0
SightDistance=25.0
MaxHealth=16
[Chicken]
AttackRange=5.0
AttackRange=2.0
AttackRate=1
AttackDamage=1.0
SightDistance=25.0
MaxHealth=4
[Cow]
AttackRange=5.0
AttackRange=2.0
AttackRate=1
AttackDamage=1.0
SightDistance=25.0
MaxHealth=10
[Pig]
AttackRange=5.0
AttackRange=2.0
AttackRate=1
AttackDamage=1.0
SightDistance=25.0
MaxHealth=10
[Sheep]
AttackRange=5.0
AttackRange=2.0
AttackRate=1
AttackDamage=1.0
SightDistance=25.0
MaxHealth=8
[Squid]
AttackRange=5.0
AttackRange=2.0
AttackRate=1
AttackDamage=1.0
SightDistance=25.0
MaxHealth=10
[Enderman]
AttackRange=5.0
AttackRange=2.0
AttackRate=1
AttackDamage=4.0
SightDistance=25.0
MaxHealth=40
[Zombiepigman]
AttackRange=5.0
AttackRange=2.0
AttackRate=1
AttackDamage=7.0
SightDistance=25.0
MaxHealth=20
[Cavespider]
AttackRange=5.0
AttackRange=2.0
AttackRate=1
AttackDamage=2.0
SightDistance=25.0
MaxHealth=12
[Creeper]
AttackRange=5.0
AttackRange=3.0
AttackRate=1
AttackDamage=0.0
SightDistance=25.0
@ -76,7 +76,7 @@ SightDistance=50.0
MaxHealth=10
[Silverfish]
AttackRange=5.0
AttackRange=2.0
AttackRate=1
AttackDamage=1.0
SightDistance=25.0
@ -89,21 +89,21 @@ SightDistance=40.0
MaxHealth=20
[Slime]
AttackRange=5.0
AttackRange=2.0
AttackRate=1
AttackDamage=4.0
SightDistance=25.0
MaxHealth=16
[Zombie]
AttackRange=5.0
AttackRange=2.0
AttackRate=1
AttackDamage=4.0
SightDistance=25.0
MaxHealth=20
[Wolf]
AttackRange=5.0
AttackRange=2.0
AttackRate=1
AttackDamage=4.0
SightDistance=25.0
@ -117,14 +117,14 @@ SightDistance=25.0
MaxHealth=20
[Villager]
AttackRange=5.0
AttackRange=2.0
AttackRate=1
AttackDamage=0.0
SightDistance=25.0
MaxHealth=20
[Witch]
AttackRange=5.0
AttackRange=2.0
AttackRate=1
AttackDamage=0.0
SightDistance=25.0
@ -132,49 +132,49 @@ MaxHealth=26
[Ocelot]
AttackRange=5.0
AttackRange=2.0
AttackRate=1
AttackDamage=0.0
SightDistance=25.0
MaxHealth=10
[Mooshroom]
AttackRange=5.0
AttackRange=2.0
AttackRate=1
AttackDamage=0.0
SightDistance=25.0
MaxHealth=10
[Magmacube]
AttackRange=5.0
AttackRange=2.0
AttackRate=1
AttackDamage=6.0
SightDistance=25.0
MaxHealth=16
[Horse]
AttackRange=5.0
AttackRange=2.0
AttackRate=1
AttackDamage=6.0
SightDistance=25.0
MaxHealth=30
[EnderDragon]
AttackRange=5.0
AttackRange=2.0
AttackRate=1
AttackDamage=6.0
SightDistance=25.0
MaxHealth=200
[Giant]
AttackRange=5.0
AttackRange=2.0
AttackRate=1
AttackDamage=6.0
SightDistance=25.0
MaxHealth=100
[IronGolem]
AttackRange=5.0
AttackRange=2.0
AttackRate=1
AttackDamage=6.0
SightDistance=25.0

0
MCServer/vg Normal file → Executable file
View File

View File

@ -12,7 +12,9 @@ Installation
To install MCServer, you can either download the repository and compile it, or download a pre-compiled version.
After you've cloned the repository, you probably want to pull down the submodules (core plugins, some dependencies). This can be achieved with `git submodule init` and then on a regular basis (to keep up to date) `git submodule update`.
If you've cloned the repository using Git, you need to pull down the submodules (core plugins, some dependencies). This can be achieved with `git submodule init` and then on a regular basis (to keep up to date) `git submodule update`.
If you downloaded a ZIP file of the sources instead, you will need to download PolarSSL, too, from https://github.com/polarssl/polarssl , and unpack it into the `lib/polarssl` folder. You will also need to manually download all the plugins that you want included.
Compilation instructions are available in the COMPILING file.

205
SetFlags.cmake Normal file
View File

@ -0,0 +1,205 @@
macro (add_flags_lnk FLAGS)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG} ${FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} ${FLAGS}")
endmacro()
macro(add_flags_cxx FLAGS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAGS}")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FLAGS}")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${FLAGS}")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${FLAGS}")
endmacro()
macro(set_flags)
# Add the preprocessor macros used for distinguishing between debug and release builds (CMake does this automatically for MSVC):
if (NOT MSVC)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNDEBUG")
endif()
if(MSVC)
# Make build use multiple threads under MSVC:
add_flags_cxx("/MP")
# Make release builds use link-time code generation:
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /GL")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG")
set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} /LTCG")
elseif(APPLE)
#on os x clang adds pthread for us but we need to add it for gcc
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11")
else()
add_flags_cxx("-pthread")
endif()
else()
# Let gcc / clang know that we're compiling a multi-threaded app:
add_flags_cxx("-pthread")
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11")
endif()
# We use a signed char (fixes #640 on RasPi)
add_flags_cxx("-fsigned-char")
endif()
# Allow for a forced 32-bit build under 64-bit OS:
if (FORCE_32)
add_flags_cxx("-m32")
add_flags_lnk("-m32")
endif()
# Have the compiler generate code specifically targeted at the current machine on Linux
if(LINUX AND NOT CROSSCOMPILE)
add_flags_cxx("-march=native")
endif()
# Use static CRT in MSVC builds:
if (MSVC)
string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
string(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
string(REPLACE "/MDd" "/MTd" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
endif()
endmacro()
macro(set_lib_flags)
# Set lower warnings-level for the libraries:
if (MSVC)
# Remove /W3 from command line -- cannot just cancel it later with /w like in unix, MSVC produces a D9025 warning (option1 overriden by option2)
string(REPLACE "/W3" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
string(REPLACE "/W3" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
string(REPLACE "/W3" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
string(REPLACE "/W3" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
else()
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -w")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -w")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -w")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -w")
endif()
# On Unix we use two dynamic loading libraries dl and ltdl.
# Preference is for dl on unknown systems as it is specified in POSIX
# the dynamic loader is used by lua and sqllite.
if (UNIX)
if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
set(DYNAMIC_LOADER ltdl)
else()
set(DYNAMIC_LOADER dl)
endif()
endif()
endmacro()
macro(enable_profile)
# Declare the flags used for profiling builds:
if (MSVC)
set (CXX_PROFILING "")
set (LNK_PROFILING "/PROFILE")
else()
set (CXX_PROFILING "-pg")
set (LNK_PROFILING "-pg")
endif()
# Declare the profiling configurations:
SET(CMAKE_CXX_FLAGS_DEBUGPROFILE
"${CMAKE_CXX_FLAGS_DEBUG} ${PCXX_ROFILING}"
CACHE STRING "Flags used by the C++ compiler during profile builds."
FORCE )
SET(CMAKE_C_FLAGS_DEBUGPROFILE
"${CMAKE_C_FLAGS_DEBUG} ${CXX_PROFILING}"
CACHE STRING "Flags used by the C compiler during profile builds."
FORCE )
SET(CMAKE_EXE_LINKER_FLAGS_DEBUGPROFILE
"${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${LNK_PROFILING}"
CACHE STRING "Flags used for linking binaries during profile builds."
FORCE )
SET(CMAKE_SHARED_LINKER_FLAGS_DEBUGPROFILE
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${LNK_PROFILING}"
CACHE STRING "Flags used by the shared libraries linker during profile builds."
FORCE )
MARK_AS_ADVANCED(
CMAKE_CXX_FLAGS_DEBUGPROFILE
CMAKE_C_FLAGS_DEBUGPROFILE
CMAKE_EXE_LINKER_FLAGS_DEBUGPROFILE
CMAKE_SHARED_LINKER_FLAGS_DEBUGPROFILE )
SET(CMAKE_CXX_FLAGS_RELEASEPROFILE
"${CMAKE_CXX_FLAGS_RELEASE} ${CXX_PROFILING}"
CACHE STRING "Flags used by the C++ compiler during profile builds."
FORCE )
SET(CMAKE_C_FLAGS_RELEASEPROFILE
"${CMAKE_C_FLAGS_RELEASE} ${CXX_PROFILING}"
CACHE STRING "Flags used by the C compiler during profile builds."
FORCE )
SET(CMAKE_EXE_LINKER_FLAGS_RELEASEPROFILE
"${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${LNK_PROFILING}"
CACHE STRING "Flags used for linking binaries during profile builds."
FORCE )
SET(CMAKE_SHARED_LINKER_FLAGS_RELEASEPROFILE
"${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${LNK_PROFILING}"
CACHE STRING "Flags used by the shared libraries linker during profile builds."
FORCE )
MARK_AS_ADVANCED(
CMAKE_CXX_FLAGS_RELEASEPROFILE
CMAKE_C_FLAGS_RELEASEPROFILE
CMAKE_EXE_LINKER_FLAGS_RELEASEPROFILE
CMAKE_SHARED_LINKER_FLAGS_RELEASEPROFILE )
# The configuration types need to be set after their respective c/cxx/linker flags and before the project directive
set(CMAKE_CONFIGURATION_TYPES "Debug;Release;DebugProfile;ReleaseProfile" CACHE STRING "" FORCE)
endmacro()
macro(set_exe_flags)
# Remove disabling the maximum warning level:
# clang does not like a command line that reads -Wall -Wextra -w -Wall -Wextra and does not output any warnings
# We do not do that for MSVC since MSVC produces an awful lot of warnings for its own STL headers;
# the important warnings are turned on using #pragma in Globals.h
if (NOT MSVC)
string(REPLACE "-w" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
string(REPLACE "-w" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
string(REPLACE "-w" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
string(REPLACE "-w" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
add_flags_cxx("-Wall -Wextra -Wno-unused-parameter -Wno-error=switch")
# we support non-IEEE 754 fpus so can make no guarentees about error
add_flags_cxx("-ffast-math")
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
# clang does not provide the __extern_always_inline macro and a part of libm depends on this when using fast-math
add_flags_cxx("-D__extern_always_inline=inline")
add_flags_cxx("-Werror -Weverything -Wno-c++98-compat-pedantic -Wno-string-conversion")
add_flags_cxx("-Wno-extra-semi -Wno-error=switch-enum -Wno-documentation")
add_flags_cxx("-Wno-error=sign-conversion -Wno-error=conversion -Wno-padded")
add_flags_cxx("-Wno-error=deprecated -Wno-error=weak-vtables -Wno-error=float-equal")
add_flags_cxx("-Wno-error=missing-prototypes -Wno-error=non-virtual-dtor")
add_flags_cxx("-Wno-error=covered-switch-default -Wno-error=shadow")
add_flags_cxx("-Wno-error=exit-time-destructors -Wno-error=missing-variable-declarations")
add_flags_cxx("-Wno-error=global-constructors -Wno-implicit-fallthrough")
add_flags_cxx("-Wno-weak-vtables -Wno-switch-enum -Wno-exit-time-destructors")
endif()
endif()
endmacro()

View File

@ -78,7 +78,7 @@ bool cBiomeRenderer::Render(cPixmap & a_Pixmap)
{
for (int i = 0; i < ARRAYCOUNT(CurBiomes); i++)
{
CurBiomes[i] = (EMCSBiome)-1;
CurBiomes[i] = biInvalidBiome;
}
break;
}

View File

@ -0,0 +1,12 @@
cmake_minimum_required(VERSION 2.8)
project(GeneratorPerformanceTest)
include_directories(../../src/Generating)
include_directories(../../src)
include_directories(../../lib)
add_executable(GeneratorPerformanceTest GeneratorPerformanceTest.cpp ../../src/StringUtils ../../src/MCLogger ../../src/Log ../../src/BlockID ../../src/Noise ../../src/Enchantments ../../src/BlockArea)
target_link_libraries(GeneratorPerformanceTest Generating)

View File

@ -0,0 +1,7 @@
#include "Globals.h"
#include "ChunkGenerator.h"
int main(int argc, char * argv[]) {
cChunkGenerator Generator = cChunkGenerator();
}

1
Tools/MCADefrag/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.mca

View File

@ -0,0 +1,97 @@
cmake_minimum_required (VERSION 2.6)
project (MCADefrag)
# Without this, the MSVC variable isn't defined for MSVC builds ( http://www.cmake.org/pipermail/cmake/2011-November/047130.html )
enable_language(CXX C)
include(../../SetFlags.cmake)
set_flags()
set_lib_flags()
enable_profile()
# Set include paths to the used libraries:
include_directories("../../lib")
include_directories("../../src")
function(flatten_files arg1)
set(res "")
foreach(f ${${arg1}})
get_filename_component(f ${f} ABSOLUTE)
list(APPEND res ${f})
endforeach()
set(${arg1} "${res}" PARENT_SCOPE)
endfunction()
# Include the libraries:
add_subdirectory(../../lib/zlib ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/lib/zlib)
set_exe_flags()
# Include the shared files:
set(SHARED_SRC
../../src/StringCompression.cpp
../../src/StringUtils.cpp
../../src/Log.cpp
../../src/MCLogger.cpp
)
set(SHARED_HDR
../../src/ByteBuffer.h
../../src/StringUtils.h
../../src/Log.h
../../src/MCLogger.h
)
flatten_files(SHARED_SRC)
flatten_files(SHARED_HDR)
source_group("Shared" FILES ${SHARED_SRC} ${SHARED_HDR})
set(SHARED_OSS_SRC
../../src/OSSupport/CriticalSection.cpp
../../src/OSSupport/File.cpp
../../src/OSSupport/IsThread.cpp
../../src/OSSupport/Timer.cpp
)
set(SHARED_OSS_HDR
../../src/OSSupport/CriticalSection.h
../../src/OSSupport/File.h
../../src/OSSupport/IsThread.h
../../src/OSSupport/Timer.h
)
flatten_files(SHARED_OSS_SRC)
flatten_files(SHARED_OSS_HDR)
source_group("Shared\\OSSupport" FILES ${SHARED_OSS_SRC} ${SHARED_OSS_HDR})
# Include the main source files:
set(SOURCES
MCADefrag.cpp
Globals.cpp
)
set(HEADERS
MCADefrag.h
Globals.h
)
source_group("" FILES ${SOURCES} ${HEADERS})
add_executable(MCADefrag
${SOURCES}
${HEADERS}
${SHARED_SRC}
${SHARED_HDR}
${SHARED_OSS_SRC}
${SHARED_OSS_HDR}
)
target_link_libraries(MCADefrag zlib)

View File

@ -0,0 +1,10 @@
// Globals.cpp
// This file is used for precompiled header generation in MSVC environments
#include "Globals.h"

232
Tools/MCADefrag/Globals.h Normal file
View File

@ -0,0 +1,232 @@
// Globals.h
// This file gets included from every module in the project, so that global symbols may be introduced easily
// Also used for precompiled header generation in MSVC environments
// Compiler-dependent stuff:
#if defined(_MSC_VER)
// MSVC produces warning C4481 on the override keyword usage, so disable the warning altogether
#pragma warning(disable:4481)
// Disable some warnings that we don't care about:
#pragma warning(disable:4100)
#define OBSOLETE __declspec(deprecated)
// No alignment needed in MSVC
#define ALIGN_8
#define ALIGN_16
#elif defined(__GNUC__)
// TODO: Can GCC explicitly mark classes as abstract (no instances can be created)?
#define abstract
// TODO: Can GCC mark virtual methods as overriding (forcing them to have a virtual function of the same signature in the base class)
#define override
#define OBSOLETE __attribute__((deprecated))
#define ALIGN_8 __attribute__((aligned(8)))
#define ALIGN_16 __attribute__((aligned(16)))
// Some portability macros :)
#define stricmp strcasecmp
#define FORMATSTRING(formatIndex,va_argsIndex)
#else
#error "You are using an unsupported compiler, you might need to #define some stuff here for your compiler"
/*
// Copy and uncomment this into another #elif section based on your compiler identification
// Explicitly mark classes as abstract (no instances can be created)
#define abstract
// Mark virtual methods as overriding (forcing them to have a virtual function of the same signature in the base class)
#define override
// Mark functions as obsolete, so that their usage results in a compile-time warning
#define OBSOLETE
// Mark types / variables for alignment. Do the platforms need it?
#define ALIGN_8
#define ALIGN_16
*/
#define FORMATSTRING(formatIndex,va_argsIndex) __attribute__((format (printf, formatIndex, va_argsIndex)))
#endif
// Integral types with predefined sizes:
typedef long long Int64;
typedef int Int32;
typedef short Int16;
typedef unsigned long long UInt64;
typedef unsigned int UInt32;
typedef unsigned short UInt16;
typedef unsigned char Byte;
// A macro to disallow the copy constructor and operator= functions
// This should be used in the private: declarations for any class that shouldn't allow copying itself
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName &); \
void operator=(const TypeName &)
// A macro that is used to mark unused function parameters, to avoid pedantic warnings in gcc
#define UNUSED(X) (void)(X)
// OS-dependent stuff:
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
// Windows SDK defines min and max macros, messing up with our std::min and std::max usage
#undef min
#undef max
// Windows SDK defines GetFreeSpace as a constant, probably a Win16 API remnant
#ifdef GetFreeSpace
#undef GetFreeSpace
#endif // GetFreeSpace
#define SocketError WSAGetLastError()
#else
#include <sys/types.h>
#include <sys/stat.h> // for mkdir
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <time.h>
#include <dirent.h>
#include <errno.h>
#include <iostream>
#include <unistd.h>
#include <cstdio>
#include <cstring>
#include <pthread.h>
#include <semaphore.h>
#include <errno.h>
#include <fcntl.h>
typedef int SOCKET;
enum
{
INVALID_SOCKET = -1,
};
#define closesocket close
#define SocketError errno
#if !defined(ANDROID_NDK)
#include <tr1/memory>
#endif
#endif
#if !defined(ANDROID_NDK)
#define USE_SQUIRREL
#endif
#if defined(ANDROID_NDK)
#define FILE_IO_PREFIX "/sdcard/mcserver/"
#else
#define FILE_IO_PREFIX ""
#endif
// CRT stuff:
#include <assert.h>
#include <stdio.h>
#include <math.h>
#include <stdarg.h>
#include <time.h>
// STL stuff:
#include <vector>
#include <list>
#include <deque>
#include <string>
#include <map>
#include <algorithm>
#include <memory>
// Common headers (without macros):
#include "StringUtils.h"
#include "OSSupport/CriticalSection.h"
#include "OSSupport/IsThread.h"
#include "OSSupport/File.h"
// Common definitions:
/// Evaluates to the number of elements in an array (compile-time!)
#define ARRAYCOUNT(X) (sizeof(X) / sizeof(*(X)))
/// Allows arithmetic expressions like "32 KiB" (but consider using parenthesis around it, "(32 KiB)" )
#define KiB * 1024
#define MiB * 1024 * 1024
/// Faster than (int)floorf((float)x / (float)div)
#define FAST_FLOOR_DIV( x, div ) ( (x) < 0 ? (((int)x / div) - 1) : ((int)x / div) )
// Own version of assert() that writes failed assertions to the log for review
#ifdef NDEBUG
#define ASSERT(x) ((void)0)
#else
#define ASSERT assert
#endif
// Pretty much the same as ASSERT() but stays in Release builds
#define VERIFY( x ) ( !!(x) || ( LOGERROR("Verification failed: %s, file %s, line %i", #x, __FILE__, __LINE__ ), exit(1), 0 ) )
/// A generic interface used mainly in ForEach() functions
template <typename Type> class cItemCallback
{
public:
/// Called for each item in the internal list; return true to stop the loop, or false to continue enumerating
virtual bool Item(Type * a_Type) = 0;
} ;

View File

@ -0,0 +1,421 @@
// MCADefrag.cpp
// Implements the main app entrypoint and the cMCADefrag class representing the entire app
#include "Globals.h"
#include "MCADefrag.h"
#include "MCLogger.h"
#include "zlib/zlib.h"
// An array of 4096 zero bytes, used for writing the padding
static const Byte g_Zeroes[4096] = {0};
int main(int argc, char ** argv)
{
new cMCLogger(Printf("Defrag_%08x.log", time(NULL)));
cMCADefrag Defrag;
if (!Defrag.Init(argc, argv))
{
return 1;
}
Defrag.Run();
return 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cMCADefrag:
cMCADefrag::cMCADefrag(void) :
m_NumThreads(4),
m_ShouldRecompress(true)
{
}
bool cMCADefrag::Init(int argc, char ** argv)
{
// Nothing needed yet
return true;
}
void cMCADefrag::Run(void)
{
// Fill the queue with MCA files
m_Queue = cFile::GetFolderContents(".");
// Start the processing threads:
for (int i = 0; i < m_NumThreads; i++)
{
StartThread();
}
// Wait for all the threads to finish:
while (!m_Threads.empty())
{
m_Threads.front()->Wait();
delete m_Threads.front();
m_Threads.pop_front();
}
}
void cMCADefrag::StartThread(void)
{
cThread * Thread = new cThread(*this);
m_Threads.push_back(Thread);
Thread->Start();
}
AString cMCADefrag::GetNextFileName(void)
{
cCSLock Lock(m_CS);
if (m_Queue.empty())
{
return AString();
}
AString res = m_Queue.back();
m_Queue.pop_back();
return res;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cMCADefrag::cThread:
cMCADefrag::cThread::cThread(cMCADefrag & a_Parent) :
super("MCADefrag thread"),
m_Parent(a_Parent),
m_IsChunkUncompressed(false)
{
}
void cMCADefrag::cThread::Execute(void)
{
for (;;)
{
AString FileName = m_Parent.GetNextFileName();
if (FileName.empty())
{
return;
}
ProcessFile(FileName);
}
}
void cMCADefrag::cThread::ProcessFile(const AString & a_FileName)
{
// Filter out non-MCA files:
if ((a_FileName.length() < 4) || (a_FileName.substr(a_FileName.length() - 4, 4) != ".mca"))
{
return;
}
LOGINFO("%s", a_FileName.c_str());
// Open input and output files:
AString OutFileName = a_FileName + ".new";
cFile In, Out;
if (!In.Open(a_FileName, cFile::fmRead))
{
LOGWARNING("Cannot open file %s for reading, skipping file.", a_FileName.c_str());
return;
}
if (!Out.Open(OutFileName.c_str(), cFile::fmWrite))
{
LOGWARNING("Cannot open file %s for writing, skipping file.", OutFileName.c_str());
return;
}
// Read the Locations and Timestamps from the input file:
Byte Locations[4096];
UInt32 Timestamps[1024];
if (In.Read(Locations, sizeof(Locations)) != sizeof(Locations))
{
LOGWARNING("Cannot read Locations in file %s, skipping file.", a_FileName.c_str());
return;
}
if (In.Read(Timestamps, sizeof(Timestamps)) != sizeof(Timestamps))
{
LOGWARNING("Cannot read Timestamps in file %s, skipping file.", a_FileName.c_str());
return;
}
// Write dummy Locations to the Out file (will be overwritten once the correct ones are known)
if (Out.Write(Locations, sizeof(Locations)) != sizeof(Locations))
{
LOGWARNING("Cannot write Locations to file %s, skipping file.", OutFileName.c_str());
return;
}
m_CurrentSectorOut = 2;
// Write a copy of the Timestamps into the Out file:
if (Out.Write(Timestamps, sizeof(Timestamps)) != sizeof(Timestamps))
{
LOGWARNING("Cannot write Timestamps to file %s, skipping file.", OutFileName.c_str());
return;
}
// Process each chunk:
for (size_t i = 0; i < 1024; i++)
{
size_t idx = i * 4;
if (
(Locations[idx] == 0) &&
(Locations[idx + 1] == 0) &&
(Locations[idx + 2] == 0) &&
(Locations[idx + 3] == 0)
)
{
// Chunk not present
continue;
}
m_IsChunkUncompressed = false;
if (!ReadChunk(In, Locations + idx))
{
LOGWARNING("Cannot read chunk #%d from file %s. Skipping file.", i, a_FileName.c_str());
return;
}
if (!WriteChunk(Out, Locations + idx))
{
LOGWARNING("Cannot write chunk #%d to file %s. Skipping file.", i, OutFileName.c_str());
return;
}
}
// Write the new Locations into the MCA header:
Out.Seek(0);
if (Out.Write(Locations, sizeof(Locations)) != sizeof(Locations))
{
LOGWARNING("Cannot write updated Locations to file %s, skipping file.", OutFileName.c_str());
return;
}
// Close the files, delete orig, rename new:
In.Close();
Out.Close();
cFile::Delete(a_FileName);
cFile::Rename(OutFileName, a_FileName);
}
bool cMCADefrag::cThread::ReadChunk(cFile & a_File, const Byte * a_LocationRaw)
{
int SectorNum = (a_LocationRaw[0] << 16) | (a_LocationRaw[1] << 8) | a_LocationRaw[2];
int SizeInSectors = a_LocationRaw[3] * (4 KiB);
if (a_File.Seek(SectorNum * (4 KiB)) < 0)
{
LOGWARNING("Failed to seek to chunk data - file pos %llu (%d KiB, %.02f MiB)!", (Int64)SectorNum * (4 KiB), SectorNum * 4, ((double)SectorNum) / 256);
return false;
}
// Read the exact size:
Byte Buf[4];
if (a_File.Read(Buf, 4) != 4)
{
LOGWARNING("Failed to read chunk data length");
return false;
}
m_CompressedChunkDataSize = (Buf[0] << 24) | (Buf[1] << 16) | (Buf[2] << 8) | Buf[3];
if (m_CompressedChunkDataSize > SizeInSectors)
{
LOGWARNING("Invalid chunk data - SizeInSectors (%d) smaller that RealSize (%d)", SizeInSectors, m_CompressedChunkDataSize);
return false;
}
// Read the data:
if (a_File.Read(m_CompressedChunkData, m_CompressedChunkDataSize) != m_CompressedChunkDataSize)
{
LOGWARNING("Failed to read chunk data!");
return false;
}
// Uncompress the data if recompression is active
if (m_Parent.m_ShouldRecompress)
{
m_IsChunkUncompressed = UncompressChunk();
if (!m_IsChunkUncompressed)
{
LOGINFO("Chunk failed to uncompress, will be copied verbatim instead.");
}
}
return true;
}
bool cMCADefrag::cThread::WriteChunk(cFile & a_File, Byte * a_LocationRaw)
{
// Recompress the data if recompression is active:
if (m_Parent.m_ShouldRecompress)
{
if (!CompressChunk())
{
LOGINFO("Chunk failed to recompress, will be coped verbatim instead.");
}
}
// Update the Location:
a_LocationRaw[0] = m_CurrentSectorOut >> 16;
a_LocationRaw[1] = (m_CurrentSectorOut >> 8) & 0xff;
a_LocationRaw[2] = m_CurrentSectorOut & 0xff;
a_LocationRaw[3] = (m_CompressedChunkDataSize + (4 KiB) + 3) / (4 KiB); // +3 because the m_CompressedChunkDataSize doesn't include the exact-length
m_CurrentSectorOut += a_LocationRaw[3];
// Write the data length:
Byte Buf[4];
Buf[0] = m_CompressedChunkDataSize >> 24;
Buf[1] = (m_CompressedChunkDataSize >> 16) & 0xff;
Buf[2] = (m_CompressedChunkDataSize >> 8) & 0xff;
Buf[3] = m_CompressedChunkDataSize & 0xff;
if (a_File.Write(Buf, 4) != 4)
{
LOGWARNING("Failed to write chunk length!");
return false;
}
// Write the data:
if (a_File.Write(m_CompressedChunkData, m_CompressedChunkDataSize) != m_CompressedChunkDataSize)
{
LOGWARNING("Failed to write chunk data!");
return false;
}
// Pad onto the next sector:
int NumPadding = a_LocationRaw[3] * 4096 - (m_CompressedChunkDataSize + 4);
ASSERT(NumPadding >= 0);
if ((NumPadding > 0) && (a_File.Write(g_Zeroes, NumPadding) != NumPadding))
{
LOGWARNING("Failed to write padding");
return false;
}
return true;
}
bool cMCADefrag::cThread::UncompressChunk(void)
{
switch (m_CompressedChunkData[0])
{
case COMPRESSION_GZIP: return UncompressChunkGzip();
case COMPRESSION_ZLIB: return UncompressChunkZlib();
}
LOGINFO("Chunk is compressed with in an unknown algorithm");
return false;
}
bool cMCADefrag::cThread::UncompressChunkGzip(void)
{
// TODO
// This format is not used in practice
return false;
}
bool cMCADefrag::cThread::UncompressChunkZlib(void)
{
// Uncompress the data:
z_stream strm;
strm.zalloc = (alloc_func)NULL;
strm.zfree = (free_func)NULL;
strm.opaque = NULL;
inflateInit(&strm);
strm.next_out = m_RawChunkData;
strm.avail_out = sizeof(m_RawChunkData);
strm.next_in = m_CompressedChunkData + 1; // The first byte is the compression method, skip it
strm.avail_in = m_CompressedChunkDataSize;
int res = inflate(&strm, Z_FINISH);
inflateEnd(&strm);
if (res != Z_STREAM_END)
{
LOGWARNING("Failed to uncompress chunk data: %s", strm.msg);
return false;
}
m_RawChunkDataSize = strm.total_out;
return true;
}
bool cMCADefrag::cThread::CompressChunk(void)
{
// Check that the compressed data can fit:
uLongf CompressedSize = compressBound(m_RawChunkDataSize);
if (CompressedSize > sizeof(m_CompressedChunkData))
{
LOGINFO("Too much data for the internal compression buffer!");
return false;
}
// Compress the data using the highest compression factor:
int errorcode = compress2(m_CompressedChunkData + 1, &CompressedSize, m_RawChunkData, m_RawChunkDataSize, Z_BEST_COMPRESSION);
if (errorcode != Z_OK)
{
LOGINFO("Recompression failed: %d", errorcode);
return false;
}
m_CompressedChunkData[0] = COMPRESSION_ZLIB;
m_CompressedChunkDataSize = CompressedSize + 1;
return true;
}

144
Tools/MCADefrag/MCADefrag.h Normal file
View File

@ -0,0 +1,144 @@
// MCADefrag.h
// Interfaces to the cMCADefrag class encapsulating the entire app
#pragma once
class cMCADefrag
{
public:
enum
{
MAX_COMPRESSED_CHUNK_DATA_SIZE = (1 MiB),
MAX_RAW_CHUNK_DATA_SIZE = (100 MiB),
} ;
cMCADefrag(void);
/** Reads the cmdline params and initializes the app.
Returns true if the app should continue, false if not. */
bool Init(int argc, char ** argv);
/** Runs the entire app. */
void Run(void);
protected:
/** A single thread processing MCA files from the queue */
class cThread :
public cIsThread
{
typedef cIsThread super;
public:
cThread(cMCADefrag & a_Parent);
protected:
/** The compression methods, as specified by the MCA compression method byte. */
enum
{
COMPRESSION_GZIP = 1,
COMPRESSION_ZLIB = 2,
} ;
cMCADefrag & m_Parent;
/** The current compressed chunk data. Valid after a successful ReadChunk().
This contains only the compression method byte and the compressed data,
but not the exact-length preceding the data in the MCA file. */
unsigned char m_CompressedChunkData[MAX_COMPRESSED_CHUNK_DATA_SIZE];
/** Size of the actual current compressed chunk data, excluding the 4 exact-length bytes.
This is the amount of bytes in m_CompressedChunkData[] that are valid. */
int m_CompressedChunkDataSize;
/** The current raw chunk data. Valid after a successful ReadChunk(), if recompression is active. */
unsigned char m_RawChunkData[MAX_RAW_CHUNK_DATA_SIZE];
/** Size of the actual current raw chunk data. */
int m_RawChunkDataSize;
/** Number of the sector where the next chunk will be written by WriteChunk(). */
int m_CurrentSectorOut;
/** Set to true when the chunk has been successfully uncompressed. Only used if recompression is active.
WriteChunk() tests this flag to decide whether to call Compress(). */
bool m_IsChunkUncompressed;
/** Processes the specified file. */
void ProcessFile(const AString & a_FileName);
/** Reads the chunk data into m_CompressedChunkData.
Calls DecompressChunkData() if recompression is active.
a_LocationRaw is the pointer to the first byte of the Location data in the MCA header.
Returns true if successful. */
bool ReadChunk(cFile & a_File, const Byte * a_LocationRaw);
/** Writes the chunk data from m_CompressedData or m_RawChunkData (performing recompression) into file.
Calls CompressChunkData() for the actual compression, if recompression is active.
a_LocationRaw is the pointer to the first byte of the Location data to be put into the MCA header,
the chunk's location is stored in that memory area. Updates m_CurrentSectorOut.
Returns true if successful. */
bool WriteChunk(cFile & a_File, Byte * a_LocationRaw);
/** Uncompresses the chunk data from m_CompressedChunkData into m_RawChunkData.
Returns true if successful, false on failure. */
bool UncompressChunk(void);
/** Uncompresses the chunk data from m_CompressedChunkData into m_RawChunkData, using Gzip.
Returns true if successful, false on failure. */
bool UncompressChunkGzip(void);
/** Uncompresses the chunk data from m_CompressedChunkData into m_RawChunkData, using Zlib.
Returns true if successful, false on failure. */
bool UncompressChunkZlib(void);
/** Compresses the chunk data from m_RawChunkData into m_CompressedChunkData.
Returns true if successful, false on failure. */
bool CompressChunk(void);
// cIsThread overrides:
virtual void Execute(void) override;
} ;
typedef std::list<cThread *> cThreads;
/** The mutex protecting m_Files agains multithreaded access. */
cCriticalSection m_CS;
/** The queue of MCA files to be processed by the threads. Protected by m_CS. */
AStringVector m_Queue;
/** List of threads that the server has running. */
cThreads m_Threads;
/** The number of threads that should be started. Configurable on the command line. */
int m_NumThreads;
/** If set to true, the chunk data is recompressed while saving each MCA file. */
bool m_ShouldRecompress;
/** Starts a new processing thread and adds it to cThreads. */
void StartThread(void);
/** Retrieves one file from the queue (and removes it from the queue).
Returns an empty string when queue empty. */
AString GetNextFileName(void);
} ;

View File

@ -1,6 +1,7 @@
Debug
Release
Logs/
lib/
*.log
*.nbt
*.sln

View File

@ -3,69 +3,19 @@ cmake_minimum_required (VERSION 2.6)
project (ProtoProxy)
include(../../SetFlags.cmake)
macro(add_flags_cxx FLAGS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAGS}")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FLAGS}")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${FLAGS}")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${FLAGS}")
endmacro()
# Add the preprocessor macros used for distinguishing between debug and release builds (CMake does this automatically for MSVC):
if (NOT MSVC)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNDEBUG")
endif()
if(MSVC)
# Make build use multiple threads under MSVC:
add_flags_cxx("/MP")
# Make release builds use link-time code generation:
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /GL")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG")
set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} /LTCG")
elseif(APPLE)
#on os x clang adds pthread for us but we need to add it for gcc
if (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
add_flags_cxx("-pthread")
endif()
else()
# Let gcc / clang know that we're compiling a multi-threaded app:
add_flags_cxx("-pthread")
endif()
# Use static CRT in MSVC builds:
if (MSVC)
string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
string(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
string(REPLACE "/MDd" "/MTd" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
endif()
set_flags()
set_lib_flags()
# Set include paths to the used libraries:
include_directories("../../lib")
include_directories("../../lib/polarssl/include")
include_directories("../../src")
function(flatten_files arg1)
set(res "")
foreach(f ${${arg1}})
@ -75,20 +25,10 @@ function(flatten_files arg1)
set(${arg1} "${res}" PARENT_SCOPE)
endfunction()
include(../../lib/polarssl.cmake)
add_subdirectory(../../lib/zlib ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/lib/zlib)
# Include the libraries:
file(GLOB CRYPTOPP_SRC "../../lib/cryptopp/*.cpp")
file(GLOB CRYPTOPP_HDR "../../lib/cryptopp/*.h")
flatten_files(CRYPTOPP_SRC)
flatten_files(CRYPTOPP_HDR)
source_group("CryptoPP" FILES ${CRYPTOPP_SRC} ${CRYPTOPP_HDR})
file(GLOB ZLIB_SRC "../../lib/zlib/*.c")
file(GLOB ZLIB_HDR "../../lib/zlib/*.h")
flatten_files(ZLIB_SRC)
flatten_files(ZLIB_HDR)
source_group("ZLib" FILES ${ZLIB_SRC} ${ZLIB_HDR})
set_exe_flags()
# Include the shared files:
set(SHARED_SRC
@ -96,12 +36,14 @@ set(SHARED_SRC
../../src/StringUtils.cpp
../../src/Log.cpp
../../src/MCLogger.cpp
../../src/Crypto.cpp
)
set(SHARED_HDR
../../src/ByteBuffer.h
../../src/StringUtils.h
../../src/Log.h
../../src/MCLogger.h
../../src/Crypto.h
)
set(SHARED_OSS_SRC
../../src/OSSupport/CriticalSection.cpp
@ -145,9 +87,7 @@ add_executable(ProtoProxy
${SHARED_HDR}
${SHARED_OSS_SRC}
${SHARED_OSS_HDR}
${CRYPTOPP_SRC}
${CRYPTOPP_HDR}
${ZLIB_SRC}
${ZLIB_HDR}
)
target_link_libraries(ProtoProxy zlib polarssl)

View File

@ -131,8 +131,6 @@
} \
}
#define MAX_ENC_LEN 1024
@ -243,7 +241,8 @@ void cConnection::Run(void)
FD_ZERO(&ReadFDs);
FD_SET(m_ServerSocket, &ReadFDs);
FD_SET(m_ClientSocket, &ReadFDs);
int res = select(2, &ReadFDs, NULL, NULL, NULL);
SOCKET MaxSocket = std::max(m_ServerSocket, m_ClientSocket);
int res = select(MaxSocket + 1, &ReadFDs, NULL, NULL, NULL);
if (res <= 0)
{
printf("select() failed: %d; aborting client", SocketError);
@ -377,19 +376,19 @@ bool cConnection::RelayFromServer(void)
}
case csEncryptedUnderstood:
{
m_ServerDecryptor.ProcessData((byte *)Buffer, (byte *)Buffer, res);
m_ServerDecryptor.ProcessData((Byte *)Buffer, (Byte *)Buffer, res);
DataLog(Buffer, res, "Decrypted %d bytes from the SERVER", res);
return DecodeServersPackets(Buffer, res);
}
case csEncryptedUnknown:
{
m_ServerDecryptor.ProcessData((byte *)Buffer, (byte *)Buffer, res);
m_ServerDecryptor.ProcessData((Byte *)Buffer, (Byte *)Buffer, res);
DataLog(Buffer, res, "Decrypted %d bytes from the SERVER", res);
return CLIENTSEND(Buffer, res);
}
}
return true;
ASSERT(!"Unhandled server state while relaying from server");
return false;
}
@ -422,12 +421,12 @@ bool cConnection::RelayFromClient(void)
case csEncryptedUnknown:
{
DataLog(Buffer, res, "Decrypted %d bytes from the CLIENT", res);
m_ServerEncryptor.ProcessData((byte *)Buffer, (byte *)Buffer, res);
m_ServerEncryptor.ProcessData((Byte *)Buffer, (Byte *)Buffer, res);
return SERVERSEND(Buffer, res);
}
}
return true;
ASSERT(!"Unhandled server state while relaying from client");
return false;
}
@ -443,11 +442,11 @@ double cConnection::GetRelativeTime(void)
bool cConnection::SendData(SOCKET a_Socket, const char * a_Data, int a_Size, const char * a_Peer)
bool cConnection::SendData(SOCKET a_Socket, const char * a_Data, size_t a_Size, const char * a_Peer)
{
DataLog(a_Data, a_Size, "Sending data to %s, %d bytes", a_Peer, a_Size);
DataLog(a_Data, a_Size, "Sending data to %s, %u bytes", a_Peer, (unsigned)a_Size);
int res = send(a_Socket, a_Data, a_Size, 0);
int res = send(a_Socket, a_Data, (int)a_Size, 0);
if (res <= 0)
{
Log("%s closed the socket: %d, %d; aborting connection", a_Peer, res, SocketError);
@ -472,14 +471,14 @@ bool cConnection::SendData(SOCKET a_Socket, cByteBuffer & a_Data, const char * a
bool cConnection::SendEncryptedData(SOCKET a_Socket, Encryptor & a_Encryptor, const char * a_Data, int a_Size, const char * a_Peer)
bool cConnection::SendEncryptedData(SOCKET a_Socket, cAESCFBEncryptor & a_Encryptor, const char * a_Data, size_t a_Size, const char * a_Peer)
{
DataLog(a_Data, a_Size, "Encrypting %d bytes to %s", a_Size, a_Peer);
const byte * Data = (const byte *)a_Data;
const Byte * Data = (const Byte *)a_Data;
while (a_Size > 0)
{
byte Buffer[64 KiB];
int NumBytes = (a_Size > sizeof(Buffer)) ? sizeof(Buffer) : a_Size;
Byte Buffer[64 KiB];
size_t NumBytes = (a_Size > sizeof(Buffer)) ? sizeof(Buffer) : a_Size;
a_Encryptor.ProcessData(Buffer, Data, NumBytes);
bool res = SendData(a_Socket, (const char *)Buffer, NumBytes, a_Peer);
if (!res)
@ -496,7 +495,7 @@ bool cConnection::SendEncryptedData(SOCKET a_Socket, Encryptor & a_Encryptor, co
bool cConnection::SendEncryptedData(SOCKET a_Socket, Encryptor & a_Encryptor, cByteBuffer & a_Data, const char * a_Peer)
bool cConnection::SendEncryptedData(SOCKET a_Socket, cAESCFBEncryptor & a_Encryptor, cByteBuffer & a_Data, const char * a_Peer)
{
AString All;
a_Data.ReadAll(All);
@ -1301,6 +1300,7 @@ bool cConnection::HandleServerLoginEncryptionKeyRequest(void)
}
Log("Got PACKET_ENCRYPTION_KEY_REQUEST from the SERVER:");
Log(" ServerID = %s", ServerID.c_str());
DataLog(PublicKey.data(), PublicKey.size(), " Public key (%u bytes)", (unsigned)PublicKey.size());
// Reply to the server:
SendEncryptionKeyResponse(PublicKey, Nonce);
@ -2261,7 +2261,9 @@ bool cConnection::HandleServerSpawnObjectVehicle(void)
HANDLE_SERVER_PACKET_READ(ReadByte, Byte, Yaw);
HANDLE_SERVER_PACKET_READ(ReadBEInt, int, DataIndicator);
AString ExtraData;
short VelocityX, VelocityY, VelocityZ;
short VelocityX = 0;
short VelocityY = 0;
short VelocityZ = 0;
if (DataIndicator != 0)
{
HANDLE_SERVER_PACKET_READ(ReadBEShort, short, SpeedX);
@ -2695,12 +2697,12 @@ bool cConnection::ParseMetadata(cByteBuffer & a_Buffer, AString & a_Metadata)
a_Metadata.push_back(x);
while (x != 0x7f)
{
int Index = ((unsigned)((unsigned char)x)) & 0x1f; // Lower 5 bits = index
// int Index = ((unsigned)((unsigned char)x)) & 0x1f; // Lower 5 bits = index
int Type = ((unsigned)((unsigned char)x)) >> 5; // Upper 3 bits = type
int Length = 0;
switch (Type)
{
case 0: Length = 1; break; // byte
case 0: Length = 1; break; // Byte
case 1: Length = 2; break; // short
case 2: Length = 4; break; // int
case 3: Length = 4; break; // float
@ -2770,7 +2772,7 @@ void cConnection::LogMetadata(const AString & a_Metadata, size_t a_IndentCount)
{
int Index = ((unsigned)((unsigned char)a_Metadata[pos])) & 0x1f; // Lower 5 bits = index
int Type = ((unsigned)((unsigned char)a_Metadata[pos])) >> 5; // Upper 3 bits = type
int Length = 0;
// int Length = 0;
switch (Type)
{
case 0:
@ -2825,7 +2827,7 @@ void cConnection::LogMetadata(const AString & a_Metadata, size_t a_IndentCount)
ASSERT(!"Cannot parse item description from metadata");
return;
}
int After = bb.GetReadableSpace();
// int After = bb.GetReadableSpace();
int BytesConsumed = BytesLeft - bb.GetReadableSpace();
Log("%sslot[%d] = %s (%d bytes)", Indent.c_str(), Index, ItemDesc.c_str(), BytesConsumed);
@ -2859,37 +2861,42 @@ void cConnection::LogMetadata(const AString & a_Metadata, size_t a_IndentCount)
void cConnection::SendEncryptionKeyResponse(const AString & a_ServerPublicKey, const AString & a_Nonce)
{
// Generate the shared secret and encrypt using the server's public key
byte SharedSecret[16];
byte EncryptedSecret[128];
Byte SharedSecret[16];
Byte EncryptedSecret[128];
memset(SharedSecret, 0, sizeof(SharedSecret)); // Use all zeroes for the initial secret
RSA::PublicKey pk;
CryptoPP::StringSource src(a_ServerPublicKey, true);
ByteQueue bq;
src.TransferTo(bq);
bq.MessageEnd();
pk.Load(bq);
RSAES<PKCS1v15>::Encryptor rsaEncryptor(pk);
RandomPool rng;
time_t CurTime = time(NULL);
rng.Put((const byte *)&CurTime, sizeof(CurTime));
int EncryptedLength = rsaEncryptor.FixedCiphertextLength();
ASSERT(EncryptedLength <= sizeof(EncryptedSecret));
rsaEncryptor.Encrypt(rng, SharedSecret, sizeof(SharedSecret), EncryptedSecret);
m_ServerEncryptor.SetKey(SharedSecret, 16, MakeParameters(Name::IV(), ConstByteArrayParameter(SharedSecret, 16, true))(Name::FeedbackSize(), 1));
m_ServerDecryptor.SetKey(SharedSecret, 16, MakeParameters(Name::IV(), ConstByteArrayParameter(SharedSecret, 16, true))(Name::FeedbackSize(), 1));
cPublicKey PubKey(a_ServerPublicKey);
int res = PubKey.Encrypt(SharedSecret, sizeof(SharedSecret), EncryptedSecret, sizeof(EncryptedSecret));
if (res < 0)
{
Log("Shared secret encryption failed: %d (0x%x)", res, res);
return;
}
m_ServerEncryptor.Init(SharedSecret, SharedSecret);
m_ServerDecryptor.Init(SharedSecret, SharedSecret);
// Encrypt the nonce:
byte EncryptedNonce[128];
rsaEncryptor.Encrypt(rng, (const byte *)(a_Nonce.data()), a_Nonce.size(), EncryptedNonce);
Byte EncryptedNonce[128];
res = PubKey.Encrypt((const Byte *)a_Nonce.data(), a_Nonce.size(), EncryptedNonce, sizeof(EncryptedNonce));
if (res < 0)
{
Log("Nonce encryption failed: %d (0x%x)", res, res);
return;
}
// Send the packet to the server:
Log("Sending PACKET_ENCRYPTION_KEY_RESPONSE to the SERVER");
cByteBuffer ToServer(1024);
ToServer.WriteByte(0x01); // To server: Encryption key response
ToServer.WriteBEShort(EncryptedLength);
ToServer.WriteBuf(EncryptedSecret, EncryptedLength);
ToServer.WriteBEShort(EncryptedLength);
ToServer.WriteBuf(EncryptedNonce, EncryptedLength);
ToServer.WriteBEShort((short)sizeof(EncryptedSecret));
ToServer.WriteBuf(EncryptedSecret, sizeof(EncryptedSecret));
ToServer.WriteBEShort((short)sizeof(EncryptedNonce));
ToServer.WriteBuf(EncryptedNonce, sizeof(EncryptedNonce));
DataLog(EncryptedSecret, sizeof(EncryptedSecret), "Encrypted secret (%u bytes)", (unsigned)sizeof(EncryptedSecret));
DataLog(EncryptedNonce, sizeof(EncryptedNonce), "Encrypted nonce (%u bytes)", (unsigned)sizeof(EncryptedNonce));
cByteBuffer Len(5);
Len.WriteVarInt(ToServer.GetReadableSpace());
SERVERSEND(Len);
SERVERSEND(ToServer);
m_ServerState = csEncryptedUnderstood;
m_IsServerEncrypted = true;

View File

@ -62,14 +62,12 @@ public:
void LogFlush(void);
protected:
typedef CFB_Mode<AES>::Encryption Encryptor;
typedef CFB_Mode<AES>::Decryption Decryptor;
cByteBuffer m_ClientBuffer;
cByteBuffer m_ServerBuffer;
Decryptor m_ServerDecryptor;
Encryptor m_ServerEncryptor;
cAESCFBDecryptor m_ServerDecryptor;
cAESCFBEncryptor m_ServerEncryptor;
AString m_ServerEncryptionBuffer; // Buffer for the data to be sent to the server once encryption is established
@ -105,16 +103,16 @@ protected:
double GetRelativeTime(void);
/// Sends data to the specified socket. If sending fails, prints a fail message using a_Peer and returns false.
bool SendData(SOCKET a_Socket, const char * a_Data, int a_Size, const char * a_Peer);
bool SendData(SOCKET a_Socket, const char * a_Data, size_t a_Size, const char * a_Peer);
/// Sends data to the specified socket. If sending fails, prints a fail message using a_Peer and returns false.
bool SendData(SOCKET a_Socket, cByteBuffer & a_Data, const char * a_Peer);
/// Sends data to the specfied socket, after encrypting it using a_Encryptor. If sending fails, prints a fail message using a_Peer and returns false
bool SendEncryptedData(SOCKET a_Socket, Encryptor & a_Encryptor, const char * a_Data, int a_Size, const char * a_Peer);
bool SendEncryptedData(SOCKET a_Socket, cAESCFBEncryptor & a_Encryptor, const char * a_Data, size_t a_Size, const char * a_Peer);
/// Sends data to the specfied socket, after encrypting it using a_Encryptor. If sending fails, prints a fail message using a_Peer and returns false
bool SendEncryptedData(SOCKET a_Socket, Encryptor & a_Encryptor, cByteBuffer & a_Data, const char * a_Peer);
bool SendEncryptedData(SOCKET a_Socket, cAESCFBEncryptor & a_Encryptor, cByteBuffer & a_Data, const char * a_Peer);
/// Decodes packets coming from the client, sends appropriate counterparts to the server; returns false if the connection is to be dropped
bool DecodeClientsPackets(const char * a_Data, int a_Size);

View File

@ -22,6 +22,8 @@
#define ALIGN_8
#define ALIGN_16
#define FORMATSTRING(formatIndex, va_argsIndex)
#elif defined(__GNUC__)
// TODO: Can GCC explicitly mark classes as abstract (no instances can be created)?
@ -37,6 +39,8 @@
// Some portability macros :)
#define stricmp strcasecmp
#define FORMATSTRING(formatIndex, va_argsIndex)
#else
@ -59,6 +63,9 @@
#define ALIGN_16
*/
#define FORMATSTRING(formatIndex, va_argsIndex) __attribute__((format (printf, formatIndex, va_argsIndex)))
#endif
@ -74,6 +81,8 @@ typedef unsigned long long UInt64;
typedef unsigned int UInt32;
typedef unsigned short UInt16;
typedef unsigned char Byte;
@ -223,16 +232,12 @@ public:
#include "cryptopp/randpool.h"
#include "cryptopp/aes.h"
#include "cryptopp/rsa.h"
#include "cryptopp/modes.h"
#include "../../src/Crypto.h"
using namespace CryptoPP;
#define LOGERROR printf
#define LOGINFO printf
#define LOGWARNING printf
#define LOGWARNING printf

View File

@ -34,12 +34,8 @@ int cServer::Init(short a_ListenPort, short a_ConnectPort)
#endif // _WIN32
printf("Generating protocol encryption keypair...\n");
time_t CurTime = time(NULL);
RandomPool rng;
rng.Put((const byte *)&CurTime, sizeof(CurTime));
m_PrivateKey.GenerateRandomWithKeySize(rng, 1024);
RSA::PublicKey pk(m_PrivateKey);
m_PublicKey = pk;
m_PrivateKey.Generate();
m_PublicKeyDER = m_PrivateKey.GetPubKeyDER();
m_ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in local;

View File

@ -17,8 +17,8 @@
class cServer
{
SOCKET m_ListenSocket;
RSA::PrivateKey m_PrivateKey;
RSA::PublicKey m_PublicKey;
cRSAPrivateKey m_PrivateKey;
AString m_PublicKeyDER;
short m_ConnectPort;
public:
@ -27,8 +27,8 @@ public:
int Init(short a_ListenPort, short a_ConnectPort);
void Run(void);
RSA::PrivateKey & GetPrivateKey(void) { return m_PrivateKey; }
RSA::PublicKey & GetPublicKey (void) { return m_PublicKey; }
cRSAPrivateKey & GetPrivateKey(void) { return m_PrivateKey; }
const AString & GetPublicKeyDER (void) { return m_PublicKeyDER; }
short GetConnectPort(void) const { return m_ConnectPort; }
} ;

View File

@ -1,14 +0,0 @@
cmake_minimum_required (VERSION 2.6)
project (cryptopp)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCRYPTOPP_DISABLE_ASM")
endif()
include_directories ("${PROJECT_SOURCE_DIR}/../../src/")
file(GLOB cryptopp_SRC
"*.cpp"
)
add_library(cryptopp ${cryptopp_SRC})

File diff suppressed because it is too large Load Diff

View File

@ -1,51 +0,0 @@
Compilation Copyright (c) 1995-2013 by Wei Dai. All rights reserved.
This copyright applies only to this software distribution package
as a compilation, and does not imply a copyright on any particular
file in the package.
All individual files in this compilation are placed in the public domain by
Wei Dai and other contributors.
I would like to thank the following authors for placing their works into
the public domain:
Joan Daemen - 3way.cpp
Leonard Janke - cast.cpp, seal.cpp
Steve Reid - cast.cpp
Phil Karn - des.cpp
Andrew M. Kuchling - md2.cpp, md4.cpp
Colin Plumb - md5.cpp
Seal Woods - rc6.cpp
Chris Morgan - rijndael.cpp
Paulo Baretto - rijndael.cpp, skipjack.cpp, square.cpp
Richard De Moliner - safer.cpp
Matthew Skala - twofish.cpp
Kevin Springle - camellia.cpp, shacal2.cpp, ttmac.cpp, whrlpool.cpp, ripemd.cpp
Ronny Van Keer - sha3.cpp
The Crypto++ Library (as a compilation) is currently licensed under the Boost
Software License 1.0 (http://www.boost.org/users/license.html).
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
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
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
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
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
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
DEALINGS IN THE SOFTWARE.

View File

@ -1,452 +0,0 @@
Crypto++: a C++ Class Library of Cryptographic Schemes
Version 5.6.2 - 2/20/2013
Crypto++ Library is a free C++ class library of cryptographic schemes.
Currently the library contains the following algorithms:
algorithm type name
authenticated encryption schemes GCM, CCM, EAX
high speed stream ciphers Panama, Sosemanuk, Salsa20, XSalsa20
AES and AES candidates AES (Rijndael), RC6, MARS, Twofish, Serpent,
CAST-256
IDEA, Triple-DES (DES-EDE2 and DES-EDE3),
other block ciphers Camellia, SEED, RC5, Blowfish, TEA, XTEA,
Skipjack, SHACAL-2
block cipher modes of operation ECB, CBC, CBC ciphertext stealing (CTS),
CFB, OFB, counter mode (CTR)
message authentication codes VMAC, HMAC, GMAC, CMAC, CBC-MAC, DMAC,
Two-Track-MAC
SHA-1, SHA-2 (SHA-224, SHA-256, SHA-384, and
hash functions SHA-512), SHA-3, Tiger, WHIRLPOOL, RIPEMD-128,
RIPEMD-256, RIPEMD-160, RIPEMD-320
RSA, DSA, ElGamal, Nyberg-Rueppel (NR),
public-key cryptography Rabin-Williams (RW), LUC, LUCELG,
DLIES (variants of DHAES), ESIGN
padding schemes for public-key PKCS#1 v2.0, OAEP, PSS, PSSR, IEEE P1363
systems EMSA2 and EMSA5
Diffie-Hellman (DH), Unified Diffie-Hellman
key agreement schemes (DH2), Menezes-Qu-Vanstone (MQV), LUCDIF,
XTR-DH
elliptic curve cryptography ECDSA, ECNR, ECIES, ECDH, ECMQV
insecure or obsolescent MD2, MD4, MD5, Panama Hash, DES, ARC4, SEAL
algorithms retained for backwards 3.0, WAKE-OFB, DESX (DES-XEX3), RC2,
compatibility and historical SAFER, 3-WAY, GOST, SHARK, CAST-128, Square
value
Other features include:
* pseudo random number generators (PRNG): ANSI X9.17 appendix C, RandomPool
* password based key derivation functions: PBKDF1 and PBKDF2 from PKCS #5,
PBKDF from PKCS #12 appendix B
* Shamir's secret sharing scheme and Rabin's information dispersal algorithm
(IDA)
* fast multi-precision integer (bignum) and polynomial operations
* finite field arithmetics, including GF(p) and GF(2^n)
* prime number generation and verification
* useful non-cryptographic algorithms
+ DEFLATE (RFC 1951) compression/decompression with gzip (RFC 1952) and
zlib (RFC 1950) format support
+ hex, base-32, and base-64 coding/decoding
+ 32-bit CRC and Adler32 checksum
* class wrappers for these operating system features (optional):
+ high resolution timers on Windows, Unix, and Mac OS
+ Berkeley and Windows style sockets
+ Windows named pipes
+ /dev/random, /dev/urandom, /dev/srandom
+ Microsoft's CryptGenRandom on Windows
* A high level interface for most of the above, using a filter/pipeline
metaphor
* benchmarks and validation testing
* x86, x86-64 (x64), MMX, and SSE2 assembly code for the most commonly used
algorithms, with run-time CPU feature detection and code selection
* some versions are available in FIPS 140-2 validated form
You are welcome to use it for any purpose without paying me, but see
License.txt for the fine print.
The following compilers are supported for this release. Please visit
http://www.cryptopp.com the most up to date build instructions and porting notes.
* MSVC 6.0 - 2010
* GCC 3.3 - 4.5
* C++Builder 2010
* Intel C++ Compiler 9 - 11.1
* Sun Studio 12u1, Express 11/08, Express 06/10
*** Important Usage Notes ***
1. If a constructor for A takes a pointer to an object B (except primitive
types such as int and char), then A owns B and will delete B at A's
destruction. If a constructor for A takes a reference to an object B,
then the caller retains ownership of B and should not destroy it until
A no longer needs it.
2. Crypto++ is thread safe at the class level. This means you can use
Crypto++ safely in a multithreaded application, but you must provide
synchronization when multiple threads access a common Crypto++ object.
*** MSVC-Specific Information ***
On Windows, Crypto++ can be compiled into 3 forms: a static library
including all algorithms, a DLL with only FIPS Approved algorithms, and
a static library with only algorithms not in the DLL.
(FIPS Approved means Approved according to the FIPS 140-2 standard.)
The DLL may be used by itself, or it may be used together with the second
form of the static library. MSVC project files are included to build
all three forms, and sample applications using each of the three forms
are also included.
To compile Crypto++ with MSVC, open the "cryptest.dsw" (for MSVC 6 and MSVC .NET
2003) or "cryptest.sln" (for MSVC 2005 - 2010) workspace file and build one or
more of the following projects:
cryptopp - This builds the DLL. Please note that if you wish to use Crypto++
as a FIPS validated module, you must use a pre-built DLL that has undergone
the FIPS validation process instead of building your own.
dlltest - This builds a sample application that only uses the DLL.
cryptest Non-DLL-Import Configuration - This builds the full static library
along with a full test driver.
cryptest DLL-Import Configuration - This builds a static library containing
only algorithms not in the DLL, along with a full test driver that uses
both the DLL and the static library.
To use the Crypto++ DLL in your application, #include "dll.h" before including
any other Crypto++ header files, and place the DLL in the same directory as
your .exe file. dll.h includes the line #pragma comment(lib, "cryptopp")
so you don't have to explicitly list the import library in your project
settings. To use a static library form of Crypto++, make the "cryptlib"
project a dependency of your application project, or specify it as
an additional library to link with in your project settings.
In either case you should check the compiler options to
make sure that the library and your application are using the same C++
run-time libraries and calling conventions.
*** DLL Memory Management ***
Because it's possible for the Crypto++ DLL to delete objects allocated
by the calling application, they must use the same C++ memory heap. Three
methods are provided to achieve this.
1. The calling application can tell Crypto++ what heap to use. This method
is required when the calling application uses a non-standard heap.
2. Crypto++ can tell the calling application what heap to use. This method
is required when the calling application uses a statically linked C++ Run
Time Library. (Method 1 does not work in this case because the Crypto++ DLL
is initialized before the calling application's heap is initialized.)
3. Crypto++ can automatically use the heap provided by the calling application's
dynamically linked C++ Run Time Library. The calling application must
make sure that the dynamically linked C++ Run Time Library is initialized
before Crypto++ is loaded. (At this time it is not clear if it is possible
to control the order in which DLLs are initialized on Windows 9x machines,
so it might be best to avoid using this method.)
When Crypto++ attaches to a new process, it searches all modules loaded
into the process space for exported functions "GetNewAndDeleteForCryptoPP"
and "SetNewAndDeleteFromCryptoPP". If one of these functions is found,
Crypto++ uses methods 1 or 2, respectively, by calling the function.
Otherwise, method 3 is used.
*** GCC-Specific Information ***
A makefile is included for you to compile Crypto++ with GCC. Make sure
you are using GNU Make and GNU ld. The make process will produce two files,
libcryptopp.a and cryptest.exe. Run "cryptest.exe v" for the validation
suite.
*** Documentation and Support ***
Crypto++ is documented through inline comments in header files, which are
processed through Doxygen to produce an HTML reference manual. You can find
a link to the manual from http://www.cryptopp.com. Also at that site is
the Crypto++ FAQ, which you should browse through before attempting to
use this library, because it will likely answer many of questions that
may come up.
If you run into any problems, please try the Crypto++ mailing list.
The subscription information and the list archive are available on
http://www.cryptopp.com. You can also email me directly by visiting
http://www.weidai.com, but you will probably get a faster response through
the mailing list.
*** History ***
1.0 - First public release. Withdrawn at the request of RSA DSI.
- included Blowfish, BBS, DES, DH, Diamond, DSA, ElGamal, IDEA,
MD5, RC4, RC5, RSA, SHA, WAKE, secret sharing, DEFLATE compression
- had a serious bug in the RSA key generation code.
1.1 - Removed RSA, RC4, RC5
- Disabled calls to RSAREF's non-public functions
- Minor bugs fixed
2.0 - a completely new, faster multiprecision integer class
- added MD5-MAC, HAVAL, 3-WAY, TEA, SAFER, LUC, Rabin, BlumGoldwasser,
elliptic curve algorithms
- added the Lucas strong probable primality test
- ElGamal encryption and signature schemes modified to avoid weaknesses
- Diamond changed to Diamond2 because of key schedule weakness
- fixed bug in WAKE key setup
- SHS class renamed to SHA
- lots of miscellaneous optimizations
2.1 - added Tiger, HMAC, GOST, RIPE-MD160, LUCELG, LUCDIF, XOR-MAC,
OAEP, PSSR, SHARK
- added precomputation to DH, ElGamal, DSA, and elliptic curve algorithms
- added back RC5 and a new RSA
- optimizations in elliptic curves over GF(p)
- changed Rabin to use OAEP and PSSR
- changed many classes to allow copy constructors to work correctly
- improved exception generation and handling
2.2 - added SEAL, CAST-128, Square
- fixed bug in HAVAL (padding problem)
- fixed bug in triple-DES (decryption order was reversed)
- fixed bug in RC5 (couldn't handle key length not a multiple of 4)
- changed HMAC to conform to RFC-2104 (which is not compatible
with the original HMAC)
- changed secret sharing and information dispersal to use GF(2^32)
instead of GF(65521)
- removed zero knowledge prover/verifier for graph isomorphism
- removed several utility classes in favor of the C++ standard library
2.3 - ported to EGCS
- fixed incomplete workaround of min/max conflict in MSVC
3.0 - placed all names into the "CryptoPP" namespace
- added MD2, RC2, RC6, MARS, RW, DH2, MQV, ECDHC, CBC-CTS
- added abstract base classes PK_SimpleKeyAgreementDomain and
PK_AuthenticatedKeyAgreementDomain
- changed DH and LUCDIF to implement the PK_SimpleKeyAgreementDomain
interface and to perform domain parameter and key validation
- changed interfaces of PK_Signer and PK_Verifier to sign and verify
messages instead of message digests
- changed OAEP to conform to PKCS#1 v2.0
- changed benchmark code to produce HTML tables as output
- changed PSSR to track IEEE P1363a
- renamed ElGamalSignature to NR and changed it to track IEEE P1363
- renamed ECKEP to ECMQVC and changed it to track IEEE P1363
- renamed several other classes for clarity
- removed support for calling RSAREF
- removed option to compile old SHA (SHA-0)
- removed option not to throw exceptions
3.1 - added ARC4, Rijndael, Twofish, Serpent, CBC-MAC, DMAC
- added interface for querying supported key lengths of symmetric ciphers
and MACs
- added sample code for RSA signature and verification
- changed CBC-CTS to be compatible with RFC 2040
- updated SEAL to version 3.0 of the cipher specification
- optimized multiprecision squaring and elliptic curves over GF(p)
- fixed bug in MARS key setup
- fixed bug with attaching objects to Deflator
3.2 - added DES-XEX3, ECDSA, DefaultEncryptorWithMAC
- renamed DES-EDE to DES-EDE2 and TripleDES to DES-EDE3
- optimized ARC4
- generalized DSA to allow keys longer than 1024 bits
- fixed bugs in GF2N and ModularArithmetic that can cause calculation errors
- fixed crashing bug in Inflator when given invalid inputs
- fixed endian bug in Serpent
- fixed padding bug in Tiger
4.0 - added Skipjack, CAST-256, Panama, SHA-2 (SHA-256, SHA-384, and SHA-512),
and XTR-DH
- added a faster variant of Rabin's Information Dispersal Algorithm (IDA)
- added class wrappers for these operating system features:
- high resolution timers on Windows, Unix, and MacOS
- Berkeley and Windows style sockets
- Windows named pipes
- /dev/random and /dev/urandom on Linux and FreeBSD
- Microsoft's CryptGenRandom on Windows
- added support for SEC 1 elliptic curve key format and compressed points
- added support for X.509 public key format (subjectPublicKeyInfo) for
RSA, DSA, and elliptic curve schemes
- added support for DER and OpenPGP signature format for DSA
- added support for ZLIB compressed data format (RFC 1950)
- changed elliptic curve encryption to use ECIES (as defined in SEC 1)
- changed MARS key schedule to reflect the latest specification
- changed BufferedTransformation interface to support multiple channels
and messages
- changed CAST and SHA-1 implementations to use public domain source code
- fixed bug in StringSource
- optmized multi-precision integer code for better performance
4.1 - added more support for the recommended elliptic curve parameters in SEC 2
- added Panama MAC, MARC4
- added IV stealing feature to CTS mode
- added support for PKCS #8 private key format for RSA, DSA, and elliptic
curve schemes
- changed Deflate, MD5, Rijndael, and Twofish to use public domain code
- fixed a bug with flushing compressed streams
- fixed a bug with decompressing stored blocks
- fixed a bug with EC point decompression using non-trinomial basis
- fixed a bug in NetworkSource::GeneralPump()
- fixed a performance issue with EC over GF(p) decryption
- fixed syntax to allow GCC to compile without -fpermissive
- relaxed some restrictions in the license
4.2 - added support for longer HMAC keys
- added MD4 (which is not secure so use for compatibility purposes only)
- added compatibility fixes/workarounds for STLport 4.5, GCC 3.0.2,
and MSVC 7.0
- changed MD2 to use public domain code
- fixed a bug with decompressing multiple messages with the same object
- fixed a bug in CBC-MAC with MACing multiple messages with the same object
- fixed a bug in RC5 and RC6 with zero-length keys
- fixed a bug in Adler32 where incorrect checksum may be generated
5.0 - added ESIGN, DLIES, WAKE-OFB, PBKDF1 and PBKDF2 from PKCS #5
- added key validation for encryption and signature public/private keys
- renamed StreamCipher interface to SymmetricCipher, which is now implemented
by both stream ciphers and block cipher modes including ECB and CBC
- added keying interfaces to support resetting of keys and IVs without
having to destroy and recreate objects
- changed filter interface to support non-blocking input/output
- changed SocketSource and SocketSink to use overlapped I/O on Microsoft Windows
- grouped related classes inside structs to help templates, for example
AESEncryption and AESDecryption are now AES::Encryption and AES::Decryption
- where possible, typedefs have been added to improve backwards
compatibility when the CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY macro is defined
- changed Serpent, HAVAL and IDEA to use public domain code
- implemented SSE2 optimizations for Integer operations
- fixed a bug in HMAC::TruncatedFinal()
- fixed SKIPJACK byte ordering following NIST clarification dated 5/9/02
5.01 - added known answer test for X9.17 RNG in FIPS 140 power-up self test
- submitted to NIST/CSE, but not publicly released
5.02 - changed EDC test to MAC integrity check using HMAC/SHA1
- improved performance of integrity check
- added blinding to defend against RSA timing attack
5.03 - created DLL version of Crypto++ for FIPS 140-2 validation
- fixed vulnerabilities in GetNextIV for CTR and OFB modes
5.0.4 - Removed DES, SHA-256, SHA-384, SHA-512 from DLL
5.1 - added PSS padding and changed PSSR to track IEEE P1363a draft standard
- added blinding for RSA and Rabin to defend against timing attacks
on decryption operations
- changed signing and decryption APIs to support the above
- changed WaitObjectContainer to allow waiting for more than 64
objects at a time on Win32 platforms
- fixed a bug in CBC and ECB modes with processing non-aligned data
- fixed standard conformance bugs in DLIES (DHAES mode) and RW/EMSA2
signature scheme (these fixes are not backwards compatible)
- fixed a number of compiler warnings, minor bugs, and portability problems
- removed Sapphire
5.2 - merged in changes for 5.01 - 5.0.4
- added support for using encoding parameters and key derivation parameters
with public key encryption (implemented by OAEP and DL/ECIES)
- added Camellia, SHACAL-2, Two-Track-MAC, Whirlpool, RIPEMD-320,
RIPEMD-128, RIPEMD-256, Base-32 coding, FIPS variant of CFB mode
- added ThreadUserTimer for timing thread CPU usage
- added option for password-based key derivation functions
to iterate until a mimimum elapsed thread CPU time is reached
- added option (on by default) for DEFLATE compression to detect
uncompressible files and process them more quickly
- improved compatibility and performance on 64-bit platforms,
including Alpha, IA-64, x86-64, PPC64, Sparc64, and MIPS64
- fixed ONE_AND_ZEROS_PADDING to use 0x80 instead 0x01 as padding.
- fixed encoding/decoding of PKCS #8 privateKeyInfo to properly
handle optional attributes
5.2.1 - fixed bug in the "dlltest" DLL testing program
- fixed compiling with STLport using VC .NET
- fixed compiling with -fPIC using GCC
- fixed compiling with -msse2 on systems without memalign()
- fixed inability to instantiate PanamaMAC
- fixed problems with inline documentation
5.2.2 - added SHA-224
- put SHA-256, SHA-384, SHA-512, RSASSA-PSS into DLL
5.2.3 - fixed issues with FIPS algorithm test vectors
- put RSASSA-ISO into DLL
5.3 - ported to MSVC 2005 with support for x86-64
- added defense against AES timing attacks, and more AES test vectors
- changed StaticAlgorithmName() of Rijndael to "AES", CTR to "CTR"
5.4 - added Salsa20
- updated Whirlpool to version 3.0
- ported to GCC 4.1, Sun C++ 5.8, and Borland C++Builder 2006
5.5 - added VMAC and Sosemanuk (with x86-64 and SSE2 assembly)
- improved speed of integer arithmetic, AES, SHA-512, Tiger, Salsa20,
Whirlpool, and PANAMA cipher using assembly (x86-64, MMX, SSE2)
- optimized Camellia and added defense against timing attacks
- updated benchmarks code to show cycles per byte and to time key/IV setup
- started using OpenMP for increased multi-core speed
- enabled GCC optimization flags by default in GNUmakefile
- added blinding and computational error checking for RW signing
- changed RandomPool, X917RNG, GetNextIV, DSA/NR/ECDSA/ECNR to reduce
the risk of reusing random numbers and IVs after virtual machine state
rollback
- changed default FIPS mode RNG from AutoSeededX917RNG<DES_EDE3> to
AutoSeededX917RNG<AES>
- fixed PANAMA cipher interface to accept 256-bit key and 256-bit IV
- moved MD2, MD4, MD5, PanamaHash, ARC4, WAKE_CFB into the namespace "Weak"
- removed HAVAL, MD5-MAC, XMAC
5.5.1 - fixed VMAC validation failure on 32-bit big-endian machines
5.5.2 - ported x64 assembly language code for AES, Salsa20, Sosemanuk, and Panama
to MSVC 2005 (using MASM since MSVC doesn't support inline assembly on x64)
- fixed Salsa20 initialization crash on non-SSE2 machines
- fixed Whirlpool crash on Pentium 2 machines
- fixed possible branch prediction analysis (BPA) vulnerability in
MontgomeryReduce(), which may affect security of RSA, RW, LUC
- fixed link error with MSVC 2003 when using "debug DLL" form of runtime library
- fixed crash in SSE2_Add on P4 machines when compiled with
MSVC 6.0 SP5 with Processor Pack
- ported to MSVC 2008, GCC 4.2, Sun CC 5.9, Intel C++ Compiler 10.0,
and Borland C++Builder 2007
5.6.0 - added AuthenticatedSymmetricCipher interface class and Filter wrappers
- added CCM, GCM (with SSE2 assembly), EAX, CMAC, XSalsa20, and SEED
- added support for variable length IVs
- added OIDs for Brainpool elliptic curve parameters
- improved AES and SHA-256 speed on x86 and x64
- changed BlockTransformation interface to no longer assume data alignment
- fixed incorrect VMAC computation on message lengths
that are >64 mod 128 (x86 assembly version is not affected)
- fixed compiler error in vmac.cpp on x86 with GCC -fPIC
- fixed run-time validation error on x86-64 with GCC 4.3.2 -O2
- fixed HashFilter bug when putMessage=true
- fixed AES-CTR data alignment bug that causes incorrect encryption on ARM
- removed WORD64_AVAILABLE; compiler support for 64-bit int is now required
- ported to GCC 4.3, C++Builder 2009, Sun CC 5.10, Intel C++ Compiler 11
5.6.1 - added support for AES-NI and CLMUL instruction sets in AES and GMAC/GCM
- removed WAKE-CFB
- fixed several bugs in the SHA-256 x86/x64 assembly code:
* incorrect hash on non-SSE2 x86 machines on non-aligned input
* incorrect hash on x86 machines when input crosses 0x80000000
* incorrect hash on x64 when compiled with GCC with optimizations enabled
- fixed bugs in AES x86 and x64 assembly causing crashes in some MSVC build configurations
- switched to a public domain implementation of MARS
- ported to MSVC 2010, GCC 4.5.1, Sun Studio 12u1, C++Builder 2010, Intel C++ Compiler 11.1
- renamed the MSVC DLL project to "cryptopp" for compatibility with MSVC 2010
5.6.2 - changed license to Boost Software License 1.0
- added SHA-3 (Keccak)
- updated DSA to FIPS 186-3 (see DSA2 class)
- fixed Blowfish minimum keylength to be 4 bytes (32 bits)
- fixed Salsa validation failure when compiling with GCC 4.6
- fixed infinite recursion when on x64, assembly disabled, and no AESNI
- ported to MSVC 2012, GCC 4.7, Clang 3.2, Solaris Studio 12.3, Intel C++ Compiler 13.0
Written by Wei Dai

View File

@ -1,77 +0,0 @@
// adler32.cpp - written and placed in the public domain by Wei Dai
#include "pch.h"
#include "adler32.h"
NAMESPACE_BEGIN(CryptoPP)
void Adler32::Update(const byte *input, size_t length)
{
const unsigned long BASE = 65521;
unsigned long s1 = m_s1;
unsigned long s2 = m_s2;
if (length % 8 != 0)
{
do
{
s1 += *input++;
s2 += s1;
length--;
} while (length % 8 != 0);
if (s1 >= BASE)
s1 -= BASE;
s2 %= BASE;
}
while (length > 0)
{
s1 += input[0]; s2 += s1;
s1 += input[1]; s2 += s1;
s1 += input[2]; s2 += s1;
s1 += input[3]; s2 += s1;
s1 += input[4]; s2 += s1;
s1 += input[5]; s2 += s1;
s1 += input[6]; s2 += s1;
s1 += input[7]; s2 += s1;
length -= 8;
input += 8;
if (s1 >= BASE)
s1 -= BASE;
if (length % 0x8000 == 0)
s2 %= BASE;
}
assert(s1 < BASE);
assert(s2 < BASE);
m_s1 = (word16)s1;
m_s2 = (word16)s2;
}
void Adler32::TruncatedFinal(byte *hash, size_t size)
{
ThrowIfInvalidTruncatedSize(size);
switch (size)
{
default:
hash[3] = byte(m_s1);
case 3:
hash[2] = byte(m_s1 >> 8);
case 2:
hash[1] = byte(m_s2);
case 1:
hash[0] = byte(m_s2 >> 8);
case 0:
;
}
Reset();
}
NAMESPACE_END

View File

@ -1,28 +0,0 @@
#ifndef CRYPTOPP_ADLER32_H
#define CRYPTOPP_ADLER32_H
#include "cryptlib.h"
NAMESPACE_BEGIN(CryptoPP)
//! ADLER-32 checksum calculations
class Adler32 : public HashTransformation
{
public:
CRYPTOPP_CONSTANT(DIGESTSIZE = 4)
Adler32() {Reset();}
void Update(const byte *input, size_t length);
void TruncatedFinal(byte *hash, size_t size);
unsigned int DigestSize() const {return DIGESTSIZE;}
static const char * StaticAlgorithmName() {return "Adler32";}
std::string AlgorithmName() const {return StaticAlgorithmName();}
private:
void Reset() {m_s1 = 1; m_s2 = 0;}
word16 m_s1, m_s2;
};
NAMESPACE_END
#endif

View File

@ -1,16 +0,0 @@
#ifndef CRYPTOPP_AES_H
#define CRYPTOPP_AES_H
#include "rijndael.h"
NAMESPACE_BEGIN(CryptoPP)
//! <a href="http://www.cryptolounge.org/wiki/AES">AES</a> winner, announced on 10/2/2000
DOCUMENTED_TYPEDEF(Rijndael, AES);
typedef RijndaelEncryption AESEncryption;
typedef RijndaelDecryption AESDecryption;
NAMESPACE_END
#endif

View File

@ -1,340 +0,0 @@
// algebra.cpp - written and placed in the public domain by Wei Dai
#include "pch.h"
#ifndef CRYPTOPP_ALGEBRA_CPP // SunCC workaround: compiler could cause this file to be included twice
#define CRYPTOPP_ALGEBRA_CPP
#include "algebra.h"
#include "integer.h"
#include <vector>
NAMESPACE_BEGIN(CryptoPP)
template <class T> const T& AbstractGroup<T>::Double(const Element &a) const
{
return this->Add(a, a);
}
template <class T> const T& AbstractGroup<T>::Subtract(const Element &a, const Element &b) const
{
// make copy of a in case Inverse() overwrites it
Element a1(a);
return this->Add(a1, Inverse(b));
}
template <class T> T& AbstractGroup<T>::Accumulate(Element &a, const Element &b) const
{
return a = this->Add(a, b);
}
template <class T> T& AbstractGroup<T>::Reduce(Element &a, const Element &b) const
{
return a = this->Subtract(a, b);
}
template <class T> const T& AbstractRing<T>::Square(const Element &a) const
{
return this->Multiply(a, a);
}
template <class T> const T& AbstractRing<T>::Divide(const Element &a, const Element &b) const
{
// make copy of a in case MultiplicativeInverse() overwrites it
Element a1(a);
return this->Multiply(a1, this->MultiplicativeInverse(b));
}
template <class T> const T& AbstractEuclideanDomain<T>::Mod(const Element &a, const Element &b) const
{
Element q;
this->DivisionAlgorithm(result, q, a, b);
return result;
}
template <class T> const T& AbstractEuclideanDomain<T>::Gcd(const Element &a, const Element &b) const
{
Element g[3]={b, a};
unsigned int i0=0, i1=1, i2=2;
while (!this->Equal(g[i1], this->Identity()))
{
g[i2] = this->Mod(g[i0], g[i1]);
unsigned int t = i0; i0 = i1; i1 = i2; i2 = t;
}
return result = g[i0];
}
template <class T> const typename QuotientRing<T>::Element& QuotientRing<T>::MultiplicativeInverse(const Element &a) const
{
Element g[3]={m_modulus, a};
Element v[3]={m_domain.Identity(), m_domain.MultiplicativeIdentity()};
Element y;
unsigned int i0=0, i1=1, i2=2;
while (!this->Equal(g[i1], this->Identity()))
{
// y = g[i0] / g[i1];
// g[i2] = g[i0] % g[i1];
m_domain.DivisionAlgorithm(g[i2], y, g[i0], g[i1]);
// v[i2] = v[i0] - (v[i1] * y);
v[i2] = m_domain.Subtract(v[i0], m_domain.Multiply(v[i1], y));
unsigned int t = i0; i0 = i1; i1 = i2; i2 = t;
}
return m_domain.IsUnit(g[i0]) ? m_domain.Divide(v[i0], g[i0]) : m_domain.Identity();
}
template <class T> T AbstractGroup<T>::ScalarMultiply(const Element &base, const Integer &exponent) const
{
Element result;
this->SimultaneousMultiply(&result, base, &exponent, 1);
return result;
}
template <class T> T AbstractGroup<T>::CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const
{
const unsigned expLen = STDMAX(e1.BitCount(), e2.BitCount());
if (expLen==0)
return this->Identity();
const unsigned w = (expLen <= 46 ? 1 : (expLen <= 260 ? 2 : 3));
const unsigned tableSize = 1<<w;
std::vector<Element> powerTable(tableSize << w);
powerTable[1] = x;
powerTable[tableSize] = y;
if (w==1)
powerTable[3] = this->Add(x,y);
else
{
powerTable[2] = this->Double(x);
powerTable[2*tableSize] = this->Double(y);
unsigned i, j;
for (i=3; i<tableSize; i+=2)
powerTable[i] = Add(powerTable[i-2], powerTable[2]);
for (i=1; i<tableSize; i+=2)
for (j=i+tableSize; j<(tableSize<<w); j+=tableSize)
powerTable[j] = Add(powerTable[j-tableSize], y);
for (i=3*tableSize; i<(tableSize<<w); i+=2*tableSize)
powerTable[i] = Add(powerTable[i-2*tableSize], powerTable[2*tableSize]);
for (i=tableSize; i<(tableSize<<w); i+=2*tableSize)
for (j=i+2; j<i+tableSize; j+=2)
powerTable[j] = Add(powerTable[j-1], x);
}
Element result;
unsigned power1 = 0, power2 = 0, prevPosition = expLen-1;
bool firstTime = true;
for (int i = expLen-1; i>=0; i--)
{
power1 = 2*power1 + e1.GetBit(i);
power2 = 2*power2 + e2.GetBit(i);
if (i==0 || 2*power1 >= tableSize || 2*power2 >= tableSize)
{
unsigned squaresBefore = prevPosition-i;
unsigned squaresAfter = 0;
prevPosition = i;
while ((power1 || power2) && power1%2 == 0 && power2%2==0)
{
power1 /= 2;
power2 /= 2;
squaresBefore--;
squaresAfter++;
}
if (firstTime)
{
result = powerTable[(power2<<w) + power1];
firstTime = false;
}
else
{
while (squaresBefore--)
result = this->Double(result);
if (power1 || power2)
Accumulate(result, powerTable[(power2<<w) + power1]);
}
while (squaresAfter--)
result = this->Double(result);
power1 = power2 = 0;
}
}
return result;
}
template <class Element, class Iterator> Element GeneralCascadeMultiplication(const AbstractGroup<Element> &group, Iterator begin, Iterator end)
{
if (end-begin == 1)
return group.ScalarMultiply(begin->base, begin->exponent);
else if (end-begin == 2)
return group.CascadeScalarMultiply(begin->base, begin->exponent, (begin+1)->base, (begin+1)->exponent);
else
{
Integer q, t;
Iterator last = end;
--last;
std::make_heap(begin, end);
std::pop_heap(begin, end);
while (!!begin->exponent)
{
// last->exponent is largest exponent, begin->exponent is next largest
t = last->exponent;
Integer::Divide(last->exponent, q, t, begin->exponent);
if (q == Integer::One())
group.Accumulate(begin->base, last->base); // avoid overhead of ScalarMultiply()
else
group.Accumulate(begin->base, group.ScalarMultiply(last->base, q));
std::push_heap(begin, end);
std::pop_heap(begin, end);
}
return group.ScalarMultiply(last->base, last->exponent);
}
}
struct WindowSlider
{
WindowSlider(const Integer &expIn, bool fastNegate, unsigned int windowSizeIn=0)
: exp(expIn), windowModulus(Integer::One()), windowSize(windowSizeIn), windowBegin(0), fastNegate(fastNegate), firstTime(true), finished(false)
{
if (windowSize == 0)
{
unsigned int expLen = exp.BitCount();
windowSize = expLen <= 17 ? 1 : (expLen <= 24 ? 2 : (expLen <= 70 ? 3 : (expLen <= 197 ? 4 : (expLen <= 539 ? 5 : (expLen <= 1434 ? 6 : 7)))));
}
windowModulus <<= windowSize;
}
void FindNextWindow()
{
unsigned int expLen = exp.WordCount() * WORD_BITS;
unsigned int skipCount = firstTime ? 0 : windowSize;
firstTime = false;
while (!exp.GetBit(skipCount))
{
if (skipCount >= expLen)
{
finished = true;
return;
}
skipCount++;
}
exp >>= skipCount;
windowBegin += skipCount;
expWindow = word32(exp % (word(1) << windowSize));
if (fastNegate && exp.GetBit(windowSize))
{
negateNext = true;
expWindow = (word32(1) << windowSize) - expWindow;
exp += windowModulus;
}
else
negateNext = false;
}
Integer exp, windowModulus;
unsigned int windowSize, windowBegin;
word32 expWindow;
bool fastNegate, negateNext, firstTime, finished;
};
template <class T>
void AbstractGroup<T>::SimultaneousMultiply(T *results, const T &base, const Integer *expBegin, unsigned int expCount) const
{
std::vector<std::vector<Element> > buckets(expCount);
std::vector<WindowSlider> exponents;
exponents.reserve(expCount);
unsigned int i;
for (i=0; i<expCount; i++)
{
assert(expBegin->NotNegative());
exponents.push_back(WindowSlider(*expBegin++, InversionIsFast(), 0));
exponents[i].FindNextWindow();
buckets[i].resize(1<<(exponents[i].windowSize-1), Identity());
}
unsigned int expBitPosition = 0;
Element g = base;
bool notDone = true;
while (notDone)
{
notDone = false;
for (i=0; i<expCount; i++)
{
if (!exponents[i].finished && expBitPosition == exponents[i].windowBegin)
{
Element &bucket = buckets[i][exponents[i].expWindow/2];
if (exponents[i].negateNext)
Accumulate(bucket, Inverse(g));
else
Accumulate(bucket, g);
exponents[i].FindNextWindow();
}
notDone = notDone || !exponents[i].finished;
}
if (notDone)
{
g = Double(g);
expBitPosition++;
}
}
for (i=0; i<expCount; i++)
{
Element &r = *results++;
r = buckets[i][buckets[i].size()-1];
if (buckets[i].size() > 1)
{
for (int j = (int)buckets[i].size()-2; j >= 1; j--)
{
Accumulate(buckets[i][j], buckets[i][j+1]);
Accumulate(r, buckets[i][j]);
}
Accumulate(buckets[i][0], buckets[i][1]);
r = Add(Double(r), buckets[i][0]);
}
}
}
template <class T> T AbstractRing<T>::Exponentiate(const Element &base, const Integer &exponent) const
{
Element result;
SimultaneousExponentiate(&result, base, &exponent, 1);
return result;
}
template <class T> T AbstractRing<T>::CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const
{
return MultiplicativeGroup().AbstractGroup<T>::CascadeScalarMultiply(x, e1, y, e2);
}
template <class Element, class Iterator> Element GeneralCascadeExponentiation(const AbstractRing<Element> &ring, Iterator begin, Iterator end)
{
return GeneralCascadeMultiplication<Element>(ring.MultiplicativeGroup(), begin, end);
}
template <class T>
void AbstractRing<T>::SimultaneousExponentiate(T *results, const T &base, const Integer *exponents, unsigned int expCount) const
{
MultiplicativeGroup().AbstractGroup<T>::SimultaneousMultiply(results, base, exponents, expCount);
}
NAMESPACE_END
#endif

View File

@ -1,285 +0,0 @@
#ifndef CRYPTOPP_ALGEBRA_H
#define CRYPTOPP_ALGEBRA_H
#include "config.h"
NAMESPACE_BEGIN(CryptoPP)
class Integer;
// "const Element&" returned by member functions are references
// to internal data members. Since each object may have only
// one such data member for holding results, the following code
// will produce incorrect results:
// abcd = group.Add(group.Add(a,b), group.Add(c,d));
// But this should be fine:
// abcd = group.Add(a, group.Add(b, group.Add(c,d));
//! Abstract Group
template <class T> class CRYPTOPP_NO_VTABLE AbstractGroup
{
public:
typedef T Element;
virtual ~AbstractGroup() {}
virtual bool Equal(const Element &a, const Element &b) const =0;
virtual const Element& Identity() const =0;
virtual const Element& Add(const Element &a, const Element &b) const =0;
virtual const Element& Inverse(const Element &a) const =0;
virtual bool InversionIsFast() const {return false;}
virtual const Element& Double(const Element &a) const;
virtual const Element& Subtract(const Element &a, const Element &b) const;
virtual Element& Accumulate(Element &a, const Element &b) const;
virtual Element& Reduce(Element &a, const Element &b) const;
virtual Element ScalarMultiply(const Element &a, const Integer &e) const;
virtual Element CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const;
virtual void SimultaneousMultiply(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
};
//! Abstract Ring
template <class T> class CRYPTOPP_NO_VTABLE AbstractRing : public AbstractGroup<T>
{
public:
typedef T Element;
AbstractRing() {m_mg.m_pRing = this;}
AbstractRing(const AbstractRing &source) {m_mg.m_pRing = this;}
AbstractRing& operator=(const AbstractRing &source) {return *this;}
virtual bool IsUnit(const Element &a) const =0;
virtual const Element& MultiplicativeIdentity() const =0;
virtual const Element& Multiply(const Element &a, const Element &b) const =0;
virtual const Element& MultiplicativeInverse(const Element &a) const =0;
virtual const Element& Square(const Element &a) const;
virtual const Element& Divide(const Element &a, const Element &b) const;
virtual Element Exponentiate(const Element &a, const Integer &e) const;
virtual Element CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const;
virtual void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
virtual const AbstractGroup<T>& MultiplicativeGroup() const
{return m_mg;}
private:
class MultiplicativeGroupT : public AbstractGroup<T>
{
public:
const AbstractRing<T>& GetRing() const
{return *m_pRing;}
bool Equal(const Element &a, const Element &b) const
{return GetRing().Equal(a, b);}
const Element& Identity() const
{return GetRing().MultiplicativeIdentity();}
const Element& Add(const Element &a, const Element &b) const
{return GetRing().Multiply(a, b);}
Element& Accumulate(Element &a, const Element &b) const
{return a = GetRing().Multiply(a, b);}
const Element& Inverse(const Element &a) const
{return GetRing().MultiplicativeInverse(a);}
const Element& Subtract(const Element &a, const Element &b) const
{return GetRing().Divide(a, b);}
Element& Reduce(Element &a, const Element &b) const
{return a = GetRing().Divide(a, b);}
const Element& Double(const Element &a) const
{return GetRing().Square(a);}
Element ScalarMultiply(const Element &a, const Integer &e) const
{return GetRing().Exponentiate(a, e);}
Element CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const
{return GetRing().CascadeExponentiate(x, e1, y, e2);}
void SimultaneousMultiply(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const
{GetRing().SimultaneousExponentiate(results, base, exponents, exponentsCount);}
const AbstractRing<T> *m_pRing;
};
MultiplicativeGroupT m_mg;
};
// ********************************************************
//! Base and Exponent
template <class T, class E = Integer>
struct BaseAndExponent
{
public:
BaseAndExponent() {}
BaseAndExponent(const T &base, const E &exponent) : base(base), exponent(exponent) {}
bool operator<(const BaseAndExponent<T, E> &rhs) const {return exponent < rhs.exponent;}
T base;
E exponent;
};
// VC60 workaround: incomplete member template support
template <class Element, class Iterator>
Element GeneralCascadeMultiplication(const AbstractGroup<Element> &group, Iterator begin, Iterator end);
template <class Element, class Iterator>
Element GeneralCascadeExponentiation(const AbstractRing<Element> &ring, Iterator begin, Iterator end);
// ********************************************************
//! Abstract Euclidean Domain
template <class T> class CRYPTOPP_NO_VTABLE AbstractEuclideanDomain : public AbstractRing<T>
{
public:
typedef T Element;
virtual void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const =0;
virtual const Element& Mod(const Element &a, const Element &b) const =0;
virtual const Element& Gcd(const Element &a, const Element &b) const;
protected:
mutable Element result;
};
// ********************************************************
//! EuclideanDomainOf
template <class T> class EuclideanDomainOf : public AbstractEuclideanDomain<T>
{
public:
typedef T Element;
EuclideanDomainOf() {}
bool Equal(const Element &a, const Element &b) const
{return a==b;}
const Element& Identity() const
{return Element::Zero();}
const Element& Add(const Element &a, const Element &b) const
{return result = a+b;}
Element& Accumulate(Element &a, const Element &b) const
{return a+=b;}
const Element& Inverse(const Element &a) const
{return result = -a;}
const Element& Subtract(const Element &a, const Element &b) const
{return result = a-b;}
Element& Reduce(Element &a, const Element &b) const
{return a-=b;}
const Element& Double(const Element &a) const
{return result = a.Doubled();}
const Element& MultiplicativeIdentity() const
{return Element::One();}
const Element& Multiply(const Element &a, const Element &b) const
{return result = a*b;}
const Element& Square(const Element &a) const
{return result = a.Squared();}
bool IsUnit(const Element &a) const
{return a.IsUnit();}
const Element& MultiplicativeInverse(const Element &a) const
{return result = a.MultiplicativeInverse();}
const Element& Divide(const Element &a, const Element &b) const
{return result = a/b;}
const Element& Mod(const Element &a, const Element &b) const
{return result = a%b;}
void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const
{Element::Divide(r, q, a, d);}
bool operator==(const EuclideanDomainOf<T> &rhs) const
{return true;}
private:
mutable Element result;
};
//! Quotient Ring
template <class T> class QuotientRing : public AbstractRing<typename T::Element>
{
public:
typedef T EuclideanDomain;
typedef typename T::Element Element;
QuotientRing(const EuclideanDomain &domain, const Element &modulus)
: m_domain(domain), m_modulus(modulus) {}
const EuclideanDomain & GetDomain() const
{return m_domain;}
const Element& GetModulus() const
{return m_modulus;}
bool Equal(const Element &a, const Element &b) const
{return m_domain.Equal(m_domain.Mod(m_domain.Subtract(a, b), m_modulus), m_domain.Identity());}
const Element& Identity() const
{return m_domain.Identity();}
const Element& Add(const Element &a, const Element &b) const
{return m_domain.Add(a, b);}
Element& Accumulate(Element &a, const Element &b) const
{return m_domain.Accumulate(a, b);}
const Element& Inverse(const Element &a) const
{return m_domain.Inverse(a);}
const Element& Subtract(const Element &a, const Element &b) const
{return m_domain.Subtract(a, b);}
Element& Reduce(Element &a, const Element &b) const
{return m_domain.Reduce(a, b);}
const Element& Double(const Element &a) const
{return m_domain.Double(a);}
bool IsUnit(const Element &a) const
{return m_domain.IsUnit(m_domain.Gcd(a, m_modulus));}
const Element& MultiplicativeIdentity() const
{return m_domain.MultiplicativeIdentity();}
const Element& Multiply(const Element &a, const Element &b) const
{return m_domain.Mod(m_domain.Multiply(a, b), m_modulus);}
const Element& Square(const Element &a) const
{return m_domain.Mod(m_domain.Square(a), m_modulus);}
const Element& MultiplicativeInverse(const Element &a) const;
bool operator==(const QuotientRing<T> &rhs) const
{return m_domain == rhs.m_domain && m_modulus == rhs.m_modulus;}
protected:
EuclideanDomain m_domain;
Element m_modulus;
};
NAMESPACE_END
#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
#include "algebra.cpp"
#endif
#endif

View File

@ -1,75 +0,0 @@
// algparam.cpp - written and placed in the public domain by Wei Dai
#include "pch.h"
#ifndef CRYPTOPP_IMPORTS
#include "algparam.h"
NAMESPACE_BEGIN(CryptoPP)
PAssignIntToInteger g_pAssignIntToInteger = NULL;
bool CombinedNameValuePairs::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
{
if (strcmp(name, "ValueNames") == 0)
return m_pairs1.GetVoidValue(name, valueType, pValue) && m_pairs2.GetVoidValue(name, valueType, pValue);
else
return m_pairs1.GetVoidValue(name, valueType, pValue) || m_pairs2.GetVoidValue(name, valueType, pValue);
}
void AlgorithmParametersBase::operator=(const AlgorithmParametersBase& rhs)
{
assert(false);
}
bool AlgorithmParametersBase::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
{
if (strcmp(name, "ValueNames") == 0)
{
NameValuePairs::ThrowIfTypeMismatch(name, typeid(std::string), valueType);
if (m_next.get())
m_next->GetVoidValue(name, valueType, pValue);
(*reinterpret_cast<std::string *>(pValue) += m_name) += ";";
return true;
}
else if (strcmp(name, m_name) == 0)
{
AssignValue(name, valueType, pValue);
m_used = true;
return true;
}
else if (m_next.get())
return m_next->GetVoidValue(name, valueType, pValue);
else
return false;
}
AlgorithmParameters::AlgorithmParameters()
: m_defaultThrowIfNotUsed(true)
{
}
AlgorithmParameters::AlgorithmParameters(const AlgorithmParameters &x)
: m_defaultThrowIfNotUsed(x.m_defaultThrowIfNotUsed)
{
m_next.reset(const_cast<AlgorithmParameters &>(x).m_next.release());
}
AlgorithmParameters & AlgorithmParameters::operator=(const AlgorithmParameters &x)
{
m_next.reset(const_cast<AlgorithmParameters &>(x).m_next.release());
return *this;
}
bool AlgorithmParameters::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
{
if (m_next.get())
return m_next->GetVoidValue(name, valueType, pValue);
else
return false;
}
NAMESPACE_END
#endif

View File

@ -1,398 +0,0 @@
#ifndef CRYPTOPP_ALGPARAM_H
#define CRYPTOPP_ALGPARAM_H
#include "cryptlib.h"
#include "smartptr.h"
#include "secblock.h"
NAMESPACE_BEGIN(CryptoPP)
//! used to pass byte array input as part of a NameValuePairs object
/*! the deepCopy option is used when the NameValuePairs object can't
keep a copy of the data available */
class ConstByteArrayParameter
{
public:
ConstByteArrayParameter(const char *data = NULL, bool deepCopy = false)
{
Assign((const byte *)data, data ? strlen(data) : 0, deepCopy);
}
ConstByteArrayParameter(const byte *data, size_t size, bool deepCopy = false)
{
Assign(data, size, deepCopy);
}
template <class T> ConstByteArrayParameter(const T &string, bool deepCopy = false)
{
CRYPTOPP_COMPILE_ASSERT(sizeof(CPP_TYPENAME T::value_type) == 1);
Assign((const byte *)string.data(), string.size(), deepCopy);
}
void Assign(const byte *data, size_t size, bool deepCopy)
{
if (deepCopy)
m_block.Assign(data, size);
else
{
m_data = data;
m_size = size;
}
m_deepCopy = deepCopy;
}
const byte *begin() const {return m_deepCopy ? m_block.begin() : m_data;}
const byte *end() const {return m_deepCopy ? m_block.end() : m_data + m_size;}
size_t size() const {return m_deepCopy ? m_block.size() : m_size;}
private:
bool m_deepCopy;
const byte *m_data;
size_t m_size;
SecByteBlock m_block;
};
class ByteArrayParameter
{
public:
ByteArrayParameter(byte *data = NULL, unsigned int size = 0)
: m_data(data), m_size(size) {}
ByteArrayParameter(SecByteBlock &block)
: m_data(block.begin()), m_size(block.size()) {}
byte *begin() const {return m_data;}
byte *end() const {return m_data + m_size;}
size_t size() const {return m_size;}
private:
byte *m_data;
size_t m_size;
};
class CRYPTOPP_DLL CombinedNameValuePairs : public NameValuePairs
{
public:
CombinedNameValuePairs(const NameValuePairs &pairs1, const NameValuePairs &pairs2)
: m_pairs1(pairs1), m_pairs2(pairs2) {}
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
private:
const NameValuePairs &m_pairs1, &m_pairs2;
};
template <class T, class BASE>
class GetValueHelperClass
{
public:
GetValueHelperClass(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst)
: m_pObject(pObject), m_name(name), m_valueType(&valueType), m_pValue(pValue), m_found(false), m_getValueNames(false)
{
if (strcmp(m_name, "ValueNames") == 0)
{
m_found = m_getValueNames = true;
NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(std::string), *m_valueType);
if (searchFirst)
searchFirst->GetVoidValue(m_name, valueType, pValue);
if (typeid(T) != typeid(BASE))
pObject->BASE::GetVoidValue(m_name, valueType, pValue);
((*reinterpret_cast<std::string *>(m_pValue) += "ThisPointer:") += typeid(T).name()) += ';';
}
if (!m_found && strncmp(m_name, "ThisPointer:", 12) == 0 && strcmp(m_name+12, typeid(T).name()) == 0)
{
NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T *), *m_valueType);
*reinterpret_cast<const T **>(pValue) = pObject;
m_found = true;
return;
}
if (!m_found && searchFirst)
m_found = searchFirst->GetVoidValue(m_name, valueType, pValue);
if (!m_found && typeid(T) != typeid(BASE))
m_found = pObject->BASE::GetVoidValue(m_name, valueType, pValue);
}
operator bool() const {return m_found;}
template <class R>
GetValueHelperClass<T,BASE> & operator()(const char *name, const R & (T::*pm)() const)
{
if (m_getValueNames)
(*reinterpret_cast<std::string *>(m_pValue) += name) += ";";
if (!m_found && strcmp(name, m_name) == 0)
{
NameValuePairs::ThrowIfTypeMismatch(name, typeid(R), *m_valueType);
*reinterpret_cast<R *>(m_pValue) = (m_pObject->*pm)();
m_found = true;
}
return *this;
}
GetValueHelperClass<T,BASE> &Assignable()
{
#ifndef __INTEL_COMPILER // ICL 9.1 workaround: Intel compiler copies the vTable pointer for some reason
if (m_getValueNames)
((*reinterpret_cast<std::string *>(m_pValue) += "ThisObject:") += typeid(T).name()) += ';';
if (!m_found && strncmp(m_name, "ThisObject:", 11) == 0 && strcmp(m_name+11, typeid(T).name()) == 0)
{
NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T), *m_valueType);
*reinterpret_cast<T *>(m_pValue) = *m_pObject;
m_found = true;
}
#endif
return *this;
}
private:
const T *m_pObject;
const char *m_name;
const std::type_info *m_valueType;
void *m_pValue;
bool m_found, m_getValueNames;
};
template <class BASE, class T>
GetValueHelperClass<T, BASE> GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULL, BASE *dummy=NULL)
{
return GetValueHelperClass<T, BASE>(pObject, name, valueType, pValue, searchFirst);
}
template <class T>
GetValueHelperClass<T, T> GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULL)
{
return GetValueHelperClass<T, T>(pObject, name, valueType, pValue, searchFirst);
}
// ********************************************************
template <class R>
R Hack_DefaultValueFromConstReferenceType(const R &)
{
return R();
}
template <class R>
bool Hack_GetValueIntoConstReference(const NameValuePairs &source, const char *name, const R &value)
{
return source.GetValue(name, const_cast<R &>(value));
}
template <class T, class BASE>
class AssignFromHelperClass
{
public:
AssignFromHelperClass(T *pObject, const NameValuePairs &source)
: m_pObject(pObject), m_source(source), m_done(false)
{
if (source.GetThisObject(*pObject))
m_done = true;
else if (typeid(BASE) != typeid(T))
pObject->BASE::AssignFrom(source);
}
template <class R>
AssignFromHelperClass & operator()(const char *name, void (T::*pm)(R)) // VC60 workaround: "const R &" here causes compiler error
{
if (!m_done)
{
R value = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<R>(*(int *)NULL));
if (!Hack_GetValueIntoConstReference(m_source, name, value))
throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name + "'");
(m_pObject->*pm)(value);
}
return *this;
}
template <class R, class S>
AssignFromHelperClass & operator()(const char *name1, const char *name2, void (T::*pm)(R, S)) // VC60 workaround: "const R &" here causes compiler error
{
if (!m_done)
{
R value1 = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<R>(*(int *)NULL));
if (!Hack_GetValueIntoConstReference(m_source, name1, value1))
throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name1 + "'");
S value2 = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<S>(*(int *)NULL));
if (!Hack_GetValueIntoConstReference(m_source, name2, value2))
throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name2 + "'");
(m_pObject->*pm)(value1, value2);
}
return *this;
}
private:
T *m_pObject;
const NameValuePairs &m_source;
bool m_done;
};
template <class BASE, class T>
AssignFromHelperClass<T, BASE> AssignFromHelper(T *pObject, const NameValuePairs &source, BASE *dummy=NULL)
{
return AssignFromHelperClass<T, BASE>(pObject, source);
}
template <class T>
AssignFromHelperClass<T, T> AssignFromHelper(T *pObject, const NameValuePairs &source)
{
return AssignFromHelperClass<T, T>(pObject, source);
}
// ********************************************************
// to allow the linker to discard Integer code if not needed.
typedef bool (CRYPTOPP_API * PAssignIntToInteger)(const std::type_info &valueType, void *pInteger, const void *pInt);
CRYPTOPP_DLL extern PAssignIntToInteger g_pAssignIntToInteger;
CRYPTOPP_DLL const std::type_info & CRYPTOPP_API IntegerTypeId();
class CRYPTOPP_DLL AlgorithmParametersBase
{
public:
class ParameterNotUsed : public Exception
{
public:
ParameterNotUsed(const char *name) : Exception(OTHER_ERROR, std::string("AlgorithmParametersBase: parameter \"") + name + "\" not used") {}
};
// this is actually a move, not a copy
AlgorithmParametersBase(const AlgorithmParametersBase &x)
: m_name(x.m_name), m_throwIfNotUsed(x.m_throwIfNotUsed), m_used(x.m_used)
{
m_next.reset(const_cast<AlgorithmParametersBase &>(x).m_next.release());
x.m_used = true;
}
AlgorithmParametersBase(const char *name, bool throwIfNotUsed)
: m_name(name), m_throwIfNotUsed(throwIfNotUsed), m_used(false) {}
virtual ~AlgorithmParametersBase()
{
#ifdef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
if (!std::uncaught_exception())
#else
try
#endif
{
if (m_throwIfNotUsed && !m_used)
throw ParameterNotUsed(m_name);
}
#ifndef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
catch(...)
{
}
#endif
}
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
protected:
friend class AlgorithmParameters;
void operator=(const AlgorithmParametersBase& rhs); // assignment not allowed, declare this for VC60
virtual void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const =0;
virtual void MoveInto(void *p) const =0; // not really const
const char *m_name;
bool m_throwIfNotUsed;
mutable bool m_used;
member_ptr<AlgorithmParametersBase> m_next;
};
template <class T>
class AlgorithmParametersTemplate : public AlgorithmParametersBase
{
public:
AlgorithmParametersTemplate(const char *name, const T &value, bool throwIfNotUsed)
: AlgorithmParametersBase(name, throwIfNotUsed), m_value(value)
{
}
void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const
{
// special case for retrieving an Integer parameter when an int was passed in
if (!(g_pAssignIntToInteger != NULL && typeid(T) == typeid(int) && g_pAssignIntToInteger(valueType, pValue, &m_value)))
{
NameValuePairs::ThrowIfTypeMismatch(name, typeid(T), valueType);
*reinterpret_cast<T *>(pValue) = m_value;
}
}
void MoveInto(void *buffer) const
{
AlgorithmParametersTemplate<T>* p = new(buffer) AlgorithmParametersTemplate<T>(*this);
}
protected:
T m_value;
};
CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<bool>;
CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<int>;
CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<ConstByteArrayParameter>;
class CRYPTOPP_DLL AlgorithmParameters : public NameValuePairs
{
public:
AlgorithmParameters();
#ifdef __BORLANDC__
template <class T>
AlgorithmParameters(const char *name, const T &value, bool throwIfNotUsed=true)
: m_next(new AlgorithmParametersTemplate<T>(name, value, throwIfNotUsed))
, m_defaultThrowIfNotUsed(throwIfNotUsed)
{
}
#endif
AlgorithmParameters(const AlgorithmParameters &x);
AlgorithmParameters & operator=(const AlgorithmParameters &x);
template <class T>
AlgorithmParameters & operator()(const char *name, const T &value, bool throwIfNotUsed)
{
member_ptr<AlgorithmParametersBase> p(new AlgorithmParametersTemplate<T>(name, value, throwIfNotUsed));
p->m_next.reset(m_next.release());
m_next.reset(p.release());
m_defaultThrowIfNotUsed = throwIfNotUsed;
return *this;
}
template <class T>
AlgorithmParameters & operator()(const char *name, const T &value)
{
return operator()(name, value, m_defaultThrowIfNotUsed);
}
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
protected:
member_ptr<AlgorithmParametersBase> m_next;
bool m_defaultThrowIfNotUsed;
};
//! Create an object that implements NameValuePairs for passing parameters
/*! \param throwIfNotUsed if true, the object will throw an exception if the value is not accessed
\note throwIfNotUsed is ignored if using a compiler that does not support std::uncaught_exception(),
such as MSVC 7.0 and earlier.
\note A NameValuePairs object containing an arbitrary number of name value pairs may be constructed by
repeatedly using operator() on the object returned by MakeParameters, for example:
AlgorithmParameters parameters = MakeParameters(name1, value1)(name2, value2)(name3, value3);
*/
#ifdef __BORLANDC__
typedef AlgorithmParameters MakeParameters;
#else
template <class T>
AlgorithmParameters MakeParameters(const char *name, const T &value, bool throwIfNotUsed = true)
{
return AlgorithmParameters()(name, value, throwIfNotUsed);
}
#endif
#define CRYPTOPP_GET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Get##name)
#define CRYPTOPP_SET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Set##name)
#define CRYPTOPP_SET_FUNCTION_ENTRY2(name1, name2) (Name::name1(), Name::name2(), &ThisClass::Set##name1##And##name2)
NAMESPACE_END
#endif

View File

@ -1,81 +0,0 @@
#ifndef CRYPTOPP_ARGNAMES_H
#define CRYPTOPP_ARGNAMES_H
#include "cryptlib.h"
NAMESPACE_BEGIN(CryptoPP)
DOCUMENTED_NAMESPACE_BEGIN(Name)
#define CRYPTOPP_DEFINE_NAME_STRING(name) inline const char *name() {return #name;}
CRYPTOPP_DEFINE_NAME_STRING(ValueNames) //!< string, a list of value names with a semicolon (';') after each name
CRYPTOPP_DEFINE_NAME_STRING(Version) //!< int
CRYPTOPP_DEFINE_NAME_STRING(Seed) //!< ConstByteArrayParameter
CRYPTOPP_DEFINE_NAME_STRING(Key) //!< ConstByteArrayParameter
CRYPTOPP_DEFINE_NAME_STRING(IV) //!< ConstByteArrayParameter, also accepts const byte * for backwards compatibility
CRYPTOPP_DEFINE_NAME_STRING(StolenIV) //!< byte *
CRYPTOPP_DEFINE_NAME_STRING(Rounds) //!< int
CRYPTOPP_DEFINE_NAME_STRING(FeedbackSize) //!< int
CRYPTOPP_DEFINE_NAME_STRING(WordSize) //!< int, in bytes
CRYPTOPP_DEFINE_NAME_STRING(BlockSize) //!< int, in bytes
CRYPTOPP_DEFINE_NAME_STRING(EffectiveKeyLength) //!< int, in bits
CRYPTOPP_DEFINE_NAME_STRING(KeySize) //!< int, in bits
CRYPTOPP_DEFINE_NAME_STRING(ModulusSize) //!< int, in bits
CRYPTOPP_DEFINE_NAME_STRING(SubgroupOrderSize) //!< int, in bits
CRYPTOPP_DEFINE_NAME_STRING(PrivateExponentSize)//!< int, in bits
CRYPTOPP_DEFINE_NAME_STRING(Modulus) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(PublicExponent) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(PrivateExponent) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(PublicElement) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(SubgroupOrder) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(Cofactor) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(SubgroupGenerator) //!< Integer, ECP::Point, or EC2N::Point
CRYPTOPP_DEFINE_NAME_STRING(Curve) //!< ECP or EC2N
CRYPTOPP_DEFINE_NAME_STRING(GroupOID) //!< OID
CRYPTOPP_DEFINE_NAME_STRING(PointerToPrimeSelector) //!< const PrimeSelector *
CRYPTOPP_DEFINE_NAME_STRING(Prime1) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(Prime2) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(ModPrime1PrivateExponent) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(ModPrime2PrivateExponent) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(MultiplicativeInverseOfPrime2ModPrime1) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(QuadraticResidueModPrime1) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(QuadraticResidueModPrime2) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(PutMessage) //!< bool
CRYPTOPP_DEFINE_NAME_STRING(TruncatedDigestSize) //!< int
CRYPTOPP_DEFINE_NAME_STRING(BlockPaddingScheme) //!< StreamTransformationFilter::BlockPaddingScheme
CRYPTOPP_DEFINE_NAME_STRING(HashVerificationFilterFlags) //!< word32
CRYPTOPP_DEFINE_NAME_STRING(AuthenticatedDecryptionFilterFlags) //!< word32
CRYPTOPP_DEFINE_NAME_STRING(SignatureVerificationFilterFlags) //!< word32
CRYPTOPP_DEFINE_NAME_STRING(InputBuffer) //!< ConstByteArrayParameter
CRYPTOPP_DEFINE_NAME_STRING(OutputBuffer) //!< ByteArrayParameter
CRYPTOPP_DEFINE_NAME_STRING(InputFileName) //!< const char *
CRYPTOPP_DEFINE_NAME_STRING(InputFileNameWide) //!< const wchar_t *
CRYPTOPP_DEFINE_NAME_STRING(InputStreamPointer) //!< std::istream *
CRYPTOPP_DEFINE_NAME_STRING(InputBinaryMode) //!< bool
CRYPTOPP_DEFINE_NAME_STRING(OutputFileName) //!< const char *
CRYPTOPP_DEFINE_NAME_STRING(OutputFileNameWide) //!< const wchar_t *
CRYPTOPP_DEFINE_NAME_STRING(OutputStreamPointer) //!< std::ostream *
CRYPTOPP_DEFINE_NAME_STRING(OutputBinaryMode) //!< bool
CRYPTOPP_DEFINE_NAME_STRING(EncodingParameters) //!< ConstByteArrayParameter
CRYPTOPP_DEFINE_NAME_STRING(KeyDerivationParameters) //!< ConstByteArrayParameter
CRYPTOPP_DEFINE_NAME_STRING(Separator) //< ConstByteArrayParameter
CRYPTOPP_DEFINE_NAME_STRING(Terminator) //< ConstByteArrayParameter
CRYPTOPP_DEFINE_NAME_STRING(Uppercase) //< bool
CRYPTOPP_DEFINE_NAME_STRING(GroupSize) //< int
CRYPTOPP_DEFINE_NAME_STRING(Pad) //< bool
CRYPTOPP_DEFINE_NAME_STRING(PaddingByte) //< byte
CRYPTOPP_DEFINE_NAME_STRING(Log2Base) //< int
CRYPTOPP_DEFINE_NAME_STRING(EncodingLookupArray) //< const byte *
CRYPTOPP_DEFINE_NAME_STRING(DecodingLookupArray) //< const byte *
CRYPTOPP_DEFINE_NAME_STRING(InsertLineBreaks) //< bool
CRYPTOPP_DEFINE_NAME_STRING(MaxLineLength) //< int
CRYPTOPP_DEFINE_NAME_STRING(DigestSize) //!< int, in bytes
CRYPTOPP_DEFINE_NAME_STRING(L1KeyLength) //!< int, in bytes
CRYPTOPP_DEFINE_NAME_STRING(TableSize) //!< int, in bytes
DOCUMENTED_NAMESPACE_END
NAMESPACE_END
#endif

View File

@ -1,597 +0,0 @@
// asn.cpp - written and placed in the public domain by Wei Dai
#include "pch.h"
#ifndef CRYPTOPP_IMPORTS
#include "asn.h"
#include <iomanip>
#include <time.h>
NAMESPACE_BEGIN(CryptoPP)
USING_NAMESPACE(std)
/// DER Length
size_t DERLengthEncode(BufferedTransformation &bt, lword length)
{
size_t i=0;
if (length <= 0x7f)
{
bt.Put(byte(length));
i++;
}
else
{
bt.Put(byte(BytePrecision(length) | 0x80));
i++;
for (int j=BytePrecision(length); j; --j)
{
bt.Put(byte(length >> (j-1)*8));
i++;
}
}
return i;
}
bool BERLengthDecode(BufferedTransformation &bt, lword &length, bool &definiteLength)
{
byte b;
if (!bt.Get(b))
return false;
if (!(b & 0x80))
{
definiteLength = true;
length = b;
}
else
{
unsigned int lengthBytes = b & 0x7f;
if (lengthBytes == 0)
{
definiteLength = false;
return true;
}
definiteLength = true;
length = 0;
while (lengthBytes--)
{
if (length >> (8*(sizeof(length)-1)))
BERDecodeError(); // length about to overflow
if (!bt.Get(b))
return false;
length = (length << 8) | b;
}
}
return true;
}
bool BERLengthDecode(BufferedTransformation &bt, size_t &length)
{
lword lw;
bool definiteLength;
if (!BERLengthDecode(bt, lw, definiteLength))
BERDecodeError();
if (!SafeConvert(lw, length))
BERDecodeError();
return definiteLength;
}
void DEREncodeNull(BufferedTransformation &out)
{
out.Put(TAG_NULL);
out.Put(0);
}
void BERDecodeNull(BufferedTransformation &in)
{
byte b;
if (!in.Get(b) || b != TAG_NULL)
BERDecodeError();
size_t length;
if (!BERLengthDecode(in, length) || length != 0)
BERDecodeError();
}
/// ASN Strings
size_t DEREncodeOctetString(BufferedTransformation &bt, const byte *str, size_t strLen)
{
bt.Put(OCTET_STRING);
size_t lengthBytes = DERLengthEncode(bt, strLen);
bt.Put(str, strLen);
return 1+lengthBytes+strLen;
}
size_t DEREncodeOctetString(BufferedTransformation &bt, const SecByteBlock &str)
{
return DEREncodeOctetString(bt, str.begin(), str.size());
}
size_t BERDecodeOctetString(BufferedTransformation &bt, SecByteBlock &str)
{
byte b;
if (!bt.Get(b) || b != OCTET_STRING)
BERDecodeError();
size_t bc;
if (!BERLengthDecode(bt, bc))
BERDecodeError();
str.resize(bc);
if (bc != bt.Get(str, bc))
BERDecodeError();
return bc;
}
size_t BERDecodeOctetString(BufferedTransformation &bt, BufferedTransformation &str)
{
byte b;
if (!bt.Get(b) || b != OCTET_STRING)
BERDecodeError();
size_t bc;
if (!BERLengthDecode(bt, bc))
BERDecodeError();
bt.TransferTo(str, bc);
return bc;
}
size_t DEREncodeTextString(BufferedTransformation &bt, const std::string &str, byte asnTag)
{
bt.Put(asnTag);
size_t lengthBytes = DERLengthEncode(bt, str.size());
bt.Put((const byte *)str.data(), str.size());
return 1+lengthBytes+str.size();
}
size_t BERDecodeTextString(BufferedTransformation &bt, std::string &str, byte asnTag)
{
byte b;
if (!bt.Get(b) || b != asnTag)
BERDecodeError();
size_t bc;
if (!BERLengthDecode(bt, bc))
BERDecodeError();
SecByteBlock temp(bc);
if (bc != bt.Get(temp, bc))
BERDecodeError();
str.assign((char *)temp.begin(), bc);
return bc;
}
/// ASN BitString
size_t DEREncodeBitString(BufferedTransformation &bt, const byte *str, size_t strLen, unsigned int unusedBits)
{
bt.Put(BIT_STRING);
size_t lengthBytes = DERLengthEncode(bt, strLen+1);
bt.Put((byte)unusedBits);
bt.Put(str, strLen);
return 2+lengthBytes+strLen;
}
size_t BERDecodeBitString(BufferedTransformation &bt, SecByteBlock &str, unsigned int &unusedBits)
{
byte b;
if (!bt.Get(b) || b != BIT_STRING)
BERDecodeError();
size_t bc;
if (!BERLengthDecode(bt, bc))
BERDecodeError();
byte unused;
if (!bt.Get(unused))
BERDecodeError();
unusedBits = unused;
str.resize(bc-1);
if ((bc-1) != bt.Get(str, bc-1))
BERDecodeError();
return bc-1;
}
void DERReencode(BufferedTransformation &source, BufferedTransformation &dest)
{
byte tag;
source.Peek(tag);
BERGeneralDecoder decoder(source, tag);
DERGeneralEncoder encoder(dest, tag);
if (decoder.IsDefiniteLength())
decoder.TransferTo(encoder, decoder.RemainingLength());
else
{
while (!decoder.EndReached())
DERReencode(decoder, encoder);
}
decoder.MessageEnd();
encoder.MessageEnd();
}
void OID::EncodeValue(BufferedTransformation &bt, word32 v)
{
for (unsigned int i=RoundUpToMultipleOf(STDMAX(7U,BitPrecision(v)), 7U)-7; i != 0; i-=7)
bt.Put((byte)(0x80 | ((v >> i) & 0x7f)));
bt.Put((byte)(v & 0x7f));
}
size_t OID::DecodeValue(BufferedTransformation &bt, word32 &v)
{
byte b;
size_t i=0;
v = 0;
while (true)
{
if (!bt.Get(b))
BERDecodeError();
i++;
if (v >> (8*sizeof(v)-7)) // v about to overflow
BERDecodeError();
v <<= 7;
v += b & 0x7f;
if (!(b & 0x80))
return i;
}
}
void OID::DEREncode(BufferedTransformation &bt) const
{
assert(m_values.size() >= 2);
ByteQueue temp;
temp.Put(byte(m_values[0] * 40 + m_values[1]));
for (size_t i=2; i<m_values.size(); i++)
EncodeValue(temp, m_values[i]);
bt.Put(OBJECT_IDENTIFIER);
DERLengthEncode(bt, temp.CurrentSize());
temp.TransferTo(bt);
}
void OID::BERDecode(BufferedTransformation &bt)
{
byte b;
if (!bt.Get(b) || b != OBJECT_IDENTIFIER)
BERDecodeError();
size_t length;
if (!BERLengthDecode(bt, length) || length < 1)
BERDecodeError();
if (!bt.Get(b))
BERDecodeError();
length--;
m_values.resize(2);
m_values[0] = b / 40;
m_values[1] = b % 40;
while (length > 0)
{
word32 v;
size_t valueLen = DecodeValue(bt, v);
if (valueLen > length)
BERDecodeError();
m_values.push_back(v);
length -= valueLen;
}
}
void OID::BERDecodeAndCheck(BufferedTransformation &bt) const
{
OID oid(bt);
if (*this != oid)
BERDecodeError();
}
inline BufferedTransformation & EncodedObjectFilter::CurrentTarget()
{
if (m_flags & PUT_OBJECTS)
return *AttachedTransformation();
else
return TheBitBucket();
}
void EncodedObjectFilter::Put(const byte *inString, size_t length)
{
if (m_nCurrentObject == m_nObjects)
{
AttachedTransformation()->Put(inString, length);
return;
}
LazyPutter lazyPutter(m_queue, inString, length);
while (m_queue.AnyRetrievable())
{
switch (m_state)
{
case IDENTIFIER:
if (!m_queue.Get(m_id))
return;
m_queue.TransferTo(CurrentTarget(), 1);
m_state = LENGTH; // fall through
case LENGTH:
{
byte b;
if (m_level > 0 && m_id == 0 && m_queue.Peek(b) && b == 0)
{
m_queue.TransferTo(CurrentTarget(), 1);
m_level--;
m_state = IDENTIFIER;
break;
}
ByteQueue::Walker walker(m_queue);
bool definiteLength;
if (!BERLengthDecode(walker, m_lengthRemaining, definiteLength))
return;
m_queue.TransferTo(CurrentTarget(), walker.GetCurrentPosition());
if (!((m_id & CONSTRUCTED) || definiteLength))
BERDecodeError();
if (!definiteLength)
{
if (!(m_id & CONSTRUCTED))
BERDecodeError();
m_level++;
m_state = IDENTIFIER;
break;
}
m_state = BODY; // fall through
}
case BODY:
m_lengthRemaining -= m_queue.TransferTo(CurrentTarget(), m_lengthRemaining);
if (m_lengthRemaining == 0)
m_state = IDENTIFIER;
}
if (m_state == IDENTIFIER && m_level == 0)
{
// just finished processing a level 0 object
++m_nCurrentObject;
if (m_flags & PUT_MESSANGE_END_AFTER_EACH_OBJECT)
AttachedTransformation()->MessageEnd();
if (m_nCurrentObject == m_nObjects)
{
if (m_flags & PUT_MESSANGE_END_AFTER_ALL_OBJECTS)
AttachedTransformation()->MessageEnd();
if (m_flags & PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS)
AttachedTransformation()->MessageSeriesEnd();
m_queue.TransferAllTo(*AttachedTransformation());
return;
}
}
}
}
BERGeneralDecoder::BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag)
: m_inQueue(inQueue), m_finished(false)
{
Init(asnTag);
}
BERGeneralDecoder::BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag)
: m_inQueue(inQueue), m_finished(false)
{
Init(asnTag);
}
void BERGeneralDecoder::Init(byte asnTag)
{
byte b;
if (!m_inQueue.Get(b) || b != asnTag)
BERDecodeError();
if (!BERLengthDecode(m_inQueue, m_length, m_definiteLength))
BERDecodeError();
if (!m_definiteLength && !(asnTag & CONSTRUCTED))
BERDecodeError(); // cannot be primitive and have indefinite length
}
BERGeneralDecoder::~BERGeneralDecoder()
{
try // avoid throwing in constructor
{
if (!m_finished)
MessageEnd();
}
catch (...)
{
}
}
bool BERGeneralDecoder::EndReached() const
{
if (m_definiteLength)
return m_length == 0;
else
{ // check end-of-content octets
word16 i;
return (m_inQueue.PeekWord16(i)==2 && i==0);
}
}
byte BERGeneralDecoder::PeekByte() const
{
byte b;
if (!Peek(b))
BERDecodeError();
return b;
}
void BERGeneralDecoder::CheckByte(byte check)
{
byte b;
if (!Get(b) || b != check)
BERDecodeError();
}
void BERGeneralDecoder::MessageEnd()
{
m_finished = true;
if (m_definiteLength)
{
if (m_length != 0)
BERDecodeError();
}
else
{ // remove end-of-content octets
word16 i;
if (m_inQueue.GetWord16(i) != 2 || i != 0)
BERDecodeError();
}
}
size_t BERGeneralDecoder::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
{
if (m_definiteLength && transferBytes > m_length)
transferBytes = m_length;
size_t blockedBytes = m_inQueue.TransferTo2(target, transferBytes, channel, blocking);
ReduceLength(transferBytes);
return blockedBytes;
}
size_t BERGeneralDecoder::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
{
if (m_definiteLength)
end = STDMIN(m_length, end);
return m_inQueue.CopyRangeTo2(target, begin, end, channel, blocking);
}
lword BERGeneralDecoder::ReduceLength(lword delta)
{
if (m_definiteLength)
{
if (m_length < delta)
BERDecodeError();
m_length -= delta;
}
return delta;
}
DERGeneralEncoder::DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag)
: m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag)
{
}
DERGeneralEncoder::DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag)
: m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag)
{
}
DERGeneralEncoder::~DERGeneralEncoder()
{
try // avoid throwing in constructor
{
if (!m_finished)
MessageEnd();
}
catch (...)
{
}
}
void DERGeneralEncoder::MessageEnd()
{
m_finished = true;
lword length = CurrentSize();
m_outQueue.Put(m_asnTag);
DERLengthEncode(m_outQueue, length);
TransferTo(m_outQueue);
}
// *************************************************************
void X509PublicKey::BERDecode(BufferedTransformation &bt)
{
BERSequenceDecoder subjectPublicKeyInfo(bt);
BERSequenceDecoder algorithm(subjectPublicKeyInfo);
GetAlgorithmID().BERDecodeAndCheck(algorithm);
bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm);
algorithm.MessageEnd();
BERGeneralDecoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING);
subjectPublicKey.CheckByte(0); // unused bits
BERDecodePublicKey(subjectPublicKey, parametersPresent, (size_t)subjectPublicKey.RemainingLength());
subjectPublicKey.MessageEnd();
subjectPublicKeyInfo.MessageEnd();
}
void X509PublicKey::DEREncode(BufferedTransformation &bt) const
{
DERSequenceEncoder subjectPublicKeyInfo(bt);
DERSequenceEncoder algorithm(subjectPublicKeyInfo);
GetAlgorithmID().DEREncode(algorithm);
DEREncodeAlgorithmParameters(algorithm);
algorithm.MessageEnd();
DERGeneralEncoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING);
subjectPublicKey.Put(0); // unused bits
DEREncodePublicKey(subjectPublicKey);
subjectPublicKey.MessageEnd();
subjectPublicKeyInfo.MessageEnd();
}
void PKCS8PrivateKey::BERDecode(BufferedTransformation &bt)
{
BERSequenceDecoder privateKeyInfo(bt);
word32 version;
BERDecodeUnsigned<word32>(privateKeyInfo, version, INTEGER, 0, 0); // check version
BERSequenceDecoder algorithm(privateKeyInfo);
GetAlgorithmID().BERDecodeAndCheck(algorithm);
bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm);
algorithm.MessageEnd();
BERGeneralDecoder octetString(privateKeyInfo, OCTET_STRING);
BERDecodePrivateKey(octetString, parametersPresent, (size_t)privateKeyInfo.RemainingLength());
octetString.MessageEnd();
if (!privateKeyInfo.EndReached())
BERDecodeOptionalAttributes(privateKeyInfo);
privateKeyInfo.MessageEnd();
}
void PKCS8PrivateKey::DEREncode(BufferedTransformation &bt) const
{
DERSequenceEncoder privateKeyInfo(bt);
DEREncodeUnsigned<word32>(privateKeyInfo, 0); // version
DERSequenceEncoder algorithm(privateKeyInfo);
GetAlgorithmID().DEREncode(algorithm);
DEREncodeAlgorithmParameters(algorithm);
algorithm.MessageEnd();
DERGeneralEncoder octetString(privateKeyInfo, OCTET_STRING);
DEREncodePrivateKey(octetString);
octetString.MessageEnd();
DEREncodeOptionalAttributes(privateKeyInfo);
privateKeyInfo.MessageEnd();
}
void PKCS8PrivateKey::BERDecodeOptionalAttributes(BufferedTransformation &bt)
{
DERReencode(bt, m_optionalAttributes);
}
void PKCS8PrivateKey::DEREncodeOptionalAttributes(BufferedTransformation &bt) const
{
m_optionalAttributes.CopyTo(bt);
}
NAMESPACE_END
#endif

View File

@ -1,369 +0,0 @@
#ifndef CRYPTOPP_ASN_H
#define CRYPTOPP_ASN_H
#include "filters.h"
#include "queue.h"
#include <vector>
NAMESPACE_BEGIN(CryptoPP)
// these tags and flags are not complete
enum ASNTag
{
BOOLEAN = 0x01,
INTEGER = 0x02,
BIT_STRING = 0x03,
OCTET_STRING = 0x04,
TAG_NULL = 0x05,
OBJECT_IDENTIFIER = 0x06,
OBJECT_DESCRIPTOR = 0x07,
EXTERNAL = 0x08,
REAL = 0x09,
ENUMERATED = 0x0a,
UTF8_STRING = 0x0c,
SEQUENCE = 0x10,
SET = 0x11,
NUMERIC_STRING = 0x12,
PRINTABLE_STRING = 0x13,
T61_STRING = 0x14,
VIDEOTEXT_STRING = 0x15,
IA5_STRING = 0x16,
UTC_TIME = 0x17,
GENERALIZED_TIME = 0x18,
GRAPHIC_STRING = 0x19,
VISIBLE_STRING = 0x1a,
GENERAL_STRING = 0x1b
};
enum ASNIdFlag
{
UNIVERSAL = 0x00,
// DATA = 0x01,
// HEADER = 0x02,
CONSTRUCTED = 0x20,
APPLICATION = 0x40,
CONTEXT_SPECIFIC = 0x80,
PRIVATE = 0xc0
};
inline void BERDecodeError() {throw BERDecodeErr();}
class CRYPTOPP_DLL UnknownOID : public BERDecodeErr
{
public:
UnknownOID() : BERDecodeErr("BER decode error: unknown object identifier") {}
UnknownOID(const char *err) : BERDecodeErr(err) {}
};
// unsigned int DERLengthEncode(unsigned int length, byte *output=0);
CRYPTOPP_DLL size_t CRYPTOPP_API DERLengthEncode(BufferedTransformation &out, lword length);
// returns false if indefinite length
CRYPTOPP_DLL bool CRYPTOPP_API BERLengthDecode(BufferedTransformation &in, size_t &length);
CRYPTOPP_DLL void CRYPTOPP_API DEREncodeNull(BufferedTransformation &out);
CRYPTOPP_DLL void CRYPTOPP_API BERDecodeNull(BufferedTransformation &in);
CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeOctetString(BufferedTransformation &out, const byte *str, size_t strLen);
CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeOctetString(BufferedTransformation &out, const SecByteBlock &str);
CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeOctetString(BufferedTransformation &in, SecByteBlock &str);
CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeOctetString(BufferedTransformation &in, BufferedTransformation &str);
// for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING
CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeTextString(BufferedTransformation &out, const std::string &str, byte asnTag);
CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeTextString(BufferedTransformation &in, std::string &str, byte asnTag);
CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeBitString(BufferedTransformation &out, const byte *str, size_t strLen, unsigned int unusedBits=0);
CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeBitString(BufferedTransformation &in, SecByteBlock &str, unsigned int &unusedBits);
// BER decode from source and DER reencode into dest
CRYPTOPP_DLL void CRYPTOPP_API DERReencode(BufferedTransformation &source, BufferedTransformation &dest);
//! Object Identifier
class CRYPTOPP_DLL OID
{
public:
OID() {}
OID(word32 v) : m_values(1, v) {}
OID(BufferedTransformation &bt) {BERDecode(bt);}
inline OID & operator+=(word32 rhs) {m_values.push_back(rhs); return *this;}
void DEREncode(BufferedTransformation &bt) const;
void BERDecode(BufferedTransformation &bt);
// throw BERDecodeErr() if decoded value doesn't equal this OID
void BERDecodeAndCheck(BufferedTransformation &bt) const;
std::vector<word32> m_values;
private:
static void EncodeValue(BufferedTransformation &bt, word32 v);
static size_t DecodeValue(BufferedTransformation &bt, word32 &v);
};
class EncodedObjectFilter : public Filter
{
public:
enum Flag {PUT_OBJECTS=1, PUT_MESSANGE_END_AFTER_EACH_OBJECT=2, PUT_MESSANGE_END_AFTER_ALL_OBJECTS=4, PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS=8};
EncodedObjectFilter(BufferedTransformation *attachment = NULL, unsigned int nObjects = 1, word32 flags = 0);
void Put(const byte *inString, size_t length);
unsigned int GetNumberOfCompletedObjects() const {return m_nCurrentObject;}
unsigned long GetPositionOfObject(unsigned int i) const {return m_positions[i];}
private:
BufferedTransformation & CurrentTarget();
word32 m_flags;
unsigned int m_nObjects, m_nCurrentObject, m_level;
std::vector<unsigned int> m_positions;
ByteQueue m_queue;
enum State {IDENTIFIER, LENGTH, BODY, TAIL, ALL_DONE} m_state;
byte m_id;
lword m_lengthRemaining;
};
//! BER General Decoder
class CRYPTOPP_DLL BERGeneralDecoder : public Store
{
public:
explicit BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag);
explicit BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag);
~BERGeneralDecoder();
bool IsDefiniteLength() const {return m_definiteLength;}
lword RemainingLength() const {assert(m_definiteLength); return m_length;}
bool EndReached() const;
byte PeekByte() const;
void CheckByte(byte b);
size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
// call this to denote end of sequence
void MessageEnd();
protected:
BufferedTransformation &m_inQueue;
bool m_finished, m_definiteLength;
lword m_length;
private:
void Init(byte asnTag);
void StoreInitialize(const NameValuePairs &parameters) {assert(false);}
lword ReduceLength(lword delta);
};
//! DER General Encoder
class CRYPTOPP_DLL DERGeneralEncoder : public ByteQueue
{
public:
explicit DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED);
explicit DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED);
~DERGeneralEncoder();
// call this to denote end of sequence
void MessageEnd();
private:
BufferedTransformation &m_outQueue;
bool m_finished;
byte m_asnTag;
};
//! BER Sequence Decoder
class CRYPTOPP_DLL BERSequenceDecoder : public BERGeneralDecoder
{
public:
explicit BERSequenceDecoder(BufferedTransformation &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
: BERGeneralDecoder(inQueue, asnTag) {}
explicit BERSequenceDecoder(BERSequenceDecoder &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
: BERGeneralDecoder(inQueue, asnTag) {}
};
//! DER Sequence Encoder
class CRYPTOPP_DLL DERSequenceEncoder : public DERGeneralEncoder
{
public:
explicit DERSequenceEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
: DERGeneralEncoder(outQueue, asnTag) {}
explicit DERSequenceEncoder(DERSequenceEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
: DERGeneralEncoder(outQueue, asnTag) {}
};
//! BER Set Decoder
class CRYPTOPP_DLL BERSetDecoder : public BERGeneralDecoder
{
public:
explicit BERSetDecoder(BufferedTransformation &inQueue, byte asnTag = SET | CONSTRUCTED)
: BERGeneralDecoder(inQueue, asnTag) {}
explicit BERSetDecoder(BERSetDecoder &inQueue, byte asnTag = SET | CONSTRUCTED)
: BERGeneralDecoder(inQueue, asnTag) {}
};
//! DER Set Encoder
class CRYPTOPP_DLL DERSetEncoder : public DERGeneralEncoder
{
public:
explicit DERSetEncoder(BufferedTransformation &outQueue, byte asnTag = SET | CONSTRUCTED)
: DERGeneralEncoder(outQueue, asnTag) {}
explicit DERSetEncoder(DERSetEncoder &outQueue, byte asnTag = SET | CONSTRUCTED)
: DERGeneralEncoder(outQueue, asnTag) {}
};
template <class T>
class ASNOptional : public member_ptr<T>
{
public:
void BERDecode(BERSequenceDecoder &seqDecoder, byte tag, byte mask = ~CONSTRUCTED)
{
byte b;
if (seqDecoder.Peek(b) && (b & mask) == tag)
reset(new T(seqDecoder));
}
void DEREncode(BufferedTransformation &out)
{
if (this->get() != NULL)
this->get()->DEREncode(out);
}
};
//! _
template <class BASE>
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ASN1CryptoMaterial : public ASN1Object, public BASE
{
public:
void Save(BufferedTransformation &bt) const
{BEREncode(bt);}
void Load(BufferedTransformation &bt)
{BERDecode(bt);}
};
//! encodes/decodes subjectPublicKeyInfo
class CRYPTOPP_DLL X509PublicKey : public ASN1CryptoMaterial<PublicKey>
{
public:
void BERDecode(BufferedTransformation &bt);
void DEREncode(BufferedTransformation &bt) const;
virtual OID GetAlgorithmID() const =0;
virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt)
{BERDecodeNull(bt); return false;}
virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const
{DEREncodeNull(bt); return false;} // see RFC 2459, section 7.3.1
//! decode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header
virtual void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0;
//! encode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header
virtual void DEREncodePublicKey(BufferedTransformation &bt) const =0;
};
//! encodes/decodes privateKeyInfo
class CRYPTOPP_DLL PKCS8PrivateKey : public ASN1CryptoMaterial<PrivateKey>
{
public:
void BERDecode(BufferedTransformation &bt);
void DEREncode(BufferedTransformation &bt) const;
virtual OID GetAlgorithmID() const =0;
virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt)
{BERDecodeNull(bt); return false;}
virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const
{DEREncodeNull(bt); return false;} // see RFC 2459, section 7.3.1
//! decode privateKey part of privateKeyInfo, without the OCTET STRING header
virtual void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0;
//! encode privateKey part of privateKeyInfo, without the OCTET STRING header
virtual void DEREncodePrivateKey(BufferedTransformation &bt) const =0;
//! decode optional attributes including context-specific tag
/*! /note default implementation stores attributes to be output in DEREncodeOptionalAttributes */
virtual void BERDecodeOptionalAttributes(BufferedTransformation &bt);
//! encode optional attributes including context-specific tag
virtual void DEREncodeOptionalAttributes(BufferedTransformation &bt) const;
protected:
ByteQueue m_optionalAttributes;
};
// ********************************************************
//! DER Encode Unsigned
/*! for INTEGER, BOOLEAN, and ENUM */
template <class T>
size_t DEREncodeUnsigned(BufferedTransformation &out, T w, byte asnTag = INTEGER)
{
byte buf[sizeof(w)+1];
unsigned int bc;
if (asnTag == BOOLEAN)
{
buf[sizeof(w)] = w ? 0xff : 0;
bc = 1;
}
else
{
buf[0] = 0;
for (unsigned int i=0; i<sizeof(w); i++)
buf[i+1] = byte(w >> (sizeof(w)-1-i)*8);
bc = sizeof(w);
while (bc > 1 && buf[sizeof(w)+1-bc] == 0)
--bc;
if (buf[sizeof(w)+1-bc] & 0x80)
++bc;
}
out.Put(asnTag);
size_t lengthBytes = DERLengthEncode(out, bc);
out.Put(buf+sizeof(w)+1-bc, bc);
return 1+lengthBytes+bc;
}
//! BER Decode Unsigned
// VC60 workaround: std::numeric_limits<T>::max conflicts with MFC max macro
// CW41 workaround: std::numeric_limits<T>::max causes a template error
template <class T>
void BERDecodeUnsigned(BufferedTransformation &in, T &w, byte asnTag = INTEGER,
T minValue = 0, T maxValue = 0xffffffff)
{
byte b;
if (!in.Get(b) || b != asnTag)
BERDecodeError();
size_t bc;
BERLengthDecode(in, bc);
SecByteBlock buf(bc);
if (bc != in.Get(buf, bc))
BERDecodeError();
const byte *ptr = buf;
while (bc > sizeof(w) && *ptr == 0)
{
bc--;
ptr++;
}
if (bc > sizeof(w))
BERDecodeError();
w = 0;
for (unsigned int i=0; i<bc; i++)
w = (w << 8) | ptr[i];
if (w < minValue || w > maxValue)
BERDecodeError();
}
inline bool operator==(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
{return lhs.m_values == rhs.m_values;}
inline bool operator!=(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
{return lhs.m_values != rhs.m_values;}
inline bool operator<(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
{return std::lexicographical_compare(lhs.m_values.begin(), lhs.m_values.end(), rhs.m_values.begin(), rhs.m_values.end());}
inline ::CryptoPP::OID operator+(const ::CryptoPP::OID &lhs, unsigned long rhs)
{return ::CryptoPP::OID(lhs)+=rhs;}
NAMESPACE_END
#endif

View File

@ -1,180 +0,0 @@
// authenc.cpp - written and placed in the public domain by Wei Dai
#include "pch.h"
#ifndef CRYPTOPP_IMPORTS
#include "authenc.h"
NAMESPACE_BEGIN(CryptoPP)
void AuthenticatedSymmetricCipherBase::AuthenticateData(const byte *input, size_t len)
{
unsigned int blockSize = AuthenticationBlockSize();
unsigned int &num = m_bufferedDataLength;
byte* data = m_buffer.begin();
if (num != 0) // process left over data
{
if (num+len >= blockSize)
{
memcpy(data+num, input, blockSize-num);
AuthenticateBlocks(data, blockSize);
input += (blockSize-num);
len -= (blockSize-num);
num = 0;
// drop through and do the rest
}
else
{
memcpy(data+num, input, len);
num += (unsigned int)len;
return;
}
}
// now process the input data in blocks of blockSize bytes and save the leftovers to m_data
if (len >= blockSize)
{
size_t leftOver = AuthenticateBlocks(input, len);
input += (len - leftOver);
len = leftOver;
}
memcpy(data, input, len);
num = (unsigned int)len;
}
void AuthenticatedSymmetricCipherBase::SetKey(const byte *userKey, size_t keylength, const NameValuePairs &params)
{
m_bufferedDataLength = 0;
m_state = State_Start;
SetKeyWithoutResync(userKey, keylength, params);
m_state = State_KeySet;
size_t length;
const byte *iv = GetIVAndThrowIfInvalid(params, length);
if (iv)
Resynchronize(iv, (int)length);
}
void AuthenticatedSymmetricCipherBase::Resynchronize(const byte *iv, int length)
{
if (m_state < State_KeySet)
throw BadState(AlgorithmName(), "Resynchronize", "key is set");
m_bufferedDataLength = 0;
m_totalHeaderLength = m_totalMessageLength = m_totalFooterLength = 0;
m_state = State_KeySet;
Resync(iv, this->ThrowIfInvalidIVLength(length));
m_state = State_IVSet;
}
void AuthenticatedSymmetricCipherBase::Update(const byte *input, size_t length)
{
if (length == 0)
return;
switch (m_state)
{
case State_Start:
case State_KeySet:
throw BadState(AlgorithmName(), "Update", "setting key and IV");
case State_IVSet:
AuthenticateData(input, length);
m_totalHeaderLength += length;
break;
case State_AuthUntransformed:
case State_AuthTransformed:
AuthenticateLastConfidentialBlock();
m_bufferedDataLength = 0;
m_state = State_AuthFooter;
// fall through
case State_AuthFooter:
AuthenticateData(input, length);
m_totalFooterLength += length;
break;
default:
assert(false);
}
}
void AuthenticatedSymmetricCipherBase::ProcessData(byte *outString, const byte *inString, size_t length)
{
m_totalMessageLength += length;
if (m_state >= State_IVSet && m_totalMessageLength > MaxMessageLength())
throw InvalidArgument(AlgorithmName() + ": message length exceeds maximum");
reswitch:
switch (m_state)
{
case State_Start:
case State_KeySet:
throw BadState(AlgorithmName(), "ProcessData", "setting key and IV");
case State_AuthFooter:
throw BadState(AlgorithmName(), "ProcessData was called after footer input has started");
case State_IVSet:
AuthenticateLastHeaderBlock();
m_bufferedDataLength = 0;
m_state = AuthenticationIsOnPlaintext()==IsForwardTransformation() ? State_AuthUntransformed : State_AuthTransformed;
goto reswitch;
case State_AuthUntransformed:
AuthenticateData(inString, length);
AccessSymmetricCipher().ProcessData(outString, inString, length);
break;
case State_AuthTransformed:
AccessSymmetricCipher().ProcessData(outString, inString, length);
AuthenticateData(outString, length);
break;
default:
assert(false);
}
}
void AuthenticatedSymmetricCipherBase::TruncatedFinal(byte *mac, size_t macSize)
{
if (m_totalHeaderLength > MaxHeaderLength())
throw InvalidArgument(AlgorithmName() + ": header length of " + IntToString(m_totalHeaderLength) + " exceeds the maximum of " + IntToString(MaxHeaderLength()));
if (m_totalFooterLength > MaxFooterLength())
{
if (MaxFooterLength() == 0)
throw InvalidArgument(AlgorithmName() + ": additional authenticated data (AAD) cannot be input after data to be encrypted or decrypted");
else
throw InvalidArgument(AlgorithmName() + ": footer length of " + IntToString(m_totalFooterLength) + " exceeds the maximum of " + IntToString(MaxFooterLength()));
}
switch (m_state)
{
case State_Start:
case State_KeySet:
throw BadState(AlgorithmName(), "TruncatedFinal", "setting key and IV");
case State_IVSet:
AuthenticateLastHeaderBlock();
m_bufferedDataLength = 0;
// fall through
case State_AuthUntransformed:
case State_AuthTransformed:
AuthenticateLastConfidentialBlock();
m_bufferedDataLength = 0;
// fall through
case State_AuthFooter:
AuthenticateLastFooterBlock(mac, macSize);
m_bufferedDataLength = 0;
break;
default:
assert(false);
}
m_state = State_KeySet;
}
NAMESPACE_END
#endif

View File

@ -1,49 +0,0 @@
#ifndef CRYPTOPP_AUTHENC_H
#define CRYPTOPP_AUTHENC_H
#include "cryptlib.h"
#include "secblock.h"
NAMESPACE_BEGIN(CryptoPP)
//! .
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AuthenticatedSymmetricCipherBase : public AuthenticatedSymmetricCipher
{
public:
AuthenticatedSymmetricCipherBase() : m_state(State_Start) {}
bool IsRandomAccess() const {return false;}
bool IsSelfInverting() const {return true;}
void UncheckedSetKey(const byte *,unsigned int,const CryptoPP::NameValuePairs &) {assert(false);}
void SetKey(const byte *userKey, size_t keylength, const NameValuePairs &params);
void Restart() {if (m_state > State_KeySet) m_state = State_KeySet;}
void Resynchronize(const byte *iv, int length=-1);
void Update(const byte *input, size_t length);
void ProcessData(byte *outString, const byte *inString, size_t length);
void TruncatedFinal(byte *mac, size_t macSize);
protected:
void AuthenticateData(const byte *data, size_t len);
const SymmetricCipher & GetSymmetricCipher() const {return const_cast<AuthenticatedSymmetricCipherBase *>(this)->AccessSymmetricCipher();};
virtual SymmetricCipher & AccessSymmetricCipher() =0;
virtual bool AuthenticationIsOnPlaintext() const =0;
virtual unsigned int AuthenticationBlockSize() const =0;
virtual void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params) =0;
virtual void Resync(const byte *iv, size_t len) =0;
virtual size_t AuthenticateBlocks(const byte *data, size_t len) =0;
virtual void AuthenticateLastHeaderBlock() =0;
virtual void AuthenticateLastConfidentialBlock() {}
virtual void AuthenticateLastFooterBlock(byte *mac, size_t macSize) =0;
enum State {State_Start, State_KeySet, State_IVSet, State_AuthUntransformed, State_AuthTransformed, State_AuthFooter};
State m_state;
unsigned int m_bufferedDataLength;
lword m_totalHeaderLength, m_totalMessageLength, m_totalFooterLength;
AlignedSecByteBlock m_buffer;
};
NAMESPACE_END
#endif

View File

@ -1,39 +0,0 @@
// base32.cpp - written and placed in the public domain by Frank Palazzolo, based on hex.cpp by Wei Dai
#include "pch.h"
#include "base32.h"
NAMESPACE_BEGIN(CryptoPP)
static const byte s_vecUpper[] = "ABCDEFGHIJKMNPQRSTUVWXYZ23456789";
static const byte s_vecLower[] = "abcdefghijkmnpqrstuvwxyz23456789";
void Base32Encoder::IsolatedInitialize(const NameValuePairs &parameters)
{
bool uppercase = parameters.GetValueWithDefault(Name::Uppercase(), true);
m_filter->Initialize(CombinedNameValuePairs(
parameters,
MakeParameters(Name::EncodingLookupArray(), uppercase ? &s_vecUpper[0] : &s_vecLower[0], false)(Name::Log2Base(), 5, true)));
}
void Base32Decoder::IsolatedInitialize(const NameValuePairs &parameters)
{
BaseN_Decoder::Initialize(CombinedNameValuePairs(
parameters,
MakeParameters(Name::DecodingLookupArray(), GetDefaultDecodingLookupArray(), false)(Name::Log2Base(), 5, true)));
}
const int *Base32Decoder::GetDefaultDecodingLookupArray()
{
static volatile bool s_initialized = false;
static int s_array[256];
if (!s_initialized)
{
InitializeDecodingLookupArray(s_array, s_vecUpper, 32, true);
s_initialized = true;
}
return s_array;
}
NAMESPACE_END

View File

@ -1,38 +0,0 @@
#ifndef CRYPTOPP_BASE32_H
#define CRYPTOPP_BASE32_H
#include "basecode.h"
NAMESPACE_BEGIN(CryptoPP)
//! Converts given data to base 32, the default code is based on draft-ietf-idn-dude-02.txt
/*! To specify alternative code, call Initialize() with EncodingLookupArray parameter. */
class Base32Encoder : public SimpleProxyFilter
{
public:
Base32Encoder(BufferedTransformation *attachment = NULL, bool uppercase = true, int outputGroupSize = 0, const std::string &separator = ":", const std::string &terminator = "")
: SimpleProxyFilter(new BaseN_Encoder(new Grouper), attachment)
{
IsolatedInitialize(MakeParameters(Name::Uppercase(), uppercase)(Name::GroupSize(), outputGroupSize)(Name::Separator(), ConstByteArrayParameter(separator)));
}
void IsolatedInitialize(const NameValuePairs &parameters);
};
//! Decode base 32 data back to bytes, the default code is based on draft-ietf-idn-dude-02.txt
/*! To specify alternative code, call Initialize() with DecodingLookupArray parameter. */
class Base32Decoder : public BaseN_Decoder
{
public:
Base32Decoder(BufferedTransformation *attachment = NULL)
: BaseN_Decoder(GetDefaultDecodingLookupArray(), 5, attachment) {}
void IsolatedInitialize(const NameValuePairs &parameters);
private:
static const int * CRYPTOPP_API GetDefaultDecodingLookupArray();
};
NAMESPACE_END
#endif

View File

@ -1,42 +0,0 @@
// base64.cpp - written and placed in the public domain by Wei Dai
#include "pch.h"
#include "base64.h"
NAMESPACE_BEGIN(CryptoPP)
static const byte s_vec[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const byte s_padding = '=';
void Base64Encoder::IsolatedInitialize(const NameValuePairs &parameters)
{
bool insertLineBreaks = parameters.GetValueWithDefault(Name::InsertLineBreaks(), true);
int maxLineLength = parameters.GetIntValueWithDefault(Name::MaxLineLength(), 72);
const char *lineBreak = insertLineBreaks ? "\n" : "";
m_filter->Initialize(CombinedNameValuePairs(
parameters,
MakeParameters(Name::EncodingLookupArray(), &s_vec[0], false)
(Name::PaddingByte(), s_padding)
(Name::GroupSize(), insertLineBreaks ? maxLineLength : 0)
(Name::Separator(), ConstByteArrayParameter(lineBreak))
(Name::Terminator(), ConstByteArrayParameter(lineBreak))
(Name::Log2Base(), 6, true)));
}
const int *Base64Decoder::GetDecodingLookupArray()
{
static volatile bool s_initialized = false;
static int s_array[256];
if (!s_initialized)
{
InitializeDecodingLookupArray(s_array, s_vec, 64, false);
s_initialized = true;
}
return s_array;
}
NAMESPACE_END

View File

@ -1,36 +0,0 @@
#ifndef CRYPTOPP_BASE64_H
#define CRYPTOPP_BASE64_H
#include "basecode.h"
NAMESPACE_BEGIN(CryptoPP)
//! Base64 Encoder Class
class Base64Encoder : public SimpleProxyFilter
{
public:
Base64Encoder(BufferedTransformation *attachment = NULL, bool insertLineBreaks = true, int maxLineLength = 72)
: SimpleProxyFilter(new BaseN_Encoder(new Grouper), attachment)
{
IsolatedInitialize(MakeParameters(Name::InsertLineBreaks(), insertLineBreaks)(Name::MaxLineLength(), maxLineLength));
}
void IsolatedInitialize(const NameValuePairs &parameters);
};
//! Base64 Decoder Class
class Base64Decoder : public BaseN_Decoder
{
public:
Base64Decoder(BufferedTransformation *attachment = NULL)
: BaseN_Decoder(GetDecodingLookupArray(), 6, attachment) {}
void IsolatedInitialize(const NameValuePairs &parameters) {}
private:
static const int * CRYPTOPP_API GetDecodingLookupArray();
};
NAMESPACE_END
#endif

View File

@ -1,238 +0,0 @@
// basecode.cpp - written and placed in the public domain by Wei Dai
#include "pch.h"
#ifndef CRYPTOPP_IMPORTS
#include "basecode.h"
#include "fltrimpl.h"
#include <ctype.h>
NAMESPACE_BEGIN(CryptoPP)
void BaseN_Encoder::IsolatedInitialize(const NameValuePairs &parameters)
{
parameters.GetRequiredParameter("BaseN_Encoder", Name::EncodingLookupArray(), m_alphabet);
parameters.GetRequiredIntParameter("BaseN_Encoder", Name::Log2Base(), m_bitsPerChar);
if (m_bitsPerChar <= 0 || m_bitsPerChar >= 8)
throw InvalidArgument("BaseN_Encoder: Log2Base must be between 1 and 7 inclusive");
byte padding;
bool pad;
if (parameters.GetValue(Name::PaddingByte(), padding))
pad = parameters.GetValueWithDefault(Name::Pad(), true);
else
pad = false;
m_padding = pad ? padding : -1;
m_bytePos = m_bitPos = 0;
int i = 8;
while (i%m_bitsPerChar != 0)
i += 8;
m_outputBlockSize = i/m_bitsPerChar;
m_outBuf.New(m_outputBlockSize);
}
size_t BaseN_Encoder::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
{
FILTER_BEGIN;
while (m_inputPosition < length)
{
if (m_bytePos == 0)
memset(m_outBuf, 0, m_outputBlockSize);
{
unsigned int b = begin[m_inputPosition++], bitsLeftInSource = 8;
while (true)
{
assert(m_bitPos < m_bitsPerChar);
unsigned int bitsLeftInTarget = m_bitsPerChar-m_bitPos;
m_outBuf[m_bytePos] |= b >> (8-bitsLeftInTarget);
if (bitsLeftInSource >= bitsLeftInTarget)
{
m_bitPos = 0;
++m_bytePos;
bitsLeftInSource -= bitsLeftInTarget;
if (bitsLeftInSource == 0)
break;
b <<= bitsLeftInTarget;
b &= 0xff;
}
else
{
m_bitPos += bitsLeftInSource;
break;
}
}
}
assert(m_bytePos <= m_outputBlockSize);
if (m_bytePos == m_outputBlockSize)
{
int i;
for (i=0; i<m_bytePos; i++)
{
assert(m_outBuf[i] < (1 << m_bitsPerChar));
m_outBuf[i] = m_alphabet[m_outBuf[i]];
}
FILTER_OUTPUT(1, m_outBuf, m_outputBlockSize, 0);
m_bytePos = m_bitPos = 0;
}
}
if (messageEnd)
{
if (m_bitPos > 0)
++m_bytePos;
int i;
for (i=0; i<m_bytePos; i++)
m_outBuf[i] = m_alphabet[m_outBuf[i]];
if (m_padding != -1 && m_bytePos > 0)
{
memset(m_outBuf+m_bytePos, m_padding, m_outputBlockSize-m_bytePos);
m_bytePos = m_outputBlockSize;
}
FILTER_OUTPUT(2, m_outBuf, m_bytePos, messageEnd);
m_bytePos = m_bitPos = 0;
}
FILTER_END_NO_MESSAGE_END;
}
void BaseN_Decoder::IsolatedInitialize(const NameValuePairs &parameters)
{
parameters.GetRequiredParameter("BaseN_Decoder", Name::DecodingLookupArray(), m_lookup);
parameters.GetRequiredIntParameter("BaseN_Decoder", Name::Log2Base(), m_bitsPerChar);
if (m_bitsPerChar <= 0 || m_bitsPerChar >= 8)
throw InvalidArgument("BaseN_Decoder: Log2Base must be between 1 and 7 inclusive");
m_bytePos = m_bitPos = 0;
int i = m_bitsPerChar;
while (i%8 != 0)
i += m_bitsPerChar;
m_outputBlockSize = i/8;
m_outBuf.New(m_outputBlockSize);
}
size_t BaseN_Decoder::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
{
FILTER_BEGIN;
while (m_inputPosition < length)
{
unsigned int value;
value = m_lookup[begin[m_inputPosition++]];
if (value >= 256)
continue;
if (m_bytePos == 0 && m_bitPos == 0)
memset(m_outBuf, 0, m_outputBlockSize);
{
int newBitPos = m_bitPos + m_bitsPerChar;
if (newBitPos <= 8)
m_outBuf[m_bytePos] |= value << (8-newBitPos);
else
{
m_outBuf[m_bytePos] |= value >> (newBitPos-8);
m_outBuf[m_bytePos+1] |= value << (16-newBitPos);
}
m_bitPos = newBitPos;
while (m_bitPos >= 8)
{
m_bitPos -= 8;
++m_bytePos;
}
}
if (m_bytePos == m_outputBlockSize)
{
FILTER_OUTPUT(1, m_outBuf, m_outputBlockSize, 0);
m_bytePos = m_bitPos = 0;
}
}
if (messageEnd)
{
FILTER_OUTPUT(2, m_outBuf, m_bytePos, messageEnd);
m_bytePos = m_bitPos = 0;
}
FILTER_END_NO_MESSAGE_END;
}
void BaseN_Decoder::InitializeDecodingLookupArray(int *lookup, const byte *alphabet, unsigned int base, bool caseInsensitive)
{
std::fill(lookup, lookup+256, -1);
for (unsigned int i=0; i<base; i++)
{
if (caseInsensitive && isalpha(alphabet[i]))
{
assert(lookup[toupper(alphabet[i])] == -1);
lookup[toupper(alphabet[i])] = i;
assert(lookup[tolower(alphabet[i])] == -1);
lookup[tolower(alphabet[i])] = i;
}
else
{
assert(lookup[alphabet[i]] == -1);
lookup[alphabet[i]] = i;
}
}
}
void Grouper::IsolatedInitialize(const NameValuePairs &parameters)
{
m_groupSize = parameters.GetIntValueWithDefault(Name::GroupSize(), 0);
ConstByteArrayParameter separator, terminator;
if (m_groupSize)
parameters.GetRequiredParameter("Grouper", Name::Separator(), separator);
else
parameters.GetValue(Name::Separator(), separator);
parameters.GetValue(Name::Terminator(), terminator);
m_separator.Assign(separator.begin(), separator.size());
m_terminator.Assign(terminator.begin(), terminator.size());
m_counter = 0;
}
size_t Grouper::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
{
FILTER_BEGIN;
if (m_groupSize)
{
while (m_inputPosition < length)
{
if (m_counter == m_groupSize)
{
FILTER_OUTPUT(1, m_separator, m_separator.size(), 0);
m_counter = 0;
}
size_t len;
FILTER_OUTPUT2(2, len = STDMIN(length-m_inputPosition, m_groupSize-m_counter),
begin+m_inputPosition, len, 0);
m_inputPosition += len;
m_counter += len;
}
}
else
FILTER_OUTPUT(3, begin, length, 0);
if (messageEnd)
{
FILTER_OUTPUT(4, m_terminator, m_terminator.size(), messageEnd);
m_counter = 0;
}
FILTER_END_NO_MESSAGE_END
}
NAMESPACE_END
#endif

View File

@ -1,86 +0,0 @@
#ifndef CRYPTOPP_BASECODE_H
#define CRYPTOPP_BASECODE_H
#include "filters.h"
#include "algparam.h"
#include "argnames.h"
NAMESPACE_BEGIN(CryptoPP)
//! base n encoder, where n is a power of 2
class CRYPTOPP_DLL BaseN_Encoder : public Unflushable<Filter>
{
public:
BaseN_Encoder(BufferedTransformation *attachment=NULL)
{Detach(attachment);}
BaseN_Encoder(const byte *alphabet, int log2base, BufferedTransformation *attachment=NULL, int padding=-1)
{
Detach(attachment);
IsolatedInitialize(MakeParameters(Name::EncodingLookupArray(), alphabet)
(Name::Log2Base(), log2base)
(Name::Pad(), padding != -1)
(Name::PaddingByte(), byte(padding)));
}
void IsolatedInitialize(const NameValuePairs &parameters);
size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
private:
const byte *m_alphabet;
int m_padding, m_bitsPerChar, m_outputBlockSize;
int m_bytePos, m_bitPos;
SecByteBlock m_outBuf;
};
//! base n decoder, where n is a power of 2
class CRYPTOPP_DLL BaseN_Decoder : public Unflushable<Filter>
{
public:
BaseN_Decoder(BufferedTransformation *attachment=NULL)
{Detach(attachment);}
BaseN_Decoder(const int *lookup, int log2base, BufferedTransformation *attachment=NULL)
{
Detach(attachment);
IsolatedInitialize(MakeParameters(Name::DecodingLookupArray(), lookup)(Name::Log2Base(), log2base));
}
void IsolatedInitialize(const NameValuePairs &parameters);
size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
static void CRYPTOPP_API InitializeDecodingLookupArray(int *lookup, const byte *alphabet, unsigned int base, bool caseInsensitive);
private:
const int *m_lookup;
int m_padding, m_bitsPerChar, m_outputBlockSize;
int m_bytePos, m_bitPos;
SecByteBlock m_outBuf;
};
//! filter that breaks input stream into groups of fixed size
class CRYPTOPP_DLL Grouper : public Bufferless<Filter>
{
public:
Grouper(BufferedTransformation *attachment=NULL)
{Detach(attachment);}
Grouper(int groupSize, const std::string &separator, const std::string &terminator, BufferedTransformation *attachment=NULL)
{
Detach(attachment);
IsolatedInitialize(MakeParameters(Name::GroupSize(), groupSize)
(Name::Separator(), ConstByteArrayParameter(separator))
(Name::Terminator(), ConstByteArrayParameter(terminator)));
}
void IsolatedInitialize(const NameValuePairs &parameters);
size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
private:
SecByteBlock m_separator, m_terminator;
size_t m_groupSize, m_counter;
};
NAMESPACE_END
#endif

View File

@ -1,62 +0,0 @@
#include "pch.h"
#ifndef CRYPTOPP_IMPORTS
#include "cbcmac.h"
NAMESPACE_BEGIN(CryptoPP)
void CBC_MAC_Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
{
AccessCipher().SetKey(key, length, params);
m_reg.CleanNew(AccessCipher().BlockSize());
m_counter = 0;
}
void CBC_MAC_Base::Update(const byte *input, size_t length)
{
unsigned int blockSize = AccessCipher().BlockSize();
while (m_counter && length)
{
m_reg[m_counter++] ^= *input++;
if (m_counter == blockSize)
ProcessBuf();
length--;
}
if (length >= blockSize)
{
size_t leftOver = AccessCipher().AdvancedProcessBlocks(m_reg, input, m_reg, length, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
input += (length - leftOver);
length = leftOver;
}
while (length--)
{
m_reg[m_counter++] ^= *input++;
if (m_counter == blockSize)
ProcessBuf();
}
}
void CBC_MAC_Base::TruncatedFinal(byte *mac, size_t size)
{
ThrowIfInvalidTruncatedSize(size);
if (m_counter)
ProcessBuf();
memcpy(mac, m_reg, size);
memset(m_reg, 0, AccessCipher().BlockSize());
}
void CBC_MAC_Base::ProcessBuf()
{
AccessCipher().ProcessBlock(m_reg);
m_counter = 0;
}
NAMESPACE_END
#endif

View File

@ -1,50 +0,0 @@
#ifndef CRYPTOPP_CBCMAC_H
#define CRYPTOPP_CBCMAC_H
#include "seckey.h"
#include "secblock.h"
NAMESPACE_BEGIN(CryptoPP)
//! _
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_MAC_Base : public MessageAuthenticationCode
{
public:
CBC_MAC_Base() {}
void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
void Update(const byte *input, size_t length);
void TruncatedFinal(byte *mac, size_t size);
unsigned int DigestSize() const {return const_cast<CBC_MAC_Base*>(this)->AccessCipher().BlockSize();}
protected:
virtual BlockCipher & AccessCipher() =0;
private:
void ProcessBuf();
SecByteBlock m_reg;
unsigned int m_counter;
};
//! <a href="http://www.weidai.com/scan-mirror/mac.html#CBC-MAC">CBC-MAC</a>
/*! Compatible with FIPS 113. T should be a class derived from BlockCipherDocumentation.
Secure only for fixed length messages. For variable length messages use CMAC or DMAC.
*/
template <class T>
class CBC_MAC : public MessageAuthenticationCodeImpl<CBC_MAC_Base, CBC_MAC<T> >, public SameKeyLengthAs<T>
{
public:
CBC_MAC() {}
CBC_MAC(const byte *key, size_t length=SameKeyLengthAs<T>::DEFAULT_KEYLENGTH)
{this->SetKey(key, length);}
static std::string StaticAlgorithmName() {return std::string("CBC-MAC(") + T::StaticAlgorithmName() + ")";}
private:
BlockCipher & AccessCipher() {return m_cipher;}
typename T::Encryption m_cipher;
};
NAMESPACE_END
#endif

View File

@ -1,140 +0,0 @@
// ccm.cpp - written and placed in the public domain by Wei Dai
#include "pch.h"
#ifndef CRYPTOPP_IMPORTS
#include "ccm.h"
NAMESPACE_BEGIN(CryptoPP)
void CCM_Base::SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params)
{
BlockCipher &blockCipher = AccessBlockCipher();
blockCipher.SetKey(userKey, keylength, params);
if (blockCipher.BlockSize() != REQUIRED_BLOCKSIZE)
throw InvalidArgument(AlgorithmName() + ": block size of underlying block cipher is not 16");
m_digestSize = params.GetIntValueWithDefault(Name::DigestSize(), DefaultDigestSize());
if (m_digestSize % 2 > 0 || m_digestSize < 4 || m_digestSize > 16)
throw InvalidArgument(AlgorithmName() + ": DigestSize must be 4, 6, 8, 10, 12, 14, or 16");
m_buffer.Grow(2*REQUIRED_BLOCKSIZE);
m_L = 8;
}
void CCM_Base::Resync(const byte *iv, size_t len)
{
BlockCipher &cipher = AccessBlockCipher();
m_L = REQUIRED_BLOCKSIZE-1-(int)len;
assert(m_L >= 2);
if (m_L > 8)
m_L = 8;
m_buffer[0] = byte(m_L-1); // flag
memcpy(m_buffer+1, iv, len);
memset(m_buffer+1+len, 0, REQUIRED_BLOCKSIZE-1-len);
if (m_state >= State_IVSet)
m_ctr.Resynchronize(m_buffer, REQUIRED_BLOCKSIZE);
else
m_ctr.SetCipherWithIV(cipher, m_buffer);
m_ctr.Seek(REQUIRED_BLOCKSIZE);
m_aadLength = 0;
m_messageLength = 0;
}
void CCM_Base::UncheckedSpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength)
{
if (m_state != State_IVSet)
throw BadState(AlgorithmName(), "SpecifyDataLengths", "or after State_IVSet");
m_aadLength = headerLength;
m_messageLength = messageLength;
byte *cbcBuffer = CBC_Buffer();
const BlockCipher &cipher = GetBlockCipher();
cbcBuffer[0] = byte(64*(headerLength>0) + 8*((m_digestSize-2)/2) + (m_L-1)); // flag
PutWord<word64>(true, BIG_ENDIAN_ORDER, cbcBuffer+REQUIRED_BLOCKSIZE-8, m_messageLength);
memcpy(cbcBuffer+1, m_buffer+1, REQUIRED_BLOCKSIZE-1-m_L);
cipher.ProcessBlock(cbcBuffer);
if (headerLength>0)
{
assert(m_bufferedDataLength == 0);
if (headerLength < ((1<<16) - (1<<8)))
{
PutWord<word16>(true, BIG_ENDIAN_ORDER, m_buffer, (word16)headerLength);
m_bufferedDataLength = 2;
}
else if (headerLength < (W64LIT(1)<<32))
{
m_buffer[0] = 0xff;
m_buffer[1] = 0xfe;
PutWord<word32>(false, BIG_ENDIAN_ORDER, m_buffer+2, (word32)headerLength);
m_bufferedDataLength = 6;
}
else
{
m_buffer[0] = 0xff;
m_buffer[1] = 0xff;
PutWord<word64>(false, BIG_ENDIAN_ORDER, m_buffer+2, headerLength);
m_bufferedDataLength = 10;
}
}
}
size_t CCM_Base::AuthenticateBlocks(const byte *data, size_t len)
{
byte *cbcBuffer = CBC_Buffer();
const BlockCipher &cipher = GetBlockCipher();
return cipher.AdvancedProcessBlocks(cbcBuffer, data, cbcBuffer, len, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
}
void CCM_Base::AuthenticateLastHeaderBlock()
{
byte *cbcBuffer = CBC_Buffer();
const BlockCipher &cipher = GetBlockCipher();
if (m_aadLength != m_totalHeaderLength)
throw InvalidArgument(AlgorithmName() + ": header length doesn't match that given in SpecifyDataLengths");
if (m_bufferedDataLength > 0)
{
xorbuf(cbcBuffer, m_buffer, m_bufferedDataLength);
cipher.ProcessBlock(cbcBuffer);
m_bufferedDataLength = 0;
}
}
void CCM_Base::AuthenticateLastConfidentialBlock()
{
byte *cbcBuffer = CBC_Buffer();
const BlockCipher &cipher = GetBlockCipher();
if (m_messageLength != m_totalMessageLength)
throw InvalidArgument(AlgorithmName() + ": message length doesn't match that given in SpecifyDataLengths");
if (m_bufferedDataLength > 0)
{
xorbuf(cbcBuffer, m_buffer, m_bufferedDataLength);
cipher.ProcessBlock(cbcBuffer);
m_bufferedDataLength = 0;
}
}
void CCM_Base::AuthenticateLastFooterBlock(byte *mac, size_t macSize)
{
m_ctr.Seek(0);
m_ctr.ProcessData(mac, CBC_Buffer(), macSize);
}
NAMESPACE_END
#endif

View File

@ -1,101 +0,0 @@
#ifndef CRYPTOPP_CCM_H
#define CRYPTOPP_CCM_H
#include "authenc.h"
#include "modes.h"
NAMESPACE_BEGIN(CryptoPP)
//! .
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CCM_Base : public AuthenticatedSymmetricCipherBase
{
public:
CCM_Base()
: m_digestSize(0), m_L(0) {}
// AuthenticatedSymmetricCipher
std::string AlgorithmName() const
{return GetBlockCipher().AlgorithmName() + std::string("/CCM");}
size_t MinKeyLength() const
{return GetBlockCipher().MinKeyLength();}
size_t MaxKeyLength() const
{return GetBlockCipher().MaxKeyLength();}
size_t DefaultKeyLength() const
{return GetBlockCipher().DefaultKeyLength();}
size_t GetValidKeyLength(size_t n) const
{return GetBlockCipher().GetValidKeyLength(n);}
bool IsValidKeyLength(size_t n) const
{return GetBlockCipher().IsValidKeyLength(n);}
unsigned int OptimalDataAlignment() const
{return GetBlockCipher().OptimalDataAlignment();}
IV_Requirement IVRequirement() const
{return UNIQUE_IV;}
unsigned int IVSize() const
{return 8;}
unsigned int MinIVLength() const
{return 7;}
unsigned int MaxIVLength() const
{return 13;}
unsigned int DigestSize() const
{return m_digestSize;}
lword MaxHeaderLength() const
{return W64LIT(0)-1;}
lword MaxMessageLength() const
{return m_L<8 ? (W64LIT(1)<<(8*m_L))-1 : W64LIT(0)-1;}
bool NeedsPrespecifiedDataLengths() const
{return true;}
void UncheckedSpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength);
protected:
// AuthenticatedSymmetricCipherBase
bool AuthenticationIsOnPlaintext() const
{return true;}
unsigned int AuthenticationBlockSize() const
{return GetBlockCipher().BlockSize();}
void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params);
void Resync(const byte *iv, size_t len);
size_t AuthenticateBlocks(const byte *data, size_t len);
void AuthenticateLastHeaderBlock();
void AuthenticateLastConfidentialBlock();
void AuthenticateLastFooterBlock(byte *mac, size_t macSize);
SymmetricCipher & AccessSymmetricCipher() {return m_ctr;}
virtual BlockCipher & AccessBlockCipher() =0;
virtual int DefaultDigestSize() const =0;
const BlockCipher & GetBlockCipher() const {return const_cast<CCM_Base *>(this)->AccessBlockCipher();};
byte *CBC_Buffer() {return m_buffer+REQUIRED_BLOCKSIZE;}
enum {REQUIRED_BLOCKSIZE = 16};
int m_digestSize, m_L;
word64 m_messageLength, m_aadLength;
CTR_Mode_ExternalCipher::Encryption m_ctr;
};
//! .
template <class T_BlockCipher, int T_DefaultDigestSize, bool T_IsEncryption>
class CCM_Final : public CCM_Base
{
public:
static std::string StaticAlgorithmName()
{return T_BlockCipher::StaticAlgorithmName() + std::string("/CCM");}
bool IsForwardTransformation() const
{return T_IsEncryption;}
private:
BlockCipher & AccessBlockCipher() {return m_cipher;}
int DefaultDigestSize() const {return T_DefaultDigestSize;}
typename T_BlockCipher::Encryption m_cipher;
};
/// <a href="http://www.cryptolounge.org/wiki/CCM">CCM</a>
template <class T_BlockCipher, int T_DefaultDigestSize = 16>
struct CCM : public AuthenticatedSymmetricCipherDocumentation
{
typedef CCM_Final<T_BlockCipher, T_DefaultDigestSize, true> Encryption;
typedef CCM_Final<T_BlockCipher, T_DefaultDigestSize, false> Decryption;
};
NAMESPACE_END
#endif

View File

@ -1,309 +0,0 @@
// channels.cpp - written and placed in the public domain by Wei Dai
#include "pch.h"
#ifndef CRYPTOPP_IMPORTS
#include "channels.h"
NAMESPACE_BEGIN(CryptoPP)
USING_NAMESPACE(std)
#if 0
void MessageSwitch::AddDefaultRoute(BufferedTransformation &destination, const std::string &channel)
{
m_defaultRoutes.push_back(Route(&destination, channel));
}
void MessageSwitch::AddRoute(unsigned int begin, unsigned int end, BufferedTransformation &destination, const std::string &channel)
{
RangeRoute route(begin, end, Route(&destination, channel));
RouteList::iterator it = upper_bound(m_routes.begin(), m_routes.end(), route);
m_routes.insert(it, route);
}
/*
class MessageRouteIterator
{
public:
typedef MessageSwitch::RouteList::const_iterator RouteIterator;
typedef MessageSwitch::DefaultRouteList::const_iterator DefaultIterator;
bool m_useDefault;
RouteIterator m_itRouteCurrent, m_itRouteEnd;
DefaultIterator m_itDefaultCurrent, m_itDefaultEnd;
MessageRouteIterator(MessageSwitch &ms, const std::string &channel)
: m_channel(channel)
{
pair<MapIterator, MapIterator> range = cs.m_routeMap.equal_range(channel);
if (range.first == range.second)
{
m_useDefault = true;
m_itListCurrent = cs.m_defaultRoutes.begin();
m_itListEnd = cs.m_defaultRoutes.end();
}
else
{
m_useDefault = false;
m_itMapCurrent = range.first;
m_itMapEnd = range.second;
}
}
bool End() const
{
return m_useDefault ? m_itListCurrent == m_itListEnd : m_itMapCurrent == m_itMapEnd;
}
void Next()
{
if (m_useDefault)
++m_itListCurrent;
else
++m_itMapCurrent;
}
BufferedTransformation & Destination()
{
return m_useDefault ? *m_itListCurrent->first : *m_itMapCurrent->second.first;
}
const std::string & Message()
{
if (m_useDefault)
return m_itListCurrent->second.get() ? *m_itListCurrent->second.get() : m_channel;
else
return m_itMapCurrent->second.second;
}
};
void MessageSwitch::Put(byte inByte);
void MessageSwitch::Put(const byte *inString, unsigned int length);
void MessageSwitch::Flush(bool completeFlush, int propagation=-1);
void MessageSwitch::MessageEnd(int propagation=-1);
void MessageSwitch::PutMessageEnd(const byte *inString, unsigned int length, int propagation=-1);
void MessageSwitch::MessageSeriesEnd(int propagation=-1);
*/
#endif
//
// ChannelRouteIterator
//////////////////////////
void ChannelRouteIterator::Reset(const std::string &channel)
{
m_channel = channel;
pair<MapIterator, MapIterator> range = m_cs.m_routeMap.equal_range(channel);
if (range.first == range.second)
{
m_useDefault = true;
m_itListCurrent = m_cs.m_defaultRoutes.begin();
m_itListEnd = m_cs.m_defaultRoutes.end();
}
else
{
m_useDefault = false;
m_itMapCurrent = range.first;
m_itMapEnd = range.second;
}
}
bool ChannelRouteIterator::End() const
{
return m_useDefault ? m_itListCurrent == m_itListEnd : m_itMapCurrent == m_itMapEnd;
}
void ChannelRouteIterator::Next()
{
if (m_useDefault)
++m_itListCurrent;
else
++m_itMapCurrent;
}
BufferedTransformation & ChannelRouteIterator::Destination()
{
return m_useDefault ? *m_itListCurrent->first : *m_itMapCurrent->second.first;
}
const std::string & ChannelRouteIterator::Channel()
{
if (m_useDefault)
return m_itListCurrent->second.get() ? *m_itListCurrent->second.get() : m_channel;
else
return m_itMapCurrent->second.second;
}
//
// ChannelSwitch
///////////////////
size_t ChannelSwitch::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
{
if (m_blocked)
{
m_blocked = false;
goto WasBlocked;
}
m_it.Reset(channel);
while (!m_it.End())
{
WasBlocked:
if (m_it.Destination().ChannelPut2(m_it.Channel(), begin, length, messageEnd, blocking))
{
m_blocked = true;
return 1;
}
m_it.Next();
}
return 0;
}
void ChannelSwitch::IsolatedInitialize(const NameValuePairs &parameters/* =g_nullNameValuePairs */)
{
m_routeMap.clear();
m_defaultRoutes.clear();
m_blocked = false;
}
bool ChannelSwitch::ChannelFlush(const std::string &channel, bool completeFlush, int propagation, bool blocking)
{
if (m_blocked)
{
m_blocked = false;
goto WasBlocked;
}
m_it.Reset(channel);
while (!m_it.End())
{
WasBlocked:
if (m_it.Destination().ChannelFlush(m_it.Channel(), completeFlush, propagation, blocking))
{
m_blocked = true;
return true;
}
m_it.Next();
}
return false;
}
bool ChannelSwitch::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking)
{
if (m_blocked)
{
m_blocked = false;
goto WasBlocked;
}
m_it.Reset(channel);
while (!m_it.End())
{
WasBlocked:
if (m_it.Destination().ChannelMessageSeriesEnd(m_it.Channel(), propagation))
{
m_blocked = true;
return true;
}
m_it.Next();
}
return false;
}
byte * ChannelSwitch::ChannelCreatePutSpace(const std::string &channel, size_t &size)
{
m_it.Reset(channel);
if (!m_it.End())
{
BufferedTransformation &target = m_it.Destination();
const std::string &channel = m_it.Channel();
m_it.Next();
if (m_it.End()) // there is only one target channel
return target.ChannelCreatePutSpace(channel, size);
}
size = 0;
return NULL;
}
size_t ChannelSwitch::ChannelPutModifiable2(const std::string &channel, byte *inString, size_t length, int messageEnd, bool blocking)
{
ChannelRouteIterator it(*this);
it.Reset(channel);
if (!it.End())
{
BufferedTransformation &target = it.Destination();
const std::string &targetChannel = it.Channel();
it.Next();
if (it.End()) // there is only one target channel
return target.ChannelPutModifiable2(targetChannel, inString, length, messageEnd, blocking);
}
return ChannelPut2(channel, inString, length, messageEnd, blocking);
}
void ChannelSwitch::AddDefaultRoute(BufferedTransformation &destination)
{
m_defaultRoutes.push_back(DefaultRoute(&destination, value_ptr<std::string>(NULL)));
}
void ChannelSwitch::RemoveDefaultRoute(BufferedTransformation &destination)
{
for (DefaultRouteList::iterator it = m_defaultRoutes.begin(); it != m_defaultRoutes.end(); ++it)
if (it->first == &destination && !it->second.get())
{
m_defaultRoutes.erase(it);
break;
}
}
void ChannelSwitch::AddDefaultRoute(BufferedTransformation &destination, const std::string &outChannel)
{
m_defaultRoutes.push_back(DefaultRoute(&destination, outChannel));
}
void ChannelSwitch::RemoveDefaultRoute(BufferedTransformation &destination, const std::string &outChannel)
{
for (DefaultRouteList::iterator it = m_defaultRoutes.begin(); it != m_defaultRoutes.end(); ++it)
if (it->first == &destination && (it->second.get() && *it->second == outChannel))
{
m_defaultRoutes.erase(it);
break;
}
}
void ChannelSwitch::AddRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel)
{
m_routeMap.insert(RouteMap::value_type(inChannel, Route(&destination, outChannel)));
}
void ChannelSwitch::RemoveRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel)
{
typedef ChannelSwitch::RouteMap::iterator MapIterator;
pair<MapIterator, MapIterator> range = m_routeMap.equal_range(inChannel);
for (MapIterator it = range.first; it != range.second; ++it)
if (it->second.first == &destination && it->second.second == outChannel)
{
m_routeMap.erase(it);
break;
}
}
NAMESPACE_END
#endif

View File

@ -1,123 +0,0 @@
#ifndef CRYPTOPP_CHANNELS_H
#define CRYPTOPP_CHANNELS_H
#include "simple.h"
#include "smartptr.h"
#include <map>
#include <list>
NAMESPACE_BEGIN(CryptoPP)
#if 0
//! Route input on default channel to different and/or multiple channels based on message sequence number
class MessageSwitch : public Sink
{
public:
void AddDefaultRoute(BufferedTransformation &destination, const std::string &channel);
void AddRoute(unsigned int begin, unsigned int end, BufferedTransformation &destination, const std::string &channel);
void Put(byte inByte);
void Put(const byte *inString, unsigned int length);
void Flush(bool completeFlush, int propagation=-1);
void MessageEnd(int propagation=-1);
void PutMessageEnd(const byte *inString, unsigned int length, int propagation=-1);
void MessageSeriesEnd(int propagation=-1);
private:
typedef std::pair<BufferedTransformation *, std::string> Route;
struct RangeRoute
{
RangeRoute(unsigned int begin, unsigned int end, const Route &route)
: begin(begin), end(end), route(route) {}
bool operator<(const RangeRoute &rhs) const {return begin < rhs.begin;}
unsigned int begin, end;
Route route;
};
typedef std::list<RangeRoute> RouteList;
typedef std::list<Route> DefaultRouteList;
RouteList m_routes;
DefaultRouteList m_defaultRoutes;
unsigned int m_nCurrentMessage;
};
#endif
class ChannelSwitchTypedefs
{
public:
typedef std::pair<BufferedTransformation *, std::string> Route;
typedef std::multimap<std::string, Route> RouteMap;
typedef std::pair<BufferedTransformation *, value_ptr<std::string> > DefaultRoute;
typedef std::list<DefaultRoute> DefaultRouteList;
// SunCC workaround: can't use const_iterator here
typedef RouteMap::iterator MapIterator;
typedef DefaultRouteList::iterator ListIterator;
};
class ChannelSwitch;
class ChannelRouteIterator : public ChannelSwitchTypedefs
{
public:
ChannelSwitch& m_cs;
std::string m_channel;
bool m_useDefault;
MapIterator m_itMapCurrent, m_itMapEnd;
ListIterator m_itListCurrent, m_itListEnd;
ChannelRouteIterator(ChannelSwitch &cs) : m_cs(cs) {}
void Reset(const std::string &channel);
bool End() const;
void Next();
BufferedTransformation & Destination();
const std::string & Channel();
};
//! Route input to different and/or multiple channels based on channel ID
class CRYPTOPP_DLL ChannelSwitch : public Multichannel<Sink>, public ChannelSwitchTypedefs
{
public:
ChannelSwitch() : m_it(*this), m_blocked(false) {}
ChannelSwitch(BufferedTransformation &destination) : m_it(*this), m_blocked(false)
{
AddDefaultRoute(destination);
}
ChannelSwitch(BufferedTransformation &destination, const std::string &outChannel) : m_it(*this), m_blocked(false)
{
AddDefaultRoute(destination, outChannel);
}
void IsolatedInitialize(const NameValuePairs &parameters=g_nullNameValuePairs);
size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking);
size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking);
bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true);
bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true);
byte * ChannelCreatePutSpace(const std::string &channel, size_t &size);
void AddDefaultRoute(BufferedTransformation &destination);
void RemoveDefaultRoute(BufferedTransformation &destination);
void AddDefaultRoute(BufferedTransformation &destination, const std::string &outChannel);
void RemoveDefaultRoute(BufferedTransformation &destination, const std::string &outChannel);
void AddRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel);
void RemoveRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel);
private:
RouteMap m_routeMap;
DefaultRouteList m_defaultRoutes;
ChannelRouteIterator m_it;
bool m_blocked;
friend class ChannelRouteIterator;
};
NAMESPACE_END
#endif

View File

@ -1,122 +0,0 @@
// cmac.cpp - written and placed in the public domain by Wei Dai
#include "pch.h"
#ifndef CRYPTOPP_IMPORTS
#include "cmac.h"
NAMESPACE_BEGIN(CryptoPP)
static void MulU(byte *k, unsigned int length)
{
byte carry = 0;
for (int i=length-1; i>=1; i-=2)
{
byte carry2 = k[i] >> 7;
k[i] += k[i] + carry;
carry = k[i-1] >> 7;
k[i-1] += k[i-1] + carry2;
}
if (carry)
{
switch (length)
{
case 8:
k[7] ^= 0x1b;
break;
case 16:
k[15] ^= 0x87;
break;
case 32:
k[30] ^= 4;
k[31] ^= 0x23;
break;
default:
throw InvalidArgument("CMAC: " + IntToString(length) + " is not a supported cipher block size");
}
}
}
void CMAC_Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
{
BlockCipher &cipher = AccessCipher();
unsigned int blockSize = cipher.BlockSize();
cipher.SetKey(key, length, params);
m_reg.CleanNew(3*blockSize);
m_counter = 0;
cipher.ProcessBlock(m_reg, m_reg+blockSize);
MulU(m_reg+blockSize, blockSize);
memcpy(m_reg+2*blockSize, m_reg+blockSize, blockSize);
MulU(m_reg+2*blockSize, blockSize);
}
void CMAC_Base::Update(const byte *input, size_t length)
{
if (!length)
return;
BlockCipher &cipher = AccessCipher();
unsigned int blockSize = cipher.BlockSize();
if (m_counter > 0)
{
unsigned int len = UnsignedMin(blockSize - m_counter, length);
xorbuf(m_reg+m_counter, input, len);
length -= len;
input += len;
m_counter += len;
if (m_counter == blockSize && length > 0)
{
cipher.ProcessBlock(m_reg);
m_counter = 0;
}
}
if (length > blockSize)
{
assert(m_counter == 0);
size_t leftOver = 1 + cipher.AdvancedProcessBlocks(m_reg, input, m_reg, length-1, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
input += (length - leftOver);
length = leftOver;
}
if (length > 0)
{
assert(m_counter + length <= blockSize);
xorbuf(m_reg+m_counter, input, length);
m_counter += (unsigned int)length;
}
assert(m_counter > 0);
}
void CMAC_Base::TruncatedFinal(byte *mac, size_t size)
{
ThrowIfInvalidTruncatedSize(size);
BlockCipher &cipher = AccessCipher();
unsigned int blockSize = cipher.BlockSize();
if (m_counter < blockSize)
{
m_reg[m_counter] ^= 0x80;
cipher.AdvancedProcessBlocks(m_reg, m_reg+2*blockSize, m_reg, blockSize, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
}
else
cipher.AdvancedProcessBlocks(m_reg, m_reg+blockSize, m_reg, blockSize, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
memcpy(mac, m_reg, size);
m_counter = 0;
memset(m_reg, 0, blockSize);
}
NAMESPACE_END
#endif

View File

@ -1,52 +0,0 @@
#ifndef CRYPTOPP_CMAC_H
#define CRYPTOPP_CMAC_H
#include "seckey.h"
#include "secblock.h"
NAMESPACE_BEGIN(CryptoPP)
//! _
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CMAC_Base : public MessageAuthenticationCode
{
public:
CMAC_Base() {}
void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
void Update(const byte *input, size_t length);
void TruncatedFinal(byte *mac, size_t size);
unsigned int DigestSize() const {return GetCipher().BlockSize();}
unsigned int OptimalBlockSize() const {return GetCipher().BlockSize();}
unsigned int OptimalDataAlignment() const {return GetCipher().OptimalDataAlignment();}
protected:
friend class EAX_Base;
const BlockCipher & GetCipher() const {return const_cast<CMAC_Base*>(this)->AccessCipher();}
virtual BlockCipher & AccessCipher() =0;
void ProcessBuf();
SecByteBlock m_reg;
unsigned int m_counter;
};
/// <a href="http://www.cryptolounge.org/wiki/CMAC">CMAC</a>
/*! Template parameter T should be a class derived from BlockCipherDocumentation, for example AES, with a block size of 8, 16, or 32 */
template <class T>
class CMAC : public MessageAuthenticationCodeImpl<CMAC_Base, CMAC<T> >, public SameKeyLengthAs<T>
{
public:
CMAC() {}
CMAC(const byte *key, size_t length=SameKeyLengthAs<T>::DEFAULT_KEYLENGTH)
{this->SetKey(key, length);}
static std::string StaticAlgorithmName() {return std::string("CMAC(") + T::StaticAlgorithmName() + ")";}
private:
BlockCipher & AccessCipher() {return m_cipher;}
typename T::Encryption m_cipher;
};
NAMESPACE_END
#endif

View File

@ -1,462 +0,0 @@
#ifndef CRYPTOPP_CONFIG_H
#define CRYPTOPP_CONFIG_H
// ***************** Important Settings ********************
// define this if running on a big-endian CPU
#if !defined(IS_LITTLE_ENDIAN) && (defined(__BIG_ENDIAN__) || defined(__sparc) || defined(__sparc__) || defined(__hppa__) || defined(__MIPSEB__) || defined(__ARMEB__) || (defined(__MWERKS__) && !defined(__INTEL__)))
# define IS_BIG_ENDIAN
#endif
// define this if running on a little-endian CPU
// big endian will be assumed if IS_LITTLE_ENDIAN is not defined
#ifndef IS_BIG_ENDIAN
# define IS_LITTLE_ENDIAN
#endif
// define this if you want to disable all OS-dependent features,
// such as sockets and OS-provided random number generators
#define NO_OS_DEPENDENCE
// Define this to use features provided by Microsoft's CryptoAPI.
// Currently the only feature used is random number generation.
// This macro will be ignored if NO_OS_DEPENDENCE is defined.
// #define USE_MS_CRYPTOAPI
// Define this to 1 to enforce the requirement in FIPS 186-2 Change Notice 1 that only 1024 bit moduli be used
#ifndef DSA_1024_BIT_MODULUS_ONLY
# define DSA_1024_BIT_MODULUS_ONLY 1
#endif
// ***************** Less Important Settings ***************
// define this to retain (as much as possible) old deprecated function and class names
// #define CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
#define GZIP_OS_CODE 0
// Try this if your CPU has 256K internal cache or a slow multiply instruction
// and you want a (possibly) faster IDEA implementation using log tables
// #define IDEA_LARGECACHE
// Define this if, for the linear congruential RNG, you want to use
// the original constants as specified in S.K. Park and K.W. Miller's
// CACM paper.
// #define LCRNG_ORIGINAL_NUMBERS
// choose which style of sockets to wrap (mostly useful for cygwin which has both)
#define PREFER_BERKELEY_STYLE_SOCKETS
// #define PREFER_WINDOWS_STYLE_SOCKETS
// set the name of Rijndael cipher, was "Rijndael" before version 5.3
#define CRYPTOPP_RIJNDAEL_NAME "AES"
// ***************** Important Settings Again ********************
// But the defaults should be ok.
// namespace support is now required
#ifdef NO_NAMESPACE
# error namespace support is now required
#endif
// Define this to workaround a Microsoft CryptoAPI bug where
// each call to CryptAcquireContext causes a 100 KB memory leak.
// Defining this will cause Crypto++ to make only one call to CryptAcquireContext.
#define WORKAROUND_MS_BUG_Q258000
#ifdef CRYPTOPP_DOXYGEN_PROCESSING
// Avoid putting "CryptoPP::" in front of everything in Doxygen output
# define CryptoPP
# define NAMESPACE_BEGIN(x)
# define NAMESPACE_END
// Get Doxygen to generate better documentation for these typedefs
# define DOCUMENTED_TYPEDEF(x, y) class y : public x {};
#else
# define NAMESPACE_BEGIN(x) namespace x {
# define NAMESPACE_END }
# define DOCUMENTED_TYPEDEF(x, y) typedef x y;
#endif
#define ANONYMOUS_NAMESPACE_BEGIN namespace {
#define USING_NAMESPACE(x) using namespace x;
#define DOCUMENTED_NAMESPACE_BEGIN(x) namespace x {
#define DOCUMENTED_NAMESPACE_END }
// What is the type of the third parameter to bind?
// For Unix, the new standard is ::socklen_t (typically unsigned int), and the old standard is int.
// Unfortunately there is no way to tell whether or not socklen_t is defined.
// To work around this, TYPE_OF_SOCKLEN_T is a macro so that you can change it from the makefile.
#ifndef TYPE_OF_SOCKLEN_T
# if defined(_WIN32) || defined(__CYGWIN__)
# define TYPE_OF_SOCKLEN_T int
# else
# define TYPE_OF_SOCKLEN_T ::socklen_t
# endif
#endif
#if defined(__CYGWIN__) && defined(PREFER_WINDOWS_STYLE_SOCKETS)
# define __USE_W32_SOCKETS
#endif
typedef unsigned char byte; // put in global namespace to avoid ambiguity with other byte typedefs
NAMESPACE_BEGIN(CryptoPP)
typedef unsigned short word16;
typedef unsigned int word32;
#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef unsigned __int64 word64;
#define W64LIT(x) x##ui64
#else
typedef unsigned long long word64;
#define W64LIT(x) x##ULL
#endif
// define large word type, used for file offsets and such
typedef word64 lword;
const lword LWORD_MAX = W64LIT(0xffffffffffffffff);
#ifdef __GNUC__
#define CRYPTOPP_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#endif
// define hword, word, and dword. these are used for multiprecision integer arithmetic
// Intel compiler won't have _umul128 until version 10.0. See http://softwarecommunity.intel.com/isn/Community/en-US/forums/thread/30231625.aspx
#if (defined(_MSC_VER) && (!defined(__INTEL_COMPILER) || __INTEL_COMPILER >= 1000) && (defined(_M_X64) || defined(_M_IA64))) || (defined(__DECCXX) && defined(__alpha__)) || (defined(__INTEL_COMPILER) && defined(__x86_64__)) || (defined(__SUNPRO_CC) && defined(__x86_64__))
typedef word32 hword;
typedef word64 word;
#else
#define CRYPTOPP_NATIVE_DWORD_AVAILABLE
#if defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) || defined(__x86_64__) || defined(__mips64) || defined(__sparc64__)
#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !(CRYPTOPP_GCC_VERSION == 40001 && defined(__APPLE__)) && CRYPTOPP_GCC_VERSION >= 30400
// GCC 4.0.1 on MacOS X is missing __umodti3 and __udivti3
// mode(TI) division broken on amd64 with GCC earlier than GCC 3.4
typedef word32 hword;
typedef word64 word;
typedef __uint128_t dword;
typedef __uint128_t word128;
#define CRYPTOPP_WORD128_AVAILABLE
#else
// if we're here, it means we're on a 64-bit CPU but we don't have a way to obtain 128-bit multiplication results
typedef word16 hword;
typedef word32 word;
typedef word64 dword;
#endif
#else
// being here means the native register size is probably 32 bits or less
#define CRYPTOPP_BOOL_SLOW_WORD64 1
typedef word16 hword;
typedef word32 word;
typedef word64 dword;
#endif
#endif
#ifndef CRYPTOPP_BOOL_SLOW_WORD64
#define CRYPTOPP_BOOL_SLOW_WORD64 0
#endif
const unsigned int WORD_SIZE = sizeof(word);
const unsigned int WORD_BITS = WORD_SIZE * 8;
NAMESPACE_END
#ifndef CRYPTOPP_L1_CACHE_LINE_SIZE
// This should be a lower bound on the L1 cache line size. It's used for defense against timing attacks.
#if defined(_M_X64) || defined(__x86_64__)
#define CRYPTOPP_L1_CACHE_LINE_SIZE 64
#else
// L1 cache line size is 32 on Pentium III and earlier
#define CRYPTOPP_L1_CACHE_LINE_SIZE 32
#endif
#endif
#if defined(_MSC_VER)
#if _MSC_VER == 1200
#include <malloc.h>
#endif
#if _MSC_VER > 1200 || defined(_mm_free)
#define CRYPTOPP_MSVC6PP_OR_LATER // VC 6 processor pack or later
#else
#define CRYPTOPP_MSVC6_NO_PP // VC 6 without processor pack
#endif
#endif
#ifndef CRYPTOPP_ALIGN_DATA
#if defined(CRYPTOPP_MSVC6PP_OR_LATER)
#define CRYPTOPP_ALIGN_DATA(x) __declspec(align(x))
#elif defined(__GNUC__)
#define CRYPTOPP_ALIGN_DATA(x) __attribute__((aligned(x)))
#else
#define CRYPTOPP_ALIGN_DATA(x)
#endif
#endif
#ifndef CRYPTOPP_SECTION_ALIGN16
#if defined(__GNUC__) && !defined(__APPLE__)
// the alignment attribute doesn't seem to work without this section attribute when -fdata-sections is turned on
#define CRYPTOPP_SECTION_ALIGN16 __attribute__((section ("CryptoPP_Align16")))
#else
#define CRYPTOPP_SECTION_ALIGN16
#endif
#endif
#if defined(_MSC_VER) || defined(__fastcall)
#define CRYPTOPP_FASTCALL __fastcall
#else
#define CRYPTOPP_FASTCALL
#endif
// VC60 workaround: it doesn't allow typename in some places
#if defined(_MSC_VER) && (_MSC_VER < 1300)
#define CPP_TYPENAME
#else
#define CPP_TYPENAME typename
#endif
// VC60 workaround: can't cast unsigned __int64 to float or double
#if defined(_MSC_VER) && !defined(CRYPTOPP_MSVC6PP_OR_LATER)
#define CRYPTOPP_VC6_INT64 (__int64)
#else
#define CRYPTOPP_VC6_INT64
#endif
#ifdef _MSC_VER
#define CRYPTOPP_NO_VTABLE __declspec(novtable)
#else
#define CRYPTOPP_NO_VTABLE
#endif
#ifdef _MSC_VER
// 4231: nonstandard extension used : 'extern' before template explicit instantiation
// 4250: dominance
// 4251: member needs to have dll-interface
// 4275: base needs to have dll-interface
// 4660: explicitly instantiating a class that's already implicitly instantiated
// 4661: no suitable definition provided for explicit template instantiation request
// 4786: identifer was truncated in debug information
// 4355: 'this' : used in base member initializer list
// 4910: '__declspec(dllexport)' and 'extern' are incompatible on an explicit instantiation
# pragma warning(disable: 4231 4250 4251 4275 4660 4661 4786 4355 4910)
#endif
#ifdef __BORLANDC__
// 8037: non-const function called for const object. needed to work around BCB2006 bug
# pragma warn -8037
#endif
#if (defined(_MSC_VER) && _MSC_VER <= 1300) || defined(__MWERKS__) || defined(_STLPORT_VERSION) || defined(ANDROID_NDK)
#define CRYPTOPP_DISABLE_UNCAUGHT_EXCEPTION
#endif
#ifndef CRYPTOPP_DISABLE_UNCAUGHT_EXCEPTION
#define CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
#endif
#ifdef CRYPTOPP_DISABLE_X86ASM // for backwards compatibility: this macro had both meanings
#define CRYPTOPP_DISABLE_ASM
#define CRYPTOPP_DISABLE_SSE2
#endif
#if !defined(CRYPTOPP_DISABLE_ASM) && ((defined(_MSC_VER) && defined(_M_IX86)) || (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))))
// C++Builder 2010 does not allow "call label" where label is defined within inline assembly
#define CRYPTOPP_X86_ASM_AVAILABLE
#if !defined(CRYPTOPP_DISABLE_SSE2) && (defined(CRYPTOPP_MSVC6PP_OR_LATER) || CRYPTOPP_GCC_VERSION >= 30300)
#define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 1
#else
#define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 0
#endif
// SSSE3 was actually introduced in GNU as 2.17, which was released 6/23/2006, but we can't tell what version of binutils is installed.
// GCC 4.1.2 was released on 2/13/2007, so we'll use that as a proxy for the binutils version.
#if !defined(CRYPTOPP_DISABLE_SSSE3) && (_MSC_VER >= 1400 || CRYPTOPP_GCC_VERSION >= 40102)
#define CRYPTOPP_BOOL_SSSE3_ASM_AVAILABLE 1
#else
#define CRYPTOPP_BOOL_SSSE3_ASM_AVAILABLE 0
#endif
#endif
#if !defined(CRYPTOPP_DISABLE_ASM) && defined(_MSC_VER) && defined(_M_X64)
#define CRYPTOPP_X64_MASM_AVAILABLE
#endif
#if !defined(CRYPTOPP_DISABLE_ASM) && defined(__GNUC__) && defined(__x86_64__)
#define CRYPTOPP_X64_ASM_AVAILABLE
#endif
#if !defined(CRYPTOPP_DISABLE_SSE2) && (defined(CRYPTOPP_MSVC6PP_OR_LATER) || defined(__SSE2__))
#define CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE 1
#else
#define CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE 0
#endif
#if !defined(CRYPTOPP_DISABLE_SSSE3) && !defined(CRYPTOPP_DISABLE_AESNI) && CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE && (CRYPTOPP_GCC_VERSION >= 40400 || _MSC_FULL_VER >= 150030729 || __INTEL_COMPILER >= 1110)
#define CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE 1
#else
#define CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE 0
#endif
#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE || CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)
#define CRYPTOPP_BOOL_ALIGN16_ENABLED 1
#else
#define CRYPTOPP_BOOL_ALIGN16_ENABLED 0
#endif
// how to allocate 16-byte aligned memory (for SSE2)
#if defined(CRYPTOPP_MSVC6PP_OR_LATER)
#define CRYPTOPP_MM_MALLOC_AVAILABLE
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
#define CRYPTOPP_MALLOC_ALIGNMENT_IS_16
#elif defined(__linux__) || defined(__sun__) || defined(__CYGWIN__)
#define CRYPTOPP_MEMALIGN_AVAILABLE
#else
#define CRYPTOPP_NO_ALIGNED_ALLOC
#endif
// how to disable inlining
#if defined(_MSC_VER) && _MSC_VER >= 1300
# define CRYPTOPP_NOINLINE_DOTDOTDOT
# define CRYPTOPP_NOINLINE __declspec(noinline)
#elif defined(__GNUC__)
# define CRYPTOPP_NOINLINE_DOTDOTDOT
# define CRYPTOPP_NOINLINE __attribute__((noinline))
#else
# define CRYPTOPP_NOINLINE_DOTDOTDOT ...
# define CRYPTOPP_NOINLINE
#endif
// how to declare class constants
#if (defined(_MSC_VER) && _MSC_VER <= 1300) || defined(__INTEL_COMPILER)
# define CRYPTOPP_CONSTANT(x) enum {x};
#else
# define CRYPTOPP_CONSTANT(x) static const int x;
#endif
#if defined(_M_X64) || defined(__x86_64__)
#define CRYPTOPP_BOOL_X64 1
#else
#define CRYPTOPP_BOOL_X64 0
#endif
// see http://predef.sourceforge.net/prearch.html
#if defined(_M_IX86) || defined(__i386__) || defined(__i386) || defined(_X86_) || defined(__I86__) || defined(__INTEL__)
#define CRYPTOPP_BOOL_X86 1
#else
#define CRYPTOPP_BOOL_X86 0
#endif
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86 || defined(__powerpc__)
#define CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
#endif
#define CRYPTOPP_VERSION 562
// ***************** determine availability of OS features ********************
#ifndef NO_OS_DEPENDENCE
#if defined(_WIN32) || defined(__CYGWIN__)
#define CRYPTOPP_WIN32_AVAILABLE
#endif
#if defined(__unix__) || defined(__MACH__) || defined(__NetBSD__) || defined(__sun)
#define CRYPTOPP_UNIX_AVAILABLE
#endif
#if defined(CRYPTOPP_WIN32_AVAILABLE) || defined(CRYPTOPP_UNIX_AVAILABLE)
# define HIGHRES_TIMER_AVAILABLE
#endif
#ifdef CRYPTOPP_UNIX_AVAILABLE
# define HAS_BERKELEY_STYLE_SOCKETS
#endif
#ifdef CRYPTOPP_WIN32_AVAILABLE
# define HAS_WINDOWS_STYLE_SOCKETS
#endif
#if defined(HIGHRES_TIMER_AVAILABLE) && (defined(HAS_BERKELEY_STYLE_SOCKETS) || defined(HAS_WINDOWS_STYLE_SOCKETS))
# define SOCKETS_AVAILABLE
#endif
#if defined(HAS_WINDOWS_STYLE_SOCKETS) && (!defined(HAS_BERKELEY_STYLE_SOCKETS) || defined(PREFER_WINDOWS_STYLE_SOCKETS))
# define USE_WINDOWS_STYLE_SOCKETS
#else
# define USE_BERKELEY_STYLE_SOCKETS
#endif
#if defined(HIGHRES_TIMER_AVAILABLE) && defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(USE_BERKELEY_STYLE_SOCKETS)
# define WINDOWS_PIPES_AVAILABLE
#endif
#if defined(CRYPTOPP_WIN32_AVAILABLE) && defined(USE_MS_CRYPTOAPI)
# define NONBLOCKING_RNG_AVAILABLE
# define OS_RNG_AVAILABLE
#endif
#if defined(CRYPTOPP_UNIX_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
# define NONBLOCKING_RNG_AVAILABLE
# define BLOCKING_RNG_AVAILABLE
# define OS_RNG_AVAILABLE
# define HAS_PTHREADS
# define THREADS_AVAILABLE
#endif
#ifdef CRYPTOPP_WIN32_AVAILABLE
# define HAS_WINTHREADS
# define THREADS_AVAILABLE
#endif
#endif // NO_OS_DEPENDENCE
// ***************** DLL related ********************
#if defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(CRYPTOPP_DOXYGEN_PROCESSING)
#ifdef CRYPTOPP_EXPORTS
#define CRYPTOPP_IS_DLL
#define CRYPTOPP_DLL __declspec(dllexport)
#elif defined(CRYPTOPP_IMPORTS)
#define CRYPTOPP_IS_DLL
#define CRYPTOPP_DLL __declspec(dllimport)
#else
#define CRYPTOPP_DLL
#endif
#define CRYPTOPP_API __cdecl
#else // CRYPTOPP_WIN32_AVAILABLE
#define CRYPTOPP_DLL
#define CRYPTOPP_API
#endif // CRYPTOPP_WIN32_AVAILABLE
#if defined(__MWERKS__)
#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS extern class CRYPTOPP_DLL
#elif defined(__BORLANDC__) || defined(__SUNPRO_CC)
#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS template class CRYPTOPP_DLL
#else
#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS extern template class CRYPTOPP_DLL
#endif
#if defined(CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES) && !defined(CRYPTOPP_IMPORTS)
#define CRYPTOPP_DLL_TEMPLATE_CLASS template class CRYPTOPP_DLL
#else
#define CRYPTOPP_DLL_TEMPLATE_CLASS CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS
#endif
#if defined(__MWERKS__)
#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS extern class
#elif defined(__BORLANDC__) || defined(__SUNPRO_CC)
#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS template class
#else
#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS extern template class
#endif
#if defined(CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES) && !defined(CRYPTOPP_EXPORTS)
#define CRYPTOPP_STATIC_TEMPLATE_CLASS template class
#else
#define CRYPTOPP_STATIC_TEMPLATE_CLASS CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS
#endif
#endif

View File

@ -1,199 +0,0 @@
// cpu.cpp - written and placed in the public domain by Wei Dai
#include "pch.h"
#ifndef CRYPTOPP_IMPORTS
#include "cpu.h"
#include "misc.h"
#include <algorithm>
#ifndef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
#include <signal.h>
#include <setjmp.h>
#endif
#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
#include <emmintrin.h>
#endif
NAMESPACE_BEGIN(CryptoPP)
#ifdef CRYPTOPP_CPUID_AVAILABLE
#if _MSC_VER >= 1400 && CRYPTOPP_BOOL_X64
bool CpuId(word32 input, word32 *output)
{
__cpuid((int *)output, input);
return true;
}
#else
#ifndef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
extern "C" {
typedef void (*SigHandler)(int);
static jmp_buf s_jmpNoCPUID;
static void SigIllHandlerCPUID(int)
{
longjmp(s_jmpNoCPUID, 1);
}
static jmp_buf s_jmpNoSSE2;
static void SigIllHandlerSSE2(int)
{
longjmp(s_jmpNoSSE2, 1);
}
}
#endif
bool CpuId(word32 input, word32 *output)
{
#ifdef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
__try
{
__asm
{
mov eax, input
cpuid
mov edi, output
mov [edi], eax
mov [edi+4], ebx
mov [edi+8], ecx
mov [edi+12], edx
}
}
__except (1)
{
return false;
}
return true;
#else
SigHandler oldHandler = signal(SIGILL, SigIllHandlerCPUID);
if (oldHandler == SIG_ERR)
return false;
bool result = true;
if (setjmp(s_jmpNoCPUID))
result = false;
else
{
asm
(
// save ebx in case -fPIC is being used
#if CRYPTOPP_BOOL_X86
"push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
#else
"pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx"
#endif
: "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d" (output[3])
: "a" (input)
);
}
signal(SIGILL, oldHandler);
return result;
#endif
}
#endif
static bool TrySSE2()
{
#if CRYPTOPP_BOOL_X64
return true;
#elif defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY)
__try
{
#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
AS2(por xmm0, xmm0) // executing SSE2 instruction
#elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
__m128i x = _mm_setzero_si128();
return _mm_cvtsi128_si32(x) == 0;
#endif
}
__except (1)
{
return false;
}
return true;
#else
SigHandler oldHandler = signal(SIGILL, SigIllHandlerSSE2);
if (oldHandler == SIG_ERR)
return false;
bool result = true;
if (setjmp(s_jmpNoSSE2))
result = false;
else
{
#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
__asm __volatile ("por %xmm0, %xmm0");
#elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
__m128i x = _mm_setzero_si128();
result = _mm_cvtsi128_si32(x) == 0;
#endif
}
signal(SIGILL, oldHandler);
return result;
#endif
}
bool g_x86DetectionDone = false;
bool g_hasISSE = false, g_hasSSE2 = false, g_hasSSSE3 = false, g_hasMMX = false, g_hasAESNI = false, g_hasCLMUL = false, g_isP4 = false;
word32 g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
void DetectX86Features()
{
word32 cpuid[4], cpuid1[4];
if (!CpuId(0, cpuid))
return;
if (!CpuId(1, cpuid1))
return;
g_hasMMX = (cpuid1[3] & (1 << 23)) != 0;
if ((cpuid1[3] & (1 << 26)) != 0)
g_hasSSE2 = TrySSE2();
g_hasSSSE3 = g_hasSSE2 && (cpuid1[2] & (1<<9));
g_hasAESNI = g_hasSSE2 && (cpuid1[2] & (1<<25));
g_hasCLMUL = g_hasSSE2 && (cpuid1[2] & (1<<1));
if ((cpuid1[3] & (1 << 25)) != 0)
g_hasISSE = true;
else
{
word32 cpuid2[4];
CpuId(0x080000000, cpuid2);
if (cpuid2[0] >= 0x080000001)
{
CpuId(0x080000001, cpuid2);
g_hasISSE = (cpuid2[3] & (1 << 22)) != 0;
}
}
std::swap(cpuid[2], cpuid[3]);
if (memcmp(cpuid+1, "GenuineIntel", 12) == 0)
{
g_isP4 = ((cpuid1[0] >> 8) & 0xf) == 0xf;
g_cacheLineSize = 8 * GETBYTE(cpuid1[1], 1);
}
else if (memcmp(cpuid+1, "AuthenticAMD", 12) == 0)
{
CpuId(0x80000005, cpuid);
g_cacheLineSize = GETBYTE(cpuid[2], 0);
}
if (!g_cacheLineSize)
g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
g_x86DetectionDone = true;
}
#endif
NAMESPACE_END
#endif

View File

@ -1,345 +0,0 @@
#ifndef CRYPTOPP_CPU_H
#define CRYPTOPP_CPU_H
#ifdef CRYPTOPP_GENERATE_X64_MASM
#define CRYPTOPP_X86_ASM_AVAILABLE
#define CRYPTOPP_BOOL_X64 1
#define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 1
#define NAMESPACE_END
#else
#include "config.h"
#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
#include <emmintrin.h>
#endif
#if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE
#if !defined(__GNUC__) || defined(__SSSE3__) || defined(__INTEL_COMPILER)
#include <tmmintrin.h>
#else
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_shuffle_epi8 (__m128i a, __m128i b)
{
asm ("pshufb %1, %0" : "+x"(a) : "xm"(b));
return a;
}
#endif
#if !defined(__GNUC__) || defined(__SSE4_1__) || defined(__INTEL_COMPILER)
#include <smmintrin.h>
#else
__inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_extract_epi32 (__m128i a, const int i)
{
int r;
asm ("pextrd %2, %1, %0" : "=rm"(r) : "x"(a), "i"(i));
return r;
}
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_insert_epi32 (__m128i a, int b, const int i)
{
asm ("pinsrd %2, %1, %0" : "+x"(a) : "rm"(b), "i"(i));
return a;
}
#endif
#if !defined(__GNUC__) || (defined(__AES__) && defined(__PCLMUL__)) || defined(__INTEL_COMPILER)
#include <wmmintrin.h>
#else
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_clmulepi64_si128 (__m128i a, __m128i b, const int i)
{
asm ("pclmulqdq %2, %1, %0" : "+x"(a) : "xm"(b), "i"(i));
return a;
}
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_aeskeygenassist_si128 (__m128i a, const int i)
{
__m128i r;
asm ("aeskeygenassist %2, %1, %0" : "=x"(r) : "xm"(a), "i"(i));
return r;
}
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_aesimc_si128 (__m128i a)
{
__m128i r;
asm ("aesimc %1, %0" : "=x"(r) : "xm"(a));
return r;
}
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_aesenc_si128 (__m128i a, __m128i b)
{
asm ("aesenc %1, %0" : "+x"(a) : "xm"(b));
return a;
}
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_aesenclast_si128 (__m128i a, __m128i b)
{
asm ("aesenclast %1, %0" : "+x"(a) : "xm"(b));
return a;
}
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_aesdec_si128 (__m128i a, __m128i b)
{
asm ("aesdec %1, %0" : "+x"(a) : "xm"(b));
return a;
}
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_aesdeclast_si128 (__m128i a, __m128i b)
{
asm ("aesdeclast %1, %0" : "+x"(a) : "xm"(b));
return a;
}
#endif
#endif
NAMESPACE_BEGIN(CryptoPP)
#if CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X64
#define CRYPTOPP_CPUID_AVAILABLE
// these should not be used directly
extern CRYPTOPP_DLL bool g_x86DetectionDone;
extern CRYPTOPP_DLL bool g_hasSSSE3;
extern CRYPTOPP_DLL bool g_hasAESNI;
extern CRYPTOPP_DLL bool g_hasCLMUL;
extern CRYPTOPP_DLL bool g_isP4;
extern CRYPTOPP_DLL word32 g_cacheLineSize;
CRYPTOPP_DLL void CRYPTOPP_API DetectX86Features();
CRYPTOPP_DLL bool CRYPTOPP_API CpuId(word32 input, word32 *output);
#if CRYPTOPP_BOOL_X64
inline bool HasSSE2() {return true;}
inline bool HasISSE() {return true;}
inline bool HasMMX() {return true;}
#else
extern CRYPTOPP_DLL bool g_hasSSE2;
extern CRYPTOPP_DLL bool g_hasISSE;
extern CRYPTOPP_DLL bool g_hasMMX;
inline bool HasSSE2()
{
if (!g_x86DetectionDone)
DetectX86Features();
return g_hasSSE2;
}
inline bool HasISSE()
{
if (!g_x86DetectionDone)
DetectX86Features();
return g_hasISSE;
}
inline bool HasMMX()
{
if (!g_x86DetectionDone)
DetectX86Features();
return g_hasMMX;
}
#endif
inline bool HasSSSE3()
{
if (!g_x86DetectionDone)
DetectX86Features();
return g_hasSSSE3;
}
inline bool HasAESNI()
{
if (!g_x86DetectionDone)
DetectX86Features();
return g_hasAESNI;
}
inline bool HasCLMUL()
{
if (!g_x86DetectionDone)
DetectX86Features();
return g_hasCLMUL;
}
inline bool IsP4()
{
if (!g_x86DetectionDone)
DetectX86Features();
return g_isP4;
}
inline int GetCacheLineSize()
{
if (!g_x86DetectionDone)
DetectX86Features();
return g_cacheLineSize;
}
#else
inline int GetCacheLineSize()
{
return CRYPTOPP_L1_CACHE_LINE_SIZE;
}
#endif
#endif
#ifdef CRYPTOPP_GENERATE_X64_MASM
#define AS1(x) x*newline*
#define AS2(x, y) x, y*newline*
#define AS3(x, y, z) x, y, z*newline*
#define ASS(x, y, a, b, c, d) x, y, a*64+b*16+c*4+d*newline*
#define ASL(x) label##x:*newline*
#define ASJ(x, y, z) x label##y*newline*
#define ASC(x, y) x label##y*newline*
#define AS_HEX(y) 0##y##h
#elif defined(_MSC_VER) || defined(__BORLANDC__)
#define CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
#define AS1(x) __asm {x}
#define AS2(x, y) __asm {x, y}
#define AS3(x, y, z) __asm {x, y, z}
#define ASS(x, y, a, b, c, d) __asm {x, y, (a)*64+(b)*16+(c)*4+(d)}
#define ASL(x) __asm {label##x:}
#define ASJ(x, y, z) __asm {x label##y}
#define ASC(x, y) __asm {x label##y}
#define CRYPTOPP_NAKED __declspec(naked)
#define AS_HEX(y) 0x##y
#else
#define CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
// define these in two steps to allow arguments to be expanded
#define GNU_AS1(x) #x ";"
#define GNU_AS2(x, y) #x ", " #y ";"
#define GNU_AS3(x, y, z) #x ", " #y ", " #z ";"
#define GNU_ASL(x) "\n" #x ":"
#define GNU_ASJ(x, y, z) #x " " #y #z ";"
#define AS1(x) GNU_AS1(x)
#define AS2(x, y) GNU_AS2(x, y)
#define AS3(x, y, z) GNU_AS3(x, y, z)
#define ASS(x, y, a, b, c, d) #x ", " #y ", " #a "*64+" #b "*16+" #c "*4+" #d ";"
#define ASL(x) GNU_ASL(x)
#define ASJ(x, y, z) GNU_ASJ(x, y, z)
#define ASC(x, y) #x " " #y ";"
#define CRYPTOPP_NAKED
#define AS_HEX(y) 0x##y
#endif
#define IF0(y)
#define IF1(y) y
#ifdef CRYPTOPP_GENERATE_X64_MASM
#define ASM_MOD(x, y) ((x) MOD (y))
#define XMMWORD_PTR XMMWORD PTR
#else
// GNU assembler doesn't seem to have mod operator
#define ASM_MOD(x, y) ((x)-((x)/(y))*(y))
// GAS 2.15 doesn't support XMMWORD PTR. it seems necessary only for MASM
#define XMMWORD_PTR
#endif
#if CRYPTOPP_BOOL_X86
#define AS_REG_1 ecx
#define AS_REG_2 edx
#define AS_REG_3 esi
#define AS_REG_4 edi
#define AS_REG_5 eax
#define AS_REG_6 ebx
#define AS_REG_7 ebp
#define AS_REG_1d ecx
#define AS_REG_2d edx
#define AS_REG_3d esi
#define AS_REG_4d edi
#define AS_REG_5d eax
#define AS_REG_6d ebx
#define AS_REG_7d ebp
#define WORD_SZ 4
#define WORD_REG(x) e##x
#define WORD_PTR DWORD PTR
#define AS_PUSH_IF86(x) AS1(push e##x)
#define AS_POP_IF86(x) AS1(pop e##x)
#define AS_JCXZ jecxz
#elif CRYPTOPP_BOOL_X64
#ifdef CRYPTOPP_GENERATE_X64_MASM
#define AS_REG_1 rcx
#define AS_REG_2 rdx
#define AS_REG_3 r8
#define AS_REG_4 r9
#define AS_REG_5 rax
#define AS_REG_6 r10
#define AS_REG_7 r11
#define AS_REG_1d ecx
#define AS_REG_2d edx
#define AS_REG_3d r8d
#define AS_REG_4d r9d
#define AS_REG_5d eax
#define AS_REG_6d r10d
#define AS_REG_7d r11d
#else
#define AS_REG_1 rdi
#define AS_REG_2 rsi
#define AS_REG_3 rdx
#define AS_REG_4 rcx
#define AS_REG_5 r8
#define AS_REG_6 r9
#define AS_REG_7 r10
#define AS_REG_1d edi
#define AS_REG_2d esi
#define AS_REG_3d edx
#define AS_REG_4d ecx
#define AS_REG_5d r8d
#define AS_REG_6d r9d
#define AS_REG_7d r10d
#endif
#define WORD_SZ 8
#define WORD_REG(x) r##x
#define WORD_PTR QWORD PTR
#define AS_PUSH_IF86(x)
#define AS_POP_IF86(x)
#define AS_JCXZ jrcxz
#endif
// helper macro for stream cipher output
#define AS_XMM_OUTPUT4(labelPrefix, inputPtr, outputPtr, x0, x1, x2, x3, t, p0, p1, p2, p3, increment)\
AS2( test inputPtr, inputPtr)\
ASC( jz, labelPrefix##3)\
AS2( test inputPtr, 15)\
ASC( jnz, labelPrefix##7)\
AS2( pxor xmm##x0, [inputPtr+p0*16])\
AS2( pxor xmm##x1, [inputPtr+p1*16])\
AS2( pxor xmm##x2, [inputPtr+p2*16])\
AS2( pxor xmm##x3, [inputPtr+p3*16])\
AS2( add inputPtr, increment*16)\
ASC( jmp, labelPrefix##3)\
ASL(labelPrefix##7)\
AS2( movdqu xmm##t, [inputPtr+p0*16])\
AS2( pxor xmm##x0, xmm##t)\
AS2( movdqu xmm##t, [inputPtr+p1*16])\
AS2( pxor xmm##x1, xmm##t)\
AS2( movdqu xmm##t, [inputPtr+p2*16])\
AS2( pxor xmm##x2, xmm##t)\
AS2( movdqu xmm##t, [inputPtr+p3*16])\
AS2( pxor xmm##x3, xmm##t)\
AS2( add inputPtr, increment*16)\
ASL(labelPrefix##3)\
AS2( test outputPtr, 15)\
ASC( jnz, labelPrefix##8)\
AS2( movdqa [outputPtr+p0*16], xmm##x0)\
AS2( movdqa [outputPtr+p1*16], xmm##x1)\
AS2( movdqa [outputPtr+p2*16], xmm##x2)\
AS2( movdqa [outputPtr+p3*16], xmm##x3)\
ASC( jmp, labelPrefix##9)\
ASL(labelPrefix##8)\
AS2( movdqu [outputPtr+p0*16], xmm##x0)\
AS2( movdqu [outputPtr+p1*16], xmm##x1)\
AS2( movdqu [outputPtr+p2*16], xmm##x2)\
AS2( movdqu [outputPtr+p3*16], xmm##x3)\
ASL(labelPrefix##9)\
AS2( add outputPtr, increment*16)
NAMESPACE_END
#endif

View File

@ -1,160 +0,0 @@
// crc.cpp - written and placed in the public domain by Wei Dai
#include "pch.h"
#include "crc.h"
#include "misc.h"
NAMESPACE_BEGIN(CryptoPP)
/* Table of CRC-32's of all single byte values (made by makecrc.c) */
const word32 CRC32::m_tab[] = {
#ifdef IS_LITTLE_ENDIAN
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
0x2d02ef8dL
#else
0x00000000L, 0x96300777L, 0x2c610eeeL, 0xba510999L, 0x19c46d07L,
0x8ff46a70L, 0x35a563e9L, 0xa395649eL, 0x3288db0eL, 0xa4b8dc79L,
0x1ee9d5e0L, 0x88d9d297L, 0x2b4cb609L, 0xbd7cb17eL, 0x072db8e7L,
0x911dbf90L, 0x6410b71dL, 0xf220b06aL, 0x4871b9f3L, 0xde41be84L,
0x7dd4da1aL, 0xebe4dd6dL, 0x51b5d4f4L, 0xc785d383L, 0x56986c13L,
0xc0a86b64L, 0x7af962fdL, 0xecc9658aL, 0x4f5c0114L, 0xd96c0663L,
0x633d0ffaL, 0xf50d088dL, 0xc8206e3bL, 0x5e10694cL, 0xe44160d5L,
0x727167a2L, 0xd1e4033cL, 0x47d4044bL, 0xfd850dd2L, 0x6bb50aa5L,
0xfaa8b535L, 0x6c98b242L, 0xd6c9bbdbL, 0x40f9bcacL, 0xe36cd832L,
0x755cdf45L, 0xcf0dd6dcL, 0x593dd1abL, 0xac30d926L, 0x3a00de51L,
0x8051d7c8L, 0x1661d0bfL, 0xb5f4b421L, 0x23c4b356L, 0x9995bacfL,
0x0fa5bdb8L, 0x9eb80228L, 0x0888055fL, 0xb2d90cc6L, 0x24e90bb1L,
0x877c6f2fL, 0x114c6858L, 0xab1d61c1L, 0x3d2d66b6L, 0x9041dc76L,
0x0671db01L, 0xbc20d298L, 0x2a10d5efL, 0x8985b171L, 0x1fb5b606L,
0xa5e4bf9fL, 0x33d4b8e8L, 0xa2c90778L, 0x34f9000fL, 0x8ea80996L,
0x18980ee1L, 0xbb0d6a7fL, 0x2d3d6d08L, 0x976c6491L, 0x015c63e6L,
0xf4516b6bL, 0x62616c1cL, 0xd8306585L, 0x4e0062f2L, 0xed95066cL,
0x7ba5011bL, 0xc1f40882L, 0x57c40ff5L, 0xc6d9b065L, 0x50e9b712L,
0xeab8be8bL, 0x7c88b9fcL, 0xdf1ddd62L, 0x492dda15L, 0xf37cd38cL,
0x654cd4fbL, 0x5861b24dL, 0xce51b53aL, 0x7400bca3L, 0xe230bbd4L,
0x41a5df4aL, 0xd795d83dL, 0x6dc4d1a4L, 0xfbf4d6d3L, 0x6ae96943L,
0xfcd96e34L, 0x468867adL, 0xd0b860daL, 0x732d0444L, 0xe51d0333L,
0x5f4c0aaaL, 0xc97c0dddL, 0x3c710550L, 0xaa410227L, 0x10100bbeL,
0x86200cc9L, 0x25b56857L, 0xb3856f20L, 0x09d466b9L, 0x9fe461ceL,
0x0ef9de5eL, 0x98c9d929L, 0x2298d0b0L, 0xb4a8d7c7L, 0x173db359L,
0x810db42eL, 0x3b5cbdb7L, 0xad6cbac0L, 0x2083b8edL, 0xb6b3bf9aL,
0x0ce2b603L, 0x9ad2b174L, 0x3947d5eaL, 0xaf77d29dL, 0x1526db04L,
0x8316dc73L, 0x120b63e3L, 0x843b6494L, 0x3e6a6d0dL, 0xa85a6a7aL,
0x0bcf0ee4L, 0x9dff0993L, 0x27ae000aL, 0xb19e077dL, 0x44930ff0L,
0xd2a30887L, 0x68f2011eL, 0xfec20669L, 0x5d5762f7L, 0xcb676580L,
0x71366c19L, 0xe7066b6eL, 0x761bd4feL, 0xe02bd389L, 0x5a7ada10L,
0xcc4add67L, 0x6fdfb9f9L, 0xf9efbe8eL, 0x43beb717L, 0xd58eb060L,
0xe8a3d6d6L, 0x7e93d1a1L, 0xc4c2d838L, 0x52f2df4fL, 0xf167bbd1L,
0x6757bca6L, 0xdd06b53fL, 0x4b36b248L, 0xda2b0dd8L, 0x4c1b0aafL,
0xf64a0336L, 0x607a0441L, 0xc3ef60dfL, 0x55df67a8L, 0xef8e6e31L,
0x79be6946L, 0x8cb361cbL, 0x1a8366bcL, 0xa0d26f25L, 0x36e26852L,
0x95770cccL, 0x03470bbbL, 0xb9160222L, 0x2f260555L, 0xbe3bbac5L,
0x280bbdb2L, 0x925ab42bL, 0x046ab35cL, 0xa7ffd7c2L, 0x31cfd0b5L,
0x8b9ed92cL, 0x1daede5bL, 0xb0c2649bL, 0x26f263ecL, 0x9ca36a75L,
0x0a936d02L, 0xa906099cL, 0x3f360eebL, 0x85670772L, 0x13570005L,
0x824abf95L, 0x147ab8e2L, 0xae2bb17bL, 0x381bb60cL, 0x9b8ed292L,
0x0dbed5e5L, 0xb7efdc7cL, 0x21dfdb0bL, 0xd4d2d386L, 0x42e2d4f1L,
0xf8b3dd68L, 0x6e83da1fL, 0xcd16be81L, 0x5b26b9f6L, 0xe177b06fL,
0x7747b718L, 0xe65a0888L, 0x706a0fffL, 0xca3b0666L, 0x5c0b0111L,
0xff9e658fL, 0x69ae62f8L, 0xd3ff6b61L, 0x45cf6c16L, 0x78e20aa0L,
0xeed20dd7L, 0x5483044eL, 0xc2b30339L, 0x612667a7L, 0xf71660d0L,
0x4d476949L, 0xdb776e3eL, 0x4a6ad1aeL, 0xdc5ad6d9L, 0x660bdf40L,
0xf03bd837L, 0x53aebca9L, 0xc59ebbdeL, 0x7fcfb247L, 0xe9ffb530L,
0x1cf2bdbdL, 0x8ac2bacaL, 0x3093b353L, 0xa6a3b424L, 0x0536d0baL,
0x9306d7cdL, 0x2957de54L, 0xbf67d923L, 0x2e7a66b3L, 0xb84a61c4L,
0x021b685dL, 0x942b6f2aL, 0x37be0bb4L, 0xa18e0cc3L, 0x1bdf055aL,
0x8def022dL
#endif
};
CRC32::CRC32()
{
Reset();
}
void CRC32::Update(const byte *s, size_t n)
{
word32 crc = m_crc;
for(; !IsAligned<word32>(s) && n > 0; n--)
crc = m_tab[CRC32_INDEX(crc) ^ *s++] ^ CRC32_SHIFTED(crc);
while (n >= 4)
{
crc ^= *(const word32 *)s;
crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
n -= 4;
s += 4;
}
while (n--)
crc = m_tab[CRC32_INDEX(crc) ^ *s++] ^ CRC32_SHIFTED(crc);
m_crc = crc;
}
void CRC32::TruncatedFinal(byte *hash, size_t size)
{
ThrowIfInvalidTruncatedSize(size);
m_crc ^= CRC32_NEGL;
for (size_t i=0; i<size; i++)
hash[i] = GetCrcByte(i);
Reset();
}
NAMESPACE_END

View File

@ -1,42 +0,0 @@
#ifndef CRYPTOPP_CRC32_H
#define CRYPTOPP_CRC32_H
#include "cryptlib.h"
NAMESPACE_BEGIN(CryptoPP)
const word32 CRC32_NEGL = 0xffffffffL;
#ifdef IS_LITTLE_ENDIAN
#define CRC32_INDEX(c) (c & 0xff)
#define CRC32_SHIFTED(c) (c >> 8)
#else
#define CRC32_INDEX(c) (c >> 24)
#define CRC32_SHIFTED(c) (c << 8)
#endif
//! CRC Checksum Calculation
class CRC32 : public HashTransformation
{
public:
CRYPTOPP_CONSTANT(DIGESTSIZE = 4)
CRC32();
void Update(const byte *input, size_t length);
void TruncatedFinal(byte *hash, size_t size);
unsigned int DigestSize() const {return DIGESTSIZE;}
static const char * StaticAlgorithmName() {return "CRC32";}
std::string AlgorithmName() const {return StaticAlgorithmName();}
void UpdateByte(byte b) {m_crc = m_tab[CRC32_INDEX(m_crc) ^ b] ^ CRC32_SHIFTED(m_crc);}
byte GetCrcByte(size_t i) const {return ((byte *)&(m_crc))[i];}
private:
void Reset() {m_crc = CRC32_NEGL;}
static const word32 m_tab[256];
word32 m_crc;
};
NAMESPACE_END
#endif

View File

@ -1,828 +0,0 @@
// cryptlib.cpp - written and placed in the public domain by Wei Dai
#include "pch.h"
#ifndef CRYPTOPP_IMPORTS
#include "cryptlib.h"
#include "misc.h"
#include "filters.h"
#include "algparam.h"
#include "fips140.h"
#include "argnames.h"
#include "fltrimpl.h"
#include "trdlocal.h"
#include "osrng.h"
#include <memory>
NAMESPACE_BEGIN(CryptoPP)
CRYPTOPP_COMPILE_ASSERT(sizeof(byte) == 1);
CRYPTOPP_COMPILE_ASSERT(sizeof(word16) == 2);
CRYPTOPP_COMPILE_ASSERT(sizeof(word32) == 4);
CRYPTOPP_COMPILE_ASSERT(sizeof(word64) == 8);
#ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE
CRYPTOPP_COMPILE_ASSERT(sizeof(dword) == 2*sizeof(word));
#endif
const std::string DEFAULT_CHANNEL;
const std::string AAD_CHANNEL = "AAD";
const std::string &BufferedTransformation::NULL_CHANNEL = DEFAULT_CHANNEL;
class NullNameValuePairs : public NameValuePairs
{
public:
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const {return false;}
};
simple_ptr<NullNameValuePairs> s_pNullNameValuePairs(new NullNameValuePairs);
const NameValuePairs &g_nullNameValuePairs = *s_pNullNameValuePairs.m_p;
BufferedTransformation & TheBitBucket()
{
static BitBucket bitBucket;
return bitBucket;
}
Algorithm::Algorithm(bool checkSelfTestStatus)
{
if (checkSelfTestStatus && FIPS_140_2_ComplianceEnabled())
{
if (GetPowerUpSelfTestStatus() == POWER_UP_SELF_TEST_NOT_DONE && !PowerUpSelfTestInProgressOnThisThread())
throw SelfTestFailure("Cryptographic algorithms are disabled before the power-up self tests are performed.");
if (GetPowerUpSelfTestStatus() == POWER_UP_SELF_TEST_FAILED)
throw SelfTestFailure("Cryptographic algorithms are disabled after a power-up self test failed.");
}
}
void SimpleKeyingInterface::SetKey(const byte *key, size_t length, const NameValuePairs &params)
{
this->ThrowIfInvalidKeyLength(length);
this->UncheckedSetKey(key, (unsigned int)length, params);
}
void SimpleKeyingInterface::SetKeyWithRounds(const byte *key, size_t length, int rounds)
{
SetKey(key, length, MakeParameters(Name::Rounds(), rounds));
}
void SimpleKeyingInterface::SetKeyWithIV(const byte *key, size_t length, const byte *iv, size_t ivLength)
{
SetKey(key, length, MakeParameters(Name::IV(), ConstByteArrayParameter(iv, ivLength)));
}
void SimpleKeyingInterface::ThrowIfInvalidKeyLength(size_t length)
{
if (!IsValidKeyLength(length))
throw InvalidKeyLength(GetAlgorithm().AlgorithmName(), length);
}
void SimpleKeyingInterface::ThrowIfResynchronizable()
{
if (IsResynchronizable())
throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": this object requires an IV");
}
void SimpleKeyingInterface::ThrowIfInvalidIV(const byte *iv)
{
if (!iv && IVRequirement() == UNPREDICTABLE_RANDOM_IV)
throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": this object cannot use a null IV");
}
size_t SimpleKeyingInterface::ThrowIfInvalidIVLength(int size)
{
if (size < 0)
return IVSize();
else if ((size_t)size < MinIVLength())
throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": IV length " + IntToString(size) + " is less than the minimum of " + IntToString(MinIVLength()));
else if ((size_t)size > MaxIVLength())
throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": IV length " + IntToString(size) + " exceeds the maximum of " + IntToString(MaxIVLength()));
else
return size;
}
const byte * SimpleKeyingInterface::GetIVAndThrowIfInvalid(const NameValuePairs &params, size_t &size)
{
ConstByteArrayParameter ivWithLength;
const byte *iv;
bool found = false;
try {found = params.GetValue(Name::IV(), ivWithLength);}
catch (const NameValuePairs::ValueTypeMismatch &) {}
if (found)
{
iv = ivWithLength.begin();
ThrowIfInvalidIV(iv);
size = ThrowIfInvalidIVLength((int)ivWithLength.size());
return iv;
}
else if (params.GetValue(Name::IV(), iv))
{
ThrowIfInvalidIV(iv);
size = IVSize();
return iv;
}
else
{
ThrowIfResynchronizable();
size = 0;
return NULL;
}
}
void SimpleKeyingInterface::GetNextIV(RandomNumberGenerator &rng, byte *IV)
{
rng.GenerateBlock(IV, IVSize());
}
size_t BlockTransformation::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const
{
size_t blockSize = BlockSize();
size_t inIncrement = (flags & (BT_InBlockIsCounter|BT_DontIncrementInOutPointers)) ? 0 : blockSize;
size_t xorIncrement = xorBlocks ? blockSize : 0;
size_t outIncrement = (flags & BT_DontIncrementInOutPointers) ? 0 : blockSize;
if (flags & BT_ReverseDirection)
{
assert(length % blockSize == 0);
inBlocks += length - blockSize;
xorBlocks += length - blockSize;
outBlocks += length - blockSize;
inIncrement = 0-inIncrement;
xorIncrement = 0-xorIncrement;
outIncrement = 0-outIncrement;
}
while (length >= blockSize)
{
if (flags & BT_XorInput)
{
xorbuf(outBlocks, xorBlocks, inBlocks, blockSize);
ProcessBlock(outBlocks);
}
else
ProcessAndXorBlock(inBlocks, xorBlocks, outBlocks);
if (flags & BT_InBlockIsCounter)
const_cast<byte *>(inBlocks)[blockSize-1]++;
inBlocks += inIncrement;
outBlocks += outIncrement;
xorBlocks += xorIncrement;
length -= blockSize;
}
return length;
}
unsigned int BlockTransformation::OptimalDataAlignment() const
{
return GetAlignmentOf<word32>();
}
unsigned int StreamTransformation::OptimalDataAlignment() const
{
return GetAlignmentOf<word32>();
}
unsigned int HashTransformation::OptimalDataAlignment() const
{
return GetAlignmentOf<word32>();
}
void StreamTransformation::ProcessLastBlock(byte *outString, const byte *inString, size_t length)
{
assert(MinLastBlockSize() == 0); // this function should be overriden otherwise
if (length == MandatoryBlockSize())
ProcessData(outString, inString, length);
else if (length != 0)
throw NotImplemented(AlgorithmName() + ": this object does't support a special last block");
}
void AuthenticatedSymmetricCipher::SpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength)
{
if (headerLength > MaxHeaderLength())
throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": header length " + IntToString(headerLength) + " exceeds the maximum of " + IntToString(MaxHeaderLength()));
if (messageLength > MaxMessageLength())
throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": message length " + IntToString(messageLength) + " exceeds the maximum of " + IntToString(MaxMessageLength()));
if (footerLength > MaxFooterLength())
throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": footer length " + IntToString(footerLength) + " exceeds the maximum of " + IntToString(MaxFooterLength()));
UncheckedSpecifyDataLengths(headerLength, messageLength, footerLength);
}
void AuthenticatedSymmetricCipher::EncryptAndAuthenticate(byte *ciphertext, byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *message, size_t messageLength)
{
Resynchronize(iv, ivLength);
SpecifyDataLengths(headerLength, messageLength);
Update(header, headerLength);
ProcessString(ciphertext, message, messageLength);
TruncatedFinal(mac, macSize);
}
bool AuthenticatedSymmetricCipher::DecryptAndVerify(byte *message, const byte *mac, size_t macLength, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *ciphertext, size_t ciphertextLength)
{
Resynchronize(iv, ivLength);
SpecifyDataLengths(headerLength, ciphertextLength);
Update(header, headerLength);
ProcessString(message, ciphertext, ciphertextLength);
return TruncatedVerify(mac, macLength);
}
unsigned int RandomNumberGenerator::GenerateBit()
{
return GenerateByte() & 1;
}
byte RandomNumberGenerator::GenerateByte()
{
byte b;
GenerateBlock(&b, 1);
return b;
}
word32 RandomNumberGenerator::GenerateWord32(word32 min, word32 max)
{
word32 range = max-min;
const int maxBits = BitPrecision(range);
word32 value;
do
{
GenerateBlock((byte *)&value, sizeof(value));
value = Crop(value, maxBits);
} while (value > range);
return value+min;
}
void RandomNumberGenerator::GenerateBlock(byte *output, size_t size)
{
ArraySink s(output, size);
GenerateIntoBufferedTransformation(s, DEFAULT_CHANNEL, size);
}
void RandomNumberGenerator::DiscardBytes(size_t n)
{
GenerateIntoBufferedTransformation(TheBitBucket(), DEFAULT_CHANNEL, n);
}
void RandomNumberGenerator::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length)
{
FixedSizeSecBlock<byte, 256> buffer;
while (length)
{
size_t len = UnsignedMin(buffer.size(), length);
GenerateBlock(buffer, len);
target.ChannelPut(channel, buffer, len);
length -= len;
}
}
//! see NullRNG()
class ClassNullRNG : public RandomNumberGenerator
{
public:
std::string AlgorithmName() const {return "NullRNG";}
void GenerateBlock(byte *output, size_t size) {throw NotImplemented("NullRNG: NullRNG should only be passed to functions that don't need to generate random bytes");}
};
RandomNumberGenerator & NullRNG()
{
static ClassNullRNG s_nullRNG;
return s_nullRNG;
}
bool HashTransformation::TruncatedVerify(const byte *digestIn, size_t digestLength)
{
ThrowIfInvalidTruncatedSize(digestLength);
SecByteBlock digest(digestLength);
TruncatedFinal(digest, digestLength);
return VerifyBufsEqual(digest, digestIn, digestLength);
}
void HashTransformation::ThrowIfInvalidTruncatedSize(size_t size) const
{
if (size > DigestSize())
throw InvalidArgument("HashTransformation: can't truncate a " + IntToString(DigestSize()) + " byte digest to " + IntToString(size) + " bytes");
}
unsigned int BufferedTransformation::GetMaxWaitObjectCount() const
{
const BufferedTransformation *t = AttachedTransformation();
return t ? t->GetMaxWaitObjectCount() : 0;
}
void BufferedTransformation::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
{
BufferedTransformation *t = AttachedTransformation();
if (t)
t->GetWaitObjects(container, callStack); // reduce clutter by not adding to stack here
}
void BufferedTransformation::Initialize(const NameValuePairs &parameters, int propagation)
{
assert(!AttachedTransformation());
IsolatedInitialize(parameters);
}
bool BufferedTransformation::Flush(bool hardFlush, int propagation, bool blocking)
{
assert(!AttachedTransformation());
return IsolatedFlush(hardFlush, blocking);
}
bool BufferedTransformation::MessageSeriesEnd(int propagation, bool blocking)
{
assert(!AttachedTransformation());
return IsolatedMessageSeriesEnd(blocking);
}
byte * BufferedTransformation::ChannelCreatePutSpace(const std::string &channel, size_t &size)
{
if (channel.empty())
return CreatePutSpace(size);
else
throw NoChannelSupport(AlgorithmName());
}
size_t BufferedTransformation::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
{
if (channel.empty())
return Put2(begin, length, messageEnd, blocking);
else
throw NoChannelSupport(AlgorithmName());
}
size_t BufferedTransformation::ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking)
{
if (channel.empty())
return PutModifiable2(begin, length, messageEnd, blocking);
else
return ChannelPut2(channel, begin, length, messageEnd, blocking);
}
bool BufferedTransformation::ChannelFlush(const std::string &channel, bool completeFlush, int propagation, bool blocking)
{
if (channel.empty())
return Flush(completeFlush, propagation, blocking);
else
throw NoChannelSupport(AlgorithmName());
}
bool BufferedTransformation::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking)
{
if (channel.empty())
return MessageSeriesEnd(propagation, blocking);
else
throw NoChannelSupport(AlgorithmName());
}
lword BufferedTransformation::MaxRetrievable() const
{
if (AttachedTransformation())
return AttachedTransformation()->MaxRetrievable();
else
return CopyTo(TheBitBucket());
}
bool BufferedTransformation::AnyRetrievable() const
{
if (AttachedTransformation())
return AttachedTransformation()->AnyRetrievable();
else
{
byte b;
return Peek(b) != 0;
}
}
size_t BufferedTransformation::Get(byte &outByte)
{
if (AttachedTransformation())
return AttachedTransformation()->Get(outByte);
else
return Get(&outByte, 1);
}
size_t BufferedTransformation::Get(byte *outString, size_t getMax)
{
if (AttachedTransformation())
return AttachedTransformation()->Get(outString, getMax);
else
{
ArraySink arraySink(outString, getMax);
return (size_t)TransferTo(arraySink, getMax);
}
}
size_t BufferedTransformation::Peek(byte &outByte) const
{
if (AttachedTransformation())
return AttachedTransformation()->Peek(outByte);
else
return Peek(&outByte, 1);
}
size_t BufferedTransformation::Peek(byte *outString, size_t peekMax) const
{
if (AttachedTransformation())
return AttachedTransformation()->Peek(outString, peekMax);
else
{
ArraySink arraySink(outString, peekMax);
return (size_t)CopyTo(arraySink, peekMax);
}
}
lword BufferedTransformation::Skip(lword skipMax)
{
if (AttachedTransformation())
return AttachedTransformation()->Skip(skipMax);
else
return TransferTo(TheBitBucket(), skipMax);
}
lword BufferedTransformation::TotalBytesRetrievable() const
{
if (AttachedTransformation())
return AttachedTransformation()->TotalBytesRetrievable();
else
return MaxRetrievable();
}
unsigned int BufferedTransformation::NumberOfMessages() const
{
if (AttachedTransformation())
return AttachedTransformation()->NumberOfMessages();
else
return CopyMessagesTo(TheBitBucket());
}
bool BufferedTransformation::AnyMessages() const
{
if (AttachedTransformation())
return AttachedTransformation()->AnyMessages();
else
return NumberOfMessages() != 0;
}
bool BufferedTransformation::GetNextMessage()
{
if (AttachedTransformation())
return AttachedTransformation()->GetNextMessage();
else
{
assert(!AnyMessages());
return false;
}
}
unsigned int BufferedTransformation::SkipMessages(unsigned int count)
{
if (AttachedTransformation())
return AttachedTransformation()->SkipMessages(count);
else
return TransferMessagesTo(TheBitBucket(), count);
}
size_t BufferedTransformation::TransferMessagesTo2(BufferedTransformation &target, unsigned int &messageCount, const std::string &channel, bool blocking)
{
if (AttachedTransformation())
return AttachedTransformation()->TransferMessagesTo2(target, messageCount, channel, blocking);
else
{
unsigned int maxMessages = messageCount;
for (messageCount=0; messageCount < maxMessages && AnyMessages(); messageCount++)
{
size_t blockedBytes;
lword transferredBytes;
while (AnyRetrievable())
{
transferredBytes = LWORD_MAX;
blockedBytes = TransferTo2(target, transferredBytes, channel, blocking);
if (blockedBytes > 0)
return blockedBytes;
}
if (target.ChannelMessageEnd(channel, GetAutoSignalPropagation(), blocking))
return 1;
bool result = GetNextMessage();
assert(result);
}
return 0;
}
}
unsigned int BufferedTransformation::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const
{
if (AttachedTransformation())
return AttachedTransformation()->CopyMessagesTo(target, count, channel);
else
return 0;
}
void BufferedTransformation::SkipAll()
{
if (AttachedTransformation())
AttachedTransformation()->SkipAll();
else
{
while (SkipMessages()) {}
while (Skip()) {}
}
}
size_t BufferedTransformation::TransferAllTo2(BufferedTransformation &target, const std::string &channel, bool blocking)
{
if (AttachedTransformation())
return AttachedTransformation()->TransferAllTo2(target, channel, blocking);
else
{
assert(!NumberOfMessageSeries());
unsigned int messageCount;
do
{
messageCount = UINT_MAX;
size_t blockedBytes = TransferMessagesTo2(target, messageCount, channel, blocking);
if (blockedBytes)
return blockedBytes;
}
while (messageCount != 0);
lword byteCount;
do
{
byteCount = ULONG_MAX;
size_t blockedBytes = TransferTo2(target, byteCount, channel, blocking);
if (blockedBytes)
return blockedBytes;
}
while (byteCount != 0);
return 0;
}
}
void BufferedTransformation::CopyAllTo(BufferedTransformation &target, const std::string &channel) const
{
if (AttachedTransformation())
AttachedTransformation()->CopyAllTo(target, channel);
else
{
assert(!NumberOfMessageSeries());
while (CopyMessagesTo(target, UINT_MAX, channel)) {}
}
}
void BufferedTransformation::SetRetrievalChannel(const std::string &channel)
{
if (AttachedTransformation())
AttachedTransformation()->SetRetrievalChannel(channel);
}
size_t BufferedTransformation::ChannelPutWord16(const std::string &channel, word16 value, ByteOrder order, bool blocking)
{
PutWord(false, order, m_buf, value);
return ChannelPut(channel, m_buf, 2, blocking);
}
size_t BufferedTransformation::ChannelPutWord32(const std::string &channel, word32 value, ByteOrder order, bool blocking)
{
PutWord(false, order, m_buf, value);
return ChannelPut(channel, m_buf, 4, blocking);
}
size_t BufferedTransformation::PutWord16(word16 value, ByteOrder order, bool blocking)
{
return ChannelPutWord16(DEFAULT_CHANNEL, value, order, blocking);
}
size_t BufferedTransformation::PutWord32(word32 value, ByteOrder order, bool blocking)
{
return ChannelPutWord32(DEFAULT_CHANNEL, value, order, blocking);
}
size_t BufferedTransformation::PeekWord16(word16 &value, ByteOrder order) const
{
byte buf[2] = {0, 0};
size_t len = Peek(buf, 2);
if (order)
value = (buf[0] << 8) | buf[1];
else
value = (buf[1] << 8) | buf[0];
return len;
}
size_t BufferedTransformation::PeekWord32(word32 &value, ByteOrder order) const
{
byte buf[4] = {0, 0, 0, 0};
size_t len = Peek(buf, 4);
if (order)
value = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf [3];
else
value = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf [0];
return len;
}
size_t BufferedTransformation::GetWord16(word16 &value, ByteOrder order)
{
return (size_t)Skip(PeekWord16(value, order));
}
size_t BufferedTransformation::GetWord32(word32 &value, ByteOrder order)
{
return (size_t)Skip(PeekWord32(value, order));
}
void BufferedTransformation::Attach(BufferedTransformation *newOut)
{
if (AttachedTransformation() && AttachedTransformation()->Attachable())
AttachedTransformation()->Attach(newOut);
else
Detach(newOut);
}
void GeneratableCryptoMaterial::GenerateRandomWithKeySize(RandomNumberGenerator &rng, unsigned int keySize)
{
GenerateRandom(rng, MakeParameters("KeySize", (int)keySize));
}
class PK_DefaultEncryptionFilter : public Unflushable<Filter>
{
public:
PK_DefaultEncryptionFilter(RandomNumberGenerator &rng, const PK_Encryptor &encryptor, BufferedTransformation *attachment, const NameValuePairs &parameters)
: m_rng(rng), m_encryptor(encryptor), m_parameters(parameters)
{
Detach(attachment);
}
size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
{
FILTER_BEGIN;
m_plaintextQueue.Put(inString, length);
if (messageEnd)
{
{
size_t plaintextLength;
if (!SafeConvert(m_plaintextQueue.CurrentSize(), plaintextLength))
throw InvalidArgument("PK_DefaultEncryptionFilter: plaintext too long");
size_t ciphertextLength = m_encryptor.CiphertextLength(plaintextLength);
SecByteBlock plaintext(plaintextLength);
m_plaintextQueue.Get(plaintext, plaintextLength);
m_ciphertext.resize(ciphertextLength);
m_encryptor.Encrypt(m_rng, plaintext, plaintextLength, m_ciphertext, m_parameters);
}
FILTER_OUTPUT(1, m_ciphertext, m_ciphertext.size(), messageEnd);
}
FILTER_END_NO_MESSAGE_END;
}
RandomNumberGenerator &m_rng;
const PK_Encryptor &m_encryptor;
const NameValuePairs &m_parameters;
ByteQueue m_plaintextQueue;
SecByteBlock m_ciphertext;
};
BufferedTransformation * PK_Encryptor::CreateEncryptionFilter(RandomNumberGenerator &rng, BufferedTransformation *attachment, const NameValuePairs &parameters) const
{
return new PK_DefaultEncryptionFilter(rng, *this, attachment, parameters);
}
class PK_DefaultDecryptionFilter : public Unflushable<Filter>
{
public:
PK_DefaultDecryptionFilter(RandomNumberGenerator &rng, const PK_Decryptor &decryptor, BufferedTransformation *attachment, const NameValuePairs &parameters)
: m_rng(rng), m_decryptor(decryptor), m_parameters(parameters)
{
Detach(attachment);
}
size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
{
FILTER_BEGIN;
m_ciphertextQueue.Put(inString, length);
if (messageEnd)
{
{
size_t ciphertextLength;
if (!SafeConvert(m_ciphertextQueue.CurrentSize(), ciphertextLength))
throw InvalidArgument("PK_DefaultDecryptionFilter: ciphertext too long");
size_t maxPlaintextLength = m_decryptor.MaxPlaintextLength(ciphertextLength);
SecByteBlock ciphertext(ciphertextLength);
m_ciphertextQueue.Get(ciphertext, ciphertextLength);
m_plaintext.resize(maxPlaintextLength);
m_result = m_decryptor.Decrypt(m_rng, ciphertext, ciphertextLength, m_plaintext, m_parameters);
if (!m_result.isValidCoding)
throw InvalidCiphertext(m_decryptor.AlgorithmName() + ": invalid ciphertext");
}
FILTER_OUTPUT(1, m_plaintext, m_result.messageLength, messageEnd);
}
FILTER_END_NO_MESSAGE_END;
}
RandomNumberGenerator &m_rng;
const PK_Decryptor &m_decryptor;
const NameValuePairs &m_parameters;
ByteQueue m_ciphertextQueue;
SecByteBlock m_plaintext;
DecodingResult m_result;
};
BufferedTransformation * PK_Decryptor::CreateDecryptionFilter(RandomNumberGenerator &rng, BufferedTransformation *attachment, const NameValuePairs &parameters) const
{
return new PK_DefaultDecryptionFilter(rng, *this, attachment, parameters);
}
size_t PK_Signer::Sign(RandomNumberGenerator &rng, PK_MessageAccumulator *messageAccumulator, byte *signature) const
{
std::auto_ptr<PK_MessageAccumulator> m(messageAccumulator);
return SignAndRestart(rng, *m, signature, false);
}
size_t PK_Signer::SignMessage(RandomNumberGenerator &rng, const byte *message, size_t messageLen, byte *signature) const
{
std::auto_ptr<PK_MessageAccumulator> m(NewSignatureAccumulator(rng));
m->Update(message, messageLen);
return SignAndRestart(rng, *m, signature, false);
}
size_t PK_Signer::SignMessageWithRecovery(RandomNumberGenerator &rng, const byte *recoverableMessage, size_t recoverableMessageLength,
const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength, byte *signature) const
{
std::auto_ptr<PK_MessageAccumulator> m(NewSignatureAccumulator(rng));
InputRecoverableMessage(*m, recoverableMessage, recoverableMessageLength);
m->Update(nonrecoverableMessage, nonrecoverableMessageLength);
return SignAndRestart(rng, *m, signature, false);
}
bool PK_Verifier::Verify(PK_MessageAccumulator *messageAccumulator) const
{
std::auto_ptr<PK_MessageAccumulator> m(messageAccumulator);
return VerifyAndRestart(*m);
}
bool PK_Verifier::VerifyMessage(const byte *message, size_t messageLen, const byte *signature, size_t signatureLength) const
{
std::auto_ptr<PK_MessageAccumulator> m(NewVerificationAccumulator());
InputSignature(*m, signature, signatureLength);
m->Update(message, messageLen);
return VerifyAndRestart(*m);
}
DecodingResult PK_Verifier::Recover(byte *recoveredMessage, PK_MessageAccumulator *messageAccumulator) const
{
std::auto_ptr<PK_MessageAccumulator> m(messageAccumulator);
return RecoverAndRestart(recoveredMessage, *m);
}
DecodingResult PK_Verifier::RecoverMessage(byte *recoveredMessage,
const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength,
const byte *signature, size_t signatureLength) const
{
std::auto_ptr<PK_MessageAccumulator> m(NewVerificationAccumulator());
InputSignature(*m, signature, signatureLength);
m->Update(nonrecoverableMessage, nonrecoverableMessageLength);
return RecoverAndRestart(recoveredMessage, *m);
}
void SimpleKeyAgreementDomain::GenerateKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
{
GeneratePrivateKey(rng, privateKey);
GeneratePublicKey(rng, privateKey, publicKey);
}
void AuthenticatedKeyAgreementDomain::GenerateStaticKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
{
GenerateStaticPrivateKey(rng, privateKey);
GenerateStaticPublicKey(rng, privateKey, publicKey);
}
void AuthenticatedKeyAgreementDomain::GenerateEphemeralKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
{
GenerateEphemeralPrivateKey(rng, privateKey);
GenerateEphemeralPublicKey(rng, privateKey, publicKey);
}
NAMESPACE_END
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,258 +0,0 @@
// default.cpp - written and placed in the public domain by Wei Dai
#include "pch.h"
#include "default.h"
#include "queue.h"
#include <time.h>
#include <memory>
NAMESPACE_BEGIN(CryptoPP)
static const unsigned int MASH_ITERATIONS = 200;
static const unsigned int SALTLENGTH = 8;
static const unsigned int BLOCKSIZE = Default_BlockCipher::Encryption::BLOCKSIZE;
static const unsigned int KEYLENGTH = Default_BlockCipher::Encryption::DEFAULT_KEYLENGTH;
// The purpose of this function Mash() is to take an arbitrary length input
// string and *deterministicly* produce an arbitrary length output string such
// that (1) it looks random, (2) no information about the input is
// deducible from it, and (3) it contains as much entropy as it can hold, or
// the amount of entropy in the input string, whichever is smaller.
static void Mash(const byte *in, size_t inLen, byte *out, size_t outLen, int iterations)
{
if (BytePrecision(outLen) > 2)
throw InvalidArgument("Mash: output legnth too large");
size_t bufSize = RoundUpToMultipleOf(outLen, (size_t)DefaultHashModule::DIGESTSIZE);
byte b[2];
SecByteBlock buf(bufSize);
SecByteBlock outBuf(bufSize);
DefaultHashModule hash;
unsigned int i;
for(i=0; i<outLen; i+=DefaultHashModule::DIGESTSIZE)
{
b[0] = (byte) (i >> 8);
b[1] = (byte) i;
hash.Update(b, 2);
hash.Update(in, inLen);
hash.Final(outBuf+i);
}
while (iterations-- > 1)
{
memcpy(buf, outBuf, bufSize);
for (i=0; i<bufSize; i+=DefaultHashModule::DIGESTSIZE)
{
b[0] = (byte) (i >> 8);
b[1] = (byte) i;
hash.Update(b, 2);
hash.Update(buf, bufSize);
hash.Final(outBuf+i);
}
}
memcpy(out, outBuf, outLen);
}
static void GenerateKeyIV(const byte *passphrase, size_t passphraseLength, const byte *salt, size_t saltLength, byte *key, byte *IV)
{
SecByteBlock temp(passphraseLength+saltLength);
memcpy(temp, passphrase, passphraseLength);
memcpy(temp+passphraseLength, salt, saltLength);
SecByteBlock keyIV(KEYLENGTH+BLOCKSIZE);
Mash(temp, passphraseLength + saltLength, keyIV, KEYLENGTH+BLOCKSIZE, MASH_ITERATIONS);
memcpy(key, keyIV, KEYLENGTH);
memcpy(IV, keyIV+KEYLENGTH, BLOCKSIZE);
}
// ********************************************************
DefaultEncryptor::DefaultEncryptor(const char *passphrase, BufferedTransformation *attachment)
: ProxyFilter(NULL, 0, 0, attachment), m_passphrase((const byte *)passphrase, strlen(passphrase))
{
}
DefaultEncryptor::DefaultEncryptor(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment)
: ProxyFilter(NULL, 0, 0, attachment), m_passphrase(passphrase, passphraseLength)
{
}
void DefaultEncryptor::FirstPut(const byte *)
{
// VC60 workaround: __LINE__ expansion bug
CRYPTOPP_COMPILE_ASSERT_INSTANCE(SALTLENGTH <= DefaultHashModule::DIGESTSIZE, 1);
CRYPTOPP_COMPILE_ASSERT_INSTANCE(BLOCKSIZE <= DefaultHashModule::DIGESTSIZE, 2);
SecByteBlock salt(DefaultHashModule::DIGESTSIZE), keyCheck(DefaultHashModule::DIGESTSIZE);
DefaultHashModule hash;
// use hash(passphrase | time | clock) as salt
hash.Update(m_passphrase, m_passphrase.size());
time_t t=time(0);
hash.Update((byte *)&t, sizeof(t));
clock_t c=clock();
hash.Update((byte *)&c, sizeof(c));
hash.Final(salt);
// use hash(passphrase | salt) as key check
hash.Update(m_passphrase, m_passphrase.size());
hash.Update(salt, SALTLENGTH);
hash.Final(keyCheck);
AttachedTransformation()->Put(salt, SALTLENGTH);
// mash passphrase and salt together into key and IV
SecByteBlock key(KEYLENGTH);
SecByteBlock IV(BLOCKSIZE);
GenerateKeyIV(m_passphrase, m_passphrase.size(), salt, SALTLENGTH, key, IV);
m_cipher.SetKeyWithIV(key, key.size(), IV);
SetFilter(new StreamTransformationFilter(m_cipher));
m_filter->Put(keyCheck, BLOCKSIZE);
}
void DefaultEncryptor::LastPut(const byte *inString, size_t length)
{
m_filter->MessageEnd();
}
// ********************************************************
DefaultDecryptor::DefaultDecryptor(const char *p, BufferedTransformation *attachment, bool throwException)
: ProxyFilter(NULL, SALTLENGTH+BLOCKSIZE, 0, attachment)
, m_state(WAITING_FOR_KEYCHECK)
, m_passphrase((const byte *)p, strlen(p))
, m_throwException(throwException)
{
}
DefaultDecryptor::DefaultDecryptor(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment, bool throwException)
: ProxyFilter(NULL, SALTLENGTH+BLOCKSIZE, 0, attachment)
, m_state(WAITING_FOR_KEYCHECK)
, m_passphrase(passphrase, passphraseLength)
, m_throwException(throwException)
{
}
void DefaultDecryptor::FirstPut(const byte *inString)
{
CheckKey(inString, inString+SALTLENGTH);
}
void DefaultDecryptor::LastPut(const byte *inString, size_t length)
{
if (m_filter.get() == NULL)
{
m_state = KEY_BAD;
if (m_throwException)
throw KeyBadErr();
}
else
{
m_filter->MessageEnd();
m_state = WAITING_FOR_KEYCHECK;
}
}
void DefaultDecryptor::CheckKey(const byte *salt, const byte *keyCheck)
{
SecByteBlock check(STDMAX((unsigned int)2*BLOCKSIZE, (unsigned int)DefaultHashModule::DIGESTSIZE));
DefaultHashModule hash;
hash.Update(m_passphrase, m_passphrase.size());
hash.Update(salt, SALTLENGTH);
hash.Final(check);
SecByteBlock key(KEYLENGTH);
SecByteBlock IV(BLOCKSIZE);
GenerateKeyIV(m_passphrase, m_passphrase.size(), salt, SALTLENGTH, key, IV);
m_cipher.SetKeyWithIV(key, key.size(), IV);
std::auto_ptr<StreamTransformationFilter> decryptor(new StreamTransformationFilter(m_cipher));
decryptor->Put(keyCheck, BLOCKSIZE);
decryptor->ForceNextPut();
decryptor->Get(check+BLOCKSIZE, BLOCKSIZE);
SetFilter(decryptor.release());
if (!VerifyBufsEqual(check, check+BLOCKSIZE, BLOCKSIZE))
{
m_state = KEY_BAD;
if (m_throwException)
throw KeyBadErr();
}
else
m_state = KEY_GOOD;
}
// ********************************************************
static DefaultMAC * NewDefaultEncryptorMAC(const byte *passphrase, size_t passphraseLength)
{
size_t macKeyLength = DefaultMAC::StaticGetValidKeyLength(16);
SecByteBlock macKey(macKeyLength);
// since the MAC is encrypted there is no reason to mash the passphrase for many iterations
Mash(passphrase, passphraseLength, macKey, macKeyLength, 1);
return new DefaultMAC(macKey, macKeyLength);
}
DefaultEncryptorWithMAC::DefaultEncryptorWithMAC(const char *passphrase, BufferedTransformation *attachment)
: ProxyFilter(NULL, 0, 0, attachment)
, m_mac(NewDefaultEncryptorMAC((const byte *)passphrase, strlen(passphrase)))
{
SetFilter(new HashFilter(*m_mac, new DefaultEncryptor(passphrase), true));
}
DefaultEncryptorWithMAC::DefaultEncryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment)
: ProxyFilter(NULL, 0, 0, attachment)
, m_mac(NewDefaultEncryptorMAC(passphrase, passphraseLength))
{
SetFilter(new HashFilter(*m_mac, new DefaultEncryptor(passphrase, passphraseLength), true));
}
void DefaultEncryptorWithMAC::LastPut(const byte *inString, size_t length)
{
m_filter->MessageEnd();
}
// ********************************************************
DefaultDecryptorWithMAC::DefaultDecryptorWithMAC(const char *passphrase, BufferedTransformation *attachment, bool throwException)
: ProxyFilter(NULL, 0, 0, attachment)
, m_mac(NewDefaultEncryptorMAC((const byte *)passphrase, strlen(passphrase)))
, m_throwException(throwException)
{
SetFilter(new DefaultDecryptor(passphrase, m_hashVerifier=new HashVerifier(*m_mac, NULL, HashVerifier::PUT_MESSAGE), throwException));
}
DefaultDecryptorWithMAC::DefaultDecryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment, bool throwException)
: ProxyFilter(NULL, 0, 0, attachment)
, m_mac(NewDefaultEncryptorMAC(passphrase, passphraseLength))
, m_throwException(throwException)
{
SetFilter(new DefaultDecryptor(passphrase, passphraseLength, m_hashVerifier=new HashVerifier(*m_mac, NULL, HashVerifier::PUT_MESSAGE), throwException));
}
DefaultDecryptor::State DefaultDecryptorWithMAC::CurrentState() const
{
return static_cast<const DefaultDecryptor *>(m_filter.get())->CurrentState();
}
bool DefaultDecryptorWithMAC::CheckLastMAC() const
{
return m_hashVerifier->GetLastResult();
}
void DefaultDecryptorWithMAC::LastPut(const byte *inString, size_t length)
{
m_filter->MessageEnd();
if (m_throwException && !CheckLastMAC())
throw MACBadErr();
}
NAMESPACE_END

Some files were not shown because too many files have changed in this diff Show More