PageRenderTime 58ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/otp.php

http://otpauth.googlecode.com/
PHP | 744 lines | 173 code | 41 blank | 530 comment | 27 complexity | f160bd204cc9b6e408a3de89f72b9769 MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /* **************************************************************************************
  3. * FILE : otp.php
  4. * LAST UPDATED : July 2007 by james.barkley@gmail.com
  5. *
  6. * DESCRIPTION : Conains functions for generating and validating one-time passwords,
  7. * checksums, etc. This code is RFC 2289 (RFC2289) compliant.
  8. *
  9. * LICENSE : GPL
  10. *
  11. *
  12. ************************************************************************************** */
  13. require_once('alphanums.php');
  14. // require_once('iso-646.ivcs.clean.php');
  15. require_once('iso-646.ivcs.php');
  16. require_once('nutils.php');
  17. #require_once('io_interface.php'); /* this should contain i/o function */
  18. define ('__OTPSIZE', 50); /* size of otp lists produced */
  19. define ('__OTP_MD5', 1);
  20. define ('__OTP_SHA1', 2);
  21. define ('__OTP_SHA256', 3);
  22. define ('__OTP_HASH_FUNCTION', __OTP_SHA1);
  23. /* **************************************************************************************
  24. * FUNCTION : validate_otp
  25. * LAST UPDATED : February 2005
  26. * PARAMS :
  27. * $otp a six-word format OTP, typically from user input.
  28. *
  29. * DESCRIPTION : Checks to see if the input OTP is valid based on hash of previous.
  30. *
  31. ************************************************************************************** */
  32. function validate_otp($otp) {
  33. /* six word format */
  34. if (!is_array($otp)) {
  35. $otp = explode(' ', $otp);
  36. }
  37. $cur = ivcs_transform_from($otp);
  38. $last = __otp_hash(hash_wrapper($cur));
  39. $match = compare_last_otp($last);
  40. if (!$match) {
  41. return false;
  42. } else {
  43. return set_last_otp($cur);
  44. }
  45. return false;
  46. }
  47. /* **************************************************************************************
  48. * FUNCTION : generate_otp_list()
  49. * LAST UPDATED : February 2005
  50. * PARAMS : none
  51. *
  52. * DESCRIPTION : returns a six-word format list of N OTPs, and stores the first hash
  53. * in the database.
  54. *
  55. ************************************************************************************** */
  56. function generate_otp_list_and_store() {
  57. $S = simplifiedInitialStep();
  58. $otpList = computationStep($S, __OTPSIZE);
  59. $firstToBeUsed = $otpList[count($otpList)-1];
  60. $initialHash = __otp_hash(hash_wrapper($firstToBeUsed));
  61. // 1 indicates that the user should use OTP #1 for first access
  62. //store_hash(1, $initialHash);
  63. $otpList = array_reverse($otpList);
  64. // turn into six-word format so user
  65. // doesn't have to type a lengthy hex string
  66. //$otpSixWordList = convertToSixWordFormat($otpList);
  67. $otpSixWordList = ivcs_transform_array_to($otpList);
  68. return $otpSixWordList;
  69. }
  70. /* **************************************************************************************
  71. * FUNCTION : generate_otp_list()
  72. * LAST UPDATED : February 2005
  73. * PARAMS : none
  74. *
  75. * DESCRIPTION : returns a six-word format list of N OTPs, and stores the first hash
  76. * in the database.
  77. *
  78. ************************************************************************************** */
  79. function generate_otp_list() {
  80. $S = simplifiedInitialStep();
  81. $otpList = computationStep($S, __OTPSIZE);
  82. $firstToBeUsed = $otpList[count($otpList)-1];
  83. $initialHash = __otp_hash(hash_wrapper($firstToBeUsed));
  84. // 1 indicates that the user should use OTP #1 for first access
  85. //store_hash(1, $initialHash);
  86. $initial = array();
  87. $initial['sequence'] = 1;
  88. $initial['hash'] = $initialHash;
  89. $otpList = array_reverse($otpList);
  90. // turn into six-word format so user
  91. // doesn't have to type a lengthy hex string
  92. $retval['initial'] = $initial;
  93. $retval['list'] = ivcs_transform_array_to($otpList);
  94. unset($retval['list'][0]);
  95. return $retval;
  96. }
  97. /* **************************************************************************************
  98. * FUNCTION : simplifiedInitialStep()
  99. * LAST UPDATED : February 2005
  100. * PARAMS : none
  101. *
  102. * DESCRIPTION : Creates the initial hash based off random seed
  103. *
  104. ************************************************************************************** */
  105. function simplifiedInitialStep() {
  106. // 8 random bytes for an initial hash
  107. $S = randomBytes(64);
  108. $hash = __otp_hash(hash_wrapper($S));
  109. return $S;
  110. }
  111. /* **************************************************************************************
  112. * FUNCTION : computationStep()
  113. * LAST UPDATED : February 2005
  114. * PARAMS :
  115. * $S $initial hash
  116. * $numberOfOTPs $size of list to create
  117. *
  118. * DESCRIPTION : This function takes an initial hash and the number of OTPs to create
  119. * and returns a list of size $numberOfOTPs
  120. *
  121. ************************************************************************************** */
  122. function computationStep($S, $numberOfOTPs) {
  123. $hash = $S;
  124. for($i = 1; $i <= $numberOfOTPs; $i++) {
  125. $hash = __otp_hash(hash_wrapper($hash));
  126. /////////////////////// length integrity check//////////////////////////
  127. if (strlen($hash) != 16) {
  128. error_log("computation step : __otp_hash produced strlen(hash) = ".strlen($hash));
  129. }
  130. ///////////////////////////////////////////////////////////////////////
  131. $otpList[$i] = $hash;
  132. }
  133. return $otpList;
  134. }
  135. /* **************************************************************************************
  136. * FUNCTION : ivcs_transform_array_to()
  137. * LAST UPDATED : December 2008
  138. * PARAMS :
  139. * $otpList An array of OTPs of variable size
  140. *
  141. * DESCRIPTION : This function takes an otp list and returns the same list in
  142. * six-word format. Invalid otps in the list are return as nulls.
  143. *
  144. * UPDATE : Added exception throwing for certain error conditions
  145. *
  146. ************************************************************************************** */
  147. function ivcs_transform_array_to($otpList) {
  148. if (!is_array($otpList)) {
  149. throw new Exception("passed list is not array!");
  150. return false;
  151. }
  152. $len = count($otpList);
  153. if ($len < 1) {
  154. throw new Exception("passed list is not array!");
  155. return false;
  156. }
  157. $sixWord = array();
  158. for($i = 0; $i < $len; $i++) {
  159. if (null == $otpList[$i]) {
  160. $sixWord[$i] = null;
  161. } elseif (!is_string($otpList[$i])) {
  162. $sixWord[$i] = null;
  163. } elseif (strlen($otpList[$i]) < 1) {
  164. $sixWord[$i] = null;
  165. } else {
  166. $sixWord[$i] = implode(" ", ivcs_transform_to($otpList[$i]));
  167. //////////////////// invertibilty integrity check ////////////////////////////////////
  168. $testinverse = ivcs_transform_from(explode(" ", $sixWord[$i]));
  169. if (strcmp($otpList[$i], $testinverse) != 0) {
  170. error_log("ivcs_transform_array_to : ivcs_transform not invertible");
  171. error_log("ivcs_transform_array_to : original = ".$otpList[$i].", strlen = ".strlen($otpList[$i]));
  172. error_log("ivcs_transform_array_to : transform= ".$sixWord[$i]);
  173. error_log("ivcs_transform_array_to : inverted = ".$testinverse.", strlen = ".strlen($testinverse));
  174. }
  175. ////////////////////////////////////////////////////////////////////////////////////
  176. }
  177. }
  178. return $sixWord;
  179. }
  180. /* **************************************************************************************
  181. * FUNCTION : ivcs_transform_to
  182. * LAST UPDATED : February 2005
  183. * PARAMS :
  184. * $hex a string representation of a hex number
  185. *
  186. * DESCRIPTION : Takes $hex and returns an ivcs word form of the number
  187. *
  188. ************************************************************************************** */
  189. function ivcs_transform_to($hex) {
  190. global $ivcs;
  191. $boolArr = hexString_2_booleanArray($hex);
  192. // Convert Hex input to an array of 1's and 0's
  193. $boolArr = array_merge($boolArr, rfc2289_checksum($boolArr)); // append checksum to form 66 bit array
  194. for($i = 0; $i < 6; $i++) {
  195. $arrSlice = array_slice($boolArr, $i * 11, 11);
  196. // extract the 11 bits that we want
  197. $index = binstr2int(implode($arrSlice));
  198. // create an integer index from the bits
  199. $word[$i] = $ivcs[$index];
  200. // look up the code word
  201. }
  202. return $word;
  203. }
  204. /* **************************************************************************************
  205. * FUNCTION : ivcs_transform_from
  206. * LAST UPDATED : February 2005
  207. * PARAMS :
  208. * $six_word An array or whitespace separated string of six-words in the ivcs list
  209. *
  210. * DESCRIPTION : Takes six-word ivcs format and returns a hex representation
  211. *
  212. ************************************************************************************** */
  213. function ivcs_transform_from($six_word) {
  214. global $rev_ivcs;
  215. if (!is_array($six_word)) {
  216. error_log("*************** non - array argument ****************");
  217. error_log("ivcs_transform_from : non-array argument");
  218. return false; // conversion to an array
  219. // is responsibility of calling routines
  220. }
  221. /* translate all six words into
  222. unsigned long versions of their
  223. int values as defined by their offset
  224. into $ivcs (iso-646 2048-word dictionary) */
  225. $binArray = array();
  226. for($i = 0 ; $i < 6 ; $i++) {
  227. $lutIndex = strtoupper($six_word[$i]);
  228. $packedIndex = pack("L", $rev_ivcs[$lutIndex]);
  229. $wordArray = str2arr(ulong2binstr($packedIndex));
  230. $binArray = array_merge($binArray, array_slice($wordArray, 21, 11));
  231. }
  232. $checksumCheckArray = rfc2289_checksum($binArray);
  233. if (($binArray[64] != $checksumCheckArray[0]) || ($binArray[65] != $checksumCheckArray[1]) ) {
  234. error_log("***************checksum error!****************");
  235. error_log("ivcs_transform_from : Checksum error");
  236. return false;
  237. }
  238. return booleanArray_2_hexString(array_slice($binArray, 0, 64));
  239. }
  240. /* **************************************************************************************
  241. * FUNCTION : __otp_hash
  242. * LAST UPDATED : February 2005
  243. * PARAMS :
  244. * $hexstr a hex-string
  245. *
  246. * DESCRIPTION : Breaks $hexstr (a hex string) into five 32-bit/4-byte values.
  247. * This is 160 bits total, and is ALWAYS the size of a sha1 hash value
  248. * regardless of hash input. Applies folding algorithm to condense
  249. * into 64-bit hash.
  250. *
  251. ************************************************************************************** */
  252. function __otp_hash($hexstr) {
  253. for ($i = 0; $i < 5; ++$i) {
  254. $cur[$i] = substr($hexstr, $i * 8, 8);
  255. $cur[$i] = pack("L", hexstr2int($cur[$i]));
  256. }
  257. /* now apply xor algorithm to fold into 64 bit key
  258. according to algorithm RFC 2289 :
  259. "The secure hash algorithms listed above have the property that they
  260. accept an input that is arbitrarily long and produce a fixed size
  261. output. The OTP system folds this output to 64 bits using the
  262. algorithms in the Appendix A. 64 bits is also the length of the one-
  263. time passwords. This is believed to be long enough to be secure and
  264. short enough to be entered manually (see below, Form of Output) when
  265. necessary."
  266. AND
  267. "Fold the 160 bit result to 64 bits
  268. sha.digest[0] ^= sha.digest[2];
  269. sha.digest[1] ^= sha.digest[3];
  270. sha.digest[0] ^= sha.digest[4];"
  271. */
  272. $fin[0] = pack("L", 0x00);
  273. $fin[1] = pack("L", 0x00);
  274. $cur[0] = $cur[0] ^ $cur[2];
  275. $fin[1] = $cur[1] ^ $cur[3];
  276. $fin[0] = $cur[0] ^ $cur[4];
  277. /* note should force specific byte-order to be little endian here */
  278. return (ulong2hexstr($fin[0], 8).ulong2hexstr($fin[1], 8)); // added left-zero padding to force return size of 16 hex digits
  279. }
  280. /* **************************************************************************************
  281. * FUNCTION : rfc2289_checksum
  282. * LAST UPDATED : February 2005
  283. * PARAMS :
  284. * $boolArr
  285. *
  286. * DESCRIPTION : Calculates checksum per RFC2289 spec. Returns 2 lsb's of checksum
  287. * in an array.
  288. *
  289. ************************************************************************************** */
  290. function rfc2289_checksum($boolArr) // returns 2 lsb's of checksum in an array
  291. {
  292. //Calculate checksum per RFC2289 spec.
  293. $checksum = 0;
  294. for($i = 0; $i < 64; $i += 2) {
  295. $checksum += $boolArr[$i+1] + (2 * $boolArr[$i]);
  296. }
  297. $checksumLSBs[0] = fmod((floor($checksum/2)), 2);
  298. $checksumLSBs[1] = fmod($checksum, 2);
  299. return $checksumLSBs;
  300. }
  301. /* **************************************************************************************
  302. * FUNCTION : hash_wrapper
  303. * LAST UPDATED : January 2009
  304. * PARAMS :
  305. * $str String to hash
  306. *
  307. * DESCRIPTION : performs a hashing algorithm according to __OTP_HASH_FUNCTION
  308. * and returns resultant hash
  309. *
  310. ************************************************************************************** */
  311. function hash_wrapper($str) {
  312. switch(__OTP_HASH_FUNCTION) {
  313. case __OTP_MD5:
  314. if (function_exists(md5)) {
  315. return md5($str);
  316. }
  317. case __OTP_SHA1:
  318. if (function_exists(sha1)) {
  319. return sha1($str);
  320. }
  321. case __OTP_SHA256:
  322. if (function_exists(sha256)) {
  323. return sha256($str);
  324. }
  325. default:
  326. if (function_exists(sha1)) {
  327. return sha1($str);
  328. }
  329. print "DANGER WILL ROBINSON!!!";
  330. exit();
  331. }
  332. }
  333. ?>
  334. <?php
  335. /**************************************************************************************************
  336. GNU GENERAL PUBLIC LICENSE
  337. Version 2, June 1991
  338. Copyright (C) 1989, 1991 Free Software Foundation, Inc.
  339. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  340. Everyone is permitted to copy and distribute verbatim copies
  341. of this license document, but changing it is not allowed.
  342. Preamble
  343. The licenses for most software are designed to take away your
  344. freedom to share and change it. By contrast, the GNU General Public
  345. License is intended to guarantee your freedom to share and change free
  346. software--to make sure the software is free for all its users. This
  347. General Public License applies to most of the Free Software
  348. Foundation's software and to any other program whose authors commit to
  349. using it. (Some other Free Software Foundation software is covered by
  350. the GNU Library General Public License instead.) You can apply it to
  351. your programs, too.
  352. When we speak of free software, we are referring to freedom, not
  353. price. Our General Public Licenses are designed to make sure that you
  354. have the freedom to distribute copies of free software (and charge for
  355. this service if you wish), that you receive source code or can get it
  356. if you want it, that you can change the software or use pieces of it
  357. in new free programs; and that you know you can do these things.
  358. To protect your rights, we need to make restrictions that forbid
  359. anyone to deny you these rights or to ask you to surrender the rights.
  360. These restrictions translate to certain responsibilities for you if you
  361. distribute copies of the software, or if you modify it.
  362. For example, if you distribute copies of such a program, whether
  363. gratis or for a fee, you must give the recipients all the rights that
  364. you have. You must make sure that they, too, receive or can get the
  365. source code. And you must show them these terms so they know their
  366. rights.
  367. We protect your rights with two steps: (1) copyright the software, and
  368. (2) offer you this license which gives you legal permission to copy,
  369. distribute and/or modify the software.
  370. Also, for each author's protection and ours, we want to make certain
  371. that everyone understands that there is no warranty for this free
  372. software. If the software is modified by someone else and passed on, we
  373. want its recipients to know that what they have is not the original, so
  374. that any problems introduced by others will not reflect on the original
  375. authors' reputations.
  376. Finally, any free program is threatened constantly by software
  377. patents. We wish to avoid the danger that redistributors of a free
  378. program will individually obtain patent licenses, in effect making the
  379. program proprietary. To prevent this, we have made it clear that any
  380. patent must be licensed for everyone's free use or not licensed at all.
  381. The precise terms and conditions for copying, distribution and
  382. modification follow.
  383. GNU GENERAL PUBLIC LICENSE
  384. TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
  385. 0. This License applies to any program or other work which contains
  386. a notice placed by the copyright holder saying it may be distributed
  387. under the terms of this General Public License. The "Program", below,
  388. refers to any such program or work, and a "work based on the Program"
  389. means either the Program or any derivative work under copyright law:
  390. that is to say, a work containing the Program or a portion of it,
  391. either verbatim or with modifications and/or translated into another
  392. language. (Hereinafter, translation is included without limitation in
  393. the term "modification".) Each licensee is addressed as "you".
  394. Activities other than copying, distribution and modification are not
  395. covered by this License; they are outside its scope. The act of
  396. running the Program is not restricted, and the output from the Program
  397. is covered only if its contents constitute a work based on the
  398. Program (independent of having been made by running the Program).
  399. Whether that is true depends on what the Program does.
  400. 1. You may copy and distribute verbatim copies of the Program's
  401. source code as you receive it, in any medium, provided that you
  402. conspicuously and appropriately publish on each copy an appropriate
  403. copyright notice and disclaimer of warranty; keep intact all the
  404. notices that refer to this License and to the absence of any warranty;
  405. and give any other recipients of the Program a copy of this License
  406. along with the Program.
  407. You may charge a fee for the physical act of transferring a copy, and
  408. you may at your option offer warranty protection in exchange for a fee.
  409. 2. You may modify your copy or copies of the Program or any portion
  410. of it, thus forming a work based on the Program, and copy and
  411. distribute such modifications or work under the terms of Section 1
  412. above, provided that you also meet all of these conditions:
  413. a) You must cause the modified files to carry prominent notices
  414. stating that you changed the files and the date of any change.
  415. b) You must cause any work that you distribute or publish, that in
  416. whole or in part contains or is derived from the Program or any
  417. part thereof, to be licensed as a whole at no charge to all third
  418. parties under the terms of this License.
  419. c) If the modified program normally reads commands interactively
  420. when run, you must cause it, when started running for such
  421. interactive use in the most ordinary way, to print or display an
  422. announcement including an appropriate copyright notice and a
  423. notice that there is no warranty (or else, saying that you provide
  424. a warranty) and that users may redistribute the program under
  425. these conditions, and telling the user how to view a copy of this
  426. License. (Exception: if the Program itself is interactive but
  427. does not normally print such an announcement, your work based on
  428. the Program is not required to print an announcement.)
  429. These requirements apply to the modified work as a whole. If
  430. identifiable sections of that work are not derived from the Program,
  431. and can be reasonably considered independent and separate works in
  432. themselves, then this License, and its terms, do not apply to those
  433. sections when you distribute them as separate works. But when you
  434. distribute the same sections as part of a whole which is a work based
  435. on the Program, the distribution of the whole must be on the terms of
  436. this License, whose permissions for other licensees extend to the
  437. entire whole, and thus to each and every part regardless of who wrote it.
  438. Thus, it is not the intent of this section to claim rights or contest
  439. your rights to work written entirely by you; rather, the intent is to
  440. exercise the right to control the distribution of derivative or
  441. collective works based on the Program.
  442. In addition, mere aggregation of another work not based on the Program
  443. with the Program (or with a work based on the Program) on a volume of
  444. a storage or distribution medium does not bring the other work under
  445. the scope of this License.
  446. 3. You may copy and distribute the Program (or a work based on it,
  447. under Section 2) in object code or executable form under the terms of
  448. Sections 1 and 2 above provided that you also do one of the following:
  449. a) Accompany it with the complete corresponding machine-readable
  450. source code, which must be distributed under the terms of Sections
  451. 1 and 2 above on a medium customarily used for software interchange; or,
  452. b) Accompany it with a written offer, valid for at least three
  453. years, to give any third party, for a charge no more than your
  454. cost of physically performing source distribution, a complete
  455. machine-readable copy of the corresponding source code, to be
  456. distributed under the terms of Sections 1 and 2 above on a medium
  457. customarily used for software interchange; or,
  458. c) Accompany it with the information you received as to the offer
  459. to distribute corresponding source code. (This alternative is
  460. allowed only for noncommercial distribution and only if you
  461. received the program in object code or executable form with such
  462. an offer, in accord with Subsection b above.)
  463. The source code for a work means the preferred form of the work for
  464. making modifications to it. For an executable work, complete source
  465. code means all the source code for all modules it contains, plus any
  466. associated interface definition files, plus the scripts used to
  467. control compilation and installation of the executable. However, as a
  468. special exception, the source code distributed need not include
  469. anything that is normally distributed (in either source or binary
  470. form) with the major components (compiler, kernel, and so on) of the
  471. operating system on which the executable runs, unless that component
  472. itself accompanies the executable.
  473. If distribution of executable or object code is made by offering
  474. access to copy from a designated place, then offering equivalent
  475. access to copy the source code from the same place counts as
  476. distribution of the source code, even though third parties are not
  477. compelled to copy the source along with the object code.
  478. 4. You may not copy, modify, sublicense, or distribute the Program
  479. except as expressly provided under this License. Any attempt
  480. otherwise to copy, modify, sublicense or distribute the Program is
  481. void, and will automatically terminate your rights under this License.
  482. However, parties who have received copies, or rights, from you under
  483. this License will not have their licenses terminated so long as such
  484. parties remain in full compliance.
  485. 5. You are not required to accept this License, since you have not
  486. signed it. However, nothing else grants you permission to modify or
  487. distribute the Program or its derivative works. These actions are
  488. prohibited by law if you do not accept this License. Therefore, by
  489. modifying or distributing the Program (or any work based on the
  490. Program), you indicate your acceptance of this License to do so, and
  491. all its terms and conditions for copying, distributing or modifying
  492. the Program or works based on it.
  493. 6. Each time you redistribute the Program (or any work based on the
  494. Program), the recipient automatically receives a license from the
  495. original licensor to copy, distribute or modify the Program subject to
  496. these terms and conditions. You may not impose any further
  497. restrictions on the recipients' exercise of the rights granted herein.
  498. You are not responsible for enforcing compliance by third parties to
  499. this License.
  500. 7. If, as a consequence of a court judgment or allegation of patent
  501. infringement or for any other reason (not limited to patent issues),
  502. conditions are imposed on you (whether by court order, agreement or
  503. otherwise) that contradict the conditions of this License, they do not
  504. excuse you from the conditions of this License. If you cannot
  505. distribute so as to satisfy simultaneously your obligations under this
  506. License and any other pertinent obligations, then as a consequence you
  507. may not distribute the Program at all. For example, if a patent
  508. license would not permit royalty-free redistribution of the Program by
  509. all those who receive copies directly or indirectly through you, then
  510. the only way you could satisfy both it and this License would be to
  511. refrain entirely from distribution of the Program.
  512. If any portion of this section is held invalid or unenforceable under
  513. any particular circumstance, the balance of the section is intended to
  514. apply and the section as a whole is intended to apply in other
  515. circumstances.
  516. It is not the purpose of this section to induce you to infringe any
  517. patents or other property right claims or to contest validity of any
  518. such claims; this section has the sole purpose of protecting the
  519. integrity of the free software distribution system, which is
  520. implemented by public license practices. Many people have made
  521. generous contributions to the wide range of software distributed
  522. through that system in reliance on consistent application of that
  523. system; it is up to the author/donor to decide if he or she is willing
  524. to distribute software through any other system and a licensee cannot
  525. impose that choice.
  526. This section is intended to make thoroughly clear what is believed to
  527. be a consequence of the rest of this License.
  528. 8. If the distribution and/or use of the Program is restricted in
  529. certain countries either by patents or by copyrighted interfaces, the
  530. original copyright holder who places the Program under this License
  531. may add an explicit geographical distribution limitation excluding
  532. those countries, so that distribution is permitted only in or among
  533. countries not thus excluded. In such case, this License incorporates
  534. the limitation as if written in the body of this License.
  535. 9. The Free Software Foundation may publish revised and/or new versions
  536. of the General Public License from time to time. Such new versions will
  537. be similar in spirit to the present version, but may differ in detail to
  538. address new problems or concerns.
  539. Each version is given a distinguishing version number. If the Program
  540. specifies a version number of this License which applies to it and "any
  541. later version", you have the option of following the terms and conditions
  542. either of that version or of any later version published by the Free
  543. Software Foundation. If the Program does not specify a version number of
  544. this License, you may choose any version ever published by the Free Software
  545. Foundation.
  546. 10. If you wish to incorporate parts of the Program into other free
  547. programs whose distribution conditions are different, write to the author
  548. to ask for permission. For software which is copyrighted by the Free
  549. Software Foundation, write to the Free Software Foundation; we sometimes
  550. make exceptions for this. Our decision will be guided by the two goals
  551. of preserving the free status of all derivatives of our free software and
  552. of promoting the sharing and reuse of software generally.
  553. NO WARRANTY
  554. 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
  555. FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
  556. OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
  557. PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
  558. OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  559. MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
  560. TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
  561. PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
  562. REPAIR OR CORRECTION.
  563. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
  564. WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
  565. REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
  566. INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
  567. OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
  568. TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
  569. YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
  570. PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
  571. POSSIBILITY OF SUCH DAMAGES.
  572. END OF TERMS AND CONDITIONS
  573. How to Apply These Terms to Your New Programs
  574. If you develop a new program, and you want it to be of the greatest
  575. possible use to the public, the best way to achieve this is to make it
  576. free software which everyone can redistribute and change under these terms.
  577. To do so, attach the following notices to the program. It is safest
  578. to attach them to the start of each source file to most effectively
  579. convey the exclusion of warranty; and each file should have at least
  580. the "copyright" line and a pointer to where the full notice is found.
  581. <one line to give the program's name and a brief idea of what it does.>
  582. Copyright (C) <year> <name of author>
  583. This program is free software; you can redistribute it and/or modify
  584. it under the terms of the GNU General Public License as published by
  585. the Free Software Foundation; either version 2 of the License, or
  586. (at your option) any later version.
  587. This program is distributed in the hope that it will be useful,
  588. but WITHOUT ANY WARRANTY; without even the implied warranty of
  589. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  590. GNU General Public License for more details.
  591. You should have received a copy of the GNU General Public License
  592. along with this program; if not, write to the Free Software
  593. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  594. Also add information on how to contact you by electronic and paper mail.
  595. If the program is interactive, make it output a short notice like this
  596. when it starts in an interactive mode:
  597. Gnomovision version 69, Copyright (C) year name of author
  598. Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
  599. This is free software, and you are welcome to redistribute it
  600. under certain conditions; type `show c' for details.
  601. The hypothetical commands `show w' and `show c' should show the appropriate
  602. parts of the General Public License. Of course, the commands you use may
  603. be called something other than `show w' and `show c'; they could even be
  604. mouse-clicks or menu items--whatever suits your program.
  605. You should also get your employer (if you work as a programmer) or your
  606. school, if any, to sign a "copyright disclaimer" for the program, if
  607. necessary. Here is a sample; alter the names:
  608. Yoyodyne, Inc., hereby disclaims all copyright interest in the program
  609. `Gnomovision' (which makes passes at compilers) written by James Hacker.
  610. <signature of Ty Coon>, 1 April 1989
  611. Ty Coon, President of Vice
  612. This General Public License does not permit incorporating your program into
  613. proprietary programs. If your program is a subroutine library, you may
  614. consider it more useful to permit linking proprietary applications with the
  615. library. If this is what you want to do, use the GNU Library General
  616. Public License instead of this License.
  617. ******************************************************************************************/
  618. /* Special thanks to |-|3xR3|g/\/$ for contributing, testing, and hardening this code (seriously w3 ph34r j00) */
  619. /*
  620. -----BEGIN PGP MESSAGE-----
  621. Version: GnuPG v1.2.1 (GNU/Linux)
  622. hQIOA6jz1R+atzBZEAf9EJXPCKrk9SPzLNALLY61g9oxSIq/eExVKDkTeTed9y5p
  623. HV37pp2tJXBoT5kNJ46Y2/xd1tDmfnSCD/cOVcjOafis7eGKElR39o4VXFi6ToqN
  624. w7RKZyY6TvL+uaFkNTHED4oSFRH7IYK9zxHBKoiO9qAcWBSaoMMgA1uyBoDvM6Hf
  625. +1TpyAO3I10KG50/rdWVLXWLaNaPk+dhmx7s965k9wrmYV6fdH79P1E/Z7grjv8o
  626. oPbNnF0PSruSc42ZTk4nfoMHI5ORJ5qAtN0BfWsFm+/zuwCci/zdNWDyY/7jrJWN
  627. lc2We5rVF4F6OLmKXUWWIIS2okAorIRmZt9Xc/e7Zgf9HtMZeJAJgHoLRgV9IHuw
  628. 9Ul6hqk2634UpcIiRwfMU/0towB8qGRmm6f8ZEGy8FsYvdlO7JmRinVTY5RulhPD
  629. R8LWN/Y6kUd5DnS2ddfn75WrUuInTBtq0LKpLPZt6dZimdqO4skCxC2qkwVGEtjH
  630. hgyH9ItonQPD8Wkp2KliTq3D7NeTDfYC1fEkGzO2avIjue80mA0yfzCW1UNk2wd3
  631. kvHTicScLi40sUq57nKPZc4EM0/KngegNjSFNRuunN5iJ0Y4cvRs8bh/toLfcrQi
  632. 7DxDs9BQMcPcbXSWoWYYwjWkcgI/mYAEKNnaegqG2NUh+yXJzhUSZsEnCLYEsKUg
  633. vtKZAb5HIw8MWdSSWzBvmzVDBX7TnXtwQVHfUTtZQZ17ZHE1pzKhSYQCOG/4OcFa
  634. EVMhXzyPRJ+DyrnZc85/5vrpAYNE1GLYatSb2jky2c4Alguk8KjzYvlZtDbnn8hs
  635. LgDvOA4zFzaVdEwlqJYzdRA5cEDDMDPWUaXgGYcfUoacp41fLPv9uWb/RHlaR4Ku
  636. ArepJGt9N5/Ztc3i
  637. =YHhe
  638. -----END PGP MESSAGE-----
  639. */
  640. ?>