├── .gitignore ├── .gitmodules ├── .travis.yml ├── CMakeLists.txt ├── COPYING ├── INSTALL ├── Makefile.am ├── README.md ├── autogen.sh ├── cmake ├── FindB64.cmake ├── FindCURLpp.cmake ├── FindGpgme.cmake ├── Findglib.cmake ├── Findglibmm.cmake └── Findsigc++.cmake ├── config └── dpaste.conf ├── configure.ac ├── doc └── dpaste.1 ├── docker ├── DockerfileBase └── DockerfileTravis ├── m4 └── ax_cxx_compile_stdcxx.m4 ├── src ├── Makefile.am ├── aescrypto.cpp ├── aescrypto.h ├── bin.cpp ├── bin.h ├── cipher.cpp ├── cipher.h ├── conf.cpp ├── conf.h ├── curlpp │ └── Options.hpp ├── gpgcrypto.cpp ├── gpgcrypto.h ├── http_client.cpp ├── http_client.h ├── log.cpp ├── log.h ├── main.cpp ├── node.cpp └── node.h └── tests ├── Makefile.am ├── aes.cpp ├── bin.cpp ├── conf.cpp ├── misc ├── dpaste.conf.1 └── dpaste.conf.2 ├── node.cpp ├── tests.cpp └── tests.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.o 3 | *.obj 4 | src/dpaste 5 | tests/dptest 6 | 7 | # Executables 8 | *.exe 9 | *.out 10 | *.app 11 | 12 | # git backup files 13 | *.orig 14 | 15 | # vim swap files 16 | *.swp 17 | *.swo 18 | 19 | # Ctags 20 | tags 21 | 22 | # YCM 23 | .ycm_extra_conf.py* 24 | compile_commands.json 25 | 26 | # autotools files 27 | /ac 28 | Makefile 29 | Makefile.in 30 | /aclocal.m4 31 | /autom4te.cache/ 32 | /config.* 33 | /configure 34 | /depcomp 35 | /install-sh 36 | /libtool 37 | /ltmain.sh 38 | /m4/ 39 | /missing 40 | /stamp-h? 41 | .deps/ 42 | .dirstamp 43 | .libs/ 44 | *.l[ao] 45 | *~ 46 | *.pc 47 | 48 | # CMake dir 49 | build 50 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sim590/dpaste/7a56e2b0b4204b400fa3987587c7ec287771c46e/.gitmodules -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | 3 | services: 4 | - docker 5 | 6 | language: cpp 7 | 8 | before_install: docker pull sim590/dpaste-ci 9 | 10 | script: 11 | - docker build -t dpaste-test -f docker/DockerfileTravis . 12 | - docker run dpaste-test /bin/sh -c 'cd root/dpaste && ./configure --enable-tests && make test && cd .. && rm -rf dpaste' 13 | 14 | # vim: set ts=4 sw=4 tw=80 et : 15 | 16 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | project(dpaste) 3 | set(dpaste_VERSION 0.4.1) 4 | add_definitions(-DVERSION="${dpaste_VERSION}") 5 | add_definitions(-DPACKAGE_NAME="dpaste") 6 | 7 | set(CMAKE_CXX_STANDARD 17) 8 | set(THREADS_PREFER_PTHREAD_FLAG ON) 9 | 10 | ################### 11 | # CMake modules # 12 | ################### 13 | list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") 14 | 15 | ############################ 16 | # Find required packages # 17 | ############################ 18 | find_package(opendht 1.2.0 REQUIRED) 19 | find_package(CURLpp REQUIRED) 20 | find_package(glibmm REQUIRED) 21 | find_package(B64 REQUIRED) 22 | find_package(Gpgme) 23 | find_package(Threads REQUIRED) 24 | find_package(nlohmann_json 3 REQUIRED) 25 | 26 | ##################################### 27 | # dpaste headers and source files # 28 | ##################################### 29 | list(APPEND dpaste_HEADERS 30 | src/node.h 31 | src/conf.h 32 | src/http_client.h 33 | src/bin.h 34 | src/gpgcrypto.h 35 | src/log.h 36 | src/cipher.h 37 | src/aescrypto.h 38 | ) 39 | list(APPEND dpaste_SOURCES 40 | src/main.cpp 41 | src/node.cpp 42 | src/conf.cpp 43 | src/http_client.cpp 44 | src/bin.cpp 45 | src/gpgcrypto.cpp 46 | src/log.cpp 47 | src/cipher.cpp 48 | src/aescrypto.cpp 49 | ) 50 | 51 | ################################# 52 | # dpaste building and linking # 53 | ################################# 54 | include_directories(${CURLPP_INCLUDE_DIRS} ${glibmm_INCLUDE_DIRS} ${B64_INCLUDE_DIRS} ${GPGME_INCLUDE_DIRS}) 55 | add_executable(dpaste ${dpaste_SOURCES} ${dpaste_HEADERS}) 56 | target_link_libraries(dpaste LINK_PUBLIC -lopendht -lgnutls -lnettle -largon2 -lpthread ${CURLPP_LIBRARIES} ${glibmm_LIBRARIES} ${B64_LIBRARIES} -lgpgmepp ${GPGME_VANILLA_LIBRARIES}) 57 | 58 | ##################### 59 | # install targets # 60 | ##################### 61 | install(TARGETS dpaste DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) 62 | 63 | # vim: set ts=4 sw=4 tw=120 noet : 64 | 65 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Installation Instructions 2 | ************************* 3 | 4 | Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation, 5 | Inc. 6 | 7 | Copying and distribution of this file, with or without modification, 8 | are permitted in any medium without royalty provided the copyright 9 | notice and this notice are preserved. This file is offered as-is, 10 | without warranty of any kind. 11 | 12 | Basic Installation 13 | ================== 14 | 15 | Briefly, the shell command `./configure && make && make install' 16 | should configure, build, and install this package. The following 17 | more-detailed instructions are generic; see the `README' file for 18 | instructions specific to this package. Some packages provide this 19 | `INSTALL' file but do not implement all of the features documented 20 | below. The lack of an optional feature in a given package is not 21 | necessarily a bug. More recommendations for GNU packages can be found 22 | in *note Makefile Conventions: (standards)Makefile Conventions. 23 | 24 | The `configure' shell script attempts to guess correct values for 25 | various system-dependent variables used during compilation. It uses 26 | those values to create a `Makefile' in each directory of the package. 27 | It may also create one or more `.h' files containing system-dependent 28 | definitions. Finally, it creates a shell script `config.status' that 29 | you can run in the future to recreate the current configuration, and a 30 | file `config.log' containing compiler output (useful mainly for 31 | debugging `configure'). 32 | 33 | It can also use an optional file (typically called `config.cache' 34 | and enabled with `--cache-file=config.cache' or simply `-C') that saves 35 | the results of its tests to speed up reconfiguring. Caching is 36 | disabled by default to prevent problems with accidental use of stale 37 | cache files. 38 | 39 | If you need to do unusual things to compile the package, please try 40 | to figure out how `configure' could check whether to do them, and mail 41 | diffs or instructions to the address given in the `README' so they can 42 | be considered for the next release. If you are using the cache, and at 43 | some point `config.cache' contains results you don't want to keep, you 44 | may remove or edit it. 45 | 46 | The file `configure.ac' (or `configure.in') is used to create 47 | `configure' by a program called `autoconf'. You need `configure.ac' if 48 | you want to change it or regenerate `configure' using a newer version 49 | of `autoconf'. 50 | 51 | The simplest way to compile this package is: 52 | 53 | 1. `cd' to the directory containing the package's source code and type 54 | `./configure' to configure the package for your system. 55 | 56 | Running `configure' might take a while. While running, it prints 57 | some messages telling which features it is checking for. 58 | 59 | 2. Type `make' to compile the package. 60 | 61 | 3. Optionally, type `make check' to run any self-tests that come with 62 | the package, generally using the just-built uninstalled binaries. 63 | 64 | 4. Type `make install' to install the programs and any data files and 65 | documentation. When installing into a prefix owned by root, it is 66 | recommended that the package be configured and built as a regular 67 | user, and only the `make install' phase executed with root 68 | privileges. 69 | 70 | 5. Optionally, type `make installcheck' to repeat any self-tests, but 71 | this time using the binaries in their final installed location. 72 | This target does not install anything. Running this target as a 73 | regular user, particularly if the prior `make install' required 74 | root privileges, verifies that the installation completed 75 | correctly. 76 | 77 | 6. You can remove the program binaries and object files from the 78 | source code directory by typing `make clean'. To also remove the 79 | files that `configure' created (so you can compile the package for 80 | a different kind of computer), type `make distclean'. There is 81 | also a `make maintainer-clean' target, but that is intended mainly 82 | for the package's developers. If you use it, you may have to get 83 | all sorts of other programs in order to regenerate files that came 84 | with the distribution. 85 | 86 | 7. Often, you can also type `make uninstall' to remove the installed 87 | files again. In practice, not all packages have tested that 88 | uninstallation works correctly, even though it is required by the 89 | GNU Coding Standards. 90 | 91 | 8. Some packages, particularly those that use Automake, provide `make 92 | distcheck', which can by used by developers to test that all other 93 | targets like `make install' and `make uninstall' work correctly. 94 | This target is generally not run by end users. 95 | 96 | Compilers and Options 97 | ===================== 98 | 99 | Some systems require unusual options for compilation or linking that 100 | the `configure' script does not know about. Run `./configure --help' 101 | for details on some of the pertinent environment variables. 102 | 103 | You can give `configure' initial values for configuration parameters 104 | by setting variables in the command line or in the environment. Here 105 | is an example: 106 | 107 | ./configure CC=c99 CFLAGS=-g LIBS=-lposix 108 | 109 | *Note Defining Variables::, for more details. 110 | 111 | Compiling For Multiple Architectures 112 | ==================================== 113 | 114 | You can compile the package for more than one kind of computer at the 115 | same time, by placing the object files for each architecture in their 116 | own directory. To do this, you can use GNU `make'. `cd' to the 117 | directory where you want the object files and executables to go and run 118 | the `configure' script. `configure' automatically checks for the 119 | source code in the directory that `configure' is in and in `..'. This 120 | is known as a "VPATH" build. 121 | 122 | With a non-GNU `make', it is safer to compile the package for one 123 | architecture at a time in the source code directory. After you have 124 | installed the package for one architecture, use `make distclean' before 125 | reconfiguring for another architecture. 126 | 127 | On MacOS X 10.5 and later systems, you can create libraries and 128 | executables that work on multiple system types--known as "fat" or 129 | "universal" binaries--by specifying multiple `-arch' options to the 130 | compiler but only a single `-arch' option to the preprocessor. Like 131 | this: 132 | 133 | ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ 134 | CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ 135 | CPP="gcc -E" CXXCPP="g++ -E" 136 | 137 | This is not guaranteed to produce working output in all cases, you 138 | may have to build one architecture at a time and combine the results 139 | using the `lipo' tool if you have problems. 140 | 141 | Installation Names 142 | ================== 143 | 144 | By default, `make install' installs the package's commands under 145 | `/usr/local/bin', include files under `/usr/local/include', etc. You 146 | can specify an installation prefix other than `/usr/local' by giving 147 | `configure' the option `--prefix=PREFIX', where PREFIX must be an 148 | absolute file name. 149 | 150 | You can specify separate installation prefixes for 151 | architecture-specific files and architecture-independent files. If you 152 | pass the option `--exec-prefix=PREFIX' to `configure', the package uses 153 | PREFIX as the prefix for installing programs and libraries. 154 | Documentation and other data files still use the regular prefix. 155 | 156 | In addition, if you use an unusual directory layout you can give 157 | options like `--bindir=DIR' to specify different values for particular 158 | kinds of files. Run `configure --help' for a list of the directories 159 | you can set and what kinds of files go in them. In general, the 160 | default for these options is expressed in terms of `${prefix}', so that 161 | specifying just `--prefix' will affect all of the other directory 162 | specifications that were not explicitly provided. 163 | 164 | The most portable way to affect installation locations is to pass the 165 | correct locations to `configure'; however, many packages provide one or 166 | both of the following shortcuts of passing variable assignments to the 167 | `make install' command line to change installation locations without 168 | having to reconfigure or recompile. 169 | 170 | The first method involves providing an override variable for each 171 | affected directory. For example, `make install 172 | prefix=/alternate/directory' will choose an alternate location for all 173 | directory configuration variables that were expressed in terms of 174 | `${prefix}'. Any directories that were specified during `configure', 175 | but not in terms of `${prefix}', must each be overridden at install 176 | time for the entire installation to be relocated. The approach of 177 | makefile variable overrides for each directory variable is required by 178 | the GNU Coding Standards, and ideally causes no recompilation. 179 | However, some platforms have known limitations with the semantics of 180 | shared libraries that end up requiring recompilation when using this 181 | method, particularly noticeable in packages that use GNU Libtool. 182 | 183 | The second method involves providing the `DESTDIR' variable. For 184 | example, `make install DESTDIR=/alternate/directory' will prepend 185 | `/alternate/directory' before all installation names. The approach of 186 | `DESTDIR' overrides is not required by the GNU Coding Standards, and 187 | does not work on platforms that have drive letters. On the other hand, 188 | it does better at avoiding recompilation issues, and works well even 189 | when some directory options were not specified in terms of `${prefix}' 190 | at `configure' time. 191 | 192 | Optional Features 193 | ================= 194 | 195 | If the package supports it, you can cause programs to be installed 196 | with an extra prefix or suffix on their names by giving `configure' the 197 | option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. 198 | 199 | Some packages pay attention to `--enable-FEATURE' options to 200 | `configure', where FEATURE indicates an optional part of the package. 201 | They may also pay attention to `--with-PACKAGE' options, where PACKAGE 202 | is something like `gnu-as' or `x' (for the X Window System). The 203 | `README' should mention any `--enable-' and `--with-' options that the 204 | package recognizes. 205 | 206 | For packages that use the X Window System, `configure' can usually 207 | find the X include and library files automatically, but if it doesn't, 208 | you can use the `configure' options `--x-includes=DIR' and 209 | `--x-libraries=DIR' to specify their locations. 210 | 211 | Some packages offer the ability to configure how verbose the 212 | execution of `make' will be. For these packages, running `./configure 213 | --enable-silent-rules' sets the default to minimal output, which can be 214 | overridden with `make V=1'; while running `./configure 215 | --disable-silent-rules' sets the default to verbose, which can be 216 | overridden with `make V=0'. 217 | 218 | Particular systems 219 | ================== 220 | 221 | On HP-UX, the default C compiler is not ANSI C compatible. If GNU 222 | CC is not installed, it is recommended to use the following options in 223 | order to use an ANSI C compiler: 224 | 225 | ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" 226 | 227 | and if that doesn't work, install pre-built binaries of GCC for HP-UX. 228 | 229 | HP-UX `make' updates targets which have the same time stamps as 230 | their prerequisites, which makes it generally unusable when shipped 231 | generated files such as `configure' are involved. Use GNU `make' 232 | instead. 233 | 234 | On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot 235 | parse its `' header file. The option `-nodtk' can be used as 236 | a workaround. If GNU CC is not installed, it is therefore recommended 237 | to try 238 | 239 | ./configure CC="cc" 240 | 241 | and if that doesn't work, try 242 | 243 | ./configure CC="cc -nodtk" 244 | 245 | On Solaris, don't put `/usr/ucb' early in your `PATH'. This 246 | directory contains several dysfunctional programs; working variants of 247 | these programs are available in `/usr/bin'. So, if you need `/usr/ucb' 248 | in your `PATH', put it _after_ `/usr/bin'. 249 | 250 | On Haiku, software installed for all users goes in `/boot/common', 251 | not `/usr/local'. It is recommended to use the following options: 252 | 253 | ./configure --prefix=/boot/common 254 | 255 | Specifying the System Type 256 | ========================== 257 | 258 | There may be some features `configure' cannot figure out 259 | automatically, but needs to determine by the type of machine the package 260 | will run on. Usually, assuming the package is built to be run on the 261 | _same_ architectures, `configure' can figure that out, but if it prints 262 | a message saying it cannot guess the machine type, give it the 263 | `--build=TYPE' option. TYPE can either be a short name for the system 264 | type, such as `sun4', or a canonical name which has the form: 265 | 266 | CPU-COMPANY-SYSTEM 267 | 268 | where SYSTEM can have one of these forms: 269 | 270 | OS 271 | KERNEL-OS 272 | 273 | See the file `config.sub' for the possible values of each field. If 274 | `config.sub' isn't included in this package, then this package doesn't 275 | need to know the machine type. 276 | 277 | If you are _building_ compiler tools for cross-compiling, you should 278 | use the option `--target=TYPE' to select the type of system they will 279 | produce code for. 280 | 281 | If you want to _use_ a cross compiler, that generates code for a 282 | platform different from the build platform, you should specify the 283 | "host" platform (i.e., that on which the generated programs will 284 | eventually be run) with `--host=TYPE'. 285 | 286 | Sharing Defaults 287 | ================ 288 | 289 | If you want to set default values for `configure' scripts to share, 290 | you can create a site shell script called `config.site' that gives 291 | default values for variables like `CC', `cache_file', and `prefix'. 292 | `configure' looks for `PREFIX/share/config.site' if it exists, then 293 | `PREFIX/etc/config.site' if it exists. Or, you can set the 294 | `CONFIG_SITE' environment variable to the location of the site script. 295 | A warning: not all `configure' scripts look for a site script. 296 | 297 | Defining Variables 298 | ================== 299 | 300 | Variables not defined in a site shell script can be set in the 301 | environment passed to `configure'. However, some packages may run 302 | configure again during the build, and the customized values of these 303 | variables may be lost. In order to avoid this problem, you should set 304 | them in the `configure' command line, using `VAR=value'. For example: 305 | 306 | ./configure CC=/usr/local2/bin/gcc 307 | 308 | causes the specified `gcc' to be used as the C compiler (unless it is 309 | overridden in the site shell script). 310 | 311 | Unfortunately, this technique does not work for `CONFIG_SHELL' due to 312 | an Autoconf limitation. Until the limitation is lifted, you can use 313 | this workaround: 314 | 315 | CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash 316 | 317 | `configure' Invocation 318 | ====================== 319 | 320 | `configure' recognizes the following options to control how it 321 | operates. 322 | 323 | `--help' 324 | `-h' 325 | Print a summary of all of the options to `configure', and exit. 326 | 327 | `--help=short' 328 | `--help=recursive' 329 | Print a summary of the options unique to this package's 330 | `configure', and exit. The `short' variant lists options used 331 | only in the top level, while the `recursive' variant lists options 332 | also present in any nested packages. 333 | 334 | `--version' 335 | `-V' 336 | Print the version of Autoconf used to generate the `configure' 337 | script, and exit. 338 | 339 | `--cache-file=FILE' 340 | Enable the cache: use and save the results of the tests in FILE, 341 | traditionally `config.cache'. FILE defaults to `/dev/null' to 342 | disable caching. 343 | 344 | `--config-cache' 345 | `-C' 346 | Alias for `--cache-file=config.cache'. 347 | 348 | `--quiet' 349 | `--silent' 350 | `-q' 351 | Do not print messages saying which checks are being made. To 352 | suppress all normal output, redirect it to `/dev/null' (any error 353 | messages will still be shown). 354 | 355 | `--srcdir=DIR' 356 | Look for the package's source code in directory DIR. Usually 357 | `configure' can determine that directory automatically. 358 | 359 | `--prefix=DIR' 360 | Use DIR as the installation prefix. *note Installation Names:: 361 | for more details, including other options available for fine-tuning 362 | the installation locations. 363 | 364 | `--no-create' 365 | `-n' 366 | Run the configure checks, but stop before creating any output 367 | files. 368 | 369 | `configure' also accepts some other, not widely useful, options. Run 370 | `configure --help' for more details. 371 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | dpaste_CPPFLAGS_ = ${GLIBMM_CFLAGS} ${CURLPP_CLFAGS} ${GPGME_CFLAGS} 3 | dpaste_LIBS = ${OpenDHT_LIBS} ${GLIBMM_LIBS} ${CURLPP_LIBS} -lb64 -lgpgmepp ${GPGME_LIBS} 4 | export 5 | 6 | SUBDIRS = src 7 | if DPASTE_TEST 8 | SUBDIRS += tests 9 | endif 10 | 11 | dist_man1_MANS = doc/dpaste.1 12 | 13 | ACLOCAL_AMFLAGS = -I m4 14 | 15 | DOC_FILES = \ 16 | README.md \ 17 | config/dpaste.conf \ 18 | COPYING 19 | 20 | EXTRA_DIST = \ 21 | $(DOC_FILES) 22 | 23 | test: check 24 | if DPASTE_TEST 25 | ./tests/dptest $(DPTEST_ARGS) 26 | endif 27 | 28 | # vim: set ts=4 sw=4 tw=120 noet : 29 | 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dpaste 2 | 3 | A simple pastebin for light values (max 64KB) using OpenDHT distributed hash table. 4 | ## Example 5 | 6 | Let a file `A.md` you want to share. 7 | ```sh 8 | $ dpaste < A.md 9 | DPASTE: Pasting data... 10 | dpaste:74236E62 11 | ``` 12 | 13 | You can share this PIN (one can omit the string `dpaste:`). It is used to 14 | retrieve the pasted file within 10 minutes by simply doing: 15 | ```sh 16 | $ dpaste -g dpaste:74236E62 17 | ``` 18 | 19 | ## Encryption 20 | 21 | One can encrypt his document using the option `--aes-encrypt` or 22 | `--gpg-encrypt -r {recipient}`. In the former case, AES-GCM is used and in 23 | the latter it is simple GPG encryption. One can also *sign-then-encrypt* his 24 | message by adding the flag `-s` (a working gpg configuration needs to be found 25 | on the system). If both `--aes-encrypt` and `--gpg-encrypt` (or `-s`) options 26 | are present, aes encryption method is used. 27 | 28 | ### AES 29 | 30 | When using `--aes-encrypt`, `dpaste` will generate a random 32-bit passphrase 31 | which will then be stretched using [argon2][] crypto library. This is all 32 | handled by OpenDHT crypto layer. After pasting the blob, the returned PIN will 33 | be 64 bits long instead of the classic 32 bits. Indeed, the generated 32-bit 34 | password is appended to the location code used to index on the DHT. For e.g.: 35 | 36 | ```sh 37 | $ dpaste --aes-encrypt < ${some_file} 38 | DPASTE: Encrypting (aes-gcm) data... 39 | DPASTE: Pasting data... 40 | dpaste:B79F2F91C811D5DC 41 | ``` 42 | 43 | Therefore, the blob will be pasted on `HASH("B79F2F91")` and encrypted with 44 | a key derived from the passphrase `C811D5DC`. 45 | 46 | [argon2]: https://github.com/P-H-C/phc-winner-argon2 47 | 48 | ## How to build 49 | 50 | Assuming you have the installed the project dependencies prior to this, you can 51 | either use CMake or GNU Autotools to build. A `c++17` compliant compiler is 52 | required to compile the program. 53 | 54 | ### Using GNU Autotools 55 | 56 | ```sh 57 | $ ./autogen.sh 58 | $ ./configure 59 | $ make 60 | ``` 61 | 62 | You'll then find the binary under `src/` directory. 63 | 64 | ### Using CMake 65 | 66 | ```sh 67 | $ mkdir build && cd build 68 | $ cmake .. 69 | $ make 70 | ``` 71 | 72 | You'll then find the binary `dpaste` under `build` directory. 73 | 74 | ## Package 75 | 76 | Archlinux AUR: https://aur.archlinux.org/packages/dpaste/ 77 | 78 | Milis Linux: mps kur dpaste (https://github.com/milisarge/malfs-milis/blob/master/talimatname/genel/dpaste/talimat) 79 | 80 | ## Dependencies 81 | 82 | - [OpenDHT](https://github.com/savoirfairelinux/opendht/) (minimal version: 1.2.0) 83 | - [msgpack-c](https://github.com/msgpack/msgpack-c) 84 | - [gpgmepp](https://github.com/KDE/gpgmepp) 85 | - [json.hpp](https://github.com/nlohmann/json) (required version for CMake: 2.1.1) 86 | - [cURLpp](https://github.com/jpbarrette/curlpp) (minimal version: 0.8.1) 87 | - [glibmm](https://github.com/GNOME/glibmm) 88 | - [libb64](http://libb64.sourceforge.net/) 89 | - Getopt 90 | - [catch](https://github.com/catchorg/Catch2) for unit tests 91 | 92 | ## Pastebin over DHT 93 | 94 | A DHT is efficient and requires no infrastructure. In practice, you can always 95 | count on the network to host your data for you since a distributed network is 96 | not likely to be "down". 97 | 98 | ## Roadmap 99 | 100 | - Add support for values with size greater than 64KiB (splitting values across 101 | multiple locations, see #17); 102 | - Support for multi-lingual interface (--help, info/debug messages, see #18); 103 | - Support for longer paste life time (OpenDHT's default is 10 minutes, see #19); 104 | - Switch from the currently used [small python REST API server script][pyserver] to 105 | OpenDHT's proxy (see #20); 106 | - Improve the logging code (with dedicated library?); 107 | - ~~Password based encryption (AES using gnutls)~~; 108 | - ~~Add user configuration file system;~~ 109 | - ~~Support RSA encrypt/sign using user's GPG key;~~ 110 | - ~~Support running the DHT node as service for executing dpaste operations.~~ 111 | 112 | [pyserver]: https://github.com/savoirfairelinux/opendht/blob/459c1344aac37519ccdf19aebff56027771d2e72/python/tools/http_server.py 113 | 114 | ## Author 115 | 116 | - Simon Désaulniers 117 | - Adrien Béraud 118 | 119 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | autoreconf --install --verbose -Wall 2 | -------------------------------------------------------------------------------- /cmake/FindB64.cmake: -------------------------------------------------------------------------------- 1 | if(B64_PREFER_STATIC_LIB) 2 | set(B64_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) 3 | if(WIN32) 4 | set(CMAKE_FIND_LIBRARY_SUFFIXES .a .lib ${CMAKE_FIND_LIBRARY_SUFFIXES}) 5 | else() 6 | set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) 7 | endif() 8 | endif() 9 | 10 | if(UNIX) 11 | find_package(PkgConfig QUIET) 12 | pkg_check_modules(_B64 QUIET libb64) 13 | endif() 14 | 15 | find_path(B64_INCLUDE_DIR NAMES b64/cdecode.h b64/cencode.h HINTS ${_B64_INCLUDEDIR}) 16 | find_library(B64_LIBRARY NAMES b64 HINTS ${_B64_LIBDIR}) 17 | 18 | set(B64_INCLUDE_DIRS ${B64_INCLUDE_DIR}) 19 | set(B64_LIBRARIES ${B64_LIBRARY}) 20 | 21 | include(FindPackageHandleStandardArgs) 22 | 23 | find_package_handle_standard_args(B64 24 | REQUIRED_VARS 25 | B64_LIBRARY 26 | B64_INCLUDE_DIR 27 | ) 28 | 29 | mark_as_advanced(B64_INCLUDE_DIR B64_LIBRARY) 30 | 31 | if(B64_PREFER_STATIC_LIB) 32 | set(CMAKE_FIND_LIBRARY_SUFFIXES ${B64_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) 33 | unset(B64_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES) 34 | endif() 35 | -------------------------------------------------------------------------------- /cmake/FindCURLpp.cmake: -------------------------------------------------------------------------------- 1 | #~ finds curlpp 2 | 3 | find_package(CURL REQUIRED) 4 | 5 | set(store_cfls ${CMAKE_FIND_LIBRARY_SUFFIXES}) 6 | set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ".so") 7 | set(CURLPP_FIND_NAMES curlpp libcurlpp) 8 | set(CURLPP_INCLUDE_PREFIX "curlpp/") 9 | #~ set(CURLPP_INCLUDE_SEARCHES "Easy.hpp" "cURLpp.hpp" "Info.hpp" "Infos.hpp" "Option.hpp" "Options.hpp" "Form.hpp") 10 | set(CURLPP_INCLUDE_SEARCHES "cURLpp.hpp") 11 | 12 | 13 | find_path(CURLPP_INCLUDE_DIR NAMES ${CURLPP_INCLUDE_SEARCHES} PATH_SUFFIXES ${CURLPP_INCLUDE_PREFIX}) 14 | find_library(CURLPP_LIBRARY NAMES ${CURLPP_FIND_NAMES} PATHS "/usr/local/lib") 15 | 16 | set(CURLPP_LIBRARIES ${CURL_LIBRARIES} ${CURLPP_LIBRARY}) 17 | set(CURLPP_INCLUDE_DIRS ${CURL_INCLUDE_DIRS} ${CURLPP_INCLUDE_DIR}) 18 | 19 | include(${CMAKE_ROOT}/Modules/FindPackageHandleStandardArgs.cmake) 20 | find_package_handle_standard_args(CURLpp DEFAULT_MSG CURLPP_LIBRARY CURLPP_INCLUDE_DIR) 21 | 22 | mark_as_advanced(CURLPP_LIBRARY CURLPP_INCLUDE_DIR) 23 | set(CMAKE_FIND_LIBRARY_SUFFIXES "${store_cfls}") 24 | -------------------------------------------------------------------------------- /cmake/FindGpgme.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find the gpgme library 2 | # 3 | # Algorithm: 4 | # - Windows: 5 | # On Windows, there's three gpgme variants: gpgme{,-glib,-qt}. 6 | # - The variant used determines the event loop integration possible: 7 | # - gpgme: no event loop integration possible, only synchronous operations supported 8 | # - gpgme-glib: glib event loop integration possible, only asynchronous operations supported 9 | # - gpgme-qt: qt event loop integration possible, only asynchronous operations supported 10 | # - GPGME_{VANILLA,GLIB,QT}_{FOUND,LIBRARIES} will be set for each of the above 11 | # - GPGME_INCLUDES is the same for all of the above 12 | # - GPGME_FOUND is set if any of the above was found 13 | # - *nix: 14 | # There's also three variants: gpgme{,-pthread,-pth}. 15 | # - The variant used determines the multithreaded use possible: 16 | # - gpgme: no multithreading support available 17 | # - gpgme-pthread: multithreading available using POSIX threads 18 | # - gpgme-pth: multithreading available using GNU PTH (cooperative multithreading) 19 | # - GPGME_{VANILLA,PTH,PTHREAD}_{FOUND,LIBRARIES} will be set for each of the above 20 | # - GPGME_INCLUDES is the same for all of the above 21 | # - GPGME_FOUND is set if any of the above was found 22 | # 23 | # GPGME_LIBRARY_DIR - the directory where the libraries are located 24 | 25 | # 26 | # THIS IS ALMOST A 1:1 COPY OF FindAssuan.cmake in kdepim. 27 | # Any changes here likely apply there, too. 28 | # 29 | 30 | # do away with crappy condition repetition on else/endfoo 31 | set( CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS_gpgme_saved ${CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS} ) 32 | set( CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true ) 33 | 34 | #if this is built-in, please replace, if it isn't, export into a MacroToBool.cmake of it's own 35 | macro( macro_bool_to_bool FOUND_VAR ) 36 | foreach( _current_VAR ${ARGN} ) 37 | if ( ${FOUND_VAR} ) 38 | set( ${_current_VAR} TRUE ) 39 | else() 40 | set( ${_current_VAR} FALSE ) 41 | endif() 42 | endforeach() 43 | endmacro() 44 | 45 | #HACK: local copy... 46 | MACRO(MACRO_BOOL_TO_01 FOUND_VAR ) 47 | FOREACH (_current_VAR ${ARGN}) 48 | IF(${FOUND_VAR}) 49 | SET(${_current_VAR} 1) 50 | ELSE(${FOUND_VAR}) 51 | SET(${_current_VAR} 0) 52 | ENDIF(${FOUND_VAR}) 53 | ENDFOREACH(_current_VAR) 54 | ENDMACRO(MACRO_BOOL_TO_01) 55 | 56 | 57 | if ( WIN32 ) 58 | 59 | # On Windows, we don't have a gpgme-config script, so we need to 60 | # look for the stuff ourselves: 61 | 62 | # in cmake, AND and OR have the same precedence, there's no 63 | # subexpressions, and expressions are evaluated short-circuit'ed 64 | # IOW: CMake if() suxx. 65 | # Starting with CMake 2.6.3 you can group if expressions with (), but we 66 | # don't require 2.6.3 but 2.6.2, we can't use it. Alex 67 | set( _seem_to_have_cached_gpgme false ) 68 | if ( GPGME_INCLUDES ) 69 | if ( GPGME_VANILLA_LIBRARIES OR GPGME_QT_LIBRARIES OR GPGME_GLIB_LIBRARIES ) 70 | set( _seem_to_have_cached_gpgme true ) 71 | endif() 72 | endif() 73 | 74 | if ( _seem_to_have_cached_gpgme ) 75 | 76 | macro_bool_to_bool( GPGME_VANILLA_LIBRARIES GPGME_VANILLA_FOUND ) 77 | macro_bool_to_bool( GPGME_GLIB_LIBRARIES GPGME_GLIB_FOUND ) 78 | macro_bool_to_bool( GPGME_QT_LIBRARIES GPGME_QT_FOUND ) 79 | # this would have been preferred: 80 | #set( GPGME_*_FOUND macro_bool_to_bool(GPGME_*_LIBRARIES) ) 81 | 82 | if ( GPGME_VANILLA_FOUND OR GPGME_GLIB_FOUND OR GPGME_QT_FOUND ) 83 | set( GPGME_FOUND true ) 84 | else() 85 | set( GPGME_FOUND false ) 86 | endif() 87 | 88 | else() 89 | 90 | set( GPGME_FOUND false ) 91 | set( GPGME_VANILLA_FOUND false ) 92 | set( GPGME_GLIB_FOUND false ) 93 | set( GPGME_QT_FOUND false ) 94 | 95 | find_path( GPGME_INCLUDES gpgme.h 96 | ${CMAKE_INCLUDE_PATH} 97 | ${CMAKE_INSTALL_PREFIX}/include 98 | ) 99 | 100 | find_library( _gpgme_vanilla_library NAMES gpgme libgpgme gpgme-11 libgpgme-11 101 | PATHS 102 | ${CMAKE_LIBRARY_PATH} 103 | ${CMAKE_INSTALL_PREFIX}/lib 104 | ) 105 | 106 | find_library( _gpgme_glib_library NAMES gpgme-glib libgpgme-glib gpgme-glib-11 libgpgme-glib-11 107 | PATHS 108 | ${CMAKE_LIBRARY_PATH} 109 | ${CMAKE_INSTALL_PREFIX}/lib 110 | ) 111 | 112 | find_library( _gpgme_qt_library NAMES gpgme-qt libgpgme-qt gpgme-qt-11 libgpgme-qt-11 113 | PATHS 114 | ${CMAKE_LIBRARY_PATH} 115 | ${CMAKE_INSTALL_PREFIX}/lib 116 | ) 117 | 118 | find_library( _gpg_error_library NAMES gpg-error libgpg-error gpg-error-0 libgpg-error-0 119 | PATHS 120 | ${CMAKE_LIBRARY_PATH} 121 | ${CMAKE_INSTALL_PREFIX}/lib 122 | ) 123 | 124 | set( GPGME_INCLUDES ${GPGME_INCLUDES} ) 125 | 126 | if ( _gpgme_vanilla_library AND _gpg_error_library ) 127 | set( GPGME_VANILLA_LIBRARIES ${_gpgme_vanilla_library} ${_gpg_error_library} ) 128 | set( GPGME_VANILLA_FOUND true ) 129 | set( GPGME_FOUND true ) 130 | endif() 131 | 132 | if ( _gpgme_glib_library AND _gpg_error_library ) 133 | set( GPGME_GLIB_LIBRARIES ${_gpgme_glib_library} ${_gpg_error_library} ) 134 | set( GPGME_GLIB_FOUND true ) 135 | set( GPGME_FOUND true ) 136 | endif() 137 | 138 | if ( _gpgme_qt_library AND _gpg_error_library ) 139 | set( GPGME_QT_LIBRARIES ${_gpgme_qt_library} ${_gpg_error_library} ) 140 | set( GPGME_QT_FOUND true ) 141 | set( GPGME_FOUND true ) 142 | endif() 143 | 144 | endif() 145 | 146 | # these are Unix-only: 147 | set( GPGME_PTHREAD_FOUND false ) 148 | set( GPGME_PTH_FOUND false ) 149 | set( HAVE_GPGME_PTHREAD 0 ) 150 | set( HAVE_GPGME_PTH 0 ) 151 | 152 | macro_bool_to_01( GPGME_FOUND HAVE_GPGME ) 153 | macro_bool_to_01( GPGME_VANILLA_FOUND HAVE_GPGME_VANILLA ) 154 | macro_bool_to_01( GPGME_GLIB_FOUND HAVE_GPGME_GLIB ) 155 | macro_bool_to_01( GPGME_QT_FOUND HAVE_GPGME_QT ) 156 | 157 | else() # not WIN32 158 | 159 | # On *nix, we have the gpgme-config script which can tell us all we 160 | # need to know: 161 | 162 | # see WIN32 case for an explanation of what this does: 163 | set( _seem_to_have_cached_gpgme false ) 164 | if ( GPGME_INCLUDES ) 165 | if ( GPGME_VANILLA_LIBRARIES OR GPGME_PTHREAD_LIBRARIES OR GPGME_PTH_LIBRARIES ) 166 | set( _seem_to_have_cached_gpgme true ) 167 | endif() 168 | endif() 169 | 170 | if ( _seem_to_have_cached_gpgme ) 171 | 172 | macro_bool_to_bool( GPGME_VANILLA_LIBRARIES GPGME_VANILLA_FOUND ) 173 | macro_bool_to_bool( GPGME_PTHREAD_LIBRARIES GPGME_PTHREAD_FOUND ) 174 | macro_bool_to_bool( GPGME_PTH_LIBRARIES GPGME_PTH_FOUND ) 175 | 176 | if ( GPGME_VANILLA_FOUND OR GPGME_PTHREAD_FOUND OR GPGME_PTH_FOUND ) 177 | set( GPGME_FOUND true ) 178 | else() 179 | set( GPGME_FOUND false ) 180 | endif() 181 | 182 | else() 183 | 184 | set( GPGME_FOUND false ) 185 | set( GPGME_VANILLA_FOUND false ) 186 | set( GPGME_PTHREAD_FOUND false ) 187 | set( GPGME_PTH_FOUND false ) 188 | 189 | find_program( _GPGMECONFIG_EXECUTABLE NAMES gpgme-config ) 190 | 191 | # if gpgme-config has been found 192 | if ( _GPGMECONFIG_EXECUTABLE ) 193 | 194 | message( STATUS "Found gpgme-config at ${_GPGMECONFIG_EXECUTABLE}" ) 195 | 196 | exec_program( ${_GPGMECONFIG_EXECUTABLE} ARGS --version OUTPUT_VARIABLE GPGME_VERSION ) 197 | 198 | set( _GPGME_MIN_VERSION "1.1.7" ) 199 | 200 | if ( ${GPGME_VERSION} VERSION_LESS ${_GPGME_MIN_VERSION} ) 201 | 202 | message( STATUS "The installed version of gpgme is too old: ${GPGME_VERSION} (required: >= ${_GPGME_MIN_VERSION})" ) 203 | 204 | else() 205 | 206 | message( STATUS "Found gpgme v${GPGME_VERSION}, checking for flavours..." ) 207 | 208 | exec_program( ${_GPGMECONFIG_EXECUTABLE} ARGS --libs OUTPUT_VARIABLE _gpgme_config_vanilla_libs RETURN_VALUE _ret ) 209 | if ( _ret ) 210 | set( _gpgme_config_vanilla_libs ) 211 | endif() 212 | 213 | exec_program( ${_GPGMECONFIG_EXECUTABLE} ARGS --thread=pthread --libs OUTPUT_VARIABLE _gpgme_config_pthread_libs RETURN_VALUE _ret ) 214 | if ( _ret ) 215 | set( _gpgme_config_pthread_libs ) 216 | endif() 217 | 218 | exec_program( ${_GPGMECONFIG_EXECUTABLE} ARGS --thread=pth --libs OUTPUT_VARIABLE _gpgme_config_pth_libs RETURN_VALUE _ret ) 219 | if ( _ret ) 220 | set( _gpgme_config_pth_libs ) 221 | endif() 222 | 223 | # append -lgpg-error to the list of libraries, if necessary 224 | foreach ( _flavour vanilla pthread pth ) 225 | if ( _gpgme_config_${_flavour}_libs AND NOT _gpgme_config_${_flavour}_libs MATCHES "lgpg-error" ) 226 | set( _gpgme_config_${_flavour}_libs "${_gpgme_config_${_flavour}_libs} -lgpg-error" ) 227 | endif() 228 | endforeach() 229 | 230 | if ( _gpgme_config_vanilla_libs OR _gpgme_config_pthread_libs OR _gpgme_config_pth_libs ) 231 | 232 | exec_program( ${_GPGMECONFIG_EXECUTABLE} ARGS --cflags OUTPUT_VARIABLE _GPGME_CFLAGS ) 233 | 234 | if ( _GPGME_CFLAGS ) 235 | string( REGEX REPLACE "(\r?\n)+$" " " _GPGME_CFLAGS "${_GPGME_CFLAGS}" ) 236 | string( REGEX REPLACE " *-I" ";" GPGME_INCLUDES "${_GPGME_CFLAGS}" ) 237 | endif() 238 | 239 | foreach ( _flavour vanilla pthread pth ) 240 | if ( _gpgme_config_${_flavour}_libs ) 241 | 242 | set( _gpgme_library_dirs ) 243 | set( _gpgme_library_names ) 244 | string( TOUPPER "${_flavour}" _FLAVOUR ) 245 | 246 | string( REGEX REPLACE " +" ";" _gpgme_config_${_flavour}_libs "${_gpgme_config_${_flavour}_libs}" ) 247 | 248 | foreach( _flag ${_gpgme_config_${_flavour}_libs} ) 249 | if ( "${_flag}" MATCHES "^-L" ) 250 | string( REGEX REPLACE "^-L" "" _dir "${_flag}" ) 251 | file( TO_CMAKE_PATH "${_dir}" _dir ) 252 | set( _gpgme_library_dirs ${_gpgme_library_dirs} "${_dir}" ) 253 | elseif( "${_flag}" MATCHES "^-l" ) 254 | string( REGEX REPLACE "^-l" "" _name "${_flag}" ) 255 | set( _gpgme_library_names ${_gpgme_library_names} "${_name}" ) 256 | endif() 257 | endforeach() 258 | 259 | set( GPGME_${_FLAVOUR}_FOUND true ) 260 | 261 | foreach( _name ${_gpgme_library_names} ) 262 | set( _gpgme_${_name}_lib ) 263 | 264 | # if -L options were given, look only there 265 | if ( _gpgme_library_dirs ) 266 | find_library( _gpgme_${_name}_lib NAMES ${_name} PATHS ${_gpgme_library_dirs} NO_DEFAULT_PATH ) 267 | endif() 268 | 269 | # if not found there, look in system directories 270 | if ( NOT _gpgme_${_name}_lib ) 271 | find_library( _gpgme_${_name}_lib NAMES ${_name} ) 272 | endif() 273 | 274 | # if still not found, then the whole flavour isn't found 275 | if ( NOT _gpgme_${_name}_lib ) 276 | if ( GPGME_${_FLAVOUR}_FOUND ) 277 | set( GPGME_${_FLAVOUR}_FOUND false ) 278 | set( _not_found_reason "dependant library ${_name} wasn't found" ) 279 | endif() 280 | endif() 281 | 282 | set( GPGME_${_FLAVOUR}_LIBRARIES ${GPGME_${_FLAVOUR}_LIBRARIES} "${_gpgme_${_name}_lib}" ) 283 | endforeach() 284 | 285 | #check_c_library_exists_explicit( gpgme gpgme_check_version "${_GPGME_CFLAGS}" "${GPGME_LIBRARIES}" GPGME_FOUND ) 286 | if ( GPGME_${_FLAVOUR}_FOUND ) 287 | message( STATUS " Found flavour '${_flavour}', checking whether it's usable...yes" ) 288 | else() 289 | message( STATUS " Found flavour '${_flavour}', checking whether it's usable...no" ) 290 | message( STATUS " (${_not_found_reason})" ) 291 | endif() 292 | endif() 293 | 294 | endforeach( _flavour ) 295 | 296 | # ensure that they are cached 297 | # This comment above doesn't make sense, the four following lines seem to do nothing. Alex 298 | set( GPGME_INCLUDES ${GPGME_INCLUDES} ) 299 | set( GPGME_VANILLA_LIBRARIES ${GPGME_VANILLA_LIBRARIES} ) 300 | set( GPGME_PTHREAD_LIBRARIES ${GPGME_PTHREAD_LIBRARIES} ) 301 | set( GPGME_PTH_LIBRARIES ${GPGME_PTH_LIBRARIES} ) 302 | 303 | if ( GPGME_VANILLA_FOUND OR GPGME_PTHREAD_FOUND OR GPGME_PTH_FOUND ) 304 | set( GPGME_FOUND true ) 305 | else() 306 | set( GPGME_FOUND false ) 307 | endif() 308 | 309 | endif() 310 | 311 | endif() 312 | 313 | endif() 314 | 315 | endif() 316 | 317 | # these are Windows-only: 318 | set( GPGME_GLIB_FOUND false ) 319 | set( GPGME_QT_FOUND false ) 320 | set( HAVE_GPGME_GLIB 0 ) 321 | set( HAVE_GPGME_QT 0 ) 322 | 323 | macro_bool_to_01( GPGME_FOUND HAVE_GPGME ) 324 | macro_bool_to_01( GPGME_VANILLA_FOUND HAVE_GPGME_VANILLA ) 325 | macro_bool_to_01( GPGME_PTHREAD_FOUND HAVE_GPGME_PTHREAD ) 326 | macro_bool_to_01( GPGME_PTH_FOUND HAVE_GPGME_PTH ) 327 | 328 | endif() # WIN32 | Unix 329 | 330 | 331 | set( _gpgme_flavours "" ) 332 | 333 | if ( GPGME_VANILLA_FOUND ) 334 | set( _gpgme_flavours "${_gpgme_flavours} vanilla" ) 335 | endif() 336 | 337 | if ( GPGME_GLIB_FOUND ) 338 | set( _gpgme_flavours "${_gpgme_flavours} Glib" ) 339 | endif() 340 | 341 | if ( GPGME_QT_FOUND ) 342 | set( _gpgme_flavours "${_gpgme_flavours} Qt" ) 343 | endif() 344 | 345 | if ( GPGME_PTHREAD_FOUND ) 346 | set( _gpgme_flavours "${_gpgme_flavours} pthread" ) 347 | endif() 348 | 349 | if ( GPGME_PTH_FOUND ) 350 | set( _gpgme_flavours "${_gpgme_flavours} pth" ) 351 | endif() 352 | 353 | # determine the library in one of the found flavours, can be reused e.g. by FindQgpgme.cmake, Alex 354 | foreach(_currentFlavour vanilla glib qt pth pthread) 355 | if(NOT GPGME_LIBRARY_DIR) 356 | get_filename_component(GPGME_LIBRARY_DIR "${_gpgme_${_currentFlavour}_lib}" PATH) 357 | endif() 358 | endforeach() 359 | 360 | if ( NOT Gpgme_FIND_QUIETLY ) 361 | 362 | if ( GPGME_FOUND ) 363 | message( STATUS "Usable gpgme flavours found: ${_gpgme_flavours}" ) 364 | else() 365 | message( STATUS "No usable gpgme flavours found." ) 366 | endif() 367 | 368 | endif() 369 | 370 | if ( Gpgme_FIND_REQUIRED AND NOT GPGME_FOUND ) 371 | message( FATAL_ERROR "Did not find GPGME" ) 372 | endif() 373 | 374 | 375 | if ( WIN32 ) 376 | set( _gpgme_homepage "http://www.gpg4win.org" ) 377 | else() 378 | set( _gpgme_homepage "http://www.gnupg.org/related_software/gpgme" ) 379 | endif() 380 | 381 | #set_package_properties(Gpgme PROPERTIES 382 | # DESCRIPTION "The GnuPG Made Easy (GPGME) library)" 383 | # URL ${_gpgme_homepage}) 384 | # 385 | set( CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS_gpgme_saved ) 386 | -------------------------------------------------------------------------------- /cmake/Findglib.cmake: -------------------------------------------------------------------------------- 1 | 2 | #use pkg-config 3 | FIND_PACKAGE(PkgConfig) 4 | PKG_CHECK_MODULES(PC_GLIB glib-2.0) 5 | 6 | FIND_PATH(glib_INCLUDE_DIR NAMES glib.h HINTS ${PC_GLIB_INCLUDEDIR} ${PC_GLIB_INCLUDE_DIRS}) 7 | FIND_PATH(glib_config_INCLUDE_DIR NAMES glibconfig.h HINTS ${PC_GLIB_INCLUDEDIR} ${PC_GLIB_INCLUDE_DIRS}) 8 | FIND_LIBRARY(glib_LIBRARY NAMES glib glib-2.0 HINTS ${PC_GLIB_LIBDIR} ${PC_GLIB_LIBRARY_DIRS}) 9 | 10 | SET(glib_LIBRARIES ${glib_LIBRARY} ${PC_GLIB_PKGCONF_LIBRARIES}) 11 | SET(glib_INCLUDE_DIRS ${glib_INCLUDE_DIR} ${glib_config_INCLUDE_DIR} ${PC_GLIB_PKGCONF_INCLUDE_DIRS}) 12 | 13 | INCLUDE(FindPackageHandleStandardArgs) 14 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(glib DEFAULT_MSG glib_LIBRARY glib_INCLUDE_DIR) 15 | 16 | MARK_AS_ADVANCED(glib_INCLUDE_DIR glib_config_INCLUDE_DIR glib_LIBRARY) 17 | -------------------------------------------------------------------------------- /cmake/Findglibmm.cmake: -------------------------------------------------------------------------------- 1 | IF(glibmm_FIND_REQUIRED) 2 | FIND_PACKAGE(glib REQUIRED) 3 | FIND_PACKAGE(sigc++ REQUIRED) 4 | ELSE(glibmm_FIND_REQUIRED) 5 | FIND_PACKAGE(glib) 6 | FIND_PACKAGE(sigc++) 7 | ENDIF(glibmm_FIND_REQUIRED) 8 | 9 | IF(GLIB_FOUND) 10 | 11 | #use pkg-config 12 | FIND_PACKAGE(PkgConfig) 13 | PKG_CHECK_MODULES(PC_GLIBMM glibmm-2.4) 14 | 15 | FIND_PATH(glibmm_INCLUDE_DIR NAMES glibmm/main.h HINTS ${PC_GLIBMM_INCLUDEDIR} ${PC_GLIBMM_INCLUDE_DIRS}) 16 | FIND_PATH(glibmm_config_INCLUDE_DIR NAMES glibmmconfig.h HINTS ${PC_GLIBMM_INCLUDEDIR} ${PC_GLIBMM_INCLUDE_DIRS}) 17 | FIND_LIBRARY(glibmm_LIBRARY NAMES glibmm glibmm-2.4 HINTS ${PC_GLIBMM_LIBDIR} ${PC_GLIBMM_LIBRARY_DIRS}) 18 | 19 | SET(glibmm_LIBRARIES ${glibmm_LIBRARY} ${PC_GLIBMM_PKGCONF_LIBRARIES} ${glib_LIBRARIES} ${sigc++_LIBRARIES}) 20 | SET(glibmm_INCLUDE_DIRS ${glibmm_INCLUDE_DIR} ${glibmm_config_INCLUDE_DIR} ${PC_GLIBMM_PKGCONF_INCLUDE_DIRS} ${glib_INCLUDE_DIRS} ${sigc++_INCLUDE_DIRS}) 21 | 22 | ENDIF(GLIB_FOUND) 23 | 24 | INCLUDE(FindPackageHandleStandardArgs) 25 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(glibmm DEFAULT_MSG glibmm_LIBRARY glibmm_INCLUDE_DIR) 26 | 27 | MARK_AS_ADVANCED(glibmm_INCLUDE_DIR glibmm_config_INCLUDE_DIR glibmm_LIBRARY) 28 | -------------------------------------------------------------------------------- /cmake/Findsigc++.cmake: -------------------------------------------------------------------------------- 1 | 2 | #use pkg-config 3 | FIND_PACKAGE(PkgConfig) 4 | PKG_CHECK_MODULES(PC_SIGCXX sigc++-2.0) 5 | 6 | FIND_PATH(sigc++_INCLUDE_DIR NAMES sigc++/sigc++.h HINTS ${PC_SIGCXX_INCLUDEDIR} ${PC_SIGCXX_INCLUDE_DIRS}) 7 | FIND_PATH(sigc++_config_INCLUDE_DIR NAMES sigc++config.h HINTS ${PC_SIGCXX_INCLUDEDIR} ${PC_SIGCXX_INCLUDE_DIRS}) 8 | FIND_LIBRARY(sigc++_LIBRARY NAMES sigc sigc-2.0 HINTS ${PC_SIGCXX_LIBDIR} ${PC_SIGCXX_LIBRARY_DIRS}) 9 | 10 | SET(sigc++_LIBRARIES ${sigc++_LIBRARY} ${PC_SIGCXX_PKGCONF_LIBRARIES}) 11 | SET(sigc++_INCLUDE_DIRS ${sigc++_INCLUDE_DIR} ${sigc++_config_INCLUDE_DIR} ${PC_SIGCXX_PKGCONF_INCLUDE_DIRS}) 12 | 13 | INCLUDE(FindPackageHandleStandardArgs) 14 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(sigc++ DEFAULT_MSG sigc++_LIBRARY sigc++_INCLUDE_DIR) 15 | 16 | MARK_AS_ADVANCED(sigc++_INCLUDE_DIR sigc++_config_INCLUDE_DIR sigc++_LIBRARY) 17 | -------------------------------------------------------------------------------- /config/dpaste.conf: -------------------------------------------------------------------------------- 1 | # This is the default dpaste configuration file. 2 | 3 | ########################### 4 | # OpenDHT's HTTP server # 5 | ########################### 6 | host = 127.0.0.1 7 | port = 6509 8 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT(dpaste, 0.4.1) 2 | AC_CONFIG_AUX_DIR(ac) 3 | AM_INIT_AUTOMAKE([foreign subdir-objects]) 4 | AC_CONFIG_HEADERS([config.h]) 5 | AC_CONFIG_MACRO_DIR([m4]) 6 | AC_CANONICAL_HOST 7 | 8 | AC_LANG_PUSH([C++]) 9 | AX_CXX_COMPILE_STDCXX(17,[noext],[mandatory]) 10 | # explicit c++17 in flags so that compile_commands.json yields it. 11 | CXXFLAGS="${CXXFLAGS} -std=c++17" 12 | 13 | AC_ARG_ENABLE([debug], AS_HELP_STRING([--enable-debug], [Build in debug mode, adds stricter warnings, disables optimization])) 14 | AS_IF([test "x$enable_debug" = "xyes"], 15 | [CXXFLAGS="${CXXFLAGS} -g -Wno-return-type -Wall -Wextra -Wnon-virtual-dtor -O0"], 16 | [CXXFLAGS="${CXXFLAGS} -O3"]) 17 | 18 | AC_PROG_CXX 19 | AC_PROG_RANLIB 20 | 21 | PKG_CHECK_MODULES([OpenDHT], [opendht >= 1.2]) 22 | PKG_CHECK_MODULES([CURLPP], [curlpp]) 23 | PKG_CHECK_MODULES([GLIBMM], [glibmm-2.4]) 24 | 25 | # dpaste (CPP/LD)FLAGS common with different binaries (particularly tests) 26 | AC_SUBST(OpenDHT_LIBS, "${OpenDHT_LIBS} -lpthread") 27 | 28 | AM_PATH_GPGME() 29 | 30 | AC_CONFIG_FILES([Makefile 31 | src/Makefile]) 32 | 33 | ################ 34 | # Unit tests # 35 | ################ 36 | AC_ARG_ENABLE([tests], AS_HELP_STRING([--enable-tests], [Enables unit tests compilation])) 37 | AM_CONDITIONAL([DPASTE_TEST], [test "x$enable_tests" = "xyes"]) 38 | AM_COND_IF([DPASTE_TEST], 39 | [ 40 | PKG_CHECK_MODULES([CATCH2], [catch2]) 41 | AC_DEFINE([DPASTE_TEST], [1], [Unit tests]) 42 | AC_CONFIG_FILES([tests/Makefile]) 43 | ]) 44 | 45 | AC_OUTPUT 46 | 47 | # vim: set ts=2 sw=2 tw=120 et : 48 | 49 | -------------------------------------------------------------------------------- /doc/dpaste.1: -------------------------------------------------------------------------------- 1 | .TH DPASTE 1 2017-06-26 2 | 3 | .SH NAME 4 | .B dpaste 5 | - A simple pastebin for light values (max 64KB) using OpenDHT distributed hash 6 | table. 7 | 8 | .SH SYNOPSIS 9 | .B dpaste -h 10 | 11 | .B dpaste -v 12 | 13 | .B dpaste [\fIoptions\fP...] 14 | 15 | .B dpaste -g \fIcode\fP [\fIoptions\fP...] 16 | 17 | .SH DESCRIPTION 18 | 19 | By default, \fBdpaste\fP will read its standard input for a file to paste on 20 | OpenDHT. For fetching a file, you have to provide the \fIcode\fP associated to 21 | it using the flag \fB-g\fP. 22 | 23 | .SH OPTIONS 24 | 25 | .TP 26 | \fB-h\fP 27 | Prints some help. 28 | 29 | .TP 30 | \fB-v\fP 31 | Shows the version of the program. 32 | 33 | .TP 34 | \fB-g\fP \fIcode\fP, \fB--get\fP \fIcode\fP 35 | Specifies the code \fIcode\fP used to recover the file on the DHT. 36 | 37 | .TP 38 | \fB--aes-encrypt\fP 39 | Use AES scheme for encryption. Password is automatically saved in the returned 40 | code ("dpaste:XXXXXX"). 41 | 42 | .TP 43 | \fB--gpg-encrypt\fP 44 | Use GPG scheme for encryption. 45 | 46 | .TP 47 | \fB-r\fP \fIrecipient\fP, \fB--recipients\fP \fIrecipient\fP 48 | Specify the list of recipients to use for GPG encryption (--gpg--encrypt). Use 49 | \fB-r\fP multiple times to specify a list of recipients. 50 | 51 | .TP 52 | \fB-s\fP, \fB--sign\fP 53 | Tells wether message should be signed using the user's GPG key. The key has to 54 | be configured through the configuration file (\fB$XDG_CONFIG_DIR/dpaste.conf\fP, 55 | keyword: \fBpgp_key_id\fP). 56 | 57 | .TP 58 | \fB--no-decrypt\fP 59 | Tells dpaste not to decrypt PGP data and rather output it on stdout. 60 | 61 | .TP 62 | \fB--self-recipient\fP 63 | Include self as recipient. Self refers to the key id configured for signing 64 | (see --sign description). This only takes effect if option \fB-e\fP is also 65 | used. 66 | 67 | .SH RETURN CODE 68 | The program returns 0 on success. Otherwise 1 is returned. 69 | 70 | .SH FILES 71 | 72 | .TP 73 | \fB$XDG_CONFIG_DIR/dpaste.conf\fP 74 | Main configuration file where. \fBdpaste\fP will look for this file to recover 75 | complementary information. 76 | 77 | .SH AUTHORS 78 | \(bu 79 | .\} 80 | Simon Désaulniers 81 | 82 | \(bu 83 | .\} 84 | Adrien Béraud 85 | -------------------------------------------------------------------------------- /docker/DockerfileBase: -------------------------------------------------------------------------------- 1 | # Docker hub destination: sim590/dpaste-ci 2 | FROM debian:buster-slim 3 | MAINTAINER Simon Désaulniers 4 | RUN apt-get update 5 | RUN apt-get install -y \ 6 | build-essential \ 7 | autoconf \ 8 | automake \ 9 | libopendht-dev \ 10 | libb64-dev \ 11 | libcurlpp-dev \ 12 | libcurl4-openssl-dev \ 13 | libgpgmepp-dev \ 14 | libgpgme-dev \ 15 | nlohmann-json-dev \ 16 | libglibmm-2.4-dev \ 17 | catch 18 | RUN apt-get clean 19 | 20 | # vim: set ft=dockerfile ts=4 sw=4 tw=120 et : 21 | 22 | -------------------------------------------------------------------------------- /docker/DockerfileTravis: -------------------------------------------------------------------------------- 1 | FROM sim590/dpaste-ci 2 | MAINTAINER Simon Désaulniers 3 | COPY . /root/dpaste 4 | RUN cd /root/dpaste && ./autogen.sh && ./configure && make -j8 && make install 5 | 6 | # vim: set ft=dockerfile ts=4 sw=4 tw=120 et : 7 | 8 | -------------------------------------------------------------------------------- /m4/ax_cxx_compile_stdcxx.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check for baseline language coverage in the compiler for the specified 12 | # version of the C++ standard. If necessary, add switches to CXX and 13 | # CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) 14 | # or '14' (for the C++14 standard). 15 | # 16 | # The second argument, if specified, indicates whether you insist on an 17 | # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. 18 | # -std=c++11). If neither is specified, you get whatever works, with 19 | # preference for an extended mode. 20 | # 21 | # The third argument, if specified 'mandatory' or if left unspecified, 22 | # indicates that baseline support for the specified C++ standard is 23 | # required and that the macro should error out if no mode with that 24 | # support is found. If specified 'optional', then configuration proceeds 25 | # regardless, after defining HAVE_CXX${VERSION} if and only if a 26 | # supporting mode is found. 27 | # 28 | # LICENSE 29 | # 30 | # Copyright (c) 2008 Benjamin Kosnik 31 | # Copyright (c) 2012 Zack Weinberg 32 | # Copyright (c) 2013 Roy Stogner 33 | # Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov 34 | # Copyright (c) 2015 Paul Norman 35 | # Copyright (c) 2015 Moritz Klammler 36 | # Copyright (c) 2016 Krzesimir Nowak 37 | # 38 | # Copying and distribution of this file, with or without modification, are 39 | # permitted in any medium without royalty provided the copyright notice 40 | # and this notice are preserved. This file is offered as-is, without any 41 | # warranty. 42 | 43 | #serial 6 44 | 45 | dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro 46 | dnl (serial version number 13). 47 | 48 | AX_REQUIRE_DEFINED([AC_MSG_WARN]) 49 | AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl 50 | m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], 51 | [$1], [14], [ax_cxx_compile_alternatives="14 1y"], 52 | [$1], [17], [ax_cxx_compile_alternatives="17 1z"], 53 | [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl 54 | m4_if([$2], [], [], 55 | [$2], [ext], [], 56 | [$2], [noext], [], 57 | [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl 58 | m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], 59 | [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], 60 | [$3], [optional], [ax_cxx_compile_cxx$1_required=false], 61 | [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) 62 | AC_LANG_PUSH([C++])dnl 63 | ac_success=no 64 | AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, 65 | ax_cv_cxx_compile_cxx$1, 66 | [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], 67 | [ax_cv_cxx_compile_cxx$1=yes], 68 | [ax_cv_cxx_compile_cxx$1=no])]) 69 | if test x$ax_cv_cxx_compile_cxx$1 = xyes; then 70 | ac_success=yes 71 | fi 72 | 73 | m4_if([$2], [noext], [], [dnl 74 | if test x$ac_success = xno; then 75 | for alternative in ${ax_cxx_compile_alternatives}; do 76 | switch="-std=gnu++${alternative}" 77 | cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) 78 | AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, 79 | $cachevar, 80 | [ac_save_CXX="$CXX" 81 | CXX="$CXX $switch" 82 | AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], 83 | [eval $cachevar=yes], 84 | [eval $cachevar=no]) 85 | CXX="$ac_save_CXX"]) 86 | if eval test x\$$cachevar = xyes; then 87 | CXX="$CXX $switch" 88 | if test -n "$CXXCPP" ; then 89 | CXXCPP="$CXXCPP $switch" 90 | fi 91 | ac_success=yes 92 | break 93 | fi 94 | done 95 | fi]) 96 | 97 | m4_if([$2], [ext], [], [dnl 98 | if test x$ac_success = xno; then 99 | dnl HP's aCC needs +std=c++11 according to: 100 | dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf 101 | dnl Cray's crayCC needs "-h std=c++11" 102 | for alternative in ${ax_cxx_compile_alternatives}; do 103 | for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do 104 | cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) 105 | AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, 106 | $cachevar, 107 | [ac_save_CXX="$CXX" 108 | CXX="$CXX $switch" 109 | AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], 110 | [eval $cachevar=yes], 111 | [eval $cachevar=no]) 112 | CXX="$ac_save_CXX"]) 113 | if eval test x\$$cachevar = xyes; then 114 | CXX="$CXX $switch" 115 | if test -n "$CXXCPP" ; then 116 | CXXCPP="$CXXCPP $switch" 117 | fi 118 | ac_success=yes 119 | break 120 | fi 121 | done 122 | if test x$ac_success = xyes; then 123 | break 124 | fi 125 | done 126 | fi]) 127 | AC_LANG_POP([C++]) 128 | if test x$ax_cxx_compile_cxx$1_required = xtrue; then 129 | if test x$ac_success = xno; then 130 | AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) 131 | fi 132 | fi 133 | if test x$ac_success = xno; then 134 | HAVE_CXX$1=0 135 | AC_MSG_NOTICE([No compiler with C++$1 support was found]) 136 | else 137 | HAVE_CXX$1=1 138 | AC_DEFINE(HAVE_CXX$1,1, 139 | [define if the compiler supports basic C++$1 syntax]) 140 | fi 141 | AC_SUBST(HAVE_CXX$1) 142 | m4_if([$1], [17], [AC_MSG_WARN([C++17 is not yet standardized, so the checks may change in incompatible ways anytime])]) 143 | ]) 144 | 145 | 146 | dnl Test body for checking C++11 support 147 | 148 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], 149 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 150 | ) 151 | 152 | 153 | dnl Test body for checking C++14 support 154 | 155 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], 156 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 157 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 158 | ) 159 | 160 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], 161 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 162 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 163 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 164 | ) 165 | 166 | dnl Tests for new features in C++11 167 | 168 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ 169 | 170 | // If the compiler admits that it is not ready for C++11, why torture it? 171 | // Hopefully, this will speed up the test. 172 | 173 | #ifndef __cplusplus 174 | 175 | #error "This is not a C++ compiler" 176 | 177 | #elif __cplusplus < 201103L 178 | 179 | #error "This is not a C++11 compiler" 180 | 181 | #else 182 | 183 | namespace cxx11 184 | { 185 | 186 | namespace test_static_assert 187 | { 188 | 189 | template 190 | struct check 191 | { 192 | static_assert(sizeof(int) <= sizeof(T), "not big enough"); 193 | }; 194 | 195 | } 196 | 197 | namespace test_final_override 198 | { 199 | 200 | struct Base 201 | { 202 | virtual void f() {} 203 | }; 204 | 205 | struct Derived : public Base 206 | { 207 | virtual void f() override {} 208 | }; 209 | 210 | } 211 | 212 | namespace test_double_right_angle_brackets 213 | { 214 | 215 | template < typename T > 216 | struct check {}; 217 | 218 | typedef check single_type; 219 | typedef check> double_type; 220 | typedef check>> triple_type; 221 | typedef check>>> quadruple_type; 222 | 223 | } 224 | 225 | namespace test_decltype 226 | { 227 | 228 | int 229 | f() 230 | { 231 | int a = 1; 232 | decltype(a) b = 2; 233 | return a + b; 234 | } 235 | 236 | } 237 | 238 | namespace test_type_deduction 239 | { 240 | 241 | template < typename T1, typename T2 > 242 | struct is_same 243 | { 244 | static const bool value = false; 245 | }; 246 | 247 | template < typename T > 248 | struct is_same 249 | { 250 | static const bool value = true; 251 | }; 252 | 253 | template < typename T1, typename T2 > 254 | auto 255 | add(T1 a1, T2 a2) -> decltype(a1 + a2) 256 | { 257 | return a1 + a2; 258 | } 259 | 260 | int 261 | test(const int c, volatile int v) 262 | { 263 | static_assert(is_same::value == true, ""); 264 | static_assert(is_same::value == false, ""); 265 | static_assert(is_same::value == false, ""); 266 | auto ac = c; 267 | auto av = v; 268 | auto sumi = ac + av + 'x'; 269 | auto sumf = ac + av + 1.0; 270 | static_assert(is_same::value == true, ""); 271 | static_assert(is_same::value == true, ""); 272 | static_assert(is_same::value == true, ""); 273 | static_assert(is_same::value == false, ""); 274 | static_assert(is_same::value == true, ""); 275 | return (sumf > 0.0) ? sumi : add(c, v); 276 | } 277 | 278 | } 279 | 280 | namespace test_noexcept 281 | { 282 | 283 | int f() { return 0; } 284 | int g() noexcept { return 0; } 285 | 286 | static_assert(noexcept(f()) == false, ""); 287 | static_assert(noexcept(g()) == true, ""); 288 | 289 | } 290 | 291 | namespace test_constexpr 292 | { 293 | 294 | template < typename CharT > 295 | unsigned long constexpr 296 | strlen_c_r(const CharT *const s, const unsigned long acc) noexcept 297 | { 298 | return *s ? strlen_c_r(s + 1, acc + 1) : acc; 299 | } 300 | 301 | template < typename CharT > 302 | unsigned long constexpr 303 | strlen_c(const CharT *const s) noexcept 304 | { 305 | return strlen_c_r(s, 0UL); 306 | } 307 | 308 | static_assert(strlen_c("") == 0UL, ""); 309 | static_assert(strlen_c("1") == 1UL, ""); 310 | static_assert(strlen_c("example") == 7UL, ""); 311 | static_assert(strlen_c("another\0example") == 7UL, ""); 312 | 313 | } 314 | 315 | namespace test_rvalue_references 316 | { 317 | 318 | template < int N > 319 | struct answer 320 | { 321 | static constexpr int value = N; 322 | }; 323 | 324 | answer<1> f(int&) { return answer<1>(); } 325 | answer<2> f(const int&) { return answer<2>(); } 326 | answer<3> f(int&&) { return answer<3>(); } 327 | 328 | void 329 | test() 330 | { 331 | int i = 0; 332 | const int c = 0; 333 | static_assert(decltype(f(i))::value == 1, ""); 334 | static_assert(decltype(f(c))::value == 2, ""); 335 | static_assert(decltype(f(0))::value == 3, ""); 336 | } 337 | 338 | } 339 | 340 | namespace test_uniform_initialization 341 | { 342 | 343 | struct test 344 | { 345 | static const int zero {}; 346 | static const int one {1}; 347 | }; 348 | 349 | static_assert(test::zero == 0, ""); 350 | static_assert(test::one == 1, ""); 351 | 352 | } 353 | 354 | namespace test_lambdas 355 | { 356 | 357 | void 358 | test1() 359 | { 360 | auto lambda1 = [](){}; 361 | auto lambda2 = lambda1; 362 | lambda1(); 363 | lambda2(); 364 | } 365 | 366 | int 367 | test2() 368 | { 369 | auto a = [](int i, int j){ return i + j; }(1, 2); 370 | auto b = []() -> int { return '0'; }(); 371 | auto c = [=](){ return a + b; }(); 372 | auto d = [&](){ return c; }(); 373 | auto e = [a, &b](int x) mutable { 374 | const auto identity = [](int y){ return y; }; 375 | for (auto i = 0; i < a; ++i) 376 | a += b--; 377 | return x + identity(a + b); 378 | }(0); 379 | return a + b + c + d + e; 380 | } 381 | 382 | int 383 | test3() 384 | { 385 | const auto nullary = [](){ return 0; }; 386 | const auto unary = [](int x){ return x; }; 387 | using nullary_t = decltype(nullary); 388 | using unary_t = decltype(unary); 389 | const auto higher1st = [](nullary_t f){ return f(); }; 390 | const auto higher2nd = [unary](nullary_t f1){ 391 | return [unary, f1](unary_t f2){ return f2(unary(f1())); }; 392 | }; 393 | return higher1st(nullary) + higher2nd(nullary)(unary); 394 | } 395 | 396 | } 397 | 398 | namespace test_variadic_templates 399 | { 400 | 401 | template 402 | struct sum; 403 | 404 | template 405 | struct sum 406 | { 407 | static constexpr auto value = N0 + sum::value; 408 | }; 409 | 410 | template <> 411 | struct sum<> 412 | { 413 | static constexpr auto value = 0; 414 | }; 415 | 416 | static_assert(sum<>::value == 0, ""); 417 | static_assert(sum<1>::value == 1, ""); 418 | static_assert(sum<23>::value == 23, ""); 419 | static_assert(sum<1, 2>::value == 3, ""); 420 | static_assert(sum<5, 5, 11>::value == 21, ""); 421 | static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); 422 | 423 | } 424 | 425 | // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae 426 | // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function 427 | // because of this. 428 | namespace test_template_alias_sfinae 429 | { 430 | 431 | struct foo {}; 432 | 433 | template 434 | using member = typename T::member_type; 435 | 436 | template 437 | void func(...) {} 438 | 439 | template 440 | void func(member*) {} 441 | 442 | void test(); 443 | 444 | void test() { func(0); } 445 | 446 | } 447 | 448 | } // namespace cxx11 449 | 450 | #endif // __cplusplus >= 201103L 451 | 452 | ]]) 453 | 454 | 455 | dnl Tests for new features in C++14 456 | 457 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ 458 | 459 | // If the compiler admits that it is not ready for C++14, why torture it? 460 | // Hopefully, this will speed up the test. 461 | 462 | #ifndef __cplusplus 463 | 464 | #error "This is not a C++ compiler" 465 | 466 | #elif __cplusplus < 201402L 467 | 468 | #error "This is not a C++14 compiler" 469 | 470 | #else 471 | 472 | namespace cxx14 473 | { 474 | 475 | namespace test_polymorphic_lambdas 476 | { 477 | 478 | int 479 | test() 480 | { 481 | const auto lambda = [](auto&&... args){ 482 | const auto istiny = [](auto x){ 483 | return (sizeof(x) == 1UL) ? 1 : 0; 484 | }; 485 | const int aretiny[] = { istiny(args)... }; 486 | return aretiny[0]; 487 | }; 488 | return lambda(1, 1L, 1.0f, '1'); 489 | } 490 | 491 | } 492 | 493 | namespace test_binary_literals 494 | { 495 | 496 | constexpr auto ivii = 0b0000000000101010; 497 | static_assert(ivii == 42, "wrong value"); 498 | 499 | } 500 | 501 | namespace test_generalized_constexpr 502 | { 503 | 504 | template < typename CharT > 505 | constexpr unsigned long 506 | strlen_c(const CharT *const s) noexcept 507 | { 508 | auto length = 0UL; 509 | for (auto p = s; *p; ++p) 510 | ++length; 511 | return length; 512 | } 513 | 514 | static_assert(strlen_c("") == 0UL, ""); 515 | static_assert(strlen_c("x") == 1UL, ""); 516 | static_assert(strlen_c("test") == 4UL, ""); 517 | static_assert(strlen_c("another\0test") == 7UL, ""); 518 | 519 | } 520 | 521 | namespace test_lambda_init_capture 522 | { 523 | 524 | int 525 | test() 526 | { 527 | auto x = 0; 528 | const auto lambda1 = [a = x](int b){ return a + b; }; 529 | const auto lambda2 = [a = lambda1(x)](){ return a; }; 530 | return lambda2(); 531 | } 532 | 533 | } 534 | 535 | namespace test_digit_separators 536 | { 537 | 538 | constexpr auto ten_million = 100'000'000; 539 | static_assert(ten_million == 100000000, ""); 540 | 541 | } 542 | 543 | namespace test_return_type_deduction 544 | { 545 | 546 | auto f(int& x) { return x; } 547 | decltype(auto) g(int& x) { return x; } 548 | 549 | template < typename T1, typename T2 > 550 | struct is_same 551 | { 552 | static constexpr auto value = false; 553 | }; 554 | 555 | template < typename T > 556 | struct is_same 557 | { 558 | static constexpr auto value = true; 559 | }; 560 | 561 | int 562 | test() 563 | { 564 | auto x = 0; 565 | static_assert(is_same::value, ""); 566 | static_assert(is_same::value, ""); 567 | return x; 568 | } 569 | 570 | } 571 | 572 | } // namespace cxx14 573 | 574 | #endif // __cplusplus >= 201402L 575 | 576 | ]]) 577 | 578 | 579 | dnl Tests for new features in C++17 580 | 581 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ 582 | 583 | // If the compiler admits that it is not ready for C++17, why torture it? 584 | // Hopefully, this will speed up the test. 585 | 586 | #ifndef __cplusplus 587 | 588 | #error "This is not a C++ compiler" 589 | 590 | #elif __cplusplus <= 201402L 591 | 592 | #error "This is not a C++17 compiler" 593 | 594 | #else 595 | 596 | #if defined(__clang__) 597 | #define REALLY_CLANG 598 | #else 599 | #if defined(__GNUC__) 600 | #define REALLY_GCC 601 | #endif 602 | #endif 603 | 604 | #include 605 | #include 606 | #include 607 | 608 | namespace cxx17 609 | { 610 | 611 | #if !defined(REALLY_CLANG) 612 | namespace test_constexpr_lambdas 613 | { 614 | 615 | // TODO: test it with clang++ from git 616 | 617 | constexpr int foo = [](){return 42;}(); 618 | 619 | } 620 | #endif // !defined(REALLY_CLANG) 621 | 622 | namespace test::nested_namespace::definitions 623 | { 624 | 625 | } 626 | 627 | namespace test_fold_expression 628 | { 629 | 630 | template 631 | int multiply(Args... args) 632 | { 633 | return (args * ... * 1); 634 | } 635 | 636 | template 637 | bool all(Args... args) 638 | { 639 | return (args && ...); 640 | } 641 | 642 | } 643 | 644 | namespace test_extended_static_assert 645 | { 646 | 647 | static_assert (true); 648 | 649 | } 650 | 651 | namespace test_auto_brace_init_list 652 | { 653 | 654 | auto foo = {5}; 655 | auto bar {5}; 656 | 657 | static_assert(std::is_same, decltype(foo)>::value); 658 | static_assert(std::is_same::value); 659 | } 660 | 661 | namespace test_typename_in_template_template_parameter 662 | { 663 | 664 | template typename X> struct D; 665 | 666 | } 667 | 668 | namespace test_fallthrough_nodiscard_maybe_unused_attributes 669 | { 670 | 671 | int f1() 672 | { 673 | return 42; 674 | } 675 | 676 | [[nodiscard]] int f2() 677 | { 678 | [[maybe_unused]] auto unused = f1(); 679 | 680 | switch (f1()) 681 | { 682 | case 17: 683 | f1(); 684 | [[fallthrough]]; 685 | case 42: 686 | f1(); 687 | } 688 | return f1(); 689 | } 690 | 691 | } 692 | 693 | namespace test_extended_aggregate_initialization 694 | { 695 | 696 | struct base1 697 | { 698 | int b1, b2 = 42; 699 | }; 700 | 701 | struct base2 702 | { 703 | base2() { 704 | b3 = 42; 705 | } 706 | int b3; 707 | }; 708 | 709 | struct derived : base1, base2 710 | { 711 | int d; 712 | }; 713 | 714 | derived d1 {{1, 2}, {}, 4}; // full initialization 715 | derived d2 {{}, {}, 4}; // value-initialized bases 716 | 717 | } 718 | 719 | namespace test_general_range_based_for_loop 720 | { 721 | 722 | struct iter 723 | { 724 | int i; 725 | 726 | int& operator* () 727 | { 728 | return i; 729 | } 730 | 731 | const int& operator* () const 732 | { 733 | return i; 734 | } 735 | 736 | iter& operator++() 737 | { 738 | ++i; 739 | return *this; 740 | } 741 | }; 742 | 743 | struct sentinel 744 | { 745 | int i; 746 | }; 747 | 748 | bool operator== (const iter& i, const sentinel& s) 749 | { 750 | return i.i == s.i; 751 | } 752 | 753 | bool operator!= (const iter& i, const sentinel& s) 754 | { 755 | return !(i == s); 756 | } 757 | 758 | struct range 759 | { 760 | iter begin() const 761 | { 762 | return {0}; 763 | } 764 | 765 | sentinel end() const 766 | { 767 | return {5}; 768 | } 769 | }; 770 | 771 | void f() 772 | { 773 | range r {}; 774 | 775 | for (auto i : r) 776 | { 777 | [[maybe_unused]] auto v = i; 778 | } 779 | } 780 | 781 | } 782 | 783 | namespace test_lambda_capture_asterisk_this_by_value 784 | { 785 | 786 | struct t 787 | { 788 | int i; 789 | int foo() 790 | { 791 | return [*this]() 792 | { 793 | return i; 794 | }(); 795 | } 796 | }; 797 | 798 | } 799 | 800 | namespace test_enum_class_construction 801 | { 802 | 803 | enum class byte : unsigned char 804 | {}; 805 | 806 | byte foo {42}; 807 | 808 | } 809 | 810 | namespace test_constexpr_if 811 | { 812 | 813 | template 814 | int f () 815 | { 816 | if constexpr(cond) 817 | { 818 | return 13; 819 | } 820 | else 821 | { 822 | return 42; 823 | } 824 | } 825 | 826 | } 827 | 828 | namespace test_selection_statement_with_initializer 829 | { 830 | 831 | int f() 832 | { 833 | return 13; 834 | } 835 | 836 | int f2() 837 | { 838 | if (auto i = f(); i > 0) 839 | { 840 | return 3; 841 | } 842 | 843 | switch (auto i = f(); i + 4) 844 | { 845 | case 17: 846 | return 2; 847 | 848 | default: 849 | return 1; 850 | } 851 | } 852 | 853 | } 854 | 855 | #if !defined(REALLY_CLANG) 856 | namespace test_template_argument_deduction_for_class_templates 857 | { 858 | 859 | // TODO: test it with clang++ from git 860 | 861 | template 862 | struct pair 863 | { 864 | pair (T1 p1, T2 p2) 865 | : m1 {p1}, 866 | m2 {p2} 867 | {} 868 | 869 | T1 m1; 870 | T2 m2; 871 | }; 872 | 873 | void f() 874 | { 875 | [[maybe_unused]] auto p = pair{13, 42u}; 876 | } 877 | 878 | } 879 | #endif // !defined(REALLY_CLANG) 880 | 881 | namespace test_non_type_auto_template_parameters 882 | { 883 | 884 | template 885 | struct B 886 | {}; 887 | 888 | B<5> b1; 889 | B<'a'> b2; 890 | 891 | } 892 | 893 | #if !defined(REALLY_CLANG) 894 | namespace test_structured_bindings 895 | { 896 | 897 | // TODO: test it with clang++ from git 898 | 899 | int arr[2] = { 1, 2 }; 900 | std::pair pr = { 1, 2 }; 901 | 902 | auto f1() -> int(&)[2] 903 | { 904 | return arr; 905 | } 906 | 907 | auto f2() -> std::pair& 908 | { 909 | return pr; 910 | } 911 | 912 | struct S 913 | { 914 | int x1 : 2; 915 | volatile double y1; 916 | }; 917 | 918 | S f3() 919 | { 920 | return {}; 921 | } 922 | 923 | auto [ x1, y1 ] = f1(); 924 | auto& [ xr1, yr1 ] = f1(); 925 | auto [ x2, y2 ] = f2(); 926 | auto& [ xr2, yr2 ] = f2(); 927 | const auto [ x3, y3 ] = f3(); 928 | 929 | } 930 | #endif // !defined(REALLY_CLANG) 931 | 932 | #if !defined(REALLY_CLANG) 933 | namespace test_exception_spec_type_system 934 | { 935 | 936 | // TODO: test it with clang++ from git 937 | 938 | struct Good {}; 939 | struct Bad {}; 940 | 941 | void g1() noexcept; 942 | void g2(); 943 | 944 | template 945 | Bad 946 | f(T*, T*); 947 | 948 | template 949 | Good 950 | f(T1*, T2*); 951 | 952 | static_assert (std::is_same_v); 953 | 954 | } 955 | #endif // !defined(REALLY_CLANG) 956 | 957 | namespace test_inline_variables 958 | { 959 | 960 | template void f(T) 961 | {} 962 | 963 | template inline T g(T) 964 | { 965 | return T{}; 966 | } 967 | 968 | template<> inline void f<>(int) 969 | {} 970 | 971 | template<> int g<>(int) 972 | { 973 | return 5; 974 | } 975 | 976 | } 977 | 978 | } // namespace cxx17 979 | 980 | #endif // __cplusplus <= 201402L 981 | 982 | ]]) 983 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | bin_PROGRAMS = dpaste 2 | noinst_LIBRARIES = libdpaste.a 3 | 4 | libdpaste_a_SOURCES = \ 5 | node.cpp \ 6 | conf.cpp \ 7 | http_client.cpp \ 8 | bin.cpp \ 9 | log.cpp \ 10 | cipher.cpp \ 11 | gpgcrypto.cpp \ 12 | aescrypto.cpp 13 | dpaste_SOURCES = main.cpp 14 | 15 | # Variables defined in toplevel Makefile. Thus, `make` cannot be called from 16 | # this directory. 17 | libdpaste_a_CPPFLAGS = $(dpaste_CPPFLAGS_) 18 | dpaste_CPPFLAGS = $(dpaste_CPPFLAGS_) 19 | dpaste_LDADD = libdpaste.a $(dpaste_LIBS) 20 | 21 | # vim: set ts=4 sw=4 tw=120 noet : 22 | 23 | -------------------------------------------------------------------------------- /src/aescrypto.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2017 Simon Désaulniers 3 | * Author: Simon Désaulniers 4 | * 5 | * This file is part of dpaste. 6 | * 7 | * dpaste is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * dpaste is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with dpaste. If not, see . 19 | */ 20 | 21 | #include 22 | 23 | #include "log.h" 24 | #include "aescrypto.h" 25 | 26 | namespace dpaste { 27 | namespace crypto { 28 | 29 | std::string AES::getPassword(const std::shared_ptr& params) const { 30 | if (auto p = std::get_if(params.get())) 31 | return p->password; 32 | return {}; 33 | } 34 | 35 | std::vector AES::processPlainText(std::vector plain_text, std::shared_ptr&& params) { 36 | DPASTE_MSG("Encrypting (aes-gcm) data..."); 37 | return dht::crypto::aesEncrypt(plain_text, getPassword(params)); 38 | } 39 | 40 | std::vector AES::processCipherText(std::vector cipher_text, std::shared_ptr&& params) { 41 | DPASTE_MSG("Decrypting (aes-gcm)..."); 42 | return dht::crypto::aesDecrypt(cipher_text, getPassword(params)); 43 | } 44 | 45 | } /* crypto */ 46 | } /* dpaste */ 47 | 48 | /* vim:set et sw=4 ts=4 tw=120: */ 49 | 50 | -------------------------------------------------------------------------------- /src/aescrypto.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2017 Simon Désaulniers 3 | * Author: Simon Désaulniers 4 | * 5 | * This file is part of dpaste. 6 | * 7 | * dpaste is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * dpaste is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with dpaste. If not, see . 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include "cipher.h" 28 | 29 | namespace dpaste { 30 | namespace crypto { 31 | 32 | class AES : public Cipher { 33 | public: 34 | /** 35 | * Length of the PIN if it contains the password for encrypted pasted data. 36 | * It consists of 16 hexadecimal characters: 16*4 = 64 bits. Last 32 bits 37 | * encode the password. Otherwise, PIN should be 32 bits. 38 | */ 39 | static const constexpr size_t PIN_WITH_PASS_LEN {16}; 40 | /** 41 | * Number of bytes offsetting the password in the binary representation of 42 | * the hexadecimal password. 43 | */ 44 | static const constexpr size_t CODE_PASS_OFFSET {4}; 45 | 46 | AES() {} 47 | virtual ~AES () {} 48 | 49 | std::vector 50 | processPlainText(std::vector plain_text, std::shared_ptr&& params) override; 51 | std::vector 52 | processCipherText(std::vector cipher_text, std::shared_ptr&& params) override; 53 | private: 54 | std::string getPassword(const std::shared_ptr& params) const; 55 | }; 56 | 57 | } /* crypto */ 58 | } /* dpaste */ 59 | 60 | /* vim:set et sw=4 ts=4 tw=120: */ 61 | 62 | -------------------------------------------------------------------------------- /src/bin.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2017 Simon Désaulniers 3 | * Author: Simon Désaulniers 4 | * 5 | * This file is part of dpaste. 6 | * 7 | * dpaste is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * dpaste is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with dpaste. If not, see . 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | 29 | #include "bin.h" 30 | #include "conf.h" 31 | #include "log.h" 32 | #include "gpgcrypto.h" 33 | #include "aescrypto.h" 34 | 35 | namespace dpaste { 36 | 37 | const constexpr uint8_t Bin::PROTO_VERSION; 38 | 39 | Bin::Bin() { 40 | /* load dpaste config */ 41 | auto config_file = conf::ConfigurationFile(); 42 | config_file.load(); 43 | conf_ = config_file.getConfiguration(); 44 | 45 | long port; 46 | { 47 | std::istringstream conv(conf_.at("port")); 48 | conv >> port; 49 | } 50 | 51 | node.run(); 52 | http_client_ = std::make_unique(conf_.at("host"), port); 53 | } 54 | 55 | std::string Bin::code_from_dpaste_uri(const std::string& uri) { 56 | static const std::string DUP {DPASTE_URI_PREFIX}; 57 | const auto p = uri.find(DUP); 58 | return uri.substr(p != std::string::npos ? p+DUP.length() : 0); 59 | } 60 | 61 | std::pair Bin::get(std::string&& code, bool no_decrypt) { 62 | code = code_from_dpaste_uri(code); 63 | const auto offset = crypto::AES::CODE_PASS_OFFSET*2; 64 | const auto lcode = code.substr(0, offset); 65 | const auto pwd = code.substr(offset); 66 | 67 | /* first try http server */ 68 | auto data_str = http_client_->get(lcode); 69 | std::vector data {data_str.begin(), data_str.end()}; 70 | 71 | /* if fail, then perform request from local node */ 72 | if (data.empty()) { 73 | /* get a pasted blob */ 74 | auto values = node.get(lcode); 75 | if (not values.empty()) 76 | data = values.front(); 77 | } 78 | 79 | if (not data.empty()) { 80 | Packet p; 81 | try { 82 | p.deserialize(data); 83 | auto cipher = crypto::Cipher::get(p.data, code); 84 | if (cipher and not no_decrypt) { 85 | std::shared_ptr params; 86 | if (auto aes = std::dynamic_pointer_cast(cipher)) { 87 | params = std::make_shared(); 88 | params->emplace(pwd); 89 | } 90 | data = cipher->processCipherText(p.data, std::move(params)); 91 | } else 92 | data = std::move(p.data); 93 | if (not (cipher or p.signature.empty())) { 94 | auto gc = std::dynamic_pointer_cast(crypto::Cipher::get(crypto::Cipher::Scheme::GPG, {})); 95 | DPASTE_MSG("Data is GPG signed. Verifying..."); 96 | auto res = gc->verify(p.signature, data); 97 | if (res.numSignatures() > 0) 98 | gc->comment_on_signature(res.signature(0)); 99 | } 100 | } catch (const GpgME::Exception& e) { 101 | DPASTE_MSG("%s", e.what()); 102 | return {false, ""}; 103 | } catch (const dht::crypto::DecryptError& e) { 104 | DPASTE_MSG("%s", e.what()); 105 | return {false, ""}; 106 | } catch (msgpack::type_error& e) { } /* backward compatibility with <=0.3.3 */ 107 | 108 | } 109 | return {true, {data.begin(), data.end()}}; 110 | } 111 | 112 | std::vector Bin::data_from_stream(std::stringstream&& input_stream) { 113 | std::vector buffer; 114 | buffer.resize(dht::MAX_VALUE_SIZE); 115 | input_stream.read(reinterpret_cast(buffer.data()), dht::MAX_VALUE_SIZE); 116 | buffer.resize(input_stream.gcount()); 117 | return buffer; 118 | } 119 | 120 | std::string Bin::random_pin() { 121 | static std::uniform_int_distribution dist; 122 | static std::mt19937_64 rand_; 123 | static std::random_device rdev; 124 | static std::seed_seq seed {rdev(), rdev()}; 125 | static bool initialized = false; 126 | if (not initialized) 127 | rand_.seed(seed); 128 | 129 | auto pin = dist(rand_); 130 | std::stringstream ss; 131 | ss << std::setfill('0') << std::setw(Bin::DPASTE_PIN_LEN) << std::hex << pin; 132 | auto pin_s = ss.str(); 133 | std::transform(pin_s.begin(), pin_s.end(), pin_s.begin(), ::toupper); 134 | return pin_s; 135 | } 136 | 137 | std::pair Bin::prepare_data(std::vector&& data, std::unique_ptr&& params) { 138 | Packet p; 139 | std::string pwd = ""; 140 | std::shared_ptr sparams(std::move(params)); 141 | std::shared_ptr init_params; 142 | crypto::Cipher::Scheme scheme; 143 | 144 | bool to_sign {false}; 145 | if (auto gp = std::get_if(sparams.get())) { 146 | auto& keyid = conf_.at("pgp_key_id"); 147 | to_sign = gp->sign and not keyid.empty(); 148 | scheme = gp->scheme; 149 | init_params = std::make_shared(); 150 | init_params->emplace(keyid); 151 | } else if (auto aesp = std::get_if(sparams.get())) { 152 | scheme = aesp->scheme; 153 | pwd = random_pin(); 154 | aesp->password = pwd; 155 | } 156 | 157 | auto cipher = crypto::Cipher::get(scheme, std::move(init_params)); 158 | 159 | if (cipher) { 160 | auto cipher_text = cipher->processPlainText(data, std::move(sparams)); 161 | if (cipher_text.empty()) { 162 | p.data.insert(p.data.end(), data.begin(), data.end()); 163 | if (to_sign) { 164 | DPASTE_MSG("Signing data..."); 165 | auto res = std::dynamic_pointer_cast(cipher)->sign(p.data); 166 | p.signature = res.first; 167 | } 168 | } else 169 | p.data = cipher_text; 170 | } else 171 | p.data.insert(p.data.end(), data.begin(), data.end()); 172 | return {p, pwd}; 173 | } 174 | 175 | std::string Bin::paste(std::vector&& data, std::unique_ptr&& params) { 176 | auto code = random_pin(); 177 | 178 | auto pp = prepare_data(std::forward>(data), std::forward>(params)); 179 | auto& p = pp.first; 180 | auto& pwd = pp.second; 181 | 182 | DPASTE_MSG("Pasting data..."); 183 | auto bin_packet = p.serialize(); 184 | auto success = http_client_->put(code, {bin_packet.begin(), bin_packet.end()}); 185 | if (not success) 186 | success = node.paste(code, std::move(bin_packet)); 187 | 188 | return success ? DPASTE_URI_PREFIX+code+pwd : ""; 189 | } 190 | 191 | msgpack::object* 192 | findMapValue(msgpack::object& map, const std::string& key) { 193 | if (map.type != msgpack::type::MAP) throw msgpack::type_error(); 194 | for (unsigned i = 0; i < map.via.map.size; i++) { 195 | auto& o = map.via.map.ptr[i]; 196 | if (o.key.type == msgpack::type::STR && o.key.as() == key) 197 | return &o.val; 198 | } 199 | return nullptr; 200 | } 201 | 202 | std::vector Bin::Packet::serialize() const { 203 | msgpack::sbuffer buffer; 204 | msgpack::packer pk(&buffer); 205 | 206 | pk.pack_map(3); 207 | pk.pack("v"); pk.pack(PROTO_VERSION); 208 | pk.pack("data"); pk.pack(data); 209 | pk.pack("signature"); pk.pack(signature); 210 | return {buffer.data(), buffer.data()+buffer.size()}; 211 | } 212 | 213 | void Bin::Packet::deserialize(const std::vector& pbuffer) { 214 | msgpack::unpacked unpacked = msgpack::unpack(reinterpret_cast(pbuffer.data()), pbuffer.size()); 215 | auto msgpack_object = unpacked.get(); 216 | 217 | data.clear(); 218 | if (auto d = findMapValue(msgpack_object, "data")) 219 | d->convert(data); 220 | signature.clear(); 221 | if (auto s = findMapValue(msgpack_object, "signature")) 222 | s->convert(signature); 223 | } 224 | 225 | } /* dpaste */ 226 | 227 | /* vim:set et sw=4 ts=4 tw=120: */ 228 | 229 | -------------------------------------------------------------------------------- /src/bin.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2017 Simon Désaulniers 3 | * Author: Simon Désaulniers 4 | * 5 | * This file is part of dpaste. 6 | * 7 | * dpaste is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * dpaste is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with dpaste. If not, see . 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #ifdef HAVE_CONFIG_H 32 | #include "config.h" 33 | #endif 34 | #include "node.h" 35 | #include "http_client.h" 36 | #include "cipher.h" 37 | 38 | namespace dpaste { 39 | #ifdef DPASTE_TEST 40 | namespace tests { class PirateBinTester; } /* tests */ 41 | #endif 42 | 43 | class Bin { 44 | #ifdef DPASTE_TEST 45 | friend class tests::PirateBinTester; 46 | #endif 47 | public: 48 | 49 | static const constexpr unsigned int DPASTE_PIN_LEN {8}; 50 | 51 | Bin(); 52 | virtual ~Bin () {} 53 | 54 | /** 55 | * Execute procedure to get the content stored for a given code. 56 | * 57 | * @param code The PIN for finding data in DHT. 58 | * @param no_decrypt Whether to decrypt the recovered data or not. 59 | * 60 | * @return return code (0: success, 1 fail) 61 | */ 62 | std::pair get(std::string&& code, bool no_decrypt=false); 63 | 64 | /** 65 | * Execute procedure to publish content and generate the associated code. 66 | * 67 | * @param data Data to be pasted. 68 | * @param params Cryptographic parameters. 69 | * 70 | * @return the code (key) to the pasted data. If empty, then process failed. 71 | */ 72 | std::string paste(std::vector&& data, std::unique_ptr&& params); 73 | std::string paste(std::stringstream&& input_stream, std::unique_ptr&& params) { 74 | return paste(data_from_stream(std::move(input_stream)), 75 | std::forward>(params)); 76 | } 77 | 78 | private: 79 | /* constants */ 80 | static const constexpr char* DPASTE_URI_PREFIX = "dpaste:"; 81 | static const constexpr uint8_t PROTO_VERSION = 0; 82 | 83 | struct Packet { 84 | std::vector data {}; 85 | std::vector signature {}; 86 | 87 | std::vector serialize() const; 88 | void deserialize(const std::vector& pbuffer); 89 | }; 90 | 91 | /** 92 | * Create a Packet from input data and crypto parameters. 93 | * 94 | * @param data input data in bytes. 95 | * @param params cryptographic parameters (either GPGParameters or 96 | * AESParameters). 97 | * 98 | * @return an ordered pair of a Packet and associated password. 99 | */ 100 | std::pair prepare_data(std::vector&& data, std::unique_ptr&& params); 101 | 102 | /** 103 | * Get data from input stream. 104 | * 105 | * @param input_stream The stream to read to get the data. 106 | * 107 | * @return the data 108 | */ 109 | static std::vector data_from_stream(std::stringstream&& input_stream); 110 | 111 | /** 112 | * Parse dpaste uri for code. 113 | * 114 | * @param uri The dpaste uri 115 | * 116 | * @return hexadecimal code from the uri 117 | */ 118 | static std::string code_from_dpaste_uri(const std::string& uri); 119 | 120 | static std::string random_pin(); 121 | 122 | std::map conf_; 123 | 124 | /* transport */ 125 | std::unique_ptr http_client_ {}; 126 | Node node {}; 127 | }; 128 | 129 | } /* dpaste */ 130 | 131 | /* vim:set et sw=4 ts=4 tw=120: */ 132 | 133 | -------------------------------------------------------------------------------- /src/cipher.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2017 Simon Désaulniers 3 | * Author: Simon Désaulniers 4 | * 5 | * This file is part of dpaste. 6 | * 7 | * dpaste is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * dpaste is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with dpaste. If not, see . 19 | */ 20 | 21 | #include "cipher.h" 22 | #include "gpgcrypto.h" 23 | #include "aescrypto.h" 24 | 25 | namespace dpaste { 26 | namespace crypto { 27 | 28 | void Cipher::init() { 29 | static bool initialized = false; 30 | if (initialized) return; 31 | 32 | GPG::init(); 33 | 34 | initialized = true; 35 | } 36 | 37 | std::shared_ptr Cipher::get(const std::vector& cipher_text, const std::string& pin="") { 38 | if (GPG::isGPGencrypted(cipher_text)) 39 | return std::make_shared(); 40 | else if (pin.size() == AES::PIN_WITH_PASS_LEN) 41 | return std::make_shared(); 42 | return {}; 43 | } 44 | 45 | std::shared_ptr Cipher::get(Scheme scheme, std::shared_ptr&& params) { 46 | switch (scheme) { 47 | case Scheme::AES: 48 | return std::make_shared(); 49 | case Scheme::GPG: 50 | if (auto gpg_params = std::get_if(params.get())) 51 | return std::static_pointer_cast(std::make_shared(gpg_params->key_id)); 52 | else 53 | return std::make_shared(); 54 | default: 55 | break; 56 | } 57 | return {}; 58 | } 59 | 60 | } /* crypto */ 61 | } /* dpaste */ 62 | 63 | /* vim:set et sw=4 ts=4 tw=120: */ 64 | 65 | -------------------------------------------------------------------------------- /src/cipher.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2017 Simon Désaulniers 3 | * Author: Simon Désaulniers 4 | * 5 | * This file is part of dpaste. 6 | * 7 | * dpaste is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * dpaste is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with dpaste. If not, see . 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | namespace dpaste { 31 | namespace crypto { 32 | 33 | struct GPGParameters; 34 | struct AESParameters; 35 | using Parameters = std::variant; 36 | 37 | class Cipher { 38 | public: 39 | enum class Scheme : int { NONE=0, GPG, AES }; 40 | 41 | virtual ~Cipher () {} 42 | 43 | static void init(); 44 | 45 | /** 46 | * Process the plain text according to the cipher used. 47 | * 48 | * @param plain_text The plain text. 49 | * @param params The parameters needed to process the plain text by the cipher. 50 | * 51 | * @return the resulting cipher_text 52 | */ 53 | virtual std::vector 54 | processPlainText(std::vector plain_text, std::shared_ptr&& params) = 0; 55 | 56 | /** 57 | * Process the cipher text according to the cipher used. 58 | * 59 | * @param plain_text The cipher text. 60 | * @param params The parameters needed to process the cipher text by the cipher. 61 | * 62 | * @return the resulting plain text. 63 | */ 64 | virtual std::vector 65 | processCipherText(std::vector cipher_text, std::shared_ptr&& params) = 0; 66 | 67 | /** 68 | * Get a cipher by specifying the scheme to use (either GPG or AES). 69 | * 70 | * @param scheme The scheme to use (GPG, AES). 71 | * @param init_params The initialization parameters if needed. 72 | * 73 | * @return A cipher 74 | */ 75 | static std::shared_ptr get(Scheme scheme, std::shared_ptr&& init_params={}); 76 | 77 | /** 78 | * Returns a cipher according to the cipher text put in parameters. 79 | * 80 | * @param cipher_text The cipher text to guess the cipher from. 81 | * 82 | * @return A cipher 83 | */ 84 | static std::shared_ptr get(const std::vector& cipher_text, const std::string& pin); 85 | }; 86 | 87 | struct GPGParameters { 88 | const static Cipher::Scheme scheme = Cipher::Scheme::GPG; 89 | 90 | std::string key_id; 91 | std::vector recipients; 92 | bool self_recipient; 93 | bool sign; 94 | 95 | GPGParameters() {} 96 | GPGParameters(std::string key_id) : key_id(key_id) {} 97 | GPGParameters(std::vector recipients, bool self_recipient, bool sign) 98 | : recipients(recipients), self_recipient(self_recipient), sign(sign) {} 99 | }; 100 | 101 | struct AESParameters { 102 | const static Cipher::Scheme scheme = Cipher::Scheme::AES; 103 | std::string password; 104 | 105 | AESParameters() {} 106 | AESParameters(std::string password) : password(password) {} 107 | }; 108 | 109 | } /* crypto */ 110 | } /* dpaste */ 111 | 112 | /* vim:set et sw=4 ts=4 tw=120: */ 113 | 114 | -------------------------------------------------------------------------------- /src/conf.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2017 Simon Désaulniers 3 | * Author: Simon Désaulniers 4 | * 5 | * This file is part of dpaste. 6 | * 7 | * dpaste is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * dpaste is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with dpaste. If not, see . 19 | */ 20 | 21 | #include "conf.h" 22 | 23 | namespace dpaste { 24 | namespace conf { 25 | 26 | void trim_str(std::string& str) { 27 | auto first = std::min(str.size(), str.find_first_not_of(" ")); 28 | auto last = std::min(str.size(), str.find_last_not_of(" ")); 29 | str = str.substr(first, last - first + 1); 30 | } 31 | 32 | int ConfigurationFile::load() { 33 | std::ifstream config_file(filePath_, std::ios::in); 34 | if (not config_file.is_open()) 35 | return 1; 36 | 37 | std::string line; 38 | while (std::getline(config_file, line)) { 39 | std::string arg_name; 40 | std::istringstream ss(line); 41 | while (std::getline(ss, arg_name, '=')) { 42 | std::string arg; 43 | trim_str(arg_name); 44 | auto ait = config_.find(arg_name); 45 | if (ait != config_.end()) { 46 | std::getline(ss, arg); 47 | trim_str(arg); 48 | if (not arg.empty()) 49 | ait->second = arg; 50 | } 51 | } 52 | } 53 | return 0; 54 | } 55 | 56 | } /* conf */ 57 | } /* dpaste */ 58 | 59 | /* vim: set ts=4 sw=4 tw=120 et :*/ 60 | 61 | -------------------------------------------------------------------------------- /src/conf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2017 Simon Désaulniers 3 | * Author: Simon Désaulniers 4 | * 5 | * This file is part of dpaste. 6 | * 7 | * dpaste is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * dpaste is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with dpaste. If not, see . 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | 31 | namespace dpaste { 32 | namespace conf { 33 | 34 | static const constexpr char* CONFIG_FILE_NAME = "dpaste.conf"; 35 | 36 | class ConfigurationFile final { 37 | public: 38 | ConfigurationFile(std::string file_path="") : 39 | filePath_(file_path), 40 | config_({ 41 | {"host", "127.0.0.1"}, 42 | {"port", "6509" }, 43 | {"pgp_key_id", "" } 44 | }) 45 | { 46 | if (file_path.empty()) { 47 | const auto default_file_path = Glib::get_user_config_dir() + '/' + CONFIG_FILE_NAME; 48 | filePath_ = default_file_path; 49 | } 50 | } 51 | ~ConfigurationFile() {} 52 | 53 | /** 54 | * Loads the file on disk and parses lines according to the simple following 55 | * format: 56 | * 57 | * OPTION = VALUE 58 | * 59 | * Malformed lines are omitted. 60 | * 61 | * @return 1 if configuration file cannot be opened, 0 otherwise. 62 | */ 63 | int load(); 64 | const std::map& getConfiguration() { return config_; } 65 | 66 | private: 67 | std::string filePath_ {}; 68 | std::map config_ {}; 69 | }; 70 | 71 | } /* conf */ 72 | } /* dpaste */ 73 | 74 | -------------------------------------------------------------------------------- /src/curlpp/Options.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) <2002-2009> 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files 6 | * (curlpp), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef CURLPP_OPTIONS_HPP 25 | #define CURLPP_OPTIONS_HPP 26 | 27 | 28 | #include 29 | 30 | #include 31 | 32 | 33 | #ifdef CURLPP_ALLOW_NOT_AVAILABLE 34 | #define DEF_IF_ALLOW_AVAILABLE (type,option,name) typedef curlpp::NotAvailableOptionTrait name; 35 | #endif 36 | 37 | // #begin define OPTION(version,type,option,name) 38 | // #if LIBCURL_VERSION_NUM >= version 39 | // typedef curlpp::OptionTrait name; 40 | // #else 41 | // DEF_IF_ALLOW_AVAILABLE(type,option,name) 42 | // #endif 43 | // #end 44 | 45 | 46 | namespace curlpp 47 | { 48 | 49 | 50 | namespace options 51 | { 52 | 53 | 54 | /** 55 | * Cookie interface. 56 | */ 57 | 58 | #if LIBCURL_VERSION_NUM >= 0x070d01 59 | typedef curlpp::OptionTrait CookieList; 60 | #else 61 | #ifdef CURLPP_ALLOW_NOT_AVAILABLE 62 | typedef curlpp::NotAvailableOptionTrait CookieList; 63 | #endif 64 | #endif 65 | 66 | /** 67 | * Behavior options. 68 | */ 69 | 70 | typedef curlpp::OptionTrait Verbose; 71 | typedef curlpp::OptionTrait Header; 72 | #if LIBCURL_VERSION_NUM >= 0x070A00 73 | typedef curlpp::OptionTrait NoSignal; 74 | #else 75 | #ifdef CURLPP_ALLOW_NOT_AVAILABLE 76 | typedef curlpp::NotAvailableOptionTrait NoSignal; 77 | #endif // CURLPP_ALLOW_NOT_AVAILABLE 78 | #endif // LIBCURL_VERSION_NUM 79 | 80 | typedef curlpp::OptionTrait NoProgress; 81 | 82 | 83 | /** 84 | * Callback options. 85 | */ 86 | 87 | typedef curlpp::OptionTrait 88 | WriteFunctionCurlFunction; 89 | 90 | typedef curlpp::OptionTrait 91 | WriteFunction; 92 | 93 | 94 | /** 95 | * Using this option will reset CURLOPT_WRITEFUNCTION to 96 | * default callback. In fact, use only this option if you only 97 | * want libcURL to use the FILE * given in argument instead 98 | * of stdout. 99 | */ 100 | 101 | #if LIBCURL_VERSION_NUM >= 0x070907 102 | typedef curlpp::OptionTrait WriteFile; 103 | typedef curlpp::OptionTrait WriteStream; 104 | #else 105 | #ifdef CURLPP_ALLOW_NOT_AVAILABLE 106 | typedef curlpp::NotAvailableOptionTrait WriteFile; 107 | typedef curlpp::NotAvailableOptionTrait WriteStream; 108 | #endif // CURLPP_ALLOW_NOT_AVAILABLE 109 | #endif // LIBCURL_VERSION_NUM 110 | 111 | 112 | #if LIBCURL_VERSION_NUM >= 0x070c01 113 | 114 | typedef curlpp::OptionTrait 115 | ReadFunctionCurlFunction; 116 | 117 | typedef curlpp::OptionTrait 118 | ReadFunction; 119 | 120 | #else 121 | 122 | #ifdef CURLPP_ALLOW_NOT_AVAILABLE 123 | 124 | typedef curlpp::NotAvailableOptionTrait 125 | ReadFunctionCurlFunction; 126 | 127 | typedef curlpp::NotAvailableOptionTrait 128 | ReadFunction; 129 | 130 | #endif // CURLPP_ALLOW_NOT_AVAILABLE 131 | 132 | #endif // LIBCURL_VERSION_NUM 133 | 134 | 135 | /** 136 | * Using this option will reset CURLOPT_READFUNCTION to 137 | * default callback. In fact, use only this option if you only 138 | * want libcURL to use the FILE * given in argument instead 139 | * of stdout. 140 | */ 141 | 142 | #if LIBCURL_VERSION_NUM >= 0x070907 143 | typedef curlpp::OptionTrait ReadFile; 144 | typedef curlpp::OptionTrait ReadStream; 145 | #else 146 | #ifdef CURLPP_ALLOW_NOT_AVAILABLE 147 | typedef curlpp::NotAvailableOptionTrait ReadFile; 148 | typedef curlpp::NotAvailableOptionTrait ReadStream; 149 | #endif // CURLPP_ALLOW_NOT_AVAILABLE 150 | #endif // LIBCURL_VERSION_NUM 151 | 152 | typedef curlpp::OptionTrait 153 | HeaderFunction; 154 | 155 | typedef curlpp::OptionTrait 156 | DebugFunction; 157 | 158 | typedef curlpp::OptionTrait 159 | SslCtxFunction; 160 | 161 | /** 162 | * Error options. 163 | */ 164 | 165 | typedef curlpp::OptionTrait ErrorBuffer; 166 | 167 | #ifdef FILE 168 | typedef curlpp::OptionTrait StdErr; 169 | #endif 170 | 171 | typedef curlpp::OptionTrait FailOnError; 172 | 173 | 174 | /** 175 | * Network options. 176 | */ 177 | 178 | typedef curlpp::OptionTrait Url; 179 | typedef curlpp::OptionTrait Proxy; 180 | typedef curlpp::OptionTrait ProxyPort; 181 | typedef curlpp::OptionTrait ProxyType; 182 | typedef curlpp::OptionTrait HttpProxyTunnel; 183 | typedef curlpp::OptionTrait Interface; 184 | typedef curlpp::OptionTrait DnsCacheTimeout; 185 | typedef curlpp::OptionTrait BufferSize; 186 | typedef curlpp::OptionTrait Port; 187 | 188 | typedef curlpp::OptionTrait TcpNoDelay; 189 | 190 | 191 | /** 192 | * Names and passwords options. 193 | */ 194 | 195 | typedef curlpp::OptionTrait Netrc; 196 | typedef curlpp::OptionTrait NetrcFile; 197 | typedef curlpp::OptionTrait UserPwd; 198 | typedef curlpp::OptionTrait ProxyUserPwd; 199 | typedef curlpp::OptionTrait HttpAuth; 200 | typedef curlpp::OptionTrait ProxyAuth; 201 | 202 | 203 | /** 204 | * HTTP options. 205 | */ 206 | 207 | typedef curlpp::OptionTrait AutoReferer; 208 | typedef curlpp::OptionTrait FollowLocation; 209 | typedef curlpp::OptionTrait UnrestrictedAuth; 210 | typedef curlpp::OptionTrait MaxRedirs; 211 | typedef curlpp::OptionTrait Upload; 212 | typedef curlpp::OptionTrait Post; 213 | typedef curlpp::OptionTrait PostFields; 214 | typedef curlpp::OptionTrait PostFieldSize; 215 | typedef curlpp::OptionTrait PostFieldSizeLarge; 216 | typedef curlpp::OptionTrait HttpPost; 217 | typedef curlpp::OptionTrait Referer; 218 | typedef curlpp::OptionTrait UserAgent; 219 | typedef curlpp::OptionTrait, CURLOPT_HTTPHEADER> HttpHeader; 220 | typedef curlpp::OptionTrait, CURLOPT_HTTP200ALIASES> Http200Aliases; 221 | typedef curlpp::OptionTrait Cookie; 222 | typedef curlpp::OptionTrait CookieFile; 223 | typedef curlpp::OptionTrait CookieJar; 224 | typedef curlpp::OptionTrait CookieSession; 225 | typedef curlpp::OptionTrait HttpGet; 226 | typedef curlpp::OptionTrait HttpVersion; 227 | 228 | 229 | /** 230 | * FTP options. 231 | */ 232 | 233 | typedef curlpp::OptionTrait FtpPort; 234 | typedef curlpp::OptionTrait, CURLOPT_QUOTE> Quote; 235 | typedef curlpp::OptionTrait, CURLOPT_POSTQUOTE> PostQuote; 236 | typedef curlpp::OptionTrait, CURLOPT_PREQUOTE> PreQuote; 237 | typedef curlpp::OptionTrait FtpUseEpsv; 238 | typedef curlpp::OptionTrait FtpFileMethod; 239 | typedef curlpp::OptionTrait FtpCreateMissingDirs; 240 | typedef curlpp::OptionTrait FtpSslAuth; 241 | 242 | 243 | /** 244 | * Protocol options. 245 | */ 246 | 247 | typedef curlpp::OptionTrait TransferText; 248 | typedef curlpp::OptionTrait Crlf; 249 | typedef curlpp::OptionTrait Range; 250 | typedef curlpp::OptionTrait ResumeFrom; 251 | typedef curlpp::OptionTrait ResumeFromLarge; 252 | typedef curlpp::OptionTrait CustomRequest; 253 | typedef curlpp::OptionTrait FileTime; 254 | typedef curlpp::OptionTrait NoBody; 255 | typedef curlpp::OptionTrait InfileSize; 256 | typedef curlpp::OptionTrait InfileSizeLarge; 257 | typedef curlpp::OptionTrait MaxFileSize; 258 | typedef curlpp::OptionTrait MaxFileSizeLarge; 259 | typedef curlpp::OptionTrait TimeCondition; 260 | typedef curlpp::OptionTrait TimeValue; 261 | 262 | 263 | /** 264 | * Connection options. 265 | */ 266 | 267 | typedef curlpp::OptionTrait Timeout; 268 | typedef curlpp::OptionTrait LowSpeedLimit; 269 | typedef curlpp::OptionTrait LowSpeedTime; 270 | typedef curlpp::OptionTrait MaxConnects; 271 | typedef curlpp::OptionTrait FreshConnect; 272 | typedef curlpp::OptionTrait ForbidReuse; 273 | typedef curlpp::OptionTrait ConnectTimeout; 274 | typedef curlpp::OptionTrait IpResolve; 275 | 276 | 277 | /** 278 | * SSL and security options. 279 | */ 280 | 281 | typedef curlpp::OptionTrait UseSsl; 282 | typedef curlpp::OptionTrait SslOptions; 283 | typedef curlpp::OptionTrait SslCert; 284 | typedef curlpp::OptionTrait SslCertType; 285 | typedef curlpp::OptionTrait SslKey; 286 | typedef curlpp::OptionTrait SslKeyType; 287 | typedef curlpp::OptionTrait SslEngine; 288 | typedef curlpp::NoValueOptionTrait SslEngineDefault; 289 | typedef curlpp::OptionTrait SslVersion; 290 | typedef curlpp::OptionTrait SslVerifyPeer; 291 | typedef curlpp::OptionTrait CaInfo; 292 | typedef curlpp::OptionTrait CaPath; 293 | typedef curlpp::OptionTrait SslVerifyHost; 294 | typedef curlpp::OptionTrait SslCipherList; 295 | 296 | 297 | /** 298 | * Other options. 299 | */ 300 | 301 | typedef curlpp::OptionTrait Private; 302 | 303 | #ifndef CURL_NO_OLDIES 304 | typedef curlpp::OptionTrait Krb4Level; 305 | typedef curlpp::OptionTrait SslKeyPasswd; 306 | typedef curlpp::OptionTrait SslCertPasswd; 307 | typedef curlpp::OptionTrait FtpSsl; 308 | typedef curlpp::OptionTrait FtpResponseTimeout; 309 | typedef curlpp::OptionTrait FtpAppend; 310 | typedef curlpp::OptionTrait FtpListOnly; 311 | typedef curlpp::OptionTrait Encoding; 312 | #endif 313 | 314 | //Share; 315 | //TelnetOptions 316 | 317 | 318 | } // namespace options 319 | 320 | namespace Options = options; 321 | 322 | 323 | } // namespace curlpp 324 | 325 | namespace cURLpp = curlpp; 326 | 327 | 328 | std::ostream & operator<<(std::ostream & stream, const curlpp::options::Url & url); 329 | 330 | 331 | #endif // #ifndef CURLPP_OPTIONS_HPP 332 | -------------------------------------------------------------------------------- /src/gpgcrypto.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2017 Simon Désaulniers 3 | * Author: Simon Désaulniers 4 | * 5 | * This file is part of dpaste. 6 | * 7 | * dpaste is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * dpaste is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with dpaste. If not, see . 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include "log.h" 30 | #include "gpgcrypto.h" 31 | 32 | static constexpr const size_t BUFLEN = 1024; 33 | 34 | namespace dpaste { 35 | namespace crypto { 36 | 37 | std::vector dataToVector(GpgME::Data& d) { 38 | d.seek(0, SEEK_SET); 39 | std::array buf; 40 | std::vector v; 41 | 42 | ssize_t bytes = 0; 43 | while ((bytes = d.read(buf.data(), BUFLEN)) > 0) 44 | v.insert(v.end(), buf.begin(), buf.begin()+bytes); 45 | return v; 46 | } 47 | 48 | GPG::GPG(std::string signer) : ctx(GpgME::Context::createForProtocol(GpgME::Protocol::OpenPGP)), signerKey_(signer) { 49 | ctx = std::unique_ptr(GpgME::Context::createForProtocol(GpgME::Protocol::OpenPGP)); 50 | ctx->setArmor(1); 51 | if (not signer.empty()) 52 | ctx->addSigningKey(getKey(signer)); 53 | } 54 | 55 | void GPG::init() { 56 | static bool initialized = false; 57 | if (initialized) return; 58 | 59 | GpgME::initializeLibrary(); 60 | auto err = GpgME::checkEngine(GpgME::Protocol::OpenPGP); 61 | if (err.code() != GPG_ERR_NO_ERROR) 62 | throw GpgME::Exception(err, "Failed to initialize OpenPGP engine"); 63 | 64 | initialized = true; 65 | } 66 | 67 | std::vector GPG::processPlainText(std::vector plain_text, std::shared_ptr&& params) 68 | { 69 | if (not params) 70 | return {}; 71 | 72 | auto gparams = std::get(*params); 73 | /* we include self as recipient if there's at least one other recipient */ 74 | if (not gparams.recipients.empty() and gparams.self_recipient and not signerKey_.empty()) 75 | gparams.recipients.emplace_back(signerKey_); 76 | 77 | auto to_sign = gparams.sign and not signerKey_.empty(); 78 | if (not gparams.recipients.empty()) { 79 | DPASTE_MSG("Encrypting (gpg)%s...", to_sign ? " and signing " : ""); 80 | auto res = encrypt(gparams.recipients, plain_text, to_sign); 81 | return std::get<0>(res); 82 | } 83 | 84 | return {}; 85 | } 86 | 87 | std::vector 88 | GPG::processCipherText(std::vector cipher_text, std::shared_ptr&& params) 89 | { 90 | auto gparams = params ? std::get(*params) : GPGParameters {}; 91 | 92 | DPASTE_MSG("Decrypting (gpg)..."); 93 | auto res = decryptAndVerify(cipher_text); 94 | DPASTE_MSG("Success!"); 95 | 96 | auto data = std::move(std::get<0>(res)); 97 | auto& verif_res = std::get<2>(res); 98 | if (verif_res.numSignatures() > 0) 99 | comment_on_signature(verif_res.signature(0)); 100 | return data; 101 | } 102 | 103 | std::tuple, 104 | GpgME::EncryptionResult, 105 | GpgME::SigningResult> 106 | GPG::encrypt(const std::vector& recipients, std::vector plain_text, bool sign) const { 107 | if (not ctx or (sign and ctx->signingKeys().empty())) 108 | return {}; 109 | 110 | /* Adding final null char delimiter to data */ 111 | plain_text.push_back('\0'); 112 | GpgME::Data pt {reinterpret_cast(plain_text.data()), plain_text.size()}; 113 | GpgME::Data cipher_text {}; 114 | 115 | std::vector keys; 116 | for (const auto& r : recipients) 117 | keys.emplace_back(getKey(r)); 118 | GpgME::EncryptionResult enc_res; 119 | GpgME::SigningResult sign_res; 120 | if (sign) { 121 | auto res = ctx->signAndEncrypt(keys, pt, cipher_text, GpgME::Context::EncryptionFlags::None); 122 | res.first.swap(sign_res); 123 | res.second.swap(enc_res); 124 | } else { 125 | auto res = ctx->encrypt(keys, pt, cipher_text, GpgME::Context::EncryptionFlags::None); 126 | res.swap(enc_res); 127 | } 128 | /* Adding final null char delimiter to cipher_text */ 129 | cipher_text.write("\0", 1); 130 | 131 | if (enc_res.error()) 132 | throw GpgME::Exception(enc_res.error(), "Failed to encrypt with key of ID "+recipients.front()); 133 | 134 | if (not sign_res.isNull() and sign_res.error()) 135 | throw GpgME::Exception( 136 | sign_res.error(), 137 | "Failed to sign with key of ID "+std::string{ctx->signingKey(0).primaryFingerprint()}); 138 | 139 | return std::make_tuple(dataToVector(cipher_text), std::move(enc_res), std::move(sign_res)); 140 | } 141 | 142 | std::tuple, 143 | GpgME::DecryptionResult, 144 | GpgME::VerificationResult> 145 | GPG::decryptAndVerify(const std::vector& cipher_text) const { 146 | if (not ctx) 147 | return {}; 148 | 149 | GpgME::Data ct {reinterpret_cast(cipher_text.data()), cipher_text.size()}; 150 | GpgME::Data pt {}; 151 | auto res = ctx->decryptAndVerify(ct, pt); 152 | auto& dec_res = res.first; 153 | auto& sign_res = res.second; 154 | 155 | if (dec_res.error()) 156 | throw GpgME::Exception(dec_res.error()); 157 | if (sign_res.error()) 158 | throw GpgME::Exception(sign_res.error()); 159 | 160 | return std::make_tuple(dataToVector(pt), std::move(res.first), std::move(res.second)); 161 | } 162 | 163 | std::pair, 164 | GpgME::SigningResult> 165 | GPG::sign(const std::vector& plain_text) const { 166 | if (not ctx or ctx->signingKeys().empty()) 167 | return {}; 168 | 169 | GpgME::Data pt {reinterpret_cast(plain_text.data()), plain_text.size()}; 170 | GpgME::Data signature; 171 | auto res = ctx->sign(pt, signature, GpgME::SignatureMode::NormalSignatureMode); 172 | 173 | if (res.error()) 174 | throw GpgME::Exception( 175 | res.error(), 176 | "Failed to sign with key of ID "+std::string{ctx->signingKey(0).primaryFingerprint()}); 177 | 178 | return std::make_pair(dataToVector(signature), std::move(res)); 179 | } 180 | 181 | GpgME::VerificationResult 182 | GPG::verify(const std::vector& signature, const std::vector& plain_text) const { 183 | if (not ctx) 184 | return {}; 185 | 186 | GpgME::Data pt {reinterpret_cast(plain_text.data()), plain_text.size()}; 187 | GpgME::Data sig {reinterpret_cast(signature.data()), signature.size()}; 188 | auto res = ctx->verifyOpaqueSignature(sig, pt); 189 | 190 | if (res.error()) 191 | throw GpgME::Exception(res.error()); 192 | 193 | return res; 194 | } 195 | 196 | void GPG::comment_on_signature(const GpgME::Signature& sig) { 197 | const auto& s = sig.summary(); 198 | if (s & GpgME::Signature::Valid) 199 | DPASTE_MSG("Valid signature from key with ID %s", sig.fingerprint()); 200 | } 201 | 202 | GpgME::Key GPG::getKey(const std::string& key_id) const { 203 | if (not ctx) 204 | return {}; 205 | 206 | GpgME::Error err; 207 | auto key = ctx->key(key_id.c_str(), err, false); 208 | if (err) 209 | throw GpgME::Exception(err, "Failed to retrieve key with ID "+key_id); 210 | 211 | return key; 212 | } 213 | 214 | bool GPG::isGPGencrypted(const std::vector& data) { 215 | GpgME::Data d {reinterpret_cast(data.data()), data.size()}; 216 | return d.type() == GpgME::Data::Type::PGPEncrypted; 217 | } 218 | 219 | } /* crypto */ 220 | } /* dpaste */ 221 | 222 | /* vim:set et sw=4 ts=4 tw=120: */ 223 | 224 | -------------------------------------------------------------------------------- /src/gpgcrypto.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2017 Simon Désaulniers 3 | * Author: Simon Désaulniers 4 | * 5 | * This file is part of dpaste. 6 | * 7 | * dpaste is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * dpaste is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with dpaste. If not, see . 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include "cipher.h" 36 | 37 | namespace dpaste { 38 | namespace crypto { 39 | 40 | class GPG : public Cipher { 41 | public: 42 | GPG(std::string signer=""); 43 | virtual ~GPG () {} 44 | 45 | static void init(); 46 | 47 | std::vector 48 | processPlainText(std::vector plain_text, std::shared_ptr&& params) override; 49 | 50 | std::vector 51 | processCipherText(std::vector cipher_text, std::shared_ptr&& params) override; 52 | 53 | std::tuple, 54 | GpgME::EncryptionResult, 55 | GpgME::SigningResult> 56 | encrypt(const std::vector& recipient, std::vector plain_text, bool sign=false) const; 57 | 58 | std::tuple, 59 | GpgME::DecryptionResult, 60 | GpgME::VerificationResult> 61 | decryptAndVerify(const std::vector& cipher) const; 62 | 63 | std::pair, 64 | GpgME::SigningResult> 65 | sign(const std::vector& plain_text) const; 66 | 67 | GpgME::VerificationResult verify(const std::vector& signature, const std::vector& plain_text) const; 68 | 69 | void comment_on_signature(const GpgME::Signature& sig); 70 | 71 | static bool isGPGencrypted(const std::vector& d); 72 | 73 | private: 74 | GpgME::Key getKey(const std::string& key_id) const; 75 | 76 | std::unique_ptr ctx; 77 | std::string signerKey_; 78 | }; 79 | 80 | 81 | } /* crypto */ 82 | } /* dpaste */ 83 | 84 | /* vim:set et sw=4 ts=4 tw=120: */ 85 | 86 | -------------------------------------------------------------------------------- /src/http_client.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2017 Simon Désaulniers 3 | * Author: Simon Désaulniers 4 | * 5 | * This file is part of dpaste. 6 | * 7 | * dpaste is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * dpaste is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with dpaste. If not, see . 19 | */ 20 | 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "curlpp/Options.hpp" 31 | 32 | #include "http_client.h" 33 | #include "node.h" 34 | 35 | namespace dpaste { 36 | 37 | using json = nlohmann::json; 38 | 39 | static std::ofstream null("/dev/null"); 40 | 41 | std::string HttpClient::get(const std::string& code) const { 42 | try { 43 | curlpp::Cleanup mycleanup; 44 | curlpp::Easy req; 45 | req.setOpt(port); 46 | std::stringstream response, oss; 47 | req.setOpt(HTTP_PROTO+ 48 | host+"/"+dht::InfoHash::get(code).toString() 49 | +"?user_type="+dpaste::Node::DPASTE_USER_TYPE 50 | ); 51 | req.setOpt(curlpp::Options::WriteStream(&response)); 52 | 53 | try { 54 | req.perform(); 55 | /* server gives code 200 when everything is fine. */ 56 | if (curlpp::Infos::ResponseCode::get(req) == 200) { 57 | auto pr = json::parse(response.str()); 58 | if (not pr.empty()) { 59 | std::istringstream iss((*pr.begin())["base64"].dump()); 60 | base64::decoder d; 61 | d.decode(iss, oss); 62 | } 63 | } 64 | } catch (curlpp::RuntimeError & e) { } 65 | 66 | return oss.str(); 67 | } catch (curlpp::LogicError & e) { return {}; } 68 | } 69 | 70 | bool HttpClient::put(const std::string& code, const std::string& data) const { 71 | try { 72 | curlpp::Cleanup mycleanup; 73 | curlpp::Easy req; 74 | req.setOpt(port); 75 | req.setOpt(HTTP_PROTO+host+"/"+dht::InfoHash::get(code).toString()); 76 | req.setOpt(curlpp::Options::WriteStream(&null)); 77 | { 78 | curlpp::Forms form_parts; 79 | form_parts.push_back(new curlpp::FormParts::Content("user_type", dpaste::Node::DPASTE_USER_TYPE)); 80 | form_parts.push_back(new curlpp::FormParts::Content("data", data)); 81 | req.setOpt(new curlpp::options::HttpPost(form_parts)); 82 | } 83 | 84 | try { 85 | req.perform(); 86 | return curlpp::Infos::ResponseCode::get(req) == 200; 87 | } catch (curlpp::RuntimeError & e) { 88 | return false; 89 | } 90 | } catch (curlpp::LogicError & e) { return false; } 91 | } 92 | 93 | } /* dpaste */ 94 | 95 | /* vim:set et sw=4 ts=4 tw=120: */ 96 | 97 | -------------------------------------------------------------------------------- /src/http_client.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2017 Simon Désaulniers 3 | * Author: Simon Désaulniers 4 | * 5 | * This file is part of dpaste. 6 | * 7 | * dpaste is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * dpaste is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with dpaste. If not, see . 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | namespace dpaste { 26 | 27 | class HttpClient { 28 | public: 29 | HttpClient (std::string host, long port) : host(host), port(port) {} 30 | virtual ~HttpClient () {} 31 | 32 | std::string get(const std::string& code) const; 33 | bool put(const std::string& code, const std::string& data) const; 34 | 35 | private: 36 | static const constexpr char* HTTP_PROTO = "http://"; 37 | 38 | std::string host; /* host for the http dht service */ 39 | long port; /* port for the http dht service */ 40 | }; 41 | 42 | } /* dpaste */ 43 | -------------------------------------------------------------------------------- /src/log.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2017 Simon Désaulniers 3 | * Author: Simon Désaulniers 4 | * 5 | * This file is part of dpaste. 6 | * 7 | * dpaste is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * dpaste is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with dpaste. If not, see . 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #ifdef HAVE_CONFIG_H 27 | #include "config.h" 28 | #endif 29 | #include "log.h" 30 | 31 | static constexpr const char* DPASTE_MSG_PREFIX = "DPASTE: "; 32 | 33 | void print_log(char const *m, va_list args) { 34 | std::array buffer; 35 | int ret = vsnprintf(buffer.data(), buffer.size(), m, args); 36 | if (ret < 0) 37 | return; 38 | 39 | std::cerr << DPASTE_MSG_PREFIX; 40 | 41 | // write log 42 | std::cerr.write(buffer.data(), std::min((size_t) ret, buffer.size())); 43 | if ((size_t) ret >= buffer.size()) 44 | std::cerr << "[[TRUNCATED]]"; 45 | std::cerr << std::endl; 46 | } 47 | 48 | void DPASTE_MSG(char const* format, ...) { 49 | #ifndef DPASTE_TEST 50 | va_list args; 51 | va_start(args, format); 52 | print_log(format, args); 53 | va_end(args); 54 | #endif 55 | } 56 | 57 | /* vim:set et sw=4 ts=4 tw=120: */ 58 | 59 | -------------------------------------------------------------------------------- /src/log.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2017 Simon Désaulniers 3 | * Author: Simon Désaulniers 4 | * 5 | * This file is part of dpaste. 6 | * 7 | * dpaste is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * dpaste is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with dpaste. If not, see . 19 | */ 20 | 21 | void DPASTE_MSG(char const* format, ...); 22 | 23 | /* vim:set et sw=4 ts=4 tw=120: */ 24 | 25 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2017 Simon Désaulniers 3 | * Author: Simon Désaulniers 4 | * 5 | * This file is part of dpaste. 6 | * 7 | * dpaste is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * dpaste is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with dpaste. If not, see . 19 | */ 20 | 21 | #include 22 | #include 23 | 24 | #include 25 | 26 | extern "C" { 27 | #include 28 | } 29 | 30 | #ifdef HAVE_CONFIG_H 31 | #include "config.h" 32 | #endif 33 | 34 | #include "bin.h" 35 | #include "cipher.h" 36 | 37 | /* Command line parsing */ 38 | struct ParsedArgs { 39 | bool fail {false}; 40 | bool help {false}; 41 | bool version {false}; 42 | bool sign {false}; 43 | bool aes_encrypt {false}; 44 | bool gpg_encrypt {false}; 45 | bool no_decrypt {false}; 46 | bool self_recipient {false}; 47 | std::string code; 48 | std::vector recipients; 49 | }; 50 | 51 | static const constexpr struct option long_options[] = { 52 | {"help", no_argument, nullptr, 'h'}, 53 | {"version", no_argument, nullptr, 'v'}, 54 | {"get", required_argument, nullptr, 'g'}, 55 | {"aes-encrypt", no_argument, nullptr, '3'}, 56 | {"gpg-encrypt", no_argument, nullptr, '4'}, 57 | {"recipients", required_argument, nullptr, 'r'}, 58 | {"sign", no_argument, nullptr, 's'}, 59 | {"no-decrypt", no_argument, nullptr, '1'}, 60 | {"self-recipient", no_argument, nullptr, '2'}, 61 | {nullptr, 0, nullptr, 0 } 62 | }; 63 | 64 | ParsedArgs parseArgs(int argc, char *argv[]) { 65 | ParsedArgs pa; 66 | int opt; 67 | while ((opt = getopt_long(argc, argv, "hvg:r:s", long_options, nullptr)) != -1) { 68 | switch (opt) { 69 | case 'h': 70 | pa.help = true; 71 | break; 72 | case 'v': 73 | pa.version = true; 74 | break; 75 | case 'g': 76 | pa.code = std::string(optarg); 77 | break; 78 | case '3': 79 | pa.aes_encrypt = true; 80 | break; 81 | case '4': 82 | pa.gpg_encrypt = true; 83 | break; 84 | case 'r': 85 | pa.recipients.emplace_back(std::string(optarg)); 86 | break; 87 | case 's': 88 | pa.sign = true; 89 | break; 90 | case '1': 91 | pa.no_decrypt = true; 92 | break; 93 | case '2': 94 | pa.self_recipient = true; 95 | break; 96 | default: 97 | pa.fail = true; 98 | return pa; 99 | } 100 | } 101 | return pa; 102 | } 103 | 104 | void print_help() { 105 | std::cout << PACKAGE_NAME << " -- A simple pastebin for light values (max 64KB)" 106 | << " using OpenDHT distributed hash table." << std::endl << std::endl; 107 | 108 | std::cout << "SYNOPSIS" << std::endl 109 | << " " << PACKAGE_NAME << " [-h]" << std::endl 110 | << " " << PACKAGE_NAME << " [-v]" << std::endl 111 | << " " << PACKAGE_NAME << " [-g code]" << std::endl; 112 | 113 | std::cout << "OPTIONS" 114 | << std::endl; 115 | std::cout << " -h|--help" 116 | << std::endl; 117 | std::cout << " Prints this help text." 118 | << std::endl; 119 | 120 | std::cout << " -v|--version" << std::endl 121 | << " Prints the program's version number." 122 | << std::endl; 123 | 124 | std::cout << " -g|--get {code}" << std::endl 125 | << " Get the pasted file under the code {code}." 126 | << std::endl; 127 | 128 | std::cout << " --aes-encrypt" << std::endl 129 | << " Use AES scheme for encryption. Password is automatically saved in " << std::endl; 130 | std::cout << " the returned code (\"dpaste:XXXXXX\")." << std::endl; 131 | 132 | std::cout << " --gpg-encrypt" << std::endl 133 | << " Use GPG scheme for encryption/signing." << std::endl; 134 | 135 | std::cout << " -r|--recipients {recipient}" << std::endl 136 | << " Specify the list of recipients to use for GPG encryption (--gpg--encrypt). " << std::endl 137 | << " Use '-r' multiple times to specify a list of recipients" << std::endl; 138 | 139 | std::cout << " -s|--sign" << std::endl 140 | << " Tells wether message should be signed using the user's GPG key. The key has to be configured" << std::endl; 141 | std::cout << " through the configuration file ($XDG_CONFIG_DIR/dpaste.conf, keyword: pgp_key_id)." << std::endl; 142 | 143 | std::cout << " --no-decrypt" << std::endl 144 | << " Tells dpaste not to decrypt PGP data and rather output it on stdout." 145 | << std::endl; 146 | 147 | std::cout << " --self-recipient" << std::endl 148 | << " Include self as recipient. Self refers to the key id configured for signing" << std::endl; 149 | std::cout << " (see --sign description). This only takes effect if option \"-e\" is also used." << std::endl; 150 | 151 | std::cout << std::endl; 152 | std::cout << "When -g option is ommited, " << PACKAGE_NAME << " will read its standard input for a file to paste." 153 | << std::endl; 154 | } 155 | 156 | std::unique_ptr params_from_args(const ParsedArgs& pa) { 157 | auto params = std::make_unique(); 158 | if (pa.aes_encrypt) { 159 | params->emplace(); 160 | } else if (pa.gpg_encrypt) { 161 | params->emplace(pa.recipients, pa.self_recipient, pa.sign); 162 | } else if (pa.sign) { 163 | params->emplace(); 164 | auto& p = std::get(*params); 165 | p.sign = pa.sign; 166 | } else 167 | return {}; 168 | return params; 169 | } 170 | 171 | int main(int argc, char *argv[]) { 172 | auto parsed_args = parseArgs(argc, argv); 173 | if (parsed_args.fail) { 174 | return 1; 175 | } else if (parsed_args.help) { 176 | print_help(); 177 | return 0; 178 | } else if (parsed_args.version) { 179 | std::cout << VERSION << std::endl; 180 | return 0; 181 | } 182 | 183 | dpaste::Bin dpastebin {}; 184 | dpaste::crypto::Cipher::init(); 185 | int rc; 186 | if (not parsed_args.code.empty()) { 187 | auto r = dpastebin.get(std::move(parsed_args.code), parsed_args.no_decrypt); 188 | if (r.first) { 189 | rc = 0; 190 | std::cout << r.second; 191 | } else 192 | rc = 1; 193 | } else { 194 | std::stringstream ss; 195 | ss << std::cin.rdbuf(); 196 | auto uri = dpastebin.paste(std::move(ss), params_from_args(parsed_args)); 197 | std::cout << uri << std::endl; 198 | rc = uri.empty() ? 1 : 0; 199 | } 200 | 201 | return rc; 202 | } 203 | 204 | /* vim:set et sw=4 ts=4 tw=120: */ 205 | 206 | -------------------------------------------------------------------------------- /src/node.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2017 Simon Désaulniers 3 | * Author: Simon Désaulniers 4 | * 5 | * This file is part of dpaste. 6 | * 7 | * dpaste is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * dpaste is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with dpaste. If not, see . 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | #include "node.h" 28 | 29 | namespace dpaste { 30 | 31 | const constexpr char* Node::DPASTE_USER_TYPE; 32 | 33 | bool Node::paste(const std::string& code, dht::Blob&& blob, dht::DoneCallbackSimple&& cb) { 34 | auto v = std::make_shared(std::forward(blob)); 35 | v->user_type = DPASTE_USER_TYPE; 36 | 37 | auto hash = dht::InfoHash::get(code); 38 | 39 | if (cb) { 40 | node_.put(hash, v, cb); 41 | return true; 42 | } else { 43 | std::mutex mtx; 44 | std::condition_variable cv; 45 | std::unique_lock lk(mtx); 46 | bool done, success_ {false}; 47 | node_.put(hash, v, [&](bool success) { 48 | if (not success) 49 | std::cerr << OPERATION_FAILURE_MSG << " (put)" << std::endl; 50 | else 51 | success_ = true; 52 | { 53 | std::unique_lock lk(mtx); 54 | done = true; 55 | } 56 | cv.notify_all(); 57 | }); 58 | cv.wait(lk, [&](){ return done; }); 59 | return success_; 60 | } 61 | } 62 | 63 | void Node::get(const std::string& code, PastedCallback&& pcb) { 64 | auto blobs = std::make_shared>(); 65 | node_.get(dht::InfoHash::get(code), 66 | [blobs](std::shared_ptr value) { 67 | blobs->emplace_back(value->data); 68 | return true; 69 | }, 70 | [pcb,blobs](bool success) { 71 | if (not success) 72 | std::cerr << OPERATION_FAILURE_MSG << " (get)" << std::endl; 73 | else if (pcb) 74 | pcb(*blobs); 75 | }, dht::Value::AllFilter(), dht::Where{}.userType(std::string(DPASTE_USER_TYPE)) 76 | ); 77 | } 78 | 79 | std::vector Node::get(const std::string& code) { 80 | auto values = node_.get(dht::InfoHash::get(code), 81 | dht::Value::AllFilter(), 82 | dht::Where{}.userType(DPASTE_USER_TYPE)).get(); 83 | std::vector blobs (values.size()); 84 | std::transform(values.begin(), values.end(), blobs.begin(), [] (const decltype(values)::value_type& value) { 85 | return value->data; 86 | }); 87 | return blobs; 88 | } 89 | 90 | } /* dpaste */ 91 | 92 | -------------------------------------------------------------------------------- /src/node.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2017 Simon Désaulniers 3 | * Author: Simon Désaulniers 4 | * 5 | * This file is part of dpaste. 6 | * 7 | * dpaste is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * dpaste is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with dpaste. If not, see . 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #ifdef HAVE_CONFIG_H 34 | #include "config.h" 35 | #endif 36 | 37 | namespace dpaste { 38 | #ifdef DPASTE_TEST 39 | namespace tests { class PirateNodeTester; } /* tests */ 40 | #endif 41 | 42 | class Node { 43 | #ifdef DPASTE_TEST 44 | friend class tests::PirateNodeTester; 45 | #endif 46 | static const constexpr char* DEFAULT_BOOTSTRAP_NODE = "bootstrap.ring.cx"; 47 | static const constexpr char* DEFAULT_BOOTSTRAP_PORT = "4222"; 48 | static const constexpr char* CONNECTION_FAILURE_MSG = "err.. Failed to connect to the DHT."; 49 | static const constexpr char* OPERATION_FAILURE_MSG = "err.. DHT operation failed."; 50 | 51 | public: 52 | using PastedCallback = std::function)>; 53 | 54 | static const constexpr char* DPASTE_USER_TYPE = "dpaste"; 55 | 56 | Node() {} 57 | virtual ~Node () {} 58 | 59 | void run(uint16_t port = 0, std::string bootstrap_hostname = DEFAULT_BOOTSTRAP_NODE, std::string bootstrap_port = DEFAULT_BOOTSTRAP_PORT) { 60 | if (running_) 61 | return; 62 | node_.run(port, dht::crypto::generateIdentity(), true); 63 | node_.bootstrap(bootstrap_hostname, bootstrap_port); 64 | running_ = true; 65 | }; 66 | 67 | void stop() { 68 | std::condition_variable cv; 69 | std::mutex m; 70 | std::atomic_bool done {false}; 71 | 72 | node_.shutdown([&]() 73 | { 74 | std::lock_guard lk(m); 75 | done = true; 76 | cv.notify_all(); 77 | }); 78 | 79 | // wait for shutdown 80 | std::unique_lock lk(m); 81 | cv.wait(lk, [&](){ return done.load(); }); 82 | 83 | node_.join(); 84 | running_ = false; 85 | } 86 | 87 | /** 88 | * Pastes a blob on the DHT under a given code. If no callback, the function 89 | * blocks until pasting on the DHT is done. 90 | * 91 | * @param blob The blob to paste. 92 | * @param cb A function to execute when paste is done. If empty, the 93 | * function will block until done. 94 | * 95 | * @return true if success, else false. 96 | */ 97 | bool paste(const std::string& code, dht::Blob&& blob, dht::DoneCallbackSimple&& cb = {}); 98 | 99 | /** 100 | * Recover a blob under a given code. 101 | * 102 | * @param code The code to lookup. 103 | * @param cb A function to execute when the pasted blob is retrieved. 104 | */ 105 | void get(const std::string& code, PastedCallback&& cb); 106 | 107 | /** 108 | * Recover blob values under a given code. This function blocks until the 109 | * DHT has satisfied the request. 110 | * 111 | * @param code The code to lookup. 112 | * 113 | * @return the blobs. 114 | */ 115 | std::vector get(const std::string& code); 116 | 117 | private: 118 | 119 | dht::DhtRunner node_; 120 | bool running_ {false}; 121 | 122 | std::uniform_int_distribution codeDist_; 123 | std::mt19937_64 rand_; 124 | }; 125 | 126 | } /* dpaste */ 127 | 128 | -------------------------------------------------------------------------------- /tests/Makefile.am: -------------------------------------------------------------------------------- 1 | check_PROGRAMS = dptest 2 | 3 | dptest_SOURCES = \ 4 | tests.cpp \ 5 | bin.cpp \ 6 | node.cpp \ 7 | conf.cpp \ 8 | aes.cpp 9 | 10 | # Variables defined in toplevel Makefile. Thus, `make check` cannot be called 11 | # from this directory. 12 | dptest_CPPFLAGS = -I../src $(dpaste_CPPFLAGS_) 13 | dptest_LDFLAGS = -L../src 14 | dptest_LDADD = -ldpaste $(dpaste_LIBS) 15 | 16 | # vim: set ts=4 sw=4 tw=120 noet : 17 | 18 | -------------------------------------------------------------------------------- /tests/aes.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2018 Simon Désaulniers 3 | * Author: Simon Désaulniers 4 | * 5 | * This file is part of dpaste. 6 | * 7 | * dpaste is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * dpaste is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with dpaste. If not, see . 19 | */ 20 | 21 | #include 22 | 23 | #include 24 | 25 | #include "cipher.h" 26 | #include "aescrypto.h" 27 | 28 | namespace dpaste { 29 | namespace tests { 30 | 31 | TEST_CASE("AES process plain/cipher text", "[AES][processPlainText][processCipherText]") { 32 | crypto::AES aes {}; 33 | std::vector data {0,1,2,3,4}; 34 | auto pwd = "this_is_a_really_good_pwd"; 35 | auto p = std::make_shared(); 36 | auto pp = p; 37 | p->emplace(pwd); 38 | 39 | auto ct = aes.processPlainText(data, std::move(p)); 40 | REQUIRE ( not ct.empty() ); 41 | 42 | auto pt = aes.processCipherText(ct, std::move(pp)); 43 | REQUIRE ( pt == data ); 44 | } 45 | 46 | } /* tests */ 47 | } /* dpaste */ 48 | 49 | /* vim: set ts=4 sw=4 tw=120 et :*/ 50 | 51 | -------------------------------------------------------------------------------- /tests/bin.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2018 Simon Désaulniers 3 | * Author: Simon Désaulniers 4 | * 5 | * This file is part of dpaste. 6 | * 7 | * dpaste is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * dpaste is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with dpaste. If not, see . 19 | */ 20 | 21 | #include 22 | 23 | #include 24 | 25 | #include "tests.h" 26 | #include "bin.h" 27 | 28 | namespace dpaste { 29 | namespace tests { 30 | 31 | class PirateBinTester { 32 | #define YARRRRR 33 | public: 34 | static const constexpr unsigned int LOCATION_CODE_LEN = 8; 35 | static const constexpr char* DPASTE_URI_PREFIX = "dpaste:"; 36 | 37 | PirateBinTester () {} 38 | virtual ~PirateBinTester () {} 39 | 40 | std::string code_from_dpaste_uri(const std::string& uri) const { 41 | return Bin::code_from_dpaste_uri(uri); 42 | } 43 | 44 | std::vector data_from_stream(std::stringstream&& input_stream) const { 45 | return Bin::data_from_stream(std::forward(input_stream)); 46 | } 47 | }; 48 | 49 | TEST_CASE("Bin get/paste on DHT", "[Bin][get][paste]") { 50 | using pbt = PirateBinTester; 51 | std::vector data = {0, 1, 2, 3, 4}; 52 | Bin bin {}; 53 | crypto::Cipher::init(); 54 | SECTION ( "pasting data {0,1,2,3,4}" ) { 55 | auto code = bin.paste(std::vector {data}, {}); 56 | REQUIRE ( code.size() == pbt::LOCATION_CODE_LEN+sizeof(pbt::DPASTE_URI_PREFIX)-1 ); 57 | 58 | SECTION ( "getting pasted blob back from the DHT" ) { 59 | auto rd = bin.get(std::move(code)).second; 60 | std::vector rdv {rd.begin(), rd.end()}; 61 | REQUIRE ( data == rdv ); 62 | } 63 | } 64 | SECTION ( "pasting AES encrypted {0,1,2,3,4}" ) { 65 | auto p = std::make_unique(); 66 | p->emplace(); 67 | auto code = bin.paste(std::vector {data}, std::move(p)); 68 | REQUIRE ( code.size() == 2*pbt::LOCATION_CODE_LEN+sizeof(pbt::DPASTE_URI_PREFIX)-1 ); 69 | 70 | SECTION ( "getting pasted AES encrypted blob back from the DHT" ) { 71 | auto rd = bin.get(std::move(code)).second; 72 | std::vector rdv {rd.begin(), rd.end()}; 73 | REQUIRE ( data == rdv ); 74 | } 75 | } 76 | } 77 | 78 | TEST_CASE("Bin parsing of uri code ([dpaste:]XXXXXXXX)", "[Bin][code_from_dpaste_uri]") { 79 | PirateBinTester pt; 80 | const std::string PIN = random_pin(); 81 | std::string pin_upper {PIN.begin(), PIN.end()}; 82 | std::transform(pin_upper.begin(), pin_upper.end(), pin_upper.begin(), ::toupper); 83 | 84 | SECTION ( "good pins" ) { 85 | auto gc1 = "dpaste:"+PIN; 86 | auto gc2 = PIN; 87 | REQUIRE ( pt.code_from_dpaste_uri(gc1) == PIN ); 88 | REQUIRE ( pt.code_from_dpaste_uri(gc2) == PIN ); 89 | 90 | SECTION ( "good pin (upper case)" ) { 91 | auto gc3 = "dpaste:"+pin_upper; 92 | auto gc4 = pin_upper; 93 | 94 | REQUIRE ( pt.code_from_dpaste_uri(gc3) == pin_upper ); 95 | REQUIRE ( pt.code_from_dpaste_uri(gc4) == pin_upper ); 96 | } 97 | } 98 | SECTION ( "bad pins" ) { 99 | std::string bc1 = "DPASTE:"+PIN; 100 | std::string bc2 = "DPaste:"+PIN; 101 | REQUIRE ( pt.code_from_dpaste_uri(bc1) != PIN ); 102 | REQUIRE ( pt.code_from_dpaste_uri(bc2) != PIN ); 103 | 104 | SECTION ( "bad pins (upper case)" ) { 105 | auto bc3 = "DPASTE:"+pin_upper; 106 | auto bc4 = "DPaste:"+pin_upper; 107 | 108 | REQUIRE ( pt.code_from_dpaste_uri(bc3) != pin_upper ); 109 | REQUIRE ( pt.code_from_dpaste_uri(bc4) != pin_upper ); 110 | } 111 | } 112 | } 113 | 114 | TEST_CASE("Bin conversion of stringstream to vector", "[Bin][data_from_stream]") { 115 | PirateBinTester pt; 116 | 117 | const std::string DATA = "SOME DATA"; 118 | std::stringstream ss(DATA); 119 | std::vector d {DATA.begin(), DATA.end()}; 120 | REQUIRE ( pt.data_from_stream(std::move(ss)) == d ); 121 | } 122 | 123 | } /* tests */ 124 | } /* dpaste */ 125 | 126 | /* vim: set ts=4 sw=4 tw=120 et :*/ 127 | 128 | -------------------------------------------------------------------------------- /tests/conf.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2018 Simon Désaulniers 3 | * Author: Simon Désaulniers 4 | * 5 | * This file is part of dpaste. 6 | * 7 | * dpaste is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * dpaste is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with dpaste. If not, see . 19 | */ 20 | 21 | #include 22 | 23 | #include "conf.h" 24 | 25 | namespace dpaste { 26 | namespace tests { 27 | 28 | const std::string CONFIG_FILE_PATH_PREFIX = "./tests/misc/dpaste.conf"; 29 | 30 | TEST_CASE("ConfigurationFile loading/parsing (./misc/dpaste.conf)", "[ConfigurationFile][get][load]") { 31 | SECTION ( "Well-formed file" ) { 32 | conf::ConfigurationFile f(CONFIG_FILE_PATH_PREFIX+".1"); 33 | REQUIRE ( f.load() == 0 ); 34 | 35 | auto c = f.getConfiguration(); 36 | REQUIRE ( c.at("host") == "192.168.1.100" ); 37 | REQUIRE ( c.at("port") == "6500" ); 38 | } 39 | SECTION ( "Malformed file (bad host)" ) { 40 | conf::ConfigurationFile f(CONFIG_FILE_PATH_PREFIX+".2"); 41 | REQUIRE ( f.load() == 0 ); 42 | 43 | auto c = f.getConfiguration(); 44 | REQUIRE ( c.at("host") == "127.0.0.1" ); /* the default */ 45 | REQUIRE ( c.at("port") == "6500" ); /* recovered from file */ 46 | } 47 | SECTION ( "File not found" ) { 48 | conf::ConfigurationFile f("/dpaste.conf"); /* This should not work on 49 | any computer owned by a 50 | sane person */ 51 | REQUIRE ( f.load() == 1 ); 52 | } 53 | } 54 | 55 | } /* tests */ 56 | } /* dpaste */ 57 | 58 | /* vim: set ts=4 sw=4 tw=120 et :*/ 59 | 60 | -------------------------------------------------------------------------------- /tests/misc/dpaste.conf.1: -------------------------------------------------------------------------------- 1 | host = 192.168.1.100 2 | port = 6500 3 | -------------------------------------------------------------------------------- /tests/misc/dpaste.conf.2: -------------------------------------------------------------------------------- 1 | host 192.168.1.100 2 | port = 6500 3 | -------------------------------------------------------------------------------- /tests/node.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2018 Simon Désaulniers 3 | * Author: Simon Désaulniers 4 | * 5 | * This file is part of dpaste. 6 | * 7 | * dpaste is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * dpaste is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with dpaste. If not, see . 19 | */ 20 | 21 | #include 22 | 23 | #include "tests.h" 24 | #include "node.h" 25 | 26 | namespace dpaste { 27 | namespace tests { 28 | 29 | class PirateNodeTester { 30 | #define YARRRRR 31 | public: 32 | PirateNodeTester () {} 33 | virtual ~PirateNodeTester () {} 34 | 35 | bool is_running(const dpaste::Node& n) const { return n.running_; } 36 | }; 37 | 38 | TEST_CASE("Node get/paste on DHT", "[Node][get][paste]") { 39 | PirateNodeTester pt; 40 | 41 | const std::string PIN = random_pin(); 42 | std::vector data = {0, 1, 2, 3, 4}; 43 | dpaste::Node node {}; 44 | node.run(); 45 | 46 | SECTION ( "pasting data {0,1,2,3,4}" ) { 47 | REQUIRE ( node.paste(PIN, std::vector {data}) ); 48 | 49 | SECTION ( "getting pasted blob back from the DHT" ) { 50 | auto rd = node.get(PIN); 51 | REQUIRE ( data == rd.front() ); 52 | } 53 | } 54 | 55 | node.stop(); 56 | REQUIRE ( not pt.is_running(node) ); 57 | } 58 | 59 | } /* tests */ 60 | } /* dpaste */ 61 | 62 | /* vim: set ts=4 sw=4 tw=120 et :*/ 63 | 64 | -------------------------------------------------------------------------------- /tests/tests.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2018 Simon Désaulniers 3 | * Author: Simon Désaulniers 4 | * 5 | * This file is part of dpaste. 6 | * 7 | * dpaste is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * dpaste is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with dpaste. If not, see . 19 | */ 20 | 21 | #include 22 | 23 | #define CATCH_CONFIG_MAIN 24 | #include 25 | 26 | namespace dpaste { 27 | namespace tests { 28 | 29 | static std::uniform_int_distribution dist; 30 | static std::mt19937_64 rand_; 31 | 32 | void init() { 33 | static bool initialized = false; 34 | if (initialized) 35 | return; 36 | 37 | rand_.seed(Catch::rngSeed()); 38 | 39 | initialized = true; 40 | } 41 | 42 | int random_number() { 43 | init(); 44 | return dist(rand_); 45 | } 46 | 47 | std::string random_pin() { 48 | const auto i = random_number(); 49 | std::stringstream ss; 50 | ss << std::hex << i; 51 | return ss.str(); 52 | } 53 | 54 | } /* tests */ 55 | } /* dpaste */ 56 | 57 | /* vim: set ts=4 sw=4 tw=120 et :*/ 58 | 59 | -------------------------------------------------------------------------------- /tests/tests.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2018 Simon Désaulniers 3 | * Author: Simon Désaulniers 4 | * 5 | * This file is part of dpaste. 6 | * 7 | * dpaste is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * dpaste is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with dpaste. If not, see . 19 | */ 20 | 21 | namespace dpaste { 22 | namespace tests { 23 | 24 | int random_number(); 25 | std::string random_pin(); 26 | 27 | } /* tests */ 28 | } /* dpaste */ 29 | 30 | /* vim: set ts=4 sw=4 tw=120 et :*/ 31 | 32 | --------------------------------------------------------------------------------