├── .gitignore ├── CHANGELOG ├── Doxyfile ├── LICENSE ├── README ├── doc └── examples │ ├── accessToken.cpp │ ├── getResources.cpp │ ├── getResources2.cpp │ └── requestToken.cpp ├── include ├── QtOAuth └── interface.h ├── oauth.prf ├── qoauth.pro ├── src ├── interface.cpp ├── interface.h ├── interface_p.h ├── pcfile.sh ├── qoauth.pc ├── qoauth_global.h ├── qoauth_namespace.h └── src.pro └── tests ├── ft_interface ├── ft_interface.cpp ├── ft_interface.h ├── ft_interface.pro └── rsa-testkey.pem ├── tests.pro └── ut_interface ├── empty.file ├── rsa-clean.pem ├── rsa-pass.pem ├── test.pem ├── ut_interface.cpp ├── ut_interface.h └── ut_interface.pro /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.pro.user 3 | lib 4 | Makefile* 5 | qoauth.framework 6 | tmp 7 | .DS_Store 8 | commit-message.txt 9 | moc_* 10 | *.o 11 | tests/ut_interface/ut_interface 12 | tests/ft_interface/ft_interface 13 | doc/html 14 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | v2.0.0 (28/11/2016): 2 | * Qt5 support 3 | v1.0.1 (01/08/2010): 4 | * new API: 5 | - QOAuth::Interface::networkAccessManager() 6 | - QOAuth::Interface::setNetworkAccessManager() 7 | - QOAuth::Interface::ignoreSslErrors() 8 | - QOAuth::Interface::setIgnoreSslErrors() 9 | refer to the API docs for more info, 10 | * added missing export statements to some global functions, 11 | * Percent encode consumer secret and token secret for the Signature Base String signing key [#8], 12 | * Parse for request content when sending POST [#10], 13 | * API docs and examples fixes [#9], 14 | * temporarily removed QOAuth::DELETE from QOAuth::HttpMethod enum on Windows [#4], 15 | * buildsystem fixes - install under /usr/lib64 on 64-bit Unix-like systems and 16 | make use of QT_INSTALL_HEADERS in oauth.prf. 17 | v1.0 (07/08/2009): 18 | * Added support for RSA-SHA1 signing algorithm, also working with 19 | passphrase-protected private RSA keys. 20 | * Added initial support for PLAINTEXT authorization. 21 | * inlineParameters() extended by the parameter specifying parsing method, 22 | * Introduced the QOAuth namespace, with QOAuth::Interface class holding the core 23 | functionality. 24 | v0.1.0 (23/06/2009): 25 | * Initial release of the QOAuth library, implementation of the OAuth 26 | authorization flow with support for encrypting QOAuth requests using HMAC-SHA1 27 | algorithm. 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.] 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | How to Apply These Terms to Your New Libraries 461 | 462 | If you develop a new library, and you want it to be of the greatest 463 | possible use to the public, we recommend making it free software that 464 | everyone can redistribute and change. You can do so by permitting 465 | redistribution under these terms (or, alternatively, under the terms of the 466 | ordinary General Public License). 467 | 468 | To apply these terms, attach the following notices to the library. It is 469 | safest to attach them to the start of each source file to most effectively 470 | convey the exclusion of warranty; and each file should have at least the 471 | "copyright" line and a pointer to where the full notice is found. 472 | 473 | 474 | Copyright (C) 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2.1 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 489 | 490 | Also add information on how to contact you by electronic and paper mail. 491 | 492 | You should also get your employer (if you work as a programmer) or your 493 | school, if any, to sign a "copyright disclaimer" for the library, if 494 | necessary. Here is a sample; alter the names: 495 | 496 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 497 | library `Frob' (a library for tweaking knobs) written by James Random Hacker. 498 | 499 | , 1 April 1990 500 | Ty Coon, President of Vice 501 | 502 | That's all there is to it! 503 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | QOAuth is an attempt to support interaction with OAuth-powered network services 2 | in a Qt way, i.e. simply, clearly and efficiently. It gives the application 3 | developer no more than 4 methods, namely: 4 | 5 | * requestToken() – to obtain an unauthorized Request Token, 6 | * accessToken() – to exchange Request Token for the Access Token, 7 | * createParametersString() – to construct a request according to OAuth 8 | authorization scheme, 9 | * inlineParemeters() - to construct a query string basing on given parameters 10 | (provided only for convenience). 11 | 12 | First two methods serve application authorization purposes, whilst the other two 13 | are used for accessing Protected Resources. The complete documentation is 14 | available locally. 15 | 16 | QOAuth internally makes use of QCA (Qt Cryptographic Architecture). Here is the 17 | complete list of its dependencies: 18 | 19 | 1. Qt libraries 4.4 at least, 20 | 2. QCA (Qt Cryptographic Architecture), available from Delta XMPP Project 21 | 3. OpenSSL plugin to QCA, available from QCA homepage (this pulls in 22 | a dependency on OpenSSL of course). 23 | Note: KDE users meet all the requirements out of the box. 24 | 25 | HOW TO INSTALL: 26 | $ qmake 27 | $ make 28 | $ sudo make install 29 | 30 | HOW TO USE: 31 | Add these two lines to your project: 32 | * in project file: 33 | CONFIG += oauth 34 | * in source code: 35 | #include 36 | You can start using QOAuth. 37 | 38 | BUGS AND ISSUES: 39 | report them to QOAuth's bug tracking system: 40 | http://ayoy.lighthouseapp.com/projects/32547-qoauth/tickets?q=all 41 | -------------------------------------------------------------------------------- /doc/examples/accessToken.cpp: -------------------------------------------------------------------------------- 1 | // if necessary, create a map of additional arguments required by the Service Provider 2 | QOAuth::ParamMap otherArgs; 3 | otherArgs.insert( "misc_arg1", "value1" ); 4 | otherArgs.insert( "misc_arg2", "value2" ); 5 | 6 | // send a request to exchange Request Token for an Access Token 7 | QOAuth::ParamMap reply = 8 | qoauth->accessToken( "http://example.com/access_token", QOAuth::POST, token, 9 | tokenSecret, QOAuth::HMAC_SHA1, otherArgs ); 10 | 11 | // if no error occurred, read the Access Token (and other arguments, if applicable) 12 | if ( qoauth->error() == QOAuth::NoError ) { 13 | token = reply.value( QOAuth::tokenParameterName() ); 14 | tokenSecret = reply.value( QOAuth::tokenSecretParameterName() ); 15 | otherInfo = reply.value( "misc_arg3" ); 16 | } 17 | -------------------------------------------------------------------------------- /doc/examples/getResources.cpp: -------------------------------------------------------------------------------- 1 | QByteArray url( "http://example.com/get_photo" ); 2 | // create a request parameters map 3 | QOAuth::ParamMap map; 4 | map.insert( "file", "flower_48.jpg" ); 5 | map.insert( "size", "small" ); 6 | 7 | // construct the parameters string 8 | QByteArray content = 9 | qoauth->createParametersString( requestUrl, QOAuth::GET, QOAuth::HMAC_SHA1, 10 | token, tokenSecret, map, 11 | QOAuth::ParseForInlineQuery ); 12 | // append parameters string to the URL 13 | url.append( content ); 14 | QNetworkRequest request( QUrl( url ) ); 15 | // etc... 16 | -------------------------------------------------------------------------------- /doc/examples/getResources2.cpp: -------------------------------------------------------------------------------- 1 | QByteArray url( "http://example.com/get_photo" ); 2 | // create a request parameters map 3 | QOAuth::ParamMap map; 4 | map.insert( "file", "flower_48.jpg" ); 5 | map.insert( "size", "small" ); 6 | 7 | // construct the authorization header 8 | QByteArray header = 9 | qoauth->createParametersString( requestUrl, QOAuth::GET, QOAuth::HMAC_SHA1, 10 | token, tokenSecret, map, 11 | QOAuth::ParseForHeaderArguments ); 12 | // append parameters string to the URL 13 | // alternatively you can use QOAuth::ParseForRequestContent if you want 14 | // to use the output as a POST request content (remember then of passing 15 | // QOAuth::POST above). 16 | url.append( qoauth->inlineParameters( map, QOAuth::ParseForInlineQuery ) ); 17 | QNetworkRequest request( QUrl( url ) ); 18 | request.setRawHeader( "Authorization", header ); 19 | // etc... 20 | -------------------------------------------------------------------------------- /doc/examples/requestToken.cpp: -------------------------------------------------------------------------------- 1 | QByteArray token; 2 | QByteArray tokenSecret; 3 | 4 | QOAuth::Interface *qoauth = new QOAuth::Interface; 5 | // set the consumer key and secret 6 | qoauth->setConsumerKey( "75b3d557c9268c49cfdf041a" ); 7 | qoauth->setConsumerSecret( "fd12803fbf0760d34cd2ceb9955199ce" ); 8 | // set a timeout for requests (in msecs) 9 | qoauth->setRequestTimeout( 10000 ); 10 | 11 | // send a request for an unauthorized token 12 | QOAuth::ParamMap reply = 13 | qoauth->requestToken( "http://example.com/request_token", 14 | QOAuth::GET, QOAuth::HMAC_SHA1 ); 15 | 16 | // if no error occurred, read the received token and token secret 17 | if ( qoauth->error() == QOAuth::NoError ) { 18 | token = reply.value( QOAuth::tokenParameterName() ); 19 | tokenSecret = reply.value( QOAuth::tokenSecretParameterName() ); 20 | } 21 | 22 | -------------------------------------------------------------------------------- /include/QtOAuth: -------------------------------------------------------------------------------- 1 | #include "interface.h" 2 | -------------------------------------------------------------------------------- /include/interface.h: -------------------------------------------------------------------------------- 1 | #include "../src/interface.h" 2 | -------------------------------------------------------------------------------- /oauth.prf: -------------------------------------------------------------------------------- 1 | QOAUTH_INCDIR = $$[QT_INSTALL_HEADERS] 2 | QOAUTH_LIBDIR = $$[QT_INSTALL_LIBS] 3 | 4 | QOAUTH_INCDIR ~= s!/qt[45]*!! 5 | QOAUTH_LIBDIR ~= s!/qt[45]*!! 6 | 7 | CONFIG *= qt 8 | CONFIG += crypto 9 | 10 | # if we are including oauth.prf from the qoauth tree (and not utilizing it as 11 | # an installed qmake CONFIG feature), then point to the tree. this allows our 12 | # qoauth tree apps to build before qoauth itself is installed. 13 | exists($$PWD/qoauth.pro) { 14 | QOAUTH_INCDIR = $$PWD/include 15 | QOAUTH_LIBDIR = $$PWD/lib 16 | } 17 | 18 | LINKAGE = 19 | 20 | # on mac, if qoauth was built as a framework, link against it 21 | mac: { 22 | framework_dir = $${QOAUTH_LIBDIR} 23 | exists($$framework_dir/qoauth.framework) { 24 | LIBS += -F$$framework_dir 25 | exists($$PWD/qoauth.pro): INCLUDEPATH += $$QOAUTH_INCDIR 26 | else: INCLUDEPATH += $$framework_dir/qoauth.framework/Headers 27 | LINKAGE = -framework qoauth 28 | } 29 | } 30 | 31 | # else, link normally 32 | isEmpty(LINKAGE) { 33 | exists($$PWD/qoauth.pro): INCLUDEPATH += $$QOAUTH_INCDIR 34 | else: INCLUDEPATH += $$QOAUTH_INCDIR/QtOAuth 35 | LIBS += -L$$QOAUTH_LIBDIR 36 | LINKAGE = -lqoauth 37 | CONFIG(debug, debug|release) { 38 | windows:LINKAGE = -lqoauthd1 39 | mac:LINKAGE = -lqoauth_debug 40 | } else { 41 | windows:LINKAGE = -lqoauth1 42 | } 43 | } 44 | 45 | LIBS += $$LINKAGE 46 | -------------------------------------------------------------------------------- /qoauth.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = subdirs 2 | 3 | SUBDIRS += src tests 4 | 5 | CONFIG += ordered 6 | 7 | check.target = check 8 | check.commands = ( cd tests/ut_interface && ./ut_interface ) && ( cd tests/ft_interface && ./ft_interface ) 9 | check.depends = sub-tests 10 | QMAKE_EXTRA_TARGETS += check 11 | -------------------------------------------------------------------------------- /src/interface.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2009 by Dominik Kapusta * 3 | * * 4 | * This library is free software; you can redistribute it and/or modify * 5 | * it under the terms of the GNU Lesser General Public License as * 6 | * published by the Free Software Foundation; either version 2.1 of * 7 | * the License, or (at your option) any later version. * 8 | * * 9 | * This library is distributed in the hope that it will be useful, * 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 12 | * Lesser General Public License for more details. * 13 | * * 14 | * You should have received a copy of the GNU Lesser General Public * 15 | * License along with this library; if not, write to * 16 | * the Free Software Foundation, Inc., * 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * 18 | ***************************************************************************/ 19 | 20 | 21 | #include "interface.h" 22 | #include "interface_p.h" 23 | 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | /*! 37 | \mainpage 38 | 39 | \section sec_what What is the purpose of QOAuth? 40 | 41 | The main motivation to create this library was to provide an interface to OAuth 42 | protocol for (Qt-based) C++ applications in an easy way. This is very early version 43 | of the library, and it lacks some functionality, but in the same time it is capable 44 | of sending OAuth authorization requests as well as preparing requests for accessing 45 | User's Protected Resources. 46 | 47 | \section sec_lic License and Authors 48 | 49 | The project is licensed under GNU LGPL 50 | license version 2.1 or later. The work is done by Dominik Kapusta (d at ayoy dot net). 51 | 52 | \section sec_inst How to install? 53 | 54 | \subsection ssec_deps Dependencies 55 | 56 | There are a few things necessary to get OAuth library working: 57 | 58 |
    59 |
  1. Qt libraries, version 4.4 or higher,
  2. 60 |
  3. QCA (Qt Cryptographic Architecture), available from 61 | Delta XMPP Project, version 2.0.0 62 | or higher,
  4. 63 |
  5. OpenSSL plugin to QCA (qca-ossl), available from QCA page, and requiring OpenSSL.
  6. 64 |
65 | 66 | \b Note: KDE4 users meet all the requirements out of the box. 67 | 68 | \subsection ssec_inst Installation 69 | 70 | The source code repository is hosted on GitHub 71 | and the code can be checked out from there easily using git: 72 | \verbatim 73 | $ git clone git://github.com/ayoy/qoauth.git \endverbatim 74 | 75 | To compile the code, follow the simple procedure: 76 | 77 | \verbatim 78 | $ qmake 79 | $ make 80 | $ sudo make install \endverbatim 81 | 82 | \subsection ssec_use Usage 83 | 84 | Configuring your project to work with QOAuth library is extremely simple. Firstly, 85 | append a line to your project file: 86 | \verbatim 87 | CONFIG += oauth \endverbatim 88 | 89 | Then include the following header in your code: 90 | \verbatim 91 | #include \endverbatim 92 | 93 | \b Note: This follows the Qt scheme, i.e. QT += xml ==> #include , etc. 94 | 95 | \section sec_bugs Bugs and issues 96 | 97 | Please file all the bug reports to the QOAuth bug tracking system at 98 | 99 | lighthouseapp.com. If you wish to contribute, you're extremely welcome 100 | to fork a GitHub repository and 101 | add your input there. 102 | 103 | */ 104 | 105 | /*! 106 | \class QOAuth::Interface interface.h 107 | \brief This class provides means for interaction with network services supporting 108 | OAuth authorization scheme. 109 | 110 | The QOAuth::Interface class is meant to enable OAuth support in applications in as simple way 111 | as possible. It provides 4 basic methods, two of which serve for authorization purposes: 112 | \li \ref requestToken(), 113 | \li \ref accessToken(), 114 | 115 | and the other two help with creation of requests for accessing Protected Resources: 116 | \li \ref createParametersString(), 117 | \li \ref inlineParameters(). 118 | 119 | \section sec_auth_scheme OAuth authorization scheme 120 | 121 | According to 122 | OAuth 1.0 Core specification, the OAuth protocol enables websites or applications 123 | (Consumers) to access Protected Resources from a web service (Service Provider) via an 124 | API, without requiring Users to disclose their Service Provider credentials to the 125 | Consumers. Simply, OAuth is a way of connecting an application to the Service 126 | Provider's API without needing to provide User's login or password. The authorization 127 | is based on an exchange of a Token (user-specific) together with a Consumer Key 128 | (application-specific), encrypted with a combination of so called Token Secret and 129 | Customer Secret. Getting access to Protected Resources consists in three basic steps: 130 |
    131 |
  1. obtaining an unauthorized Request Token from the Service Provider,
  2. 132 |
  3. asking the User to authorize the Request Token,
  4. 133 |
  5. exchanging the Request Token for the Access Token.
  6. 134 |
135 | Details are covered in Section 6 of the 136 | OAuth 1.0 Core Specification. As the authorization procedure is quite complex, the QOAuth 137 | library helps to simplify it by doing all the dirty work behind the scenes. 138 | 139 | \section sec_req_token OAuth authorization with QOAuth 140 | 141 | First step of OAuth authorization can be done in one line using QOAuth library. 142 | Consult the example: 143 | 144 | \include requestToken.cpp 145 | 146 | Once the unauthorized Request Token is received, User has to authorize it using 147 | Service Provider-defined method. This is beyond the scope of this library. Once User 148 | authorizes the Request Token, it can be exchanged for an Access Token that authorizes the 149 | application to access User's Protected Resources. This can be done with another one line: 150 | 151 | \include accessToken.cpp 152 | 153 | Once the Access Token is received, the application is authorized. 154 | 155 | \section sec_acc_res Requesting Protected Resources with QOAuth 156 | 157 | In order to access Protected Resources, the application has to send a request containing 158 | arguments including Customer Key and Access Token, and encrypt them with Customer Secret 159 | and Token Secret. The process of constructing such a request can be reduced to another 160 | one-line call with QOAuth::Interface. The example code for inlining all request parameters 161 | (both User-specific and OAuth-related): 162 | 163 | \include getResources.cpp 164 | 165 | If Service Provider requires the OAuth authorization to be done in the Authorization 166 | header field, then only User-specific parameters should be inlined with the URL: 167 | 168 | \include getResources2.cpp 169 | 170 | \section sec_capabilities Capabilities 171 | 172 | QOAuth library works with all 3 signature methods supported by the OAuth protocol, namely 173 | HMAC-SHA1, RSA-SHA1 and PLAINTEXT. Hovewer, RSA-SHA1 and (especially) PLAINTEXT 174 | methods may still need additional testing for various input conditions. 175 | */ 176 | 177 | 178 | QByteArray QOAuth::supportedOAuthVersion() 179 | { 180 | return InterfacePrivate::OAuthVersion; 181 | } 182 | 183 | QByteArray QOAuth::tokenParameterName() 184 | { 185 | return InterfacePrivate::ParamToken; 186 | } 187 | 188 | QByteArray QOAuth::tokenSecretParameterName() 189 | { 190 | return InterfacePrivate::ParamTokenSecret; 191 | } 192 | 193 | 194 | //! \brief The supported OAuth scheme version. 195 | const QByteArray QOAuth::InterfacePrivate::OAuthVersion = "1.0"; 196 | 197 | //! \brief The token request parameter string 198 | const QByteArray QOAuth::InterfacePrivate::ParamToken = "oauth_token"; 199 | //! \brief The token secret request parameter string 200 | const QByteArray QOAuth::InterfacePrivate::ParamTokenSecret = "oauth_token_secret"; 201 | 202 | //! \brief The consumer key request parameter string 203 | const QByteArray QOAuth::InterfacePrivate::ParamConsumerKey = "oauth_consumer_key"; 204 | //! \brief The nonce request parameter string 205 | const QByteArray QOAuth::InterfacePrivate::ParamNonce = "oauth_nonce"; 206 | //! \brief The signature request parameter string 207 | const QByteArray QOAuth::InterfacePrivate::ParamSignature = "oauth_signature"; 208 | //! \brief The signature method request parameter string 209 | const QByteArray QOAuth::InterfacePrivate::ParamSignatureMethod = "oauth_signature_method"; 210 | //! \brief The timestamp request parameter string 211 | const QByteArray QOAuth::InterfacePrivate::ParamTimestamp = "oauth_timestamp"; 212 | //! \brief The version request parameter string 213 | const QByteArray QOAuth::InterfacePrivate::ParamVersion = "oauth_version"; 214 | 215 | QOAuth::InterfacePrivate::InterfacePrivate() : 216 | privateKeySet( false ), 217 | consumerKey( QByteArray() ), 218 | consumerSecret( QByteArray() ), 219 | manager(0), 220 | loop(0), 221 | requestTimeout(0), 222 | error( NoError ) 223 | { 224 | } 225 | 226 | void QOAuth::InterfacePrivate::init() 227 | { 228 | Q_Q(QOAuth::Interface); 229 | 230 | ignoreSslErrors = false; 231 | loop = new QEventLoop(q); 232 | setupNetworkAccessManager(); 233 | 234 | q->connect( &eventHandler, SIGNAL(eventReady(int,QCA::Event)), SLOT(_q_setPassphrase(int,QCA::Event)) ); 235 | eventHandler.start(); 236 | } 237 | 238 | void QOAuth::InterfacePrivate::setupNetworkAccessManager() 239 | { 240 | Q_Q(QOAuth::Interface); 241 | 242 | if (manager == 0) 243 | manager = new QNetworkAccessManager; 244 | 245 | manager->setParent(q); 246 | q->connect( manager, SIGNAL(finished(QNetworkReply*)), loop, SLOT(quit()) ); 247 | q->connect( manager, SIGNAL(finished(QNetworkReply*)), SLOT(_q_parseReply(QNetworkReply*)) ); 248 | q->connect( manager, SIGNAL(sslErrors(QNetworkReply*,QList)), 249 | SLOT(_q_handleSslErrors(QNetworkReply*,QList)) ); 250 | } 251 | 252 | QByteArray QOAuth::InterfacePrivate::httpMethodToString( HttpMethod method ) 253 | { 254 | switch ( method ) { 255 | case GET: 256 | return "GET"; 257 | case POST: 258 | return "POST"; 259 | case HEAD: 260 | return "HEAD"; 261 | case PUT: 262 | return "PUT"; 263 | #ifndef Q_WS_WIN 264 | case DELETE: 265 | return "DELETE"; 266 | #endif 267 | default: 268 | qWarning() << __FUNCTION__ << "- Unrecognized method"; 269 | return QByteArray(); 270 | } 271 | } 272 | 273 | QByteArray QOAuth::InterfacePrivate::signatureMethodToString( SignatureMethod method ) 274 | { 275 | switch ( method ) { 276 | case HMAC_SHA1: 277 | return "HMAC-SHA1"; 278 | case RSA_SHA1: 279 | return "RSA-SHA1"; 280 | case PLAINTEXT: 281 | return "PLAINTEXT"; 282 | default: 283 | qWarning() << __FUNCTION__ << "- Unrecognized method"; 284 | return QByteArray(); 285 | } 286 | } 287 | 288 | QOAuth::ParamMap QOAuth::InterfacePrivate::replyToMap( const QByteArray &data ) 289 | { 290 | // split reply to name=value strings 291 | QList replyParams = data.split( '&' ); 292 | // we'll store them in a map 293 | ParamMap parameters; 294 | 295 | QByteArray replyParam; 296 | QByteArray key; 297 | int separatorIndex; 298 | 299 | // iterate through name=value pairs 300 | Q_FOREACH ( replyParam, replyParams ) { 301 | // find occurrence of '=' 302 | separatorIndex = replyParam.indexOf( '=' ); 303 | // key is on the left 304 | key = replyParam.left( separatorIndex ); 305 | // value is on the right 306 | parameters.insert( key , replyParam.right( replyParam.length() - separatorIndex - 1 ) ); 307 | } 308 | 309 | return parameters; 310 | } 311 | 312 | void QOAuth::InterfacePrivate::_q_parseReply( QNetworkReply *reply ) 313 | { 314 | int returnCode = reply->attribute( QNetworkRequest::HttpStatusCodeAttribute ).toInt(); 315 | 316 | switch ( returnCode ) { 317 | case NoError: 318 | replyParams = replyToMap( reply->readAll() ); 319 | if ( !replyParams.contains( InterfacePrivate::ParamToken ) ) { 320 | qWarning() << __FUNCTION__ << "- oauth_token not present in reply!"; 321 | } 322 | if ( !replyParams.contains( InterfacePrivate::ParamTokenSecret ) ) { 323 | qWarning() << __FUNCTION__ << "- oauth_token_secret not present in reply!"; 324 | } 325 | 326 | case BadRequest: 327 | case Unauthorized: 328 | case Forbidden: 329 | error = returnCode; 330 | break; 331 | default: 332 | error = OtherError; 333 | } 334 | 335 | reply->close(); 336 | } 337 | 338 | void QOAuth::InterfacePrivate::_q_handleSslErrors(QNetworkReply *reply, const QList &errors) 339 | { 340 | Q_UNUSED(errors); 341 | 342 | if (ignoreSslErrors) 343 | reply->ignoreSslErrors(); 344 | } 345 | 346 | QByteArray QOAuth::InterfacePrivate::paramsToString( const ParamMap ¶meters, ParsingMode mode ) 347 | { 348 | QByteArray middleString; 349 | QByteArray endString; 350 | QByteArray prependString; 351 | 352 | switch ( mode ) { 353 | case ParseForInlineQuery: 354 | prependString = "?"; 355 | case ParseForRequestContent: 356 | case ParseForSignatureBaseString: 357 | middleString = "="; 358 | endString = "&"; 359 | break; 360 | case ParseForHeaderArguments: 361 | prependString = "OAuth "; 362 | middleString = "=\""; 363 | endString = "\","; 364 | break; 365 | default: 366 | qWarning() << __FUNCTION__ << "- Unrecognized mode"; 367 | return QByteArray(); 368 | } 369 | 370 | QByteArray parameter; 371 | QByteArray parametersString; 372 | 373 | Q_FOREACH( parameter, parameters.uniqueKeys() ) { 374 | QList values = parameters.values( parameter ); 375 | if ( values.size() > 1 ) { 376 | qSort( values.begin(), values.end() ); 377 | } 378 | QByteArray value; 379 | Q_FOREACH ( value, values ) { 380 | parametersString.append( parameter ); 381 | parametersString.append( middleString ); 382 | parametersString.append( value ); 383 | parametersString.append( endString ); 384 | } 385 | } 386 | 387 | // remove the trailing end character (comma or ampersand) 388 | parametersString.chop(1); 389 | 390 | // prepend with the suitable string (or none) 391 | parametersString.prepend( prependString ); 392 | 393 | return parametersString; 394 | } 395 | 396 | 397 | /*! 398 | \brief Creates a new QOAuth::Interface class instance with the given \a parent 399 | */ 400 | 401 | QOAuth::Interface::Interface( QObject *parent ) : 402 | QObject( parent ), 403 | d_ptr( new InterfacePrivate ) 404 | { 405 | Q_D(Interface); 406 | 407 | d->q_ptr = this; 408 | d->init(); 409 | } 410 | 411 | /*! 412 | \brief Creates a new QOAuth::Interface class instance with the given \a parent, 413 | using \a manager for network connections. 414 | 415 | Use this constructor if you want to use your custom network access manager to 416 | handle network connections needed by the interface. 417 | 418 | /sa setNetworkAccessManager() 419 | */ 420 | 421 | QOAuth::Interface::Interface(QNetworkAccessManager *manager, QObject *parent) : 422 | QObject( parent ), 423 | d_ptr( new InterfacePrivate ) 424 | { 425 | Q_D(Interface); 426 | 427 | d->q_ptr = this; 428 | d->manager = manager; 429 | d->init(); 430 | } 431 | 432 | /*! 433 | \brief Destroys the QOAuth::Interface object 434 | */ 435 | 436 | QOAuth::Interface::~Interface() 437 | { 438 | delete d_ptr; 439 | } 440 | 441 | /*! 442 | \brief Returns the network access manager used by the interface. 443 | */ 444 | QNetworkAccessManager* QOAuth::Interface::networkAccessManager() const 445 | { 446 | Q_D(const Interface); 447 | 448 | return d->manager; 449 | } 450 | 451 | /*! 452 | \brief Sets \a manager to be the network access manager used by the interface. 453 | 454 | The interface class takes ownership of the manager. If there already is a manager, 455 | it's being deleted. 456 | 457 | /sa networkAccessManager() 458 | */ 459 | void QOAuth::Interface::setNetworkAccessManager(QNetworkAccessManager* manager) 460 | { 461 | Q_D(Interface); 462 | 463 | if (d->manager) 464 | delete d->manager; 465 | 466 | d->manager = manager; 467 | d->setupNetworkAccessManager(); 468 | } 469 | 470 | /*! 471 | \property QOAuth::Interface::ignoreSslErrors 472 | \brief This property is used to control SSL errors handling. 473 | 474 | The default value is false, meaning that the interface will fail upon an SSL error. 475 | Set it to true if you want to disregard any SSL errors encountered 476 | during the authorization process. 477 | 478 | Access functions: 479 | \li bool ignoreSslErrors() const 480 | \li void setIgnoreSslErrors( bool enabled ) 481 | */ 482 | 483 | bool QOAuth::Interface::ignoreSslErrors() const 484 | { 485 | Q_D(const QOAuth::Interface); 486 | 487 | return d->ignoreSslErrors; 488 | } 489 | 490 | void QOAuth::Interface::setIgnoreSslErrors(bool enabled) 491 | { 492 | Q_D(QOAuth::Interface); 493 | 494 | d->ignoreSslErrors = enabled; 495 | } 496 | 497 | 498 | /*! 499 | \property QOAuth::Interface::consumerKey 500 | \brief This property holds the consumer key 501 | 502 | The consumer key is used by the application to identify itself to the Service Provider. 503 | 504 | Access functions: 505 | \li QByteArray consumerKey() const 506 | \li void setConsumerKey( const QByteArray &consumerKey ) 507 | */ 508 | 509 | QByteArray QOAuth::Interface::consumerKey() const 510 | { 511 | Q_D(const Interface); 512 | 513 | return d->consumerKey; 514 | } 515 | 516 | void QOAuth::Interface::setConsumerKey( const QByteArray &consumerKey ) 517 | { 518 | Q_D(Interface); 519 | 520 | d->consumerKey = consumerKey; 521 | } 522 | 523 | /*! 524 | \property QOAuth::Interface::consumerSecret 525 | \brief This property holds the consumer secret 526 | 527 | The consumerSecret is used by the application for signing outgoing requests. 528 | 529 | Access functions: 530 | \li QByteArray consumerSecret() const 531 | \li void setConsumerSecret( const QByteArray &consumerSecret ) 532 | */ 533 | 534 | QByteArray QOAuth::Interface::consumerSecret() const 535 | { 536 | Q_D(const Interface); 537 | 538 | return d->consumerSecret; 539 | } 540 | 541 | void QOAuth::Interface::setConsumerSecret( const QByteArray &consumerSecret ) 542 | { 543 | Q_D(Interface); 544 | 545 | d->consumerSecret = consumerSecret; 546 | } 547 | 548 | /*! 549 | \property QOAuth::Interface::requestTimeout 550 | \brief This property holds the timeout value in milliseconds for issued network requests. 551 | 552 | The QOAuth::Interface class can send network requests when asked to do so by calling either 553 | requestToken() or accessToken() method. By defining the \a requestTimeout, requests 554 | can have the time constraint applied, after which they fail, setting \ref error to 555 | \ref Timeout. The \a requestTimeout value is initially set to \c 0, which in this 556 | case means that no timeout is applied to outgoing requests. 557 | 558 | Access functions: 559 | \li uint requestTimeout() const 560 | \li void setRequestTimeout( uint requestTimeout ) 561 | */ 562 | 563 | uint QOAuth::Interface::requestTimeout() const 564 | { 565 | Q_D(const Interface); 566 | 567 | return d->requestTimeout; 568 | } 569 | 570 | void QOAuth::Interface::setRequestTimeout( uint msec ) 571 | { 572 | Q_D(Interface); 573 | 574 | d->requestTimeout = msec; 575 | } 576 | 577 | 578 | /*! 579 | \property QOAuth::Interface::error 580 | \brief This property holds the error code 581 | 582 | The error code is initially set to \ref NoError, and its value is updated with every 583 | method that can cause errors. 584 | 585 | Access functions: 586 | \li int error() const 587 | 588 | \sa ErrorCode 589 | */ 590 | 591 | int QOAuth::Interface::error() const 592 | { 593 | Q_D(const Interface); 594 | 595 | return d->error; 596 | } 597 | 598 | 599 | /*! 600 | This method is useful when using OAuth with RSA-SHA1 signing algorithm. It reads the RSA 601 | private key from the string given as \a key, and stores it internally. If the key is 602 | secured by a passphrase, it should be passed as the second argument. 603 | 604 | The provided string is decoded into a private RSA key, optionally using the \a passphrase. 605 | If \a key contains a valid RSA private key, this method returns true. If any problems were 606 | encountered during decoding (either the key or the passphrase are invalid), false is 607 | returned and the error code is set to QOAuth::RSADecodingError. 608 | 609 | \sa setRSAPrivateKeyFromFile() 610 | */ 611 | 612 | bool QOAuth::Interface::setRSAPrivateKey( const QString &key, const QCA::SecureArray &passphrase ) 613 | { 614 | Q_D(Interface); 615 | 616 | d->setPrivateKey( key, passphrase, InterfacePrivate::KeyFromString ); 617 | 618 | return ( d->error == NoError ); 619 | } 620 | 621 | /*! 622 | This method is useful when using OAuth with RSA-SHA1 signing algorithm. It reads the RSA 623 | private key from the given \a file, and stores it internally. If the key is secured by 624 | a passphrase, it should be passed as the second argument. 625 | 626 | The provided file is read and decoded into a private RSA key, optionally using the \a passphrase. 627 | If it contains a valid RSA private key, this method returns true. If any problems were 628 | encountered during decoding, false is returned and the appropriate error code is set: 629 | \li QOAuth::RSAKeyFileError - when the key file doesn't exist or is unreadable 630 | \li QOAuth::RSADecodingError - if problems occurred during encoding (either the key 631 | and/or password are invalid). 632 | 633 | \sa setRSAPrivateKey() 634 | */ 635 | 636 | bool QOAuth::Interface::setRSAPrivateKeyFromFile( const QString &filename, const QCA::SecureArray &passphrase ) 637 | { 638 | Q_D(Interface); 639 | 640 | if ( ! QFileInfo( filename ).exists() ) { 641 | d->error = RSAKeyFileError; 642 | qWarning() << __FUNCTION__ << "- the given file does not exist..."; 643 | } else { 644 | d->setPrivateKey( filename, passphrase, InterfacePrivate::KeyFromFile ); 645 | } 646 | 647 | return ( d->error == NoError ); 648 | } 649 | 650 | void QOAuth::InterfacePrivate::setPrivateKey( const QString &source, 651 | const QCA::SecureArray &passphrase, KeySource from ) 652 | { 653 | 654 | if( !QCA::isSupported( "pkey" ) || 655 | !QCA::PKey::supportedIOTypes().contains( QCA::PKey::RSA ) ) { 656 | qFatal( "RSA is not supported!" ); 657 | } 658 | 659 | privateKeySet = false; 660 | this->passphrase = passphrase; 661 | 662 | QCA::KeyLoader keyLoader; 663 | QEventLoop localLoop; 664 | QObject::connect( &keyLoader, SIGNAL(finished()), &localLoop, SLOT(quit()) ); 665 | 666 | switch (from) { 667 | case KeyFromString: 668 | keyLoader.loadPrivateKeyFromPEM( source ); 669 | break; 670 | case KeyFromFile: 671 | keyLoader.loadPrivateKeyFromPEMFile( source ); 672 | break; 673 | } 674 | 675 | QTimer::singleShot( 3000, &localLoop, SLOT(quit()) ); 676 | localLoop.exec(); 677 | 678 | readKeyFromLoader( &keyLoader ); 679 | } 680 | 681 | void QOAuth::InterfacePrivate::readKeyFromLoader( QCA::KeyLoader *keyLoader ) 682 | { 683 | QCA::ConvertResult result = keyLoader->convertResult(); 684 | if ( result == QCA::ConvertGood ) { 685 | error = NoError; 686 | privateKey = keyLoader->privateKey(); 687 | privateKeySet = true; 688 | } else if ( result == QCA::ErrorDecode ) { 689 | error = RSADecodingError; 690 | // this one seems to never be set .... 691 | // } else if ( result == QCA::ErrorPassphrase ) { 692 | // error = RSAPassphraseError; 693 | } else if ( result == QCA::ErrorFile ) { 694 | error = RSAKeyFileError; 695 | } 696 | } 697 | 698 | void QOAuth::InterfacePrivate::_q_setPassphrase( int id, const QCA::Event &event ) 699 | { 700 | if ( event.isNull() ) { 701 | return; 702 | } 703 | 704 | // we're looking only for the passphrase for the RSA key 705 | if ( event.type() == QCA::Event::Password && 706 | event.passwordStyle() == QCA::Event::StylePassphrase ) { 707 | // set the passphrase to the one provided with QOAuth::Interface::setRSAPrivateKey{,FromFile}() 708 | eventHandler.submitPassword( id, passphrase ); 709 | } else { 710 | eventHandler.reject( id ); 711 | } 712 | } 713 | 714 | /*! 715 | This method constructs and sends a request for obtaining an unauthorized Request Token 716 | from the Service Provider. This is the first step of the OAuth authentication flow, 717 | according to OAuth 1.0 Core specification. 718 | The PLAINTEXT signature method uses Customer Secret and (if provided) Token Secret to 719 | sign a request. For the HMAC-SHA1 and RSA-SHA1 signature methods the 720 | Signature Base String is created 721 | using the given \a requestUrl and \a httpMethod. The optional request parameters 722 | specified by the Service Provider can be passed in the \a params ParamMap. 723 | 724 | The Signature Base String contains the \ref consumerKey and uses \ref consumerSecret 725 | for encrypting the message, so it's necessary to provide them both before issuing this 726 | request. The method will check if both \ref consumerKey and \ref consumerSecret are 727 | provided, and fail if any of them is missing. 728 | 729 | When the signature is created, the appropriate request is sent to the Service Provider 730 | (namely, the \a requestUrl). Depending on the type of the request, the parameters are 731 | passed according to the 732 | Consumer Request Parametes section of the OAuth specification, i.e.: 733 | \li for GET requests, in the HTTP Authorization header, as defined in 734 | OAuth HTTP Authorization Scheme, 735 | \li for POST requests, as a request body with \c content-type set to 736 | \c application/x-www-form-urlencoded. 737 | 738 | Once the request is sent, a local event loop is executed and set up to wait for the request 739 | to complete. If the \ref requestTimeout property is set to a non-zero value, its vaue 740 | is applied as a request timeout, after which the request is aborted. 741 | 742 | \returns If request succeded, the method returns all the data passed in the Service 743 | Provider response (including a Request Token and Token Secret), formed in a ParamMap. 744 | If request fails, the \ref error property is set to an appropriate value, and an empty 745 | ParamMap is returned. 746 | 747 | \sa accessToken(), error 748 | */ 749 | 750 | QOAuth::ParamMap QOAuth::Interface::requestToken( const QString &requestUrl, HttpMethod httpMethod, 751 | SignatureMethod signatureMethod, const ParamMap ¶ms ) 752 | { 753 | Q_D(Interface); 754 | 755 | return d->sendRequest( requestUrl, httpMethod, signatureMethod, 756 | QByteArray(), QByteArray(), params ); 757 | } 758 | 759 | /*! 760 | This method constructs and sends a request for exchanging a Request Token (obtained 761 | previously with a call to \ref requestToken()) for an Access Token, that authorizes the 762 | application to access Protected Resources. This is the third step of the OAuth 763 | authentication flow, according to OAuth 1.0 764 | Core specification. The PLAINTEXT signature method uses Customer Secret and (if 765 | provided) Token Secret to sign a request. For the HMAC-SHA1 and RSA-SHA1 766 | signature methods the Signature Base String 767 | is created using the given \a requestUrl, \a httpMethod, \a token and \a tokenSecret. 768 | The optional request parameters specified by the Service Provider can be passed in the 769 | \a params ParamMap. 770 | 771 | The Signature Base String contains the \ref consumerKey and uses \ref consumerSecret 772 | for encrypting the message, so it's necessary to provide them both before issuing 773 | this request. The method will check if both \ref consumerKey and \ref consumerSecret 774 | are provided, and fail if any of them is missing. 775 | 776 | When the signature is created, the appropriate request is sent to the Service Provider 777 | (namely, the \a requestUrl). Depending on the type of the request, the parameters are 778 | passed according to the 779 | Consumer Request Parametes section of the OAuth specification, i.e.: 780 | \li for GET requests, in the HTTP Authorization header, as defined in 781 | OAuth HTTP Authorization Scheme, 782 | \li for POST requests, as a request body with \c content-type set to 783 | \c application/x-www-form-urlencoded. 784 | 785 | Once the request is sent, a local event loop is executed and set up to wait for the request 786 | to complete. If the \ref requestTimeout property is set to a non-zero value, its vaue 787 | is applied as a request timeout, after which the request is aborted. 788 | 789 | \returns If request succeded, the method returns all the data passed in the Service 790 | Provider response (including an authorized Access Token and Token Secret), formed in 791 | a ParamMap. This request ends the authorization process, and the obtained Access Token 792 | and Token Secret should be kept by the application and provided with every future request 793 | authorized by OAuth, e.g. using \ref createParametersString(). If request fails, the 794 | \ref error property is set to an appropriate value, and an empty ParamMap is returned. 795 | 796 | \sa requestToken(), createParametersString(), error 797 | */ 798 | 799 | QOAuth::ParamMap QOAuth::Interface::accessToken( const QString &requestUrl, HttpMethod httpMethod, const QByteArray &token, 800 | const QByteArray &tokenSecret, SignatureMethod signatureMethod, 801 | const ParamMap ¶ms ) 802 | { 803 | Q_D(Interface); 804 | 805 | return d->sendRequest( requestUrl, httpMethod, signatureMethod, 806 | token, tokenSecret, params ); 807 | 808 | } 809 | 810 | /*! 811 | This method generates a parameters string required to access Protected Resources using 812 | OAuth authorization. According to OAuth 1.0 813 | Core specification, every outgoing request for accessing Protected Resources must 814 | contain information like the Consumer Key and Access Token, and has to be signed using one 815 | of the supported signature methods. 816 | 817 | The PLAINTEXT signature method uses Customer Secret and (if provided) Token Secret to 818 | sign a request. For the HMAC-SHA1 and RSA-SHA1 signature methods the 819 | Signature Base String is created using 820 | the given \a requestUrl, \a httpMethod, \a token and \a tokenSecret. The optional 821 | request parameters specified by the Service Provider can be passed in the \a params 822 | \ref ParamMap. 823 | 824 | The Signature Base String contains the \ref consumerKey and uses \ref consumerSecret 825 | for encrypting the message, so it's necessary to provide them both before issuing 826 | this request. The method will check if both \ref consumerKey and \ref consumerSecret 827 | are provided, and fail if any of them is missing. 828 | 829 | The \a mode parameter specifies the format of the parameter string. 830 | 831 | \returns The parsed parameters string, that depending on \a mode and \a httpMethod is: 832 | 833 | 834 | 835 | 836 | 837 | 838 | 839 |
\b \a mode \b outcome
QOAuth::ParseForRequestContent ready to be posted as a request body
QOAuth::ParseForInlineQuery prepended with a '?' and ready to be appended to the \a requestUrl
QOAuth::ParseForHeaderArguments ready to be set as an argument for the \c Authorization HTTP header
QOAuth::ParseForSignatureBaseString meant for internal use
840 | 841 | \sa inlineParameters() 842 | */ 843 | 844 | QByteArray QOAuth::Interface::createParametersString( const QString &requestUrl, HttpMethod httpMethod, const QByteArray &token, 845 | const QByteArray &tokenSecret, SignatureMethod signatureMethod, 846 | const ParamMap ¶ms, ParsingMode mode ) 847 | { 848 | Q_D(Interface); 849 | 850 | d->error = NoError; 851 | 852 | // copy parameters to a writeable object 853 | ParamMap parameters = params; 854 | // calculate the signature 855 | QByteArray signature = d->createSignature( requestUrl, httpMethod, signatureMethod, 856 | token, tokenSecret, ¶meters ); 857 | 858 | // return an empty bytearray when signature wasn't created 859 | if ( d->error != NoError ) { 860 | return QByteArray(); 861 | } 862 | 863 | // append it to parameters 864 | parameters.insert( InterfacePrivate::ParamSignature, signature ); 865 | // convert the map to bytearray, according to requested mode 866 | QByteArray parametersString = d->paramsToString( parameters, mode ); 867 | 868 | return parametersString; 869 | } 870 | 871 | /*! 872 | This method is provided for convenience. It generates an inline query string out of 873 | given parameter map. The resulting string can be either sent in an HTTP POST request 874 | as a request content, or appended directly to an HTTP GET request's URL as a query string. 875 | When using this method for preparing an HTTP GET query string you can set the \a mode 876 | to ParseForInlineQuery to have the string prepended with a question mark (separating 877 | the URL path from the query string). Modes other than QOAuth::ParseForRequestContent and 878 | QOAuth::ParseForInlineQuery produce an empty byte array. 879 | 880 | Use this method together with createParametersString(), when you request a header 881 | parameters string (QOAuth::ParseForHeaderArguments) together with HTTP GET method. 882 | In such case, apart from header arguments, you must provide a query string containing 883 | custom request parameters (i.e. not OAuth-related). Pass the custom parameters map 884 | to this method to receive a query string to be appended to the URL. 885 | 886 | \sa createParametersString() 887 | */ 888 | 889 | QByteArray QOAuth::Interface::inlineParameters( const ParamMap ¶ms, ParsingMode mode ) 890 | { 891 | Q_D(Interface); 892 | 893 | QByteArray query; 894 | 895 | switch (mode) { 896 | case ParseForInlineQuery: 897 | case ParseForRequestContent: 898 | query = d->paramsToString( params, mode ); 899 | break; 900 | case ParseForHeaderArguments: 901 | case ParseForSignatureBaseString: 902 | break; 903 | } 904 | 905 | return query; 906 | } 907 | 908 | QOAuth::ParamMap QOAuth::InterfacePrivate::sendRequest( const QString &requestUrl, HttpMethod httpMethod, 909 | SignatureMethod signatureMethod, const QByteArray &token, 910 | const QByteArray &tokenSecret, const ParamMap ¶ms ) 911 | { 912 | if ( httpMethod != GET && httpMethod != POST ) { 913 | qWarning() << __FUNCTION__ << "- requestToken() and accessToken() accept only GET and POST methods"; 914 | error = UnsupportedHttpMethod; 915 | return ParamMap(); 916 | } 917 | 918 | error = NoError; 919 | 920 | ParamMap parameters = params; 921 | 922 | // create signature 923 | QByteArray signature = createSignature( requestUrl, httpMethod, signatureMethod, 924 | token, tokenSecret, ¶meters ); 925 | 926 | // if signature wasn't created, return an empty map 927 | if ( error != NoError ) { 928 | return ParamMap(); 929 | } 930 | 931 | // add signature to parameters 932 | parameters.insert( InterfacePrivate::ParamSignature, signature ); 933 | 934 | QByteArray authorizationHeader; 935 | QNetworkRequest request; 936 | 937 | if ( httpMethod == GET ) { 938 | authorizationHeader = paramsToString( parameters, ParseForHeaderArguments ); 939 | // create the authorization header 940 | request.setRawHeader( "Authorization", authorizationHeader ); 941 | } else if ( httpMethod == POST ) { 942 | authorizationHeader = paramsToString( parameters, ParseForRequestContent ); 943 | // create a network request 944 | request.setHeader( QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded" ); 945 | } 946 | 947 | request.setUrl( QUrl( requestUrl ) ); 948 | 949 | // fire up a single shot timer if timeout was specified 950 | if ( requestTimeout > 0 ) { 951 | QTimer::singleShot( requestTimeout, loop, SLOT(quit()) ); 952 | // if the request finishes on time, the error value is overriden 953 | // if not, it remains equal to QOAuth::Interface::Timeout 954 | error = Timeout; 955 | } 956 | 957 | // clear the reply container and send the request 958 | replyParams.clear(); 959 | QNetworkReply *reply; 960 | if ( httpMethod == GET ) { 961 | reply = manager->get( request ); 962 | } else if ( httpMethod == POST ) { 963 | reply = manager->post( request, authorizationHeader ); 964 | } 965 | 966 | // start the event loop and wait for the response 967 | loop->exec(); 968 | 969 | // if request completed successfully, error is different than QOAuth::Interface::Timeout 970 | // if it failed, we have to abort the request 971 | if ( error == Timeout ) { 972 | reply->abort(); 973 | } 974 | 975 | return replyParams; 976 | } 977 | 978 | QByteArray QOAuth::InterfacePrivate::createSignature( const QString &requestUrl, HttpMethod httpMethod, 979 | SignatureMethod signatureMethod, const QByteArray &token, 980 | const QByteArray &tokenSecret, ParamMap *params ) 981 | { 982 | if ( ( signatureMethod == HMAC_SHA1 || 983 | signatureMethod == RSA_SHA1 ) && 984 | consumerKey.isEmpty() ) { 985 | qWarning() << __FUNCTION__ << "- consumer key is empty, make sure that you set it" 986 | "with QOAuth::Interface::setConsumerKey()"; 987 | error = ConsumerKeyEmpty; 988 | return QByteArray(); 989 | } 990 | if ( consumerSecret.isEmpty() ) { 991 | qWarning() << __FUNCTION__ << "- consumer secret is empty, make sure that you set it" 992 | "with QOAuth::Interface::setConsumerSecret()"; 993 | error = ConsumerSecretEmpty; 994 | return QByteArray(); 995 | } 996 | 997 | if ( signatureMethod == RSA_SHA1 && 998 | privateKey.isNull() ) { 999 | qWarning() << __FUNCTION__ << "- RSA private key is empty, make sure that you provide it" 1000 | "with QOAuth::Interface::setRSAPrivateKey{,FromFile}()"; 1001 | error = RSAPrivateKeyEmpty; 1002 | return QByteArray(); 1003 | } 1004 | 1005 | // create nonce 1006 | QCA::InitializationVector iv( 16 ); 1007 | QByteArray nonce = iv.toByteArray().toHex(); 1008 | 1009 | // create timestamp 1010 | uint time = QDateTime::currentDateTime().toTime_t(); 1011 | QByteArray timestamp = QByteArray::number( time ); 1012 | 1013 | // create signature base string 1014 | // 1. create the method string 1015 | QByteArray httpMethodString = httpMethodToString( httpMethod ); 1016 | // 2. prepare percent-encoded request URL 1017 | QByteArray percentRequestUrl = requestUrl.toLatin1().toPercentEncoding(); 1018 | // 3. prepare percent-encoded parameters string 1019 | params->insert( InterfacePrivate::ParamConsumerKey, consumerKey ); 1020 | params->insert( InterfacePrivate::ParamNonce, nonce ); 1021 | params->insert( InterfacePrivate::ParamSignatureMethod, 1022 | signatureMethodToString( signatureMethod ) ); 1023 | params->insert( InterfacePrivate::ParamTimestamp, timestamp ); 1024 | params->insert( InterfacePrivate::ParamVersion, InterfacePrivate::OAuthVersion ); 1025 | // append token only if it is defined (requestToken() doesn't use a token at all) 1026 | if ( !token.isEmpty() ) { 1027 | params->insert( InterfacePrivate::ParamToken, token ); 1028 | } 1029 | 1030 | QByteArray parametersString = paramsToString( *params, ParseForSignatureBaseString ); 1031 | QByteArray percentParametersString = parametersString.toPercentEncoding(); 1032 | 1033 | QByteArray digest; 1034 | 1035 | // PLAINTEXT doesn't use the Signature Base String 1036 | if ( signatureMethod == PLAINTEXT ) { 1037 | digest = createPlaintextSignature( tokenSecret ); 1038 | } else { 1039 | // 4. create signature base string 1040 | QByteArray signatureBaseString; 1041 | signatureBaseString.append( httpMethodString + "&" ); 1042 | signatureBaseString.append( percentRequestUrl + "&" ); 1043 | signatureBaseString.append( percentParametersString ); 1044 | 1045 | 1046 | if ( signatureMethod == HMAC_SHA1 ) { 1047 | if( !QCA::isSupported( "hmac(sha1)" ) ) { 1048 | qFatal( "HMAC(SHA1) is not supported!" ); 1049 | } 1050 | // create key for HMAC-SHA1 hashing 1051 | QByteArray key( consumerSecret.toPercentEncoding() + "&" + tokenSecret.toPercentEncoding() ); 1052 | 1053 | // create HMAC-SHA1 digest in Base64 1054 | QCA::MessageAuthenticationCode hmac( "hmac(sha1)", QCA::SymmetricKey( key ) ); 1055 | QCA::SecureArray array( signatureBaseString ); 1056 | hmac.update( array ); 1057 | QCA::SecureArray resultArray = hmac.final(); 1058 | digest = resultArray.toByteArray().toBase64(); 1059 | 1060 | } else if ( signatureMethod == RSA_SHA1 ) { 1061 | // sign the Signature Base String with the RSA key 1062 | digest = privateKey.signMessage( QCA::MemoryRegion( signatureBaseString ), 1063 | QCA::EMSA3_SHA1 ).toBase64(); 1064 | } 1065 | } 1066 | 1067 | // percent-encode the digest 1068 | QByteArray signature = digest.toPercentEncoding(); 1069 | return signature; 1070 | } 1071 | 1072 | QByteArray QOAuth::InterfacePrivate::createPlaintextSignature( const QByteArray &tokenSecret ) 1073 | { 1074 | if ( consumerSecret.isEmpty() ) { 1075 | qWarning() << __FUNCTION__ << "- consumer secret is empty, make sure that you set it" 1076 | "with QOAuth::Interface::setConsumerSecret()"; 1077 | error = ConsumerSecretEmpty; 1078 | return QByteArray(); 1079 | } 1080 | 1081 | // get percent encoded consumer secret and token secret, join and return 1082 | return consumerSecret.toPercentEncoding() + "&" + tokenSecret.toPercentEncoding(); 1083 | } 1084 | 1085 | #include "moc_interface.cpp" 1086 | -------------------------------------------------------------------------------- /src/interface.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2009 by Dominik Kapusta * 3 | * * 4 | * This library is free software; you can redistribute it and/or modify * 5 | * it under the terms of the GNU Lesser General Public License as * 6 | * published by the Free Software Foundation; either version 2.1 of * 7 | * the License, or (at your option) any later version. * 8 | * * 9 | * This library is distributed in the hope that it will be useful, * 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 12 | * Lesser General Public License for more details. * 13 | * * 14 | * You should have received a copy of the GNU Lesser General Public * 15 | * License along with this library; if not, write to * 16 | * the Free Software Foundation, Inc., * 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * 18 | ***************************************************************************/ 19 | 20 | 21 | /*! 22 | \file interface.h 23 | 24 | This file is a part of libqoauth. You should not include it directly in your 25 | application. Instead please use \#include <QtOAuth>. 26 | */ 27 | 28 | #ifndef INTERFACE_H 29 | #define INTERFACE_H 30 | 31 | #include 32 | 33 | #include 34 | 35 | #include "qoauth_global.h" 36 | #include "qoauth_namespace.h" 37 | 38 | class QNetworkAccessManager; 39 | class QNetworkReply; 40 | 41 | namespace QOAuth { 42 | 43 | class InterfacePrivate; 44 | 45 | class QOAUTH_EXPORT Interface : public QObject 46 | { 47 | Q_OBJECT 48 | 49 | Q_PROPERTY( QByteArray consumerKey READ consumerKey WRITE setConsumerKey ) 50 | Q_PROPERTY( QByteArray consumerSecret READ consumerSecret WRITE setConsumerSecret ) 51 | Q_PROPERTY( uint requestTimeout READ requestTimeout WRITE setRequestTimeout ) 52 | Q_PROPERTY( bool ignoreSslErrors READ ignoreSslErrors WRITE setIgnoreSslErrors ) 53 | Q_PROPERTY( int error READ error ) 54 | 55 | public: 56 | Interface( QObject *parent = 0 ); 57 | Interface( QNetworkAccessManager *manager, QObject *parent = 0 ); 58 | virtual ~Interface(); 59 | 60 | QNetworkAccessManager* networkAccessManager() const; 61 | void setNetworkAccessManager(QNetworkAccessManager *manager); 62 | 63 | bool ignoreSslErrors() const; 64 | void setIgnoreSslErrors(bool enabled); 65 | 66 | QByteArray consumerKey() const; 67 | void setConsumerKey( const QByteArray &consumerKey ); 68 | 69 | QByteArray consumerSecret() const; 70 | void setConsumerSecret( const QByteArray &consumerSecret ); 71 | 72 | uint requestTimeout() const; 73 | void setRequestTimeout( uint msec ); 74 | 75 | int error() const; 76 | 77 | bool setRSAPrivateKey( const QString &key, 78 | const QCA::SecureArray &passphrase = QCA::SecureArray() ); 79 | bool setRSAPrivateKeyFromFile( const QString &filename, 80 | const QCA::SecureArray &passphrase = QCA::SecureArray() ); 81 | 82 | 83 | ParamMap requestToken( const QString &requestUrl, HttpMethod httpMethod, 84 | SignatureMethod signatureMethod = HMAC_SHA1, const ParamMap ¶ms = ParamMap() ); 85 | 86 | ParamMap accessToken( const QString &requestUrl, HttpMethod httpMethod, const QByteArray &token, 87 | const QByteArray &tokenSecret, SignatureMethod signatureMethod = HMAC_SHA1, 88 | const ParamMap ¶ms = ParamMap() ); 89 | 90 | QByteArray createParametersString( const QString &requestUrl, HttpMethod httpMethod, 91 | const QByteArray &token, const QByteArray &tokenSecret, 92 | SignatureMethod signatureMethod, const ParamMap ¶ms, ParsingMode mode ); 93 | 94 | QByteArray inlineParameters( const ParamMap ¶ms, ParsingMode mode = ParseForRequestContent ); 95 | 96 | 97 | protected: 98 | InterfacePrivate * const d_ptr; 99 | 100 | private: 101 | Q_DISABLE_COPY(Interface) 102 | Q_DECLARE_PRIVATE(Interface) 103 | Q_PRIVATE_SLOT(d_func(), void _q_parseReply(QNetworkReply *reply)) 104 | Q_PRIVATE_SLOT(d_func(), void _q_setPassphrase(int id, const QCA::Event &event)) 105 | Q_PRIVATE_SLOT(d_func(), void _q_handleSslErrors( QNetworkReply *reply, 106 | const QList &errors )) 107 | 108 | #ifdef UNIT_TEST 109 | friend class Ut_Interface; 110 | friend class Ft_Interface; 111 | #endif 112 | }; 113 | 114 | } // namespace QOAuth 115 | 116 | #endif // INTERFACE_H 117 | -------------------------------------------------------------------------------- /src/interface_p.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2009 by Dominik Kapusta * 3 | * * 4 | * This library is free software; you can redistribute it and/or modify * 5 | * it under the terms of the GNU Lesser General Public License as * 6 | * published by the Free Software Foundation; either version 2.1 of * 7 | * the License, or (at your option) any later version. * 8 | * * 9 | * This library is distributed in the hope that it will be useful, * 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 12 | * Lesser General Public License for more details. * 13 | * * 14 | * You should have received a copy of the GNU Lesser General Public * 15 | * License along with this library; if not, write to * 16 | * the Free Software Foundation, Inc., * 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * 18 | ***************************************************************************/ 19 | 20 | 21 | /*! 22 | \file interface_p.h 23 | 24 | This file is a part of libqoauth and is considered strictly internal. You should not 25 | include it in your application. Instead please use \#include <QtOAuth>. 26 | */ 27 | 28 | #ifndef QOAUTH_P_H 29 | #define QOAUTH_P_H 30 | 31 | #include "interface.h" 32 | #include 33 | #include 34 | 35 | class QNetworkReply; 36 | class QEventLoop; 37 | 38 | namespace QOAuth { 39 | 40 | class Interface; 41 | 42 | 43 | class QOAUTH_EXPORT InterfacePrivate 44 | { 45 | Q_DECLARE_PUBLIC(Interface) 46 | 47 | public: 48 | enum Operation { 49 | RequestToken, 50 | Authorize, 51 | Authenticate, 52 | AccessToken 53 | }; 54 | 55 | enum KeySource { 56 | KeyFromString, 57 | KeyFromFile 58 | }; 59 | 60 | static const QByteArray OAuthVersion; 61 | static const QByteArray ParamToken; 62 | static const QByteArray ParamTokenSecret; 63 | 64 | static const QByteArray ParamConsumerKey; 65 | static const QByteArray ParamNonce; 66 | static const QByteArray ParamSignature; 67 | static const QByteArray ParamSignatureMethod; 68 | static const QByteArray ParamTimestamp; 69 | static const QByteArray ParamVersion; 70 | 71 | 72 | InterfacePrivate(); 73 | void init(); 74 | void setupNetworkAccessManager(); 75 | 76 | QByteArray httpMethodToString( HttpMethod method ); 77 | QByteArray signatureMethodToString( SignatureMethod method ); 78 | ParamMap replyToMap( const QByteArray &data ); 79 | QByteArray paramsToString( const ParamMap ¶meters, ParsingMode mode ); 80 | 81 | QByteArray createSignature( const QString &requestUrl, HttpMethod httpMethod, 82 | SignatureMethod signatureMethod, const QByteArray &token, 83 | const QByteArray &tokenSecret, ParamMap *params ); 84 | 85 | // for PLAINTEXT only 86 | QByteArray createPlaintextSignature( const QByteArray &tokenSecret ); 87 | 88 | ParamMap sendRequest( const QString &requestUrl, HttpMethod httpMethod, SignatureMethod signatureMethod, 89 | const QByteArray &token, const QByteArray &tokenSecret, const ParamMap ¶ms ); 90 | 91 | // RSA-SHA1 stuff 92 | void setPrivateKey( const QString &source, const QCA::SecureArray &passphrase, KeySource from ); 93 | void readKeyFromLoader( QCA::KeyLoader *keyLoader ); 94 | 95 | bool privateKeySet; 96 | 97 | QCA::Initializer initializer; 98 | QCA::PrivateKey privateKey; 99 | QCA::SecureArray passphrase; 100 | QCA::EventHandler eventHandler; 101 | // end of RSA-SHA1 stuff 102 | 103 | bool ignoreSslErrors; 104 | QByteArray consumerKey; 105 | QByteArray consumerSecret; 106 | 107 | ParamMap replyParams; 108 | 109 | QPointer manager; 110 | QEventLoop *loop; 111 | 112 | uint requestTimeout; 113 | int error; 114 | 115 | protected: 116 | Interface *q_ptr; 117 | 118 | public: 119 | void _q_parseReply( QNetworkReply *reply ); 120 | void _q_setPassphrase( int id, const QCA::Event &event ); 121 | void _q_handleSslErrors( QNetworkReply *reply, const QList &errors ); 122 | }; 123 | 124 | } // namespace QOAuth 125 | 126 | #endif // INTERFACE_P_H 127 | -------------------------------------------------------------------------------- /src/pcfile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # This "script" creates a pkg-config file basing on values set 3 | # in project file 4 | 5 | echo "prefix=$1 6 | exec_prefix=\${prefix} 7 | libdir=\${prefix}/lib 8 | includedir=\${prefix}/include/QtOAuth 9 | 10 | Name: QOAuth 11 | Description: Qt OAuth support library 12 | Version: $2 13 | Requires: QtCore QtNetwork qca2 14 | Libs: -L\${libdir} -lqoauth 15 | Cflags: -I\${includedir}" > qoauth.pc 16 | -------------------------------------------------------------------------------- /src/qoauth.pc: -------------------------------------------------------------------------------- 1 | prefix=/usr 2 | exec_prefix=${prefix} 3 | libdir=${prefix}/lib 4 | includedir=${prefix}/include/QtOAuth 5 | 6 | Name: QOAuth 7 | Description: Qt OAuth support library 8 | Version: 2.0.0 9 | Requires: QtCore QtNetwork qca2 10 | Libs: -L${libdir} -lqoauth 11 | Cflags: -I${includedir} 12 | -------------------------------------------------------------------------------- /src/qoauth_global.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2009 by Dominik Kapusta * 3 | * * 4 | * This library is free software; you can redistribute it and/or modify * 5 | * it under the terms of the GNU Lesser General Public License as * 6 | * published by the Free Software Foundation; either version 2.1 of * 7 | * the License, or (at your option) any later version. * 8 | * * 9 | * This library is distributed in the hope that it will be useful, * 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 12 | * Lesser General Public License for more details. * 13 | * * 14 | * You should have received a copy of the GNU Lesser General Public * 15 | * License along with this library; if not, write to * 16 | * the Free Software Foundation, Inc., * 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * 18 | ***************************************************************************/ 19 | 20 | 21 | /*! 22 | \file qoauth_global.h 23 | 24 | This file is a part of libqoauth and is considered strictly internal. You should not 25 | include it in your application. Instead please use \#include <QtOAuth>. 26 | */ 27 | 28 | #ifndef QOAUTH_GLOBAL_H 29 | #define QOAUTH_GLOBAL_H 30 | 31 | #include 32 | 33 | #if defined(QOAUTH) 34 | # define QOAUTH_EXPORT Q_DECL_EXPORT 35 | #else 36 | # define QOAUTH_EXPORT Q_DECL_IMPORT 37 | #endif 38 | 39 | #endif // QOAUTH_GLOBAL_H 40 | -------------------------------------------------------------------------------- /src/qoauth_namespace.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2009 by Dominik Kapusta * 3 | * * 4 | * This library is free software; you can redistribute it and/or modify * 5 | * it under the terms of the GNU Lesser General Public License as * 6 | * published by the Free Software Foundation; either version 2.1 of * 7 | * the License, or (at your option) any later version. * 8 | * * 9 | * This library is distributed in the hope that it will be useful, * 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 12 | * Lesser General Public License for more details. * 13 | * * 14 | * You should have received a copy of the GNU Lesser General Public * 15 | * License along with this library; if not, write to * 16 | * the Free Software Foundation, Inc., * 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * 18 | ***************************************************************************/ 19 | 20 | 21 | /*! 22 | \file qoauth_namespace.h 23 | 24 | This file is a part of libqoauth. You should not include it directly in your 25 | application. Instead please use \#include <QtOAuth>. 26 | */ 27 | 28 | #ifndef QOAUTH_NAMESPACE_H 29 | #define QOAUTH_NAMESPACE_H 30 | 31 | #include 32 | #include 33 | 34 | #include "qoauth_global.h" 35 | 36 | /*! 37 | \namespace QOAuth 38 | \brief This namespace encapsulates all classes and definitions provided by libqoauth. 39 | */ 40 | namespace QOAuth { 41 | 42 | /*! 43 | \typedef ParamMap 44 | \brief A typedef for the data structure for storing request parameters 45 | */ 46 | typedef QMultiMap ParamMap; 47 | 48 | /*! 49 | \enum SignatureMethod 50 | \brief This enum type describes the signature method used by the request. 51 | 52 | There are 3 different signature methods defined by the 53 | OAuth protocol. This enum 54 | is used to specify the method used by a specific request. Hence, one of its values 55 | must be passed as a parameter in any of the \ref QOAuth::Interface::requestToken(), 56 | \ref QOAuth::Interface::accessToken() or \ref QOAuth::Interface::createParametersString() 57 | method. 58 | */ 59 | enum SignatureMethod { 60 | HMAC_SHA1, //!< Sets the signature method to HMAC-SHA1 61 | RSA_SHA1, //!< Sets the signature method to RSA-SHA1 (not implemented yet) 62 | PLAINTEXT //!< Sets the signature method to PLAINTEXT (not implemented yet) 63 | }; 64 | 65 | /*! 66 | \enum HttpMethod 67 | \brief This enum type specifies the HTTP method used for creating 68 | a Signature Base String 69 | and/or sending a request. 70 | 71 | The HTTP method has to be specified in QOAuth class for two reasons: 72 | \li to know what type of request should be prepared and sent 73 | (\ref QOAuth::Interface::requestToken() and \ref QOAuth::Interface::accessToken()), 74 | \li to prepare a correct signature, as the Signature Base String contains a parameter 75 | specifying the HTTP method used for request (\ref QOAuth::Interface::createParametersString()). 76 | 77 | \note For \ref QOAuth::Interface::requestToken() and \ref QOAuth::Interface::accessToken() methods 78 | only \ref GET and \ref POST methods are allowed. 79 | */ 80 | enum HttpMethod { 81 | GET, //!< Sets the HTTP method to GET 82 | POST, //!< Sets the HTTP method to POST 83 | HEAD, //!< Sets the HTTP method to HEAD 84 | PUT //!< Sets the HTTP method to PUT 85 | #ifndef Q_WS_WIN 86 | , DELETE //!< Sets the HTTP method to DELETE 87 | #endif 88 | }; 89 | 90 | /*! 91 | \enum ParsingMode 92 | \brief This enum type specifies the method of parsing parameters into 93 | a parameter string. 94 | 95 | When creating a parameters string for a custom request using 96 | \ref QOAuth::Interface::createParametersString() the parsing mode must be defined in order 97 | to prepare the string correctly. 98 | 99 | According to what is stated in 100 | OAuth 1.0 Core specification, parameters can be passed in a request to 101 | the Service Provider in 3 different ways. When using \ref QOAuth::Interface::createParametersString(), 102 | choose the one that suits you by setting \a ParsingMode appropriatelly. 103 | 104 | \sa QOAuth::Interface::createParametersString() 105 | */ 106 | enum ParsingMode { 107 | ParseForRequestContent, //!< Inline query format (foo=bar&bar=baz&baz=foo ...), suitable for POST requests 108 | ParseForInlineQuery, /*!< Same as ParseForRequestContent, but prepends the string with a question mark - 109 | suitable for GET requests (appending parameters to the request URL) */ 110 | ParseForHeaderArguments, //!< HTTP request header format (parameters to be put inside a request header) 111 | ParseForSignatureBaseString //!< Signature Base String format, meant for internal use. 112 | }; 113 | 114 | /*! 115 | \enum ErrorCode 116 | \brief This enum type defines error types that are assigned to the 117 | \ref QOAuth::Interface::error property 118 | 119 | This error codes collection contains both network-related errors and those that 120 | can occur when incorrect arguments are provided to any of the class's methods. 121 | 122 | \sa QOAuth::Interface::error 123 | */ 124 | enum ErrorCode { 125 | NoError = 200, //!< No error occured (so far :-) ) 126 | BadRequest = 400, //!< Represents HTTP status code \c 400 (Bad Request) 127 | Unauthorized = 401, //!< Represents HTTP status code \c 401 (Unauthorized) 128 | Forbidden = 403, //!< Represents HTTP status code \c 403 (Forbidden) 129 | Timeout = 1001, //!< Represents a request timeout error 130 | ConsumerKeyEmpty, //!< Consumer key has not been provided 131 | ConsumerSecretEmpty, //!< Consumer secret has not been provided 132 | UnsupportedHttpMethod, /*!< The HTTP method is not supported by the request. 133 | \note \ref QOAuth::Interface::requestToken() and 134 | \ref QOAuth::Interface::accessToken() 135 | accept only HTTP GET and POST requests. */ 136 | 137 | RSAPrivateKeyEmpty = 1101, //!< RSA private key has not been provided 138 | // RSAPassphraseError, //!< RSA passphrase is incorrect (or has not been provided) 139 | RSADecodingError, /*!< There was a problem decoding the RSA private key 140 | (the key is invalid or the provided passphrase is incorrect)*/ 141 | RSAKeyFileError, //!< The provided key file either doesn't exist or is unreadable. 142 | OtherError //!< A network-related error not specified above 143 | }; 144 | 145 | 146 | /*! 147 | \brief Returns the supported OAuth protocol version 148 | */ 149 | QOAUTH_EXPORT QByteArray supportedOAuthVersion(); 150 | 151 | /*! 152 | \brief Returns the name of the Access Token argument parameter (oauth_token in 153 | current implementation) 154 | 155 | Useful when reading Service Provider's reply for \ref QOAuth::Interface::accessToken() request, e.g: 156 | \code 157 | QOAuth::Interface qoauth; 158 | QByteArray requestToken = "token"; 159 | QByteArray requestTokenSecret = "secret"; 160 | QOAuth::ParamMap reply = qoauth.accessToken( "http://example.com/access_token", QOAuth::POST, 161 | token, tokenSecret, QOAuth::HMAC_SHA1 ); 162 | 163 | if ( qoauth.error() == QOAuth::NoError ) { 164 | token = reply.value( QOAuth::tokenParameterName() ); 165 | tokenSecret = reply.value( QOAuth::tokenSecretParameterName() ); 166 | } 167 | \endcode 168 | */ 169 | QOAUTH_EXPORT QByteArray tokenParameterName(); 170 | 171 | /*! 172 | \brief Returns the name of the Token Secret argument parameter (oauth_token_secret in 173 | current implementation) 174 | \sa QOAuth::tokenParameterName() 175 | */ 176 | QOAUTH_EXPORT QByteArray tokenSecretParameterName(); 177 | 178 | } // namespace QOAuth 179 | 180 | #endif // QOAUTH_NAMESPACE_H 181 | -------------------------------------------------------------------------------- /src/src.pro: -------------------------------------------------------------------------------- 1 | TARGET = qoauth 2 | DESTDIR = ../lib 3 | win32:DLLDESTDIR = $${DESTDIR} 4 | 5 | equals(QT_MAJOR_VERSION, 5){ 6 | VERSION = 2.0.0 7 | } 8 | equals(QT_MAJOR_VERSION, 4) { 9 | VERSION = 1.0.1 10 | } 11 | 12 | TEMPLATE = lib 13 | QT += network 14 | QT -= gui 15 | CONFIG += \ 16 | crypto \ 17 | create_prl 18 | 19 | 20 | INC_DIR = ../include 21 | 22 | INCLUDEPATH += . 23 | win32 { 24 | CONFIG(debug, debug|release) { 25 | BUILDDIR = build/debug 26 | windows: TARGET = $$join(TARGET,,,d) 27 | mac: TARGET = $$join(TARGET,,,_debug) 28 | } else { 29 | BUILDDIR = build/release 30 | } 31 | } 32 | 33 | INCLUDEPATH += ./$${BUILDDIR} 34 | MOC_DIR += ./$${BUILDDIR} 35 | OBJECTS_DIR += ./$${BUILDDIR} 36 | UI_DIR += ./$${BUILDDIR} 37 | RCC_DIR += ./$${BUILDDIR} 38 | 39 | 40 | PUBLIC_HEADERS += \ 41 | qoauth_global.h \ 42 | qoauth_namespace.h \ 43 | interface.h 44 | 45 | PRIVATE_HEADERS += \ 46 | interface_p.h 47 | 48 | HEADERS = \ 49 | $$PUBLIC_HEADERS \ 50 | $$PRIVATE_HEADERS 51 | SOURCES += interface.cpp 52 | 53 | DEFINES += QOAUTH 54 | 55 | headers.files = \ 56 | $${PUBLIC_HEADERS} \ 57 | $${INC_DIR}/QtOAuth 58 | features.path = $$[QMAKE_MKSPECS]/features 59 | features.files = ../oauth.prf 60 | docs.files = ../doc/html 61 | 62 | macx { 63 | CONFIG += lib_bundle 64 | QMAKE_FRAMEWORK_BUNDLE_NAME = $$TARGET 65 | CONFIG(debug, debug|release): CONFIG += build_all 66 | FRAMEWORK_HEADERS.version = Versions 67 | FRAMEWORK_HEADERS.files = $$headers.files 68 | FRAMEWORK_HEADERS.path = Headers 69 | QMAKE_BUNDLE_DATA += FRAMEWORK_HEADERS 70 | target.path = $$[QT_INSTALL_LIBS] 71 | INSTALLS += \ 72 | target \ 73 | features 74 | } 75 | else:unix { 76 | isEmpty( PREFIX ):INSTALL_PREFIX = /usr 77 | else:INSTALL_PREFIX = $${PREFIX} 78 | 79 | # this creates a pkgconfig file 80 | system( ./pcfile.sh $${INSTALL_PREFIX} $${VERSION} ) 81 | pkgconfig.files = qoauth.pc 82 | 83 | contains(QMAKE_HOST.arch, x86_64) { 84 | target.path = $${INSTALL_PREFIX}/lib64 85 | } else { 86 | target.path = $${INSTALL_PREFIX}/lib 87 | } 88 | 89 | headers.path = $${INSTALL_PREFIX}/include/QtOAuth 90 | docs.path = $${INSTALL_PREFIX}/share/doc/$${TARGET}-$${VERSION}/html 91 | pkgconfig.path = $${target.path}/pkgconfig 92 | INSTALLS += \ 93 | target \ 94 | headers \ 95 | docs \ 96 | pkgconfig \ 97 | features 98 | } 99 | -------------------------------------------------------------------------------- /tests/ft_interface/ft_interface.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2009 by Dominik Kapusta * 3 | * * 4 | * This library is free software; you can redistribute it and/or modify * 5 | * it under the terms of the GNU Lesser General Public License as * 6 | * published by the Free Software Foundation; either version 2.1 of * 7 | * the License, or (at your option) any later version. * 8 | * * 9 | * This library is distributed in the hope that it will be useful, * 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 12 | * Lesser General Public License for more details. * 13 | * * 14 | * You should have received a copy of the GNU Lesser General Public * 15 | * License along with this library; if not, write to * 16 | * the Free Software Foundation, Inc., * 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * 18 | ***************************************************************************/ 19 | 20 | 21 | #include "ft_interface.h" 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | 31 | 32 | bool MyEventLoop::timeout() const 33 | { 34 | return m_timeout; 35 | } 36 | 37 | int MyEventLoop::exec( QEventLoop::ProcessEventsFlags flags ) 38 | { 39 | m_timeout = false; 40 | return QEventLoop::exec( flags ); 41 | } 42 | 43 | void MyEventLoop::quitWithTimeout() 44 | { 45 | QEventLoop::quit(); 46 | m_timeout = true; 47 | } 48 | 49 | 50 | void QOAuth::Ft_Interface::init() 51 | { 52 | m = new Interface; 53 | } 54 | 55 | void QOAuth::Ft_Interface::cleanup() 56 | { 57 | delete m; 58 | } 59 | 60 | void QOAuth::Ft_Interface::requestToken_data() 61 | { 62 | QTest::addColumn("timeout"); 63 | QTest::addColumn("key"); 64 | QTest::addColumn("secret"); 65 | QTest::addColumn("url"); 66 | QTest::addColumn("httpMethod"); 67 | QTest::addColumn("signMethod"); 68 | QTest::addColumn("error"); 69 | QTest::addColumn("requestToken"); 70 | QTest::addColumn("requestTokenSecret"); 71 | 72 | // OAuth test server at http://term.ie/oauth/example 73 | QTest::newRow("HMAC-SHA1") << (uint) 10000 74 | << QByteArray( "key" ) 75 | << QByteArray( "secret" ) 76 | << QString( "http://term.ie/oauth/example/request_token.php" ) 77 | << (int) GET 78 | << (int) HMAC_SHA1 79 | << (int) NoError 80 | << QByteArray( "requestkey" ) 81 | << QByteArray( "requestsecret" ); 82 | 83 | // term.ie fails at creating PLAINTEXT signature :( 84 | /*QTest::newRow("PLAINTEXT") << (uint) 10000 85 | << QByteArray( "key" ) 86 | << QByteArray( "secret" ) 87 | << QString( "http://term.ie/oauth/example/request_token.php" ) 88 | << (int) GET 89 | << (int) PLAINTEXT 90 | << (int) NoError 91 | << QByteArray( "requestkey" ) 92 | << QByteArray( "requestsecret" ); */ 93 | 94 | // timeout seems to be untestable for a moment 95 | // QTest::newRow("timeout") << (uint) 100 96 | // << QByteArray( "key" ) 97 | // << QByteArray( "secret" ) 98 | // << QString( "http://term.ie/oauth/example/request_token.php" ) 99 | // << (int) QOAuth::GET 100 | // << (int) QOAuth::HMAC_SHA1 101 | // << (int) QOAuth::Timeout 102 | // << QByteArray() 103 | // << QByteArray(); 104 | 105 | } 106 | 107 | void QOAuth::Ft_Interface::requestToken() 108 | { 109 | QFETCH( uint, timeout ); 110 | QFETCH( QByteArray, key ); 111 | QFETCH( QByteArray, secret ); 112 | QFETCH( QString, url ); 113 | QFETCH( int, httpMethod ); 114 | QFETCH( int, signMethod ); 115 | QFETCH( int, error ); 116 | QFETCH( QByteArray, requestToken ); 117 | QFETCH( QByteArray, requestTokenSecret ); 118 | 119 | m->setRequestTimeout( timeout ); 120 | m->setConsumerKey( key ); 121 | m->setConsumerSecret( secret ); 122 | ParamMap map = m->requestToken( url, (HttpMethod) httpMethod, (SignatureMethod) signMethod ); 123 | 124 | if ( m->error() != QOAuth::Timeout ) { 125 | QVERIFY( m->error() == error ); 126 | } else { 127 | QWARN( "Request timeout" ); 128 | } 129 | 130 | //check the reply if request finished with no errors 131 | if ( m->error() == NoError ) { 132 | QCOMPARE( map.value( tokenParameterName() ), requestToken ); 133 | QCOMPARE( map.value( tokenSecretParameterName() ), requestTokenSecret ); 134 | } 135 | } 136 | 137 | void QOAuth::Ft_Interface::requestTokenRSA_data() 138 | { 139 | QTest::addColumn("timeout"); 140 | QTest::addColumn("key"); 141 | QTest::addColumn("secret"); 142 | QTest::addColumn("rsaKeyFile"); 143 | QTest::addColumn("url"); 144 | QTest::addColumn("httpMethod"); 145 | QTest::addColumn("signMethod"); 146 | QTest::addColumn("error"); 147 | QTest::addColumn("requestToken"); 148 | QTest::addColumn("requestTokenSecret"); 149 | 150 | // OAuth test server at http://term.ie/oauth/example 151 | QTest::newRow("noError") << (uint) 10000 152 | << QByteArray( "key" ) 153 | << QByteArray( "secret" ) 154 | << QString( "rsa-testkey.pem" ) 155 | << QString( "http://term.ie/oauth/example/request_token.php" ) 156 | << (int) GET 157 | << (int) RSA_SHA1 158 | << (int) NoError 159 | << QByteArray( "requestkey" ) 160 | << QByteArray( "requestsecret" ); 161 | } 162 | 163 | void QOAuth::Ft_Interface::requestTokenRSA() 164 | { 165 | QFETCH( uint, timeout ); 166 | QFETCH( QByteArray, key ); 167 | QFETCH( QByteArray, secret ); 168 | QFETCH( QString, rsaKeyFile ); 169 | QFETCH( QString, url ); 170 | QFETCH( int, httpMethod ); 171 | QFETCH( int, signMethod ); 172 | QFETCH( int, error ); 173 | QFETCH( QByteArray, requestToken ); 174 | QFETCH( QByteArray, requestTokenSecret ); 175 | 176 | m->setRequestTimeout( timeout ); 177 | m->setConsumerKey( key ); 178 | m->setConsumerSecret( secret ); 179 | m->setRSAPrivateKeyFromFile( rsaKeyFile ); 180 | ParamMap map = m->requestToken( url, (HttpMethod) httpMethod, (SignatureMethod) signMethod ); 181 | 182 | if ( m->error() != QOAuth::Timeout ) { 183 | QVERIFY( m->error() == error ); 184 | } else { 185 | QWARN( "Request timeout" ); 186 | } 187 | 188 | //check the reply if request finished with no errors 189 | if ( m->error() == NoError ) { 190 | QCOMPARE( map.value( tokenParameterName() ), requestToken ); 191 | QCOMPARE( map.value( tokenSecretParameterName() ), requestTokenSecret ); 192 | } 193 | } 194 | 195 | 196 | void QOAuth::Ft_Interface::accessToken_data() 197 | { 198 | QTest::addColumn("timeout"); 199 | QTest::addColumn("key"); 200 | QTest::addColumn("secret"); 201 | QTest::addColumn("token"); 202 | QTest::addColumn("tokenSecret"); 203 | QTest::addColumn("url"); 204 | QTest::addColumn("httpMethod"); 205 | QTest::addColumn("signMethod"); 206 | QTest::addColumn("error"); 207 | QTest::addColumn("accessToken"); 208 | QTest::addColumn("accessTokenSecret"); 209 | 210 | // OAuth test server at http://term.ie/oauth/example 211 | QTest::newRow("HMAC-SHA1") << (uint) 10000 212 | << QByteArray( "key" ) 213 | << QByteArray( "secret" ) 214 | << QByteArray( "requestkey" ) 215 | << QByteArray( "requestsecret" ) 216 | << QString( "http://term.ie/oauth/example/access_token.php" ) 217 | << (int) GET 218 | << (int) HMAC_SHA1 219 | << (int) NoError 220 | << QByteArray( "accesskey" ) 221 | << QByteArray( "accesssecret" ); 222 | 223 | // term.ie fails at creating PLAINTEXT signature :( 224 | /*QTest::newRow("PLAINTEXT") << (uint) 10000 225 | << QByteArray( "key" ) 226 | << QByteArray( "secret" ) 227 | << QByteArray( "requestkey" ) 228 | << QByteArray( "requestsecret" ) 229 | << QString( "http://term.ie/oauth/example/access_token.php" ) 230 | << (int) GET 231 | << (int) PLAINTEXT 232 | << (int) NoError 233 | << QByteArray( "accesskey" ) 234 | << QByteArray( "accesssecret" );*/ 235 | } 236 | 237 | void QOAuth::Ft_Interface::accessToken() 238 | { 239 | QFETCH( uint, timeout ); 240 | QFETCH( QByteArray, key ); 241 | QFETCH( QByteArray, secret ); 242 | QFETCH( QByteArray, token ); 243 | QFETCH( QByteArray, tokenSecret ); 244 | QFETCH( QString, url ); 245 | QFETCH( int, httpMethod ); 246 | QFETCH( int, signMethod ); 247 | QFETCH( int, error ); 248 | QFETCH( QByteArray, accessToken ); 249 | QFETCH( QByteArray, accessTokenSecret ); 250 | 251 | m->setRequestTimeout( timeout ); 252 | m->setConsumerKey( key ); 253 | m->setConsumerSecret( secret ); 254 | ParamMap map = m->accessToken( url, (HttpMethod) httpMethod, token, tokenSecret, 255 | (SignatureMethod) signMethod ); 256 | 257 | if ( m->error() != QOAuth::Timeout ) { 258 | QVERIFY( m->error() == error ); 259 | } else { 260 | QWARN( "Request timeout" ); 261 | } 262 | 263 | //check the reply if request finished with no errors 264 | if ( m->error() == NoError ) { 265 | QCOMPARE( map.value( tokenParameterName() ), accessToken ); 266 | QCOMPARE( map.value( tokenSecretParameterName() ), accessTokenSecret ); 267 | } 268 | } 269 | 270 | 271 | void QOAuth::Ft_Interface::accessTokenRSA_data() 272 | { 273 | QTest::addColumn("timeout"); 274 | QTest::addColumn("key"); 275 | QTest::addColumn("secret"); 276 | QTest::addColumn("token"); 277 | QTest::addColumn("tokenSecret"); 278 | QTest::addColumn("rsaKeyFile"); 279 | QTest::addColumn("url"); 280 | QTest::addColumn("httpMethod"); 281 | QTest::addColumn("signMethod"); 282 | QTest::addColumn("error"); 283 | QTest::addColumn("accessToken"); 284 | QTest::addColumn("accessTokenSecret"); 285 | 286 | // OAuth test server at http://term.ie/oauth/example 287 | QTest::newRow("noError") << (uint) 10000 288 | << QByteArray( "key" ) 289 | << QByteArray( "secret" ) 290 | << QByteArray( "requestkey" ) 291 | << QByteArray( "requestsecret" ) 292 | << QString( "rsa-testkey.pem" ) 293 | << QString( "http://term.ie/oauth/example/access_token.php" ) 294 | << (int) GET 295 | << (int) RSA_SHA1 296 | << (int) NoError 297 | << QByteArray( "accesskey" ) 298 | << QByteArray( "accesssecret" ); 299 | 300 | } 301 | 302 | void QOAuth::Ft_Interface::accessTokenRSA() 303 | { 304 | QFETCH( uint, timeout ); 305 | QFETCH( QByteArray, key ); 306 | QFETCH( QByteArray, secret ); 307 | QFETCH( QByteArray, token ); 308 | QFETCH( QByteArray, tokenSecret ); 309 | QFETCH( QString, rsaKeyFile ); 310 | QFETCH( QString, url ); 311 | QFETCH( int, httpMethod ); 312 | QFETCH( int, signMethod ); 313 | QFETCH( int, error ); 314 | QFETCH( QByteArray, accessToken ); 315 | QFETCH( QByteArray, accessTokenSecret ); 316 | 317 | m->setRequestTimeout( timeout ); 318 | m->setConsumerKey( key ); 319 | m->setConsumerSecret( secret ); 320 | m->setRSAPrivateKeyFromFile( rsaKeyFile ); 321 | ParamMap map = m->accessToken( url, (HttpMethod) httpMethod, token, tokenSecret, 322 | (SignatureMethod) signMethod ); 323 | 324 | if ( m->error() != QOAuth::Timeout ) { 325 | QVERIFY( m->error() == error ); 326 | } else { 327 | QWARN( "Request timeout" ); 328 | } 329 | 330 | //check the reply if request finished with no errors 331 | if ( m->error() == NoError ) { 332 | QCOMPARE( map.value( tokenParameterName() ), accessToken ); 333 | QCOMPARE( map.value( tokenSecretParameterName() ), accessTokenSecret ); 334 | } 335 | } 336 | 337 | 338 | void QOAuth::Ft_Interface::accessResources_data() 339 | { 340 | QTest::addColumn("key"); 341 | QTest::addColumn("secret"); 342 | QTest::addColumn("token"); 343 | QTest::addColumn("tokenSecret"); 344 | QTest::addColumn("url"); 345 | QTest::addColumn("httpMethod"); 346 | QTest::addColumn("signMethod"); 347 | QTest::addColumn("param1"); 348 | QTest::addColumn("value1"); 349 | QTest::addColumn("param2"); 350 | QTest::addColumn("value2"); 351 | QTest::addColumn("param3"); 352 | QTest::addColumn("value3"); 353 | QTest::addColumn("parsingMode"); 354 | QTest::addColumn("error"); 355 | 356 | // OAuth test server at http://term.ie/oauth/example 357 | QTest::newRow("HMAC-SHA1") << QByteArray( "key" ) 358 | << QByteArray( "secret" ) 359 | << QByteArray( "accesskey" ) 360 | << QByteArray( "accesssecret" ) 361 | << QString( "http://term.ie/oauth/example/echo_api.php" ) 362 | << (int) GET 363 | << (int) HMAC_SHA1 364 | << QByteArray( "first" ) 365 | << QByteArray( "first" ) 366 | << QByteArray( "second" ) 367 | << QByteArray( "second" ) 368 | << QByteArray( "third" ) 369 | << QByteArray( "third" ) 370 | << (int) ParseForHeaderArguments 371 | << (int) NoError; 372 | 373 | // term.ie fails at creating PLAINTEXT signature :( 374 | /*QTest::newRow("PLAINTEXT") << QByteArray( "key" ) 375 | << QByteArray( "secret" ) 376 | << QByteArray( "accesskey" ) 377 | << QByteArray( "accesssecret" ) 378 | << QString( "http://term.ie/oauth/example/echo_api.php" ) 379 | << (int) GET 380 | << (int) PLAINTEXT 381 | << QByteArray( "first" ) 382 | << QByteArray( "first" ) 383 | << QByteArray( "second" ) 384 | << QByteArray( "second" ) 385 | << QByteArray( "third" ) 386 | << QByteArray( "third" ) 387 | << (int) ParseForHeaderArguments 388 | << (int) NoError;*/ 389 | } 390 | 391 | void QOAuth::Ft_Interface::accessResources() 392 | { 393 | QFETCH( QByteArray, key ); 394 | QFETCH( QByteArray, secret ); 395 | QFETCH( QByteArray, token ); 396 | QFETCH( QByteArray, tokenSecret ); 397 | QFETCH( QString, url ); 398 | QFETCH( int, httpMethod ); 399 | QFETCH( int, signMethod ); 400 | QFETCH( QByteArray, param1 ); 401 | QFETCH( QByteArray, value1 ); 402 | QFETCH( QByteArray, param2 ); 403 | QFETCH( QByteArray, value2 ); 404 | QFETCH( QByteArray, param3 ); 405 | QFETCH( QByteArray, value3 ); 406 | QFETCH( int, parsingMode ); 407 | QFETCH( int, error ); 408 | 409 | m->setConsumerKey( key ); 410 | m->setConsumerSecret( secret ); 411 | 412 | ParamMap map; 413 | map.insert( param1, value1 ); 414 | map.insert( param2, value2 ); 415 | map.insert( param3, value3 ); 416 | 417 | QByteArray parameters = m->createParametersString( url, (HttpMethod) httpMethod, token, tokenSecret, 418 | (SignatureMethod) signMethod, map, (ParsingMode) parsingMode ); 419 | 420 | url.append( m->inlineParameters( map, ParseForInlineQuery ) ); 421 | 422 | QNetworkAccessManager manager; 423 | MyEventLoop loop; 424 | 425 | connect( &manager, SIGNAL(finished(QNetworkReply*)), &loop, SLOT(quit()) ); 426 | QTimer::singleShot( 10000, &loop, SLOT(quitWithTimeout()) ); 427 | 428 | QNetworkRequest rq; 429 | rq.setUrl( QUrl( url ) ); 430 | rq.setRawHeader( "Authorization", parameters ); 431 | 432 | QNetworkReply *reply = manager.get( rq ); 433 | loop.exec(); 434 | 435 | if ( loop.timeout() ) { 436 | QWARN( "Request timeout" ); 437 | } else { 438 | ParamMap replyMap = m->d_ptr->replyToMap( reply->readAll() ); 439 | 440 | QCOMPARE( replyMap.value( param1 ), value1.toPercentEncoding() ); 441 | QCOMPARE( replyMap.value( param2 ), value2.toPercentEncoding() ); 442 | QCOMPARE( replyMap.value( param3 ), value3.toPercentEncoding() ); 443 | 444 | QVERIFY( m->error() == error ); 445 | } 446 | } 447 | 448 | void QOAuth::Ft_Interface::accessResourcesRSA_data() 449 | { 450 | QTest::addColumn("key"); 451 | QTest::addColumn("secret"); 452 | QTest::addColumn("token"); 453 | QTest::addColumn("tokenSecret"); 454 | QTest::addColumn("rsaKeyFile"); 455 | QTest::addColumn("url"); 456 | QTest::addColumn("httpMethod"); 457 | QTest::addColumn("signMethod"); 458 | QTest::addColumn("param1"); 459 | QTest::addColumn("value1"); 460 | QTest::addColumn("param2"); 461 | QTest::addColumn("value2"); 462 | QTest::addColumn("param3"); 463 | QTest::addColumn("value3"); 464 | QTest::addColumn("parsingMode"); 465 | QTest::addColumn("error"); 466 | 467 | // OAuth test server at http://term.ie/oauth/example 468 | QTest::newRow("noError") << QByteArray( "key" ) 469 | << QByteArray( "secret" ) 470 | << QByteArray( "accesskey" ) 471 | << QByteArray( "accesssecret" ) 472 | << QString( "rsa-testkey.pem" ) 473 | << QString( "http://term.ie/oauth/example/echo_api.php" ) 474 | << (int) GET 475 | << (int) RSA_SHA1 476 | << QByteArray( "first" ) 477 | << QByteArray( "first" ) 478 | << QByteArray( "second" ) 479 | << QByteArray( "second" ) 480 | << QByteArray( "third" ) 481 | << QByteArray( "third" ) 482 | << (int) ParseForHeaderArguments 483 | << (int) NoError; 484 | } 485 | 486 | void QOAuth::Ft_Interface::accessResourcesRSA() 487 | { 488 | QFETCH( QByteArray, key ); 489 | QFETCH( QByteArray, secret ); 490 | QFETCH( QByteArray, token ); 491 | QFETCH( QByteArray, tokenSecret ); 492 | QFETCH( QString, rsaKeyFile ); 493 | QFETCH( QString, url ); 494 | QFETCH( int, httpMethod ); 495 | QFETCH( int, signMethod ); 496 | QFETCH( QByteArray, param1 ); 497 | QFETCH( QByteArray, value1 ); 498 | QFETCH( QByteArray, param2 ); 499 | QFETCH( QByteArray, value2 ); 500 | QFETCH( QByteArray, param3 ); 501 | QFETCH( QByteArray, value3 ); 502 | QFETCH( int, parsingMode ); 503 | QFETCH( int, error ); 504 | 505 | m->setConsumerKey( key ); 506 | m->setConsumerSecret( secret ); 507 | m->setRSAPrivateKeyFromFile( rsaKeyFile ); 508 | 509 | ParamMap map; 510 | map.insert( param1, value1 ); 511 | map.insert( param2, value2 ); 512 | map.insert( param3, value3 ); 513 | 514 | QByteArray parameters = m->createParametersString( url, (HttpMethod) httpMethod, token, tokenSecret, 515 | (SignatureMethod) signMethod, map, (ParsingMode) parsingMode ); 516 | 517 | url.append( m->inlineParameters( map, ParseForInlineQuery ) ); 518 | 519 | QNetworkAccessManager manager; 520 | MyEventLoop loop; 521 | 522 | connect( &manager, SIGNAL(finished(QNetworkReply*)), &loop, SLOT(quit()) ); 523 | QTimer::singleShot( 10000, &loop, SLOT(quitWithTimeout()) ); 524 | 525 | QNetworkRequest rq; 526 | rq.setUrl( QUrl( url ) ); 527 | rq.setRawHeader( "Authorization", parameters ); 528 | 529 | QNetworkReply *reply = manager.get( rq ); 530 | loop.exec(); 531 | 532 | if ( loop.timeout() ) { 533 | QWARN( "Request timeout" ); 534 | } else { 535 | ParamMap replyMap = m->d_ptr->replyToMap( reply->readAll() ); 536 | 537 | QCOMPARE( replyMap.value( param1 ), value1.toPercentEncoding() ); 538 | QCOMPARE( replyMap.value( param2 ), value2.toPercentEncoding() ); 539 | QCOMPARE( replyMap.value( param3 ), value3.toPercentEncoding() ); 540 | 541 | QVERIFY( m->error() == error ); 542 | } 543 | } 544 | 545 | 546 | QTEST_MAIN(QOAuth::Ft_Interface) 547 | -------------------------------------------------------------------------------- /tests/ft_interface/ft_interface.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2009 by Dominik Kapusta * 3 | * * 4 | * This library is free software; you can redistribute it and/or modify * 5 | * it under the terms of the GNU Lesser General Public License as * 6 | * published by the Free Software Foundation; either version 2.1 of * 7 | * the License, or (at your option) any later version. * 8 | * * 9 | * This library is distributed in the hope that it will be useful, * 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 12 | * Lesser General Public License for more details. * 13 | * * 14 | * You should have received a copy of the GNU Lesser General Public * 15 | * License along with this library; if not, write to * 16 | * the Free Software Foundation, Inc., * 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * 18 | ***************************************************************************/ 19 | 20 | 21 | #ifndef FT_INTERFACE_H 22 | #define FT_INTERFACE_H 23 | 24 | #include 25 | #include 26 | 27 | class MyEventLoop : public QEventLoop 28 | { 29 | Q_OBJECT 30 | public: 31 | bool timeout() const; 32 | int exec( ProcessEventsFlags flags = AllEvents ); 33 | public slots: 34 | void quitWithTimeout(); 35 | private: 36 | bool m_timeout; 37 | }; 38 | 39 | namespace QOAuth { 40 | 41 | class Interface; 42 | 43 | class Ft_Interface : public QObject 44 | { 45 | Q_OBJECT 46 | 47 | private Q_SLOTS: 48 | void init(); 49 | void cleanup(); 50 | 51 | void requestToken_data(); 52 | void requestToken(); 53 | 54 | void requestTokenRSA_data(); 55 | void requestTokenRSA(); 56 | 57 | void accessToken_data(); 58 | void accessToken(); 59 | 60 | void accessTokenRSA_data(); 61 | void accessTokenRSA(); 62 | 63 | void accessResources_data(); 64 | void accessResources(); 65 | 66 | void accessResourcesRSA_data(); 67 | void accessResourcesRSA(); 68 | 69 | private: 70 | Interface *m; 71 | }; 72 | 73 | } // namespace QOAuth 74 | 75 | #endif // FT_INTERFACE_H 76 | -------------------------------------------------------------------------------- /tests/ft_interface/ft_interface.pro: -------------------------------------------------------------------------------- 1 | TARGET = ft_interface 2 | TEMPLATE = app 3 | 4 | DEFINES += UNIT_TEST 5 | include(../../oauth.prf) 6 | 7 | QT += testlib network 8 | QT -= gui 9 | CONFIG += crypto 10 | 11 | macx { 12 | CONFIG -= app_bundle 13 | QMAKE_POST_LINK += install_name_tool -change qoauth.framework/Versions/1/qoauth \ 14 | ../../lib/qoauth.framework/Versions/1/qoauth $${TARGET} 15 | } 16 | else:unix { 17 | # the second argument (after colon) is for 18 | # being able to run make check from the root source directory 19 | QMAKE_LFLAGS += -Wl,-rpath,../../lib:lib 20 | LIBS += -L../../lib 21 | } 22 | 23 | CONFIG(debug, debug|release) { 24 | windows: TARGET = $$join(TARGET,,,d) 25 | mac: TARGET = $$join(TARGET,,,_debug) 26 | } 27 | 28 | INCLUDEPATH += . ../../src 29 | HEADERS += ft_interface.h 30 | SOURCES += ft_interface.cpp 31 | -------------------------------------------------------------------------------- /tests/ft_interface/rsa-testkey.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALRiMLAh9iimur8V 3 | A7qVvdqxevEuUkW4K+2KdMXmnQbG9Aa7k7eBjK1S+0LYmVjPKlJGNXHDGuy5Fw/d 4 | 7rjVJ0BLB+ubPK8iA/Tw3hLQgXMRRGRXXCn8ikfuQfjUS1uZSatdLB81mydBETlJ 5 | hI6GH4twrbDJCR2Bwy/XWXgqgGRzAgMBAAECgYBYWVtleUzavkbrPjy0T5FMou8H 6 | X9u2AC2ry8vD/l7cqedtwMPp9k7TubgNFo+NGvKsl2ynyprOZR1xjQ7WgrgVB+mm 7 | uScOM/5HVceFuGRDhYTCObE+y1kxRloNYXnx3ei1zbeYLPCHdhxRYW7T0qcynNmw 8 | rn05/KO2RLjgQNalsQJBANeA3Q4Nugqy4QBUCEC09SqylT2K9FrrItqL2QKc9v0Z 9 | zO2uwllCbg0dwpVuYPYXYvikNHHg+aCWF+VXsb9rpPsCQQDWR9TT4ORdzoj+Nccn 10 | qkMsDmzt0EfNaAOwHOmVJ2RVBspPcxt5iN4HI7HNeG6U5YsFBb+/GZbgfBT3kpNG 11 | WPTpAkBI+gFhjfJvRw38n3g/+UeAkwMI2TJQS4n8+hid0uus3/zOjDySH3XHCUno 12 | cn1xOJAyZODBo47E+67R4jV1/gzbAkEAklJaspRPXP877NssM5nAZMU0/O/NGCZ+ 13 | 3jPgDUno6WbJn5cqm8MqWhW1xGkImgRk+fkDBquiq4gPiT898jusgQJAd5Zrr6Q8 14 | AO/0isr/3aa6O6NLQxISLKcPDk2NOccAfS/xOtfOz4sJYM3+Bs4Io9+dZGSDCA54 15 | Lw03eHTNQghS0A== 16 | -----END PRIVATE KEY----- 17 | -------------------------------------------------------------------------------- /tests/tests.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = subdirs 2 | SUBDIRS += ut_interface ft_interface 3 | -------------------------------------------------------------------------------- /tests/ut_interface/empty.file: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ayoy/qoauth/4b01e9fa5198f9e175f5e8e19868b32101f22b98/tests/ut_interface/empty.file -------------------------------------------------------------------------------- /tests/ut_interface/rsa-clean.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALRiMLAh9iimur8V 3 | A7qVvdqxevEuUkW4K+2KdMXmnQbG9Aa7k7eBjK1S+0LYmVjPKlJGNXHDGuy5Fw/d 4 | 7rjVJ0BLB+ubPK8iA/Tw3hLQgXMRRGRXXCn8ikfuQfjUS1uZSatdLB81mydBETlJ 5 | hI6GH4twrbDJCR2Bwy/XWXgqgGRzAgMBAAECgYBYWVtleUzavkbrPjy0T5FMou8H 6 | X9u2AC2ry8vD/l7cqedtwMPp9k7TubgNFo+NGvKsl2ynyprOZR1xjQ7WgrgVB+mm 7 | uScOM/5HVceFuGRDhYTCObE+y1kxRloNYXnx3ei1zbeYLPCHdhxRYW7T0qcynNmw 8 | rn05/KO2RLjgQNalsQJBANeA3Q4Nugqy4QBUCEC09SqylT2K9FrrItqL2QKc9v0Z 9 | zO2uwllCbg0dwpVuYPYXYvikNHHg+aCWF+VXsb9rpPsCQQDWR9TT4ORdzoj+Nccn 10 | qkMsDmzt0EfNaAOwHOmVJ2RVBspPcxt5iN4HI7HNeG6U5YsFBb+/GZbgfBT3kpNG 11 | WPTpAkBI+gFhjfJvRw38n3g/+UeAkwMI2TJQS4n8+hid0uus3/zOjDySH3XHCUno 12 | cn1xOJAyZODBo47E+67R4jV1/gzbAkEAklJaspRPXP877NssM5nAZMU0/O/NGCZ+ 13 | 3jPgDUno6WbJn5cqm8MqWhW1xGkImgRk+fkDBquiq4gPiT898jusgQJAd5Zrr6Q8 14 | AO/0isr/3aa6O6NLQxISLKcPDk2NOccAfS/xOtfOz4sJYM3+Bs4Io9+dZGSDCA54 15 | Lw03eHTNQghS0A== 16 | -----END PRIVATE KEY----- 17 | -------------------------------------------------------------------------------- /tests/ut_interface/rsa-pass.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | Proc-Type: 4,ENCRYPTED 3 | DEK-Info: DES-EDE3-CBC,7DF93A44614B772F 4 | 5 | BZZ86A/F4X3Io3IZ8SRIVQnE6WA8I8+c4ivy4Hnqb7G1yHGOYdGS2YadpCyp5r1S 6 | /M6tTDND/+ROxVK4eEqvo6kJJ5DzmGM8hOUP7U/YirSCapHDBpcuvFCbWhZDooK4 7 | FnNCbxPYe/+06bnLtsp4o/5gqYtdtfJj9mFjHotTLy5oyc4rH89YbXxPIrVpkl+6 8 | U7CD5q0AueuZo1CYb+FsG+SuUaXxcCnLsbzbschnsGFmM7J9Xc4N7jbUeJevd223 9 | +2BJvghoi+7fxONbZy/uMhoiyXj68vuO6LHfE8njXNigL0hJD61Zn++DoQiAkUsf 10 | MXD9xAcGP3xsQXaknSZVF3581qM1liubrde62f2jBIT+AhT3mgyzBOVlG8lGXOBm 11 | m+N53D9EjkXuKUhZzL54YJJqxIyqwGWCZI96YH7AxyXNPEvFLSw6aPSrky0MBSds 12 | XXO4KAKfIp5ey6CwABO4PHbpC2eoTlmpGAJpdAxv8NtEv6MKip/uSdr4PmKG6u79 13 | E/T/MygeJzgSHotgFlH8PliEqHrriHRrUomDSDKlsVeMG5425XWW2g8cuvYTQyZ8 14 | 7ss59uMFvcmlDmRqJh2ATzOqeKoEFbPdrWdhdI/w/ZEWH6BD9yDTAjP4IX6IyTl5 15 | Jaca9ZkBt/sT6zbroltlNXWOZOYq62eZNpebpg65RwQ6JNg54L38PWqQYtmpWSB1 16 | qNghu7IkgHkXUei8V1sh30KHl414xyA/8zriZZyfsF4V3uIi6p+3x6m6ECAZ5Z5O 17 | DpP+7R1b+5G3CiLXJCmMOPOxj0OtPdmlnpgN1/hKnXa3alC0llWZX+UPidAmVPHO 18 | v84tL03fDdR6cCtf1gQrb6VAgspwQV/6VeqBXeXC4VacBtqirKBQnoq0pfxOnjAr 19 | rUdMXFEjDslmux9qKf3W37bUHkLfgwMyGiUBbJbQxiCg009NZ/AND/MRcCQsU6WI 20 | WTCVaQ3aRT2BifRwGw1GDI0hm/T6ar4lHcGzDAbhEaR9fCSOMxfYZP+P4MqqymEF 21 | svhI3+93zNhVtWKa1mnhfkTHm2/H6hONSxPlJtPPjxAYghrUZWJ5liDIptANnyvX 22 | Cv/2RTIs22lihEeHVX8EKv+E90P14XbWv6pPagbFtZBfUD6wujKnOGT92UdDWEw6 23 | 3FHRfN7V6Yizq6pvl6B1wZbmor7npe1Q5jIVhyUGW7n4W0RMUjdFpQt5d4EWnBw6 24 | GIWn1wAB3OZ6q+pZQd85KmakqeuyBrtqY6GwPb+lfuGS7A6G5J/EJ/c6sQISVI5w 25 | XsDvqc4nGvS7rj9IFD6s+uFlb+G23PMVILxWEO+on5oV5PCy8CQIcvHYddQjYvYD 26 | dFen9Ey1YworxZfaY8UjYECrFj3Z4dJaeNo5sUZUELoTZMNoLNkWjWudbt29J90l 27 | sHFQWp7M99mms1ebVjVjeCo8HM1vAriScZCwqGH6n9e5Uplc4gSCA+m9Y17Z/1lY 28 | c3mv8qafdh0gCUyjdQX3YIYHG60smgpwl+HeyPO3Bg3p8KYpNfrBh4PC1C/jsP6s 29 | K4iLPS0/0CBmXhYQF1v2zqMdjpdRyIoceb8wn4ExD19Ei2Z1uFn/fw== 30 | -----END RSA PRIVATE KEY----- 31 | -------------------------------------------------------------------------------- /tests/ut_interface/test.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEoQIBAAKCAQEAurSTMsnYfzJYLmCgeNjmxOHgbW5eSB/i6iwKQ4Mxdsvj/8+c 3 | xUUNLWhAPQW/9Waqk6tzvPDuaAUv+mcVIAMkpv+n8w7xDZHXGzeBCLbBryyUijrO 4 | sdRsjIhFI3dzsh+YPDYqjvUbWH5O7b/GhOzXMeIEkLpNn7GN+ayVNIz4DOnaVuyo 5 | N4wqNwvs7qXcQantYkhqcEw1QAdQ8yTabF1AQDCN4mh9o4e3SY1SbKZ/yXZXgQNC 6 | Vwhix/5BriyPyIhdCrn4EU1aUMogIesnUwniuYd1OdodZPYq8mzz7l8o+Nt86QNz 7 | COksTvyEg+r/gBxjlqMm490Vm8MiL38yWn/fCwIBIwKCAQB1W4+5hjBP88JmS12N 8 | yiqno+wnhzPy0jbcVjJWUnbc9TA6ZT34V0ociqwJGY6aQIh6E/+bVZ0rcPmWFOi1 9 | CUo9FboGfmuiISgfvHz+KbuSrk69SYk8lCb5P7ZuEJHdrXWiMK0JZt39HDGcwa/7 10 | yBI8nLJpma0ijNzmFLWOvwJRQXZmIQCitLD32Bm4s77d7U1e+2HyI+Iecu+6ddg2 11 | MJsHGNd6LiV0gFPMKGX44Xo7eX49c9MIRSsOZAUTMOBIQmfqPCo7B9+6hHglR9bh 12 | /ISrkjcyvxRhAxVKKLOHutE3+8rU6+pyQVOaqX6dcQA8PxrlPPGEhIPUBgyG0Fpl 13 | GZ9rAoGBANs/Mc3pj6vAiG4izribedPRNpiHNq9TWqHX7CNDff8wDiFcGvkK+PsJ 14 | bYc+4DPuluYhKFjoHuoeWHScKo30ybOG+vY9dBqsGyVBJUmGmuHbN3DpIYocrgOZ 15 | QqQx1riplKQcugDM9tmZSSg1cHlctCA1n4F9jlSW7RYJRoP+x5c5AoGBANoA43CQ 16 | 9E2mZeGDFkVzqu/uU1j/IkEZUuvm8ZleTBvh70RD7NSlCGV7U+Mh0/IfKctydBmz 17 | NZzkNTlcND/sbEoDdpAY2Fu2Ig0xGWUH0aIqcwmXQsRQ2oV6dTIex/Tqk1vt6WX6 18 | imT51EFrRr/yGyQ6IrDNqnrttSbEG8F1D4RjAoGBAMh0SsrkK5W3WCouc9v73Rlu 19 | 0tSY4Ypa1oVXs1Nw6DnFiUMSYc3A46Ow2SsyLBI5OYHybggkrozoi2NM87T9EC8c 20 | UypG0I1qJ3KEtGB7EUOGmRbGhRCPQANKS47Oeyx9ybqd6+N5kTv53HyIoVkETOo/ 21 | p8bZMaxsu4HcmD4qxRyLAoGAdlhA8/brBZTYOJeeYDd6DTg739r1VooXEljMS/Fc 22 | hCoxbjOAkLFcVFjkZVuBr1K+6skadFn4iF6gjNpIP/VfW2D3OEgAbEzt6ed0L4fm 23 | 1GAv0gGn5uoQOdTDRxgGJd5tQIh3Yz7dagP24a9DqgcWDFoS1QHu1QSyy+bNPSJK 24 | QI0CgYARVyFgmt7GVMgxxDJjBG7nU5+MOzIRkVwYn5H/wbU/Y6R8NaIHtz7oOHiF 25 | NedW2z8NhD9QV9mvkhfdAccA4/il62anvKM4UI/HaD4Y0Vd7Bp2A9fy8HhC5yapb 26 | rMTWBhBzTuVfb3r/IVPp0+MVasJGL4Bda2AlKfHM+0Tn5655wg== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /tests/ut_interface/ut_interface.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2009 by Dominik Kapusta * 3 | * * 4 | * This library is free software; you can redistribute it and/or modify * 5 | * it under the terms of the GNU Lesser General Public License as * 6 | * published by the Free Software Foundation; either version 2.1 of * 7 | * the License, or (at your option) any later version. * 8 | * * 9 | * This library is distributed in the hope that it will be useful, * 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 12 | * Lesser General Public License for more details. * 13 | * * 14 | * You should have received a copy of the GNU Lesser General Public * 15 | * License along with this library; if not, write to * 16 | * the Free Software Foundation, Inc., * 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * 18 | ***************************************************************************/ 19 | 20 | 21 | #include "ut_interface.h" 22 | 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | 29 | 30 | void QOAuth::Ut_Interface::init() 31 | { 32 | m = new Interface; 33 | } 34 | 35 | void QOAuth::Ut_Interface::cleanup() 36 | { 37 | delete m; 38 | } 39 | 40 | void QOAuth::Ut_Interface::constructor() 41 | { 42 | QVERIFY( m ); 43 | QVERIFY( m->consumerKey().isEmpty() ); 44 | QVERIFY( m->consumerSecret().isEmpty() ); 45 | QVERIFY( m->error() == NoError ); 46 | QVERIFY( m->requestTimeout() == 0 ); 47 | QVERIFY( m->d_ptr ); 48 | } 49 | 50 | void QOAuth::Ut_Interface::consumerKey() 51 | { 52 | QByteArray consumerKey( "6d65216f4272d0d3932cdcf8951997c2" ); 53 | 54 | m->d_ptr->consumerKey = consumerKey; 55 | QCOMPARE( m->consumerKey(), consumerKey ); 56 | } 57 | 58 | void QOAuth::Ut_Interface::setConsumerKey() 59 | { 60 | QByteArray consumerKey( "6d65216f4272d0d3932cdcf8951997c2" ); 61 | 62 | m->setConsumerKey( consumerKey ); 63 | QCOMPARE( m->d_ptr->consumerKey, consumerKey ); 64 | } 65 | 66 | void QOAuth::Ut_Interface::consumerSecret() 67 | { 68 | QByteArray consumerSecret( "5af4e09d887c4969211ba40e9dd8f873" ); 69 | 70 | m->d_ptr->consumerSecret = consumerSecret; 71 | QCOMPARE( m->consumerSecret(), consumerSecret ); 72 | } 73 | 74 | void QOAuth::Ut_Interface::setConsumerSecret() 75 | { 76 | QByteArray consumerSecret( "5af4e09d887c4969211ba40e9dd8f873" ); 77 | 78 | m->setConsumerSecret( consumerSecret ); 79 | QCOMPARE( m->d_ptr->consumerSecret, consumerSecret ); 80 | } 81 | 82 | void QOAuth::Ut_Interface::requestTimeout() 83 | { 84 | uint timeout = 13986754; 85 | 86 | m->d_ptr->requestTimeout = timeout; 87 | QVERIFY( m->requestTimeout() == timeout ); 88 | } 89 | 90 | void QOAuth::Ut_Interface::setRequestTimeout() 91 | { 92 | uint timeout = 13986754; 93 | 94 | m->setRequestTimeout( timeout ); 95 | QVERIFY( m->d_ptr->requestTimeout == timeout ); 96 | } 97 | 98 | void QOAuth::Ut_Interface::error() 99 | { 100 | m->d_ptr->error = Forbidden; 101 | QVERIFY( m->error() == Forbidden ); 102 | } 103 | 104 | void QOAuth::Ut_Interface::requestToken_data() 105 | { 106 | QTest::addColumn("timeout"); 107 | QTest::addColumn("key"); 108 | QTest::addColumn("secret"); 109 | QTest::addColumn("url"); 110 | QTest::addColumn("httpMethod"); 111 | QTest::addColumn("signMethod"); 112 | QTest::addColumn("error"); 113 | QTest::addColumn("requestToken"); 114 | QTest::addColumn("requestTokenSecret"); 115 | 116 | 117 | QTest::newRow("key empty") << (uint) 0 118 | << QByteArray() 119 | << QByteArray( "135432" ) 120 | << QString( "http://wtf&(^%)$&#.com" ) 121 | << (int) GET 122 | << (int) HMAC_SHA1 123 | << (int) ConsumerKeyEmpty 124 | << QByteArray() 125 | << QByteArray(); 126 | 127 | 128 | QTest::newRow("secret empty") << (uint) 0 129 | << QByteArray( "135432" ) 130 | << QByteArray() 131 | << QString( "http://wtf&(^%)$&#.com" ) 132 | << (int) GET 133 | << (int) HMAC_SHA1 134 | << (int) ConsumerSecretEmpty 135 | << QByteArray() 136 | << QByteArray(); 137 | 138 | QTest::newRow("httpMethod") << (uint) 0 139 | << QByteArray( "135432" ) 140 | << QByteArray( "654316" ) 141 | << QString( "http://wtf&(^%)$&#.com" ) 142 | << (int) PUT 143 | << (int) HMAC_SHA1 144 | << (int) UnsupportedHttpMethod 145 | << QByteArray() 146 | << QByteArray(); 147 | 148 | // timeout seems to be untestable for a moment 149 | // QTest::newRow("timeout") << (uint) 100 150 | // << QByteArray( "key" ) 151 | // << QByteArray( "secret" ) 152 | // << QString( "http://term.ie/oauth/example/request_token.php" ) 153 | // << (int) QOAuth::GET 154 | // << (int) QOAuth::HMAC_SHA1 155 | // << (int) QOAuth::Timeout 156 | // << QByteArray() 157 | // << QByteArray(); 158 | 159 | } 160 | 161 | void QOAuth::Ut_Interface::requestToken() 162 | { 163 | QFETCH( uint, timeout ); 164 | QFETCH( QByteArray, key ); 165 | QFETCH( QByteArray, secret ); 166 | QFETCH( QString, url ); 167 | QFETCH( int, httpMethod ); 168 | QFETCH( int, signMethod ); 169 | QFETCH( int, error ); 170 | QFETCH( QByteArray, requestToken ); 171 | QFETCH( QByteArray, requestTokenSecret ); 172 | 173 | m->setRequestTimeout( timeout ); 174 | m->setConsumerKey( key ); 175 | m->setConsumerSecret( secret ); 176 | ParamMap map = m->requestToken( url, (HttpMethod) httpMethod, (SignatureMethod) signMethod ); 177 | 178 | QVERIFY( m->error() == error ); 179 | 180 | //check the reply if request finished with no errors 181 | if ( m->error() == NoError ) { 182 | QCOMPARE( map.value( tokenParameterName() ), requestToken ); 183 | QCOMPARE( map.value( tokenSecretParameterName() ), requestTokenSecret ); 184 | } 185 | } 186 | 187 | void QOAuth::Ut_Interface::accessToken_data() 188 | { 189 | QTest::addColumn("timeout"); 190 | QTest::addColumn("key"); 191 | QTest::addColumn("secret"); 192 | QTest::addColumn("token"); 193 | QTest::addColumn("tokenSecret"); 194 | QTest::addColumn("url"); 195 | QTest::addColumn("httpMethod"); 196 | QTest::addColumn("signMethod"); 197 | QTest::addColumn("error"); 198 | QTest::addColumn("accessToken"); 199 | QTest::addColumn("accessTokenSecret"); 200 | 201 | QTest::newRow("key empty") << (uint) 0 202 | << QByteArray() 203 | << QByteArray( "135432" ) 204 | << QByteArray( "token" ) 205 | << QByteArray( "tokensecret" ) 206 | << QString( "http://wtf&(^%)$&#.com" ) 207 | << (int) GET 208 | << (int) HMAC_SHA1 209 | << (int) ConsumerKeyEmpty 210 | << QByteArray() 211 | << QByteArray(); 212 | 213 | 214 | QTest::newRow("secret empty") << (uint) 0 215 | << QByteArray( "135432" ) 216 | << QByteArray() 217 | << QByteArray( "token" ) 218 | << QByteArray( "tokensecret" ) 219 | << QString( "http://wtf&(^%)$&#.com" ) 220 | << (int) GET 221 | << (int) HMAC_SHA1 222 | << (int) ConsumerSecretEmpty 223 | << QByteArray() 224 | << QByteArray(); 225 | 226 | QTest::newRow("httpMethod") << (uint) 0 227 | << QByteArray( "135432" ) 228 | << QByteArray( "654316" ) 229 | << QByteArray( "token" ) 230 | << QByteArray( "tokensecret" ) 231 | << QString( "http://wtf&(^%)$&#.com" ) 232 | << (int) PUT 233 | << (int) HMAC_SHA1 234 | << (int) UnsupportedHttpMethod 235 | << QByteArray() 236 | << QByteArray(); 237 | } 238 | 239 | void QOAuth::Ut_Interface::accessToken() 240 | { 241 | QFETCH( uint, timeout ); 242 | QFETCH( QByteArray, key ); 243 | QFETCH( QByteArray, secret ); 244 | QFETCH( QByteArray, token ); 245 | QFETCH( QByteArray, tokenSecret ); 246 | QFETCH( QString, url ); 247 | QFETCH( int, httpMethod ); 248 | QFETCH( int, signMethod ); 249 | QFETCH( int, error ); 250 | QFETCH( QByteArray, accessToken ); 251 | QFETCH( QByteArray, accessTokenSecret ); 252 | 253 | m->setRequestTimeout( timeout ); 254 | m->setConsumerKey( key ); 255 | m->setConsumerSecret( secret ); 256 | ParamMap map = m->accessToken( url, (HttpMethod) httpMethod, token, tokenSecret, 257 | (SignatureMethod) signMethod ); 258 | 259 | QVERIFY( m->error() == error ); 260 | 261 | //check the reply if request finished with no errors 262 | if ( m->error() == NoError ) { 263 | QCOMPARE( map.value( tokenParameterName() ), accessToken ); 264 | QCOMPARE( map.value( tokenSecretParameterName() ), accessTokenSecret ); 265 | } 266 | } 267 | 268 | void QOAuth::Ut_Interface::createParametersString_data() 269 | { 270 | QTest::addColumn("timeout"); 271 | QTest::addColumn("key"); 272 | QTest::addColumn("secret"); 273 | QTest::addColumn("token"); 274 | QTest::addColumn("tokenSecret"); 275 | QTest::addColumn("url"); 276 | QTest::addColumn("httpMethod"); 277 | QTest::addColumn("signMethod"); 278 | QTest::addColumn("param1"); 279 | QTest::addColumn("value1"); 280 | QTest::addColumn("param2"); 281 | QTest::addColumn("value2"); 282 | QTest::addColumn("param3"); 283 | QTest::addColumn("value3"); 284 | QTest::addColumn("parsingMode"); 285 | QTest::addColumn("error"); 286 | 287 | QTest::newRow("key empty") << (uint) 0 288 | << QByteArray() 289 | << QByteArray( "135432" ) 290 | << QByteArray( "token" ) 291 | << QByteArray( "tokensecret" ) 292 | << QString( "http://wtf&(^%)$&#.com" ) 293 | << (int) GET 294 | << (int) HMAC_SHA1 295 | << QByteArray() 296 | << QByteArray() 297 | << QByteArray() 298 | << QByteArray() 299 | << QByteArray() 300 | << QByteArray() 301 | << (int) ParseForInlineQuery 302 | << (int) ConsumerKeyEmpty; 303 | 304 | 305 | QTest::newRow("secret empty") << (uint) 0 306 | << QByteArray( "135432" ) 307 | << QByteArray() 308 | << QByteArray( "token" ) 309 | << QByteArray( "tokensecret" ) 310 | << QString( "http://wtf&(^%)$&#.com" ) 311 | << (int) GET 312 | << (int) HMAC_SHA1 313 | << QByteArray() 314 | << QByteArray() 315 | << QByteArray() 316 | << QByteArray() 317 | << QByteArray() 318 | << QByteArray() 319 | << (int) ParseForInlineQuery 320 | << (int) ConsumerSecretEmpty; 321 | } 322 | 323 | void QOAuth::Ut_Interface::createParametersString() 324 | { 325 | QFETCH( uint, timeout ); 326 | QFETCH( QByteArray, key ); 327 | QFETCH( QByteArray, secret ); 328 | QFETCH( QByteArray, token ); 329 | QFETCH( QByteArray, tokenSecret ); 330 | QFETCH( QString, url ); 331 | QFETCH( int, httpMethod ); 332 | QFETCH( int, signMethod ); 333 | QFETCH( QByteArray, param1 ); 334 | QFETCH( QByteArray, value1 ); 335 | QFETCH( QByteArray, param2 ); 336 | QFETCH( QByteArray, value2 ); 337 | QFETCH( QByteArray, param3 ); 338 | QFETCH( QByteArray, value3 ); 339 | QFETCH( int, parsingMode ); 340 | QFETCH( int, error ); 341 | 342 | m->setRequestTimeout( timeout ); 343 | m->setConsumerKey( key ); 344 | m->setConsumerSecret( secret ); 345 | ParamMap map; 346 | map.insert( param1, value1 ); 347 | map.insert( param2, value2 ); 348 | map.insert( param3, value3 ); 349 | QByteArray parameters = m->createParametersString( url, (HttpMethod) httpMethod, token, tokenSecret, 350 | (SignatureMethod) signMethod, map, (ParsingMode) parsingMode ); 351 | 352 | QVERIFY( m->error() == error ); 353 | } 354 | 355 | void QOAuth::Ut_Interface::inlineParameters_data() 356 | { 357 | QTest::addColumn("par1"); 358 | QTest::addColumn("val1"); 359 | QTest::addColumn("par2"); 360 | QTest::addColumn("val2"); 361 | QTest::addColumn("par3"); 362 | QTest::addColumn("val3"); 363 | QTest::addColumn("mode"); 364 | QTest::addColumn("result"); 365 | 366 | QTest::newRow("empty") << QByteArray() 367 | << QByteArray() 368 | << QByteArray() 369 | << QByteArray() 370 | << QByteArray() 371 | << QByteArray() 372 | << (int) ParseForInlineQuery 373 | << QByteArray( "?=&=&=" ); 374 | 375 | QTest::newRow("easy") << QByteArray( "one" ) 376 | << QByteArray( "two" ) 377 | << QByteArray( "three" ) 378 | << QByteArray( "four" ) 379 | << QByteArray( "six" ) 380 | << QByteArray( "ten" ) 381 | << (int) ParseForRequestContent 382 | << QByteArray( "one=two&six=ten&three=four" ); 383 | 384 | QTest::newRow("tricky") << QByteArray( "arg1" ) 385 | << QByteArray( "%%**_+%%" ) 386 | << QByteArray( "arg2" ) 387 | << QByteArray() 388 | << QByteArray( "arg2" ) 389 | << QByteArray( "&+=" ) 390 | << (int) ParseForInlineQuery 391 | << QByteArray( "?arg1=%%**_+%%&arg2=&arg2=&+=" ); 392 | 393 | QTest::newRow("wrong mode") << QByteArray( "arg1" ) 394 | << QByteArray( "%%**_+%%" ) 395 | << QByteArray( "arg2" ) 396 | << QByteArray() 397 | << QByteArray( "arg2" ) 398 | << QByteArray( "&+=" ) 399 | << (int) ParseForHeaderArguments 400 | << QByteArray( "" ); 401 | 402 | } 403 | 404 | void QOAuth::Ut_Interface::inlineParameters() 405 | { 406 | QFETCH( QByteArray, par1 ); 407 | QFETCH( QByteArray, val1 ); 408 | QFETCH( QByteArray, par2 ); 409 | QFETCH( QByteArray, val2 ); 410 | QFETCH( QByteArray, par3 ); 411 | QFETCH( QByteArray, val3 ); 412 | QFETCH( int, mode ); 413 | QFETCH( QByteArray, result ); 414 | 415 | ParamMap map; 416 | 417 | map.insert( par1, val1 ); 418 | map.insert( par2, val2 ); 419 | map.insert( par3, val3 ); 420 | 421 | QByteArray query = m->inlineParameters( map, (ParsingMode) mode ); 422 | 423 | QCOMPARE( query, result ); 424 | } 425 | 426 | void QOAuth::Ut_Interface::setRSAPrivateKey_data() 427 | { 428 | QTest::addColumn("key"); 429 | QTest::addColumn("passphrase"); 430 | QTest::addColumn("error"); 431 | 432 | QTest::newRow("clean") << 433 | "-----BEGIN PRIVATE KEY-----\n" 434 | "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALRiMLAh9iimur8V\n" 435 | "A7qVvdqxevEuUkW4K+2KdMXmnQbG9Aa7k7eBjK1S+0LYmVjPKlJGNXHDGuy5Fw/d\n" 436 | "7rjVJ0BLB+ubPK8iA/Tw3hLQgXMRRGRXXCn8ikfuQfjUS1uZSatdLB81mydBETlJ\n" 437 | "hI6GH4twrbDJCR2Bwy/XWXgqgGRzAgMBAAECgYBYWVtleUzavkbrPjy0T5FMou8H\n" 438 | "X9u2AC2ry8vD/l7cqedtwMPp9k7TubgNFo+NGvKsl2ynyprOZR1xjQ7WgrgVB+mm\n" 439 | "uScOM/5HVceFuGRDhYTCObE+y1kxRloNYXnx3ei1zbeYLPCHdhxRYW7T0qcynNmw\n" 440 | "rn05/KO2RLjgQNalsQJBANeA3Q4Nugqy4QBUCEC09SqylT2K9FrrItqL2QKc9v0Z\n" 441 | "zO2uwllCbg0dwpVuYPYXYvikNHHg+aCWF+VXsb9rpPsCQQDWR9TT4ORdzoj+Nccn\n" 442 | "qkMsDmzt0EfNaAOwHOmVJ2RVBspPcxt5iN4HI7HNeG6U5YsFBb+/GZbgfBT3kpNG\n" 443 | "WPTpAkBI+gFhjfJvRw38n3g/+UeAkwMI2TJQS4n8+hid0uus3/zOjDySH3XHCUno\n" 444 | "cn1xOJAyZODBo47E+67R4jV1/gzbAkEAklJaspRPXP877NssM5nAZMU0/O/NGCZ+\n" 445 | "3jPgDUno6WbJn5cqm8MqWhW1xGkImgRk+fkDBquiq4gPiT898jusgQJAd5Zrr6Q8\n" 446 | "AO/0isr/3aa6O6NLQxISLKcPDk2NOccAfS/xOtfOz4sJYM3+Bs4Io9+dZGSDCA54\n" 447 | "Lw03eHTNQghS0A==\n" 448 | "-----END PRIVATE KEY-----" << QByteArray() << (int) NoError; 449 | 450 | QTest::newRow("protected") << 451 | "-----BEGIN RSA PRIVATE KEY-----\n" 452 | "Proc-Type: 4,ENCRYPTED\n" 453 | "DEK-Info: DES-EDE3-CBC,7DF93A44614B772F\n" 454 | "\n" 455 | "BZZ86A/F4X3Io3IZ8SRIVQnE6WA8I8+c4ivy4Hnqb7G1yHGOYdGS2YadpCyp5r1S\n" 456 | "/M6tTDND/+ROxVK4eEqvo6kJJ5DzmGM8hOUP7U/YirSCapHDBpcuvFCbWhZDooK4\n" 457 | "FnNCbxPYe/+06bnLtsp4o/5gqYtdtfJj9mFjHotTLy5oyc4rH89YbXxPIrVpkl+6\n" 458 | "U7CD5q0AueuZo1CYb+FsG+SuUaXxcCnLsbzbschnsGFmM7J9Xc4N7jbUeJevd223\n" 459 | "+2BJvghoi+7fxONbZy/uMhoiyXj68vuO6LHfE8njXNigL0hJD61Zn++DoQiAkUsf\n" 460 | "MXD9xAcGP3xsQXaknSZVF3581qM1liubrde62f2jBIT+AhT3mgyzBOVlG8lGXOBm\n" 461 | "m+N53D9EjkXuKUhZzL54YJJqxIyqwGWCZI96YH7AxyXNPEvFLSw6aPSrky0MBSds\n" 462 | "XXO4KAKfIp5ey6CwABO4PHbpC2eoTlmpGAJpdAxv8NtEv6MKip/uSdr4PmKG6u79\n" 463 | "E/T/MygeJzgSHotgFlH8PliEqHrriHRrUomDSDKlsVeMG5425XWW2g8cuvYTQyZ8\n" 464 | "7ss59uMFvcmlDmRqJh2ATzOqeKoEFbPdrWdhdI/w/ZEWH6BD9yDTAjP4IX6IyTl5\n" 465 | "Jaca9ZkBt/sT6zbroltlNXWOZOYq62eZNpebpg65RwQ6JNg54L38PWqQYtmpWSB1\n" 466 | "qNghu7IkgHkXUei8V1sh30KHl414xyA/8zriZZyfsF4V3uIi6p+3x6m6ECAZ5Z5O\n" 467 | "DpP+7R1b+5G3CiLXJCmMOPOxj0OtPdmlnpgN1/hKnXa3alC0llWZX+UPidAmVPHO\n" 468 | "v84tL03fDdR6cCtf1gQrb6VAgspwQV/6VeqBXeXC4VacBtqirKBQnoq0pfxOnjAr\n" 469 | "rUdMXFEjDslmux9qKf3W37bUHkLfgwMyGiUBbJbQxiCg009NZ/AND/MRcCQsU6WI\n" 470 | "WTCVaQ3aRT2BifRwGw1GDI0hm/T6ar4lHcGzDAbhEaR9fCSOMxfYZP+P4MqqymEF\n" 471 | "svhI3+93zNhVtWKa1mnhfkTHm2/H6hONSxPlJtPPjxAYghrUZWJ5liDIptANnyvX\n" 472 | "Cv/2RTIs22lihEeHVX8EKv+E90P14XbWv6pPagbFtZBfUD6wujKnOGT92UdDWEw6\n" 473 | "3FHRfN7V6Yizq6pvl6B1wZbmor7npe1Q5jIVhyUGW7n4W0RMUjdFpQt5d4EWnBw6\n" 474 | "GIWn1wAB3OZ6q+pZQd85KmakqeuyBrtqY6GwPb+lfuGS7A6G5J/EJ/c6sQISVI5w\n" 475 | "XsDvqc4nGvS7rj9IFD6s+uFlb+G23PMVILxWEO+on5oV5PCy8CQIcvHYddQjYvYD\n" 476 | "dFen9Ey1YworxZfaY8UjYECrFj3Z4dJaeNo5sUZUELoTZMNoLNkWjWudbt29J90l\n" 477 | "sHFQWp7M99mms1ebVjVjeCo8HM1vAriScZCwqGH6n9e5Uplc4gSCA+m9Y17Z/1lY\n" 478 | "c3mv8qafdh0gCUyjdQX3YIYHG60smgpwl+HeyPO3Bg3p8KYpNfrBh4PC1C/jsP6s\n" 479 | "K4iLPS0/0CBmXhYQF1v2zqMdjpdRyIoceb8wn4ExD19Ei2Z1uFn/fw==\n" 480 | "-----END RSA PRIVATE KEY-----" << QByteArray( "testpassphrase" ) << (int) NoError; 481 | 482 | QTest::newRow("empty key") << "" << QByteArray() << (int) RSADecodingError; 483 | 484 | } 485 | 486 | void QOAuth::Ut_Interface::setRSAPrivateKey() 487 | { 488 | QFETCH( QString, key ); 489 | QFETCH( QByteArray, passphrase ); 490 | QFETCH( int, error ); 491 | 492 | QCA::SecureArray sa( passphrase ); 493 | 494 | m->setRSAPrivateKey( key, sa ); 495 | QCOMPARE( m->error(), error ); 496 | } 497 | 498 | void QOAuth::Ut_Interface::setRSAPrivateKeyFromFile_data() 499 | { 500 | QTest::addColumn("file"); 501 | QTest::addColumn("passphrase"); 502 | QTest::addColumn("error"); 503 | 504 | QTest::newRow("correct") << "rsa-clean.pem" << QByteArray() << (int) NoError; 505 | QTest::newRow("also correct") << "test.pem" << QByteArray() << (int) NoError; 506 | QTest::newRow("protected") << "rsa-pass.pem" << QByteArray("testpassphrase") << (int) NoError; 507 | QTest::newRow("wrong pass") << "rsa-pass.pem" << QByteArray() << (int) RSADecodingError; 508 | QTest::newRow("empty file") << "empty.file" << QByteArray() << (int) RSADecodingError; 509 | QTest::newRow("no such file") << "nosuch.file" << QByteArray() << (int) RSAKeyFileError; 510 | 511 | } 512 | 513 | void QOAuth::Ut_Interface::setRSAPrivateKeyFromFile() 514 | { 515 | QFETCH( QString, file ); 516 | QFETCH( QByteArray, passphrase ); 517 | QFETCH( int, error ); 518 | 519 | QCA::SecureArray sa( passphrase ); 520 | 521 | m->setRSAPrivateKeyFromFile( file, sa ); 522 | QCOMPARE( m->error(), error ); 523 | } 524 | 525 | QTEST_MAIN(QOAuth::Ut_Interface) 526 | -------------------------------------------------------------------------------- /tests/ut_interface/ut_interface.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2009 by Dominik Kapusta * 3 | * * 4 | * This library is free software; you can redistribute it and/or modify * 5 | * it under the terms of the GNU Lesser General Public License as * 6 | * published by the Free Software Foundation; either version 2.1 of * 7 | * the License, or (at your option) any later version. * 8 | * * 9 | * This library is distributed in the hope that it will be useful, * 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 12 | * Lesser General Public License for more details. * 13 | * * 14 | * You should have received a copy of the GNU Lesser General Public * 15 | * License along with this library; if not, write to * 16 | * the Free Software Foundation, Inc., * 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * 18 | ***************************************************************************/ 19 | 20 | 21 | #ifndef UT_INTERFACE_H 22 | #define UT_INTERFACE_H 23 | 24 | #include 25 | 26 | #include 27 | 28 | namespace QOAuth { 29 | 30 | class Interface; 31 | 32 | class Ut_Interface : public QObject 33 | { 34 | Q_OBJECT 35 | 36 | private Q_SLOTS: 37 | void init(); 38 | void cleanup(); 39 | void constructor(); 40 | 41 | void consumerKey(); 42 | void setConsumerKey(); 43 | 44 | void consumerSecret(); 45 | void setConsumerSecret(); 46 | 47 | void requestTimeout(); 48 | void setRequestTimeout(); 49 | 50 | void error(); 51 | 52 | void requestToken_data(); 53 | void requestToken(); 54 | 55 | void accessToken_data(); 56 | void accessToken(); 57 | 58 | void createParametersString_data(); 59 | void createParametersString(); 60 | 61 | void inlineParameters_data(); 62 | void inlineParameters(); 63 | 64 | void setRSAPrivateKey_data(); 65 | void setRSAPrivateKey(); 66 | 67 | void setRSAPrivateKeyFromFile_data(); 68 | void setRSAPrivateKeyFromFile(); 69 | 70 | private: 71 | Interface *m; 72 | QCA::Initializer initializer; 73 | }; 74 | 75 | } // namespace QOAuth 76 | 77 | #endif // UT_INTERFACE_H 78 | -------------------------------------------------------------------------------- /tests/ut_interface/ut_interface.pro: -------------------------------------------------------------------------------- 1 | TARGET = ut_interface 2 | TEMPLATE = app 3 | 4 | DEFINES += UNIT_TEST 5 | include(../../oauth.prf) 6 | 7 | QT += testlib network 8 | QT -= gui 9 | CONFIG += crypto 10 | 11 | macx { 12 | CONFIG -= app_bundle 13 | QMAKE_POST_LINK += install_name_tool -change qoauth.framework/Versions/1/qoauth \ 14 | ../../lib/qoauth.framework/Versions/1/qoauth $${TARGET} 15 | } 16 | else:unix { 17 | # the second argument (after colon) is for 18 | # being able to run make check from the root source directory 19 | QMAKE_LFLAGS += -Wl,-rpath,../../lib:lib 20 | LIBS += -L../../lib 21 | } 22 | 23 | CONFIG(debug, debug|release) { 24 | windows: TARGET = $$join(TARGET,,,d) 25 | mac: TARGET = $$join(TARGET,,,_debug) 26 | } 27 | 28 | INCLUDEPATH += . ../../src 29 | HEADERS += ut_interface.h 30 | SOURCES += ut_interface.cpp 31 | --------------------------------------------------------------------------------