Initial upload to TYPO3 Forge
authorstan <stan@735d13b6-9817-0410-8766-e36946ffe9aa>
Fri, 23 Jan 2009 16:55:46 +0000 (16:55 +0000)
committerstan <stan@735d13b6-9817-0410-8766-e36946ffe9aa>
Fri, 23 Jan 2009 16:55:46 +0000 (16:55 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Extensions/sr_freecap/trunk@16029 735d13b6-9817-0410-8766-e36946ffe9aa

294 files changed:
COPYING.txt [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
doc/manual.sxw [new file with mode: 0644]
ext_emconf.php [new file with mode: 0644]
ext_icon.gif [new file with mode: 0644]
ext_tables.php [new file with mode: 0644]
ext_typoscript_constants.txt [new file with mode: 0644]
ext_typoscript_setup.txt [new file with mode: 0644]
mod1/class.tx_srfreecap_fontmaker.php [new file with mode: 0644]
mod1/clear.gif [new file with mode: 0644]
mod1/conf.php [new file with mode: 0644]
mod1/fontmaker.php [new file with mode: 0644]
mod1/index.php [new file with mode: 0644]
mod1/locallang.xml [new file with mode: 0644]
mod1/locallang_mod.xml [new file with mode: 0644]
mod1/moduleicon.gif [new file with mode: 0644]
pi1/captcha.php [new file with mode: 0644]
pi1/class.tx_srfreecap_pi1.php [new file with mode: 0644]
pi1/freecap141.php [new file with mode: 0644]
pi1/locallang.xml [new file with mode: 0644]
pi2/class.tx_srfreecap_pi2.php [new file with mode: 0644]
pi2/freeCap.js [new file with mode: 0644]
pi2/locallang.xml [new file with mode: 0644]
pi3/audioCaptcha.php [new file with mode: 0644]
pi3/class.tx_srfreecap_pi3.php [new file with mode: 0644]
res/fonts/.anonymous.gdf [new file with mode: 0644]
res/fonts/.ht_freecap_extended_font1.gdf [new file with mode: 0644]
res/fonts/.ht_freecap_extended_font2.gdf [new file with mode: 0644]
res/fonts/.ht_freecap_extended_font3.gdf [new file with mode: 0644]
res/fonts/.ht_freecap_extended_font4.gdf [new file with mode: 0644]
res/fonts/.ht_freecap_font1.gdf [new file with mode: 0644]
res/fonts/.ht_freecap_font2.gdf [new file with mode: 0644]
res/fonts/.ht_freecap_font3.gdf [new file with mode: 0644]
res/fonts/.ht_freecap_font4.gdf [new file with mode: 0644]
res/fonts/.ht_freecap_font5.gdf [new file with mode: 0644]
res/images/audio.png [new file with mode: 0644]
res/voices/de/0.wav [new file with mode: 0644]
res/voices/de/1.wav [new file with mode: 0644]
res/voices/de/2.wav [new file with mode: 0644]
res/voices/de/3.wav [new file with mode: 0644]
res/voices/de/4.wav [new file with mode: 0644]
res/voices/de/5.wav [new file with mode: 0644]
res/voices/de/6.wav [new file with mode: 0644]
res/voices/de/7.wav [new file with mode: 0644]
res/voices/de/8.wav [new file with mode: 0644]
res/voices/de/9.wav [new file with mode: 0644]
res/voices/de/a.wav [new file with mode: 0644]
res/voices/de/b.wav [new file with mode: 0644]
res/voices/de/c.wav [new file with mode: 0644]
res/voices/de/d.wav [new file with mode: 0644]
res/voices/de/e.wav [new file with mode: 0644]
res/voices/de/f.wav [new file with mode: 0644]
res/voices/de/g.wav [new file with mode: 0644]
res/voices/de/h.wav [new file with mode: 0644]
res/voices/de/i.wav [new file with mode: 0644]
res/voices/de/j.wav [new file with mode: 0644]
res/voices/de/k.wav [new file with mode: 0644]
res/voices/de/l.wav [new file with mode: 0644]
res/voices/de/m.wav [new file with mode: 0644]
res/voices/de/n.wav [new file with mode: 0644]
res/voices/de/o.wav [new file with mode: 0644]
res/voices/de/p.wav [new file with mode: 0644]
res/voices/de/q.wav [new file with mode: 0644]
res/voices/de/r.wav [new file with mode: 0644]
res/voices/de/s.wav [new file with mode: 0644]
res/voices/de/t.wav [new file with mode: 0644]
res/voices/de/u.wav [new file with mode: 0644]
res/voices/de/v.wav [new file with mode: 0644]
res/voices/de/w.wav [new file with mode: 0644]
res/voices/de/x.wav [new file with mode: 0644]
res/voices/de/y.wav [new file with mode: 0644]
res/voices/de/z.wav [new file with mode: 0644]
res/voices/de/ß.wav [new file with mode: 0644]
res/voices/de/ä.wav [new file with mode: 0644]
res/voices/de/ö.wav [new file with mode: 0644]
res/voices/de/ü.wav [new file with mode: 0644]
res/voices/default/0.wav [new file with mode: 0644]
res/voices/default/1.wav [new file with mode: 0644]
res/voices/default/2.wav [new file with mode: 0644]
res/voices/default/3.wav [new file with mode: 0644]
res/voices/default/4.wav [new file with mode: 0644]
res/voices/default/5.wav [new file with mode: 0644]
res/voices/default/6.wav [new file with mode: 0644]
res/voices/default/7.wav [new file with mode: 0644]
res/voices/default/8.wav [new file with mode: 0644]
res/voices/default/9.wav [new file with mode: 0644]
res/voices/default/a.wav [new file with mode: 0644]
res/voices/default/b.wav [new file with mode: 0644]
res/voices/default/c.wav [new file with mode: 0644]
res/voices/default/d.wav [new file with mode: 0644]
res/voices/default/e.wav [new file with mode: 0644]
res/voices/default/f.wav [new file with mode: 0644]
res/voices/default/g.wav [new file with mode: 0644]
res/voices/default/h.wav [new file with mode: 0644]
res/voices/default/i.wav [new file with mode: 0644]
res/voices/default/j.wav [new file with mode: 0644]
res/voices/default/k.wav [new file with mode: 0644]
res/voices/default/l.wav [new file with mode: 0644]
res/voices/default/m.wav [new file with mode: 0644]
res/voices/default/n.wav [new file with mode: 0644]
res/voices/default/o.wav [new file with mode: 0644]
res/voices/default/p.wav [new file with mode: 0644]
res/voices/default/q.wav [new file with mode: 0644]
res/voices/default/r.wav [new file with mode: 0644]
res/voices/default/s.wav [new file with mode: 0644]
res/voices/default/t.wav [new file with mode: 0644]
res/voices/default/u.wav [new file with mode: 0644]
res/voices/default/v.wav [new file with mode: 0644]
res/voices/default/w.wav [new file with mode: 0644]
res/voices/default/x.wav [new file with mode: 0644]
res/voices/default/y.wav [new file with mode: 0644]
res/voices/default/z.wav [new file with mode: 0644]
res/voices/es/0.wav [new file with mode: 0644]
res/voices/es/1.wav [new file with mode: 0644]
res/voices/es/2.wav [new file with mode: 0644]
res/voices/es/3.wav [new file with mode: 0644]
res/voices/es/4.wav [new file with mode: 0644]
res/voices/es/5.wav [new file with mode: 0644]
res/voices/es/6.wav [new file with mode: 0644]
res/voices/es/7.wav [new file with mode: 0644]
res/voices/es/8.wav [new file with mode: 0644]
res/voices/es/9.wav [new file with mode: 0644]
res/voices/es/a.wav [new file with mode: 0644]
res/voices/es/b.wav [new file with mode: 0644]
res/voices/es/c.wav [new file with mode: 0644]
res/voices/es/d.wav [new file with mode: 0644]
res/voices/es/e.wav [new file with mode: 0644]
res/voices/es/f.wav [new file with mode: 0644]
res/voices/es/g.wav [new file with mode: 0644]
res/voices/es/h.wav [new file with mode: 0644]
res/voices/es/i.wav [new file with mode: 0644]
res/voices/es/j.wav [new file with mode: 0644]
res/voices/es/k.wav [new file with mode: 0644]
res/voices/es/l.wav [new file with mode: 0644]
res/voices/es/m.wav [new file with mode: 0644]
res/voices/es/n.wav [new file with mode: 0644]
res/voices/es/o.wav [new file with mode: 0644]
res/voices/es/p.wav [new file with mode: 0644]
res/voices/es/q.wav [new file with mode: 0644]
res/voices/es/r.wav [new file with mode: 0644]
res/voices/es/s.wav [new file with mode: 0644]
res/voices/es/t.wav [new file with mode: 0644]
res/voices/es/u.wav [new file with mode: 0644]
res/voices/es/v.wav [new file with mode: 0644]
res/voices/es/w.wav [new file with mode: 0644]
res/voices/es/x.wav [new file with mode: 0644]
res/voices/es/y.wav [new file with mode: 0644]
res/voices/es/z.wav [new file with mode: 0644]
res/voices/es/á.wav [new file with mode: 0644]
res/voices/es/é.wav [new file with mode: 0644]
res/voices/es/í.wav [new file with mode: 0644]
res/voices/es/ñ.wav [new file with mode: 0644]
res/voices/es/ó.wav [new file with mode: 0644]
res/voices/es/ú.wav [new file with mode: 0644]
res/voices/es/ü.wav [new file with mode: 0644]
res/voices/fr/0.wav [new file with mode: 0644]
res/voices/fr/1.wav [new file with mode: 0644]
res/voices/fr/2.wav [new file with mode: 0644]
res/voices/fr/3.wav [new file with mode: 0644]
res/voices/fr/4.wav [new file with mode: 0644]
res/voices/fr/5.wav [new file with mode: 0644]
res/voices/fr/6.wav [new file with mode: 0644]
res/voices/fr/7.wav [new file with mode: 0644]
res/voices/fr/8.wav [new file with mode: 0644]
res/voices/fr/9.wav [new file with mode: 0644]
res/voices/fr/a.wav [new file with mode: 0644]
res/voices/fr/b.wav [new file with mode: 0644]
res/voices/fr/c.wav [new file with mode: 0644]
res/voices/fr/d.wav [new file with mode: 0644]
res/voices/fr/e.wav [new file with mode: 0644]
res/voices/fr/f.wav [new file with mode: 0644]
res/voices/fr/g.wav [new file with mode: 0644]
res/voices/fr/h.wav [new file with mode: 0644]
res/voices/fr/i.wav [new file with mode: 0644]
res/voices/fr/j.wav [new file with mode: 0644]
res/voices/fr/k.wav [new file with mode: 0644]
res/voices/fr/l.wav [new file with mode: 0644]
res/voices/fr/m.wav [new file with mode: 0644]
res/voices/fr/n.wav [new file with mode: 0644]
res/voices/fr/o.wav [new file with mode: 0644]
res/voices/fr/p.wav [new file with mode: 0644]
res/voices/fr/q.wav [new file with mode: 0644]
res/voices/fr/r.wav [new file with mode: 0644]
res/voices/fr/s.wav [new file with mode: 0644]
res/voices/fr/t.wav [new file with mode: 0644]
res/voices/fr/u.wav [new file with mode: 0644]
res/voices/fr/v.wav [new file with mode: 0644]
res/voices/fr/w.wav [new file with mode: 0644]
res/voices/fr/x.wav [new file with mode: 0644]
res/voices/fr/y.wav [new file with mode: 0644]
res/voices/fr/z.wav [new file with mode: 0644]
res/voices/fr/à.wav [new file with mode: 0644]
res/voices/fr/â.wav [new file with mode: 0644]
res/voices/fr/ä.wav [new file with mode: 0644]
res/voices/fr/ç.wav [new file with mode: 0644]
res/voices/fr/è.wav [new file with mode: 0644]
res/voices/fr/é.wav [new file with mode: 0644]
res/voices/fr/ê.wav [new file with mode: 0644]
res/voices/fr/ë.wav [new file with mode: 0644]
res/voices/fr/î.wav [new file with mode: 0644]
res/voices/fr/ï.wav [new file with mode: 0644]
res/voices/fr/ô.wav [new file with mode: 0644]
res/voices/fr/ö.wav [new file with mode: 0644]
res/voices/fr/û.wav [new file with mode: 0644]
res/voices/fr/ü.wav [new file with mode: 0644]
res/voices/it/0.wav [new file with mode: 0644]
res/voices/it/1.wav [new file with mode: 0644]
res/voices/it/2.wav [new file with mode: 0644]
res/voices/it/3.wav [new file with mode: 0644]
res/voices/it/4.wav [new file with mode: 0644]
res/voices/it/5.wav [new file with mode: 0644]
res/voices/it/6.wav [new file with mode: 0644]
res/voices/it/7.wav [new file with mode: 0644]
res/voices/it/8.wav [new file with mode: 0644]
res/voices/it/9.wav [new file with mode: 0644]
res/voices/it/a.wav [new file with mode: 0644]
res/voices/it/b.wav [new file with mode: 0644]
res/voices/it/c.wav [new file with mode: 0644]
res/voices/it/d.wav [new file with mode: 0644]
res/voices/it/e.wav [new file with mode: 0644]
res/voices/it/f.wav [new file with mode: 0644]
res/voices/it/g.wav [new file with mode: 0644]
res/voices/it/h.wav [new file with mode: 0644]
res/voices/it/i.wav [new file with mode: 0644]
res/voices/it/j.wav [new file with mode: 0644]
res/voices/it/k.wav [new file with mode: 0644]
res/voices/it/l.wav [new file with mode: 0644]
res/voices/it/m.wav [new file with mode: 0644]
res/voices/it/n.wav [new file with mode: 0644]
res/voices/it/o.wav [new file with mode: 0644]
res/voices/it/p.wav [new file with mode: 0644]
res/voices/it/q.wav [new file with mode: 0644]
res/voices/it/r.wav [new file with mode: 0644]
res/voices/it/s.wav [new file with mode: 0644]
res/voices/it/t.wav [new file with mode: 0644]
res/voices/it/u.wav [new file with mode: 0644]
res/voices/it/v.wav [new file with mode: 0644]
res/voices/it/w.wav [new file with mode: 0644]
res/voices/it/x.wav [new file with mode: 0644]
res/voices/it/y.wav [new file with mode: 0644]
res/voices/it/z.wav [new file with mode: 0644]
res/voices/it/à.wav [new file with mode: 0644]
res/voices/it/è.wav [new file with mode: 0644]
res/voices/it/é.wav [new file with mode: 0644]
res/voices/it/ò.wav [new file with mode: 0644]
res/voices/pt/0.wav [new file with mode: 0644]
res/voices/pt/1.wav [new file with mode: 0644]
res/voices/pt/2.wav [new file with mode: 0644]
res/voices/pt/3.wav [new file with mode: 0644]
res/voices/pt/4.wav [new file with mode: 0644]
res/voices/pt/5.wav [new file with mode: 0644]
res/voices/pt/6.wav [new file with mode: 0644]
res/voices/pt/7.wav [new file with mode: 0644]
res/voices/pt/8.wav [new file with mode: 0644]
res/voices/pt/9.wav [new file with mode: 0644]
res/voices/pt/a.wav [new file with mode: 0644]
res/voices/pt/b.wav [new file with mode: 0644]
res/voices/pt/c.wav [new file with mode: 0644]
res/voices/pt/d.wav [new file with mode: 0644]
res/voices/pt/e.wav [new file with mode: 0644]
res/voices/pt/f.wav [new file with mode: 0644]
res/voices/pt/g.wav [new file with mode: 0644]
res/voices/pt/h.wav [new file with mode: 0644]
res/voices/pt/i.wav [new file with mode: 0644]
res/voices/pt/j.wav [new file with mode: 0644]
res/voices/pt/k.wav [new file with mode: 0644]
res/voices/pt/l.wav [new file with mode: 0644]
res/voices/pt/m.wav [new file with mode: 0644]
res/voices/pt/n.wav [new file with mode: 0644]
res/voices/pt/o.wav [new file with mode: 0644]
res/voices/pt/p.wav [new file with mode: 0644]
res/voices/pt/q.wav [new file with mode: 0644]
res/voices/pt/r.wav [new file with mode: 0644]
res/voices/pt/s.wav [new file with mode: 0644]
res/voices/pt/t.wav [new file with mode: 0644]
res/voices/pt/u.wav [new file with mode: 0644]
res/voices/pt/v.wav [new file with mode: 0644]
res/voices/pt/w.wav [new file with mode: 0644]
res/voices/pt/x.wav [new file with mode: 0644]
res/voices/pt/y.wav [new file with mode: 0644]
res/voices/pt/z.wav [new file with mode: 0644]
res/voices/pt/à.wav [new file with mode: 0644]
res/voices/pt/á.wav [new file with mode: 0644]
res/voices/pt/ã.wav [new file with mode: 0644]
res/voices/pt/ç.wav [new file with mode: 0644]
res/voices/pt/é.wav [new file with mode: 0644]
res/voices/pt/ê.wav [new file with mode: 0644]
res/voices/pt/í.wav [new file with mode: 0644]
res/voices/pt/ó.wav [new file with mode: 0644]
res/voices/pt/õ.wav [new file with mode: 0644]
res/voices/pt/ú.wav [new file with mode: 0644]
res/words/.ht_de_freecap_words [new file with mode: 0644]
res/words/.ht_default_freecap_words [new file with mode: 0644]
res/words/.ht_fr_freecap_words [new file with mode: 0644]

diff --git a/COPYING.txt b/COPYING.txt
new file mode 100644 (file)
index 0000000..45645b4
--- /dev/null
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE\r
+                      Version 2, June 1991\r
+\r
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.\r
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ Everyone is permitted to copy and distribute verbatim copies\r
+ of this license document, but changing it is not allowed.\r
+\r
+                           Preamble\r
+\r
+  The licenses for most software are designed to take away your\r
+freedom to share and change it.  By contrast, the GNU General Public\r
+License is intended to guarantee your freedom to share and change free\r
+software--to make sure the software is free for all its users.  This\r
+General Public License applies to most of the Free Software\r
+Foundation's software and to any other program whose authors commit to\r
+using it.  (Some other Free Software Foundation software is covered by\r
+the GNU Library General Public License instead.)  You can apply it to\r
+your programs, too.\r
+\r
+  When we speak of free software, we are referring to freedom, not\r
+price.  Our General Public Licenses are designed to make sure that you\r
+have the freedom to distribute copies of free software (and charge for\r
+this service if you wish), that you receive source code or can get it\r
+if you want it, that you can change the software or use pieces of it\r
+in new free programs; and that you know you can do these things.\r
+\r
+  To protect your rights, we need to make restrictions that forbid\r
+anyone to deny you these rights or to ask you to surrender the rights.\r
+These restrictions translate to certain responsibilities for you if you\r
+distribute copies of the software, or if you modify it.\r
+\r
+  For example, if you distribute copies of such a program, whether\r
+gratis or for a fee, you must give the recipients all the rights that\r
+you have.  You must make sure that they, too, receive or can get the\r
+source code.  And you must show them these terms so they know their\r
+rights.\r
+\r
+  We protect your rights with two steps: (1) copyright the software, and\r
+(2) offer you this license which gives you legal permission to copy,\r
+distribute and/or modify the software.\r
+\r
+  Also, for each author's protection and ours, we want to make certain\r
+that everyone understands that there is no warranty for this free\r
+software.  If the software is modified by someone else and passed on, we\r
+want its recipients to know that what they have is not the original, so\r
+that any problems introduced by others will not reflect on the original\r
+authors' reputations.\r
+\r
+  Finally, any free program is threatened constantly by software\r
+patents.  We wish to avoid the danger that redistributors of a free\r
+program will individually obtain patent licenses, in effect making the\r
+program proprietary.  To prevent this, we have made it clear that any\r
+patent must be licensed for everyone's free use or not licensed at all.\r
+\r
+  The precise terms and conditions for copying, distribution and\r
+modification follow.\r
+\f\r
+                   GNU GENERAL PUBLIC LICENSE\r
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\r
+\r
+  0. This License applies to any program or other work which contains\r
+a notice placed by the copyright holder saying it may be distributed\r
+under the terms of this General Public License.  The "Program", below,\r
+refers to any such program or work, and a "work based on the Program"\r
+means either the Program or any derivative work under copyright law:\r
+that is to say, a work containing the Program or a portion of it,\r
+either verbatim or with modifications and/or translated into another\r
+language.  (Hereinafter, translation is included without limitation in\r
+the term "modification".)  Each licensee is addressed as "you".\r
+\r
+Activities other than copying, distribution and modification are not\r
+covered by this License; they are outside its scope.  The act of\r
+running the Program is not restricted, and the output from the Program\r
+is covered only if its contents constitute a work based on the\r
+Program (independent of having been made by running the Program).\r
+Whether that is true depends on what the Program does.\r
+\r
+  1. You may copy and distribute verbatim copies of the Program's\r
+source code as you receive it, in any medium, provided that you\r
+conspicuously and appropriately publish on each copy an appropriate\r
+copyright notice and disclaimer of warranty; keep intact all the\r
+notices that refer to this License and to the absence of any warranty;\r
+and give any other recipients of the Program a copy of this License\r
+along with the Program.\r
+\r
+You may charge a fee for the physical act of transferring a copy, and\r
+you may at your option offer warranty protection in exchange for a fee.\r
+\r
+  2. You may modify your copy or copies of the Program or any portion\r
+of it, thus forming a work based on the Program, and copy and\r
+distribute such modifications or work under the terms of Section 1\r
+above, provided that you also meet all of these conditions:\r
+\r
+    a) You must cause the modified files to carry prominent notices\r
+    stating that you changed the files and the date of any change.\r
+\r
+    b) You must cause any work that you distribute or publish, that in\r
+    whole or in part contains or is derived from the Program or any\r
+    part thereof, to be licensed as a whole at no charge to all third\r
+    parties under the terms of this License.\r
+\r
+    c) If the modified program normally reads commands interactively\r
+    when run, you must cause it, when started running for such\r
+    interactive use in the most ordinary way, to print or display an\r
+    announcement including an appropriate copyright notice and a\r
+    notice that there is no warranty (or else, saying that you provide\r
+    a warranty) and that users may redistribute the program under\r
+    these conditions, and telling the user how to view a copy of this\r
+    License.  (Exception: if the Program itself is interactive but\r
+    does not normally print such an announcement, your work based on\r
+    the Program is not required to print an announcement.)\r
+\f\r
+These requirements apply to the modified work as a whole.  If\r
+identifiable sections of that work are not derived from the Program,\r
+and can be reasonably considered independent and separate works in\r
+themselves, then this License, and its terms, do not apply to those\r
+sections when you distribute them as separate works.  But when you\r
+distribute the same sections as part of a whole which is a work based\r
+on the Program, the distribution of the whole must be on the terms of\r
+this License, whose permissions for other licensees extend to the\r
+entire whole, and thus to each and every part regardless of who wrote it.\r
+\r
+Thus, it is not the intent of this section to claim rights or contest\r
+your rights to work written entirely by you; rather, the intent is to\r
+exercise the right to control the distribution of derivative or\r
+collective works based on the Program.\r
+\r
+In addition, mere aggregation of another work not based on the Program\r
+with the Program (or with a work based on the Program) on a volume of\r
+a storage or distribution medium does not bring the other work under\r
+the scope of this License.\r
+\r
+  3. You may copy and distribute the Program (or a work based on it,\r
+under Section 2) in object code or executable form under the terms of\r
+Sections 1 and 2 above provided that you also do one of the following:\r
+\r
+    a) Accompany it with the complete corresponding machine-readable\r
+    source code, which must be distributed under the terms of Sections\r
+    1 and 2 above on a medium customarily used for software interchange; or,\r
+\r
+    b) Accompany it with a written offer, valid for at least three\r
+    years, to give any third party, for a charge no more than your\r
+    cost of physically performing source distribution, a complete\r
+    machine-readable copy of the corresponding source code, to be\r
+    distributed under the terms of Sections 1 and 2 above on a medium\r
+    customarily used for software interchange; or,\r
+\r
+    c) Accompany it with the information you received as to the offer\r
+    to distribute corresponding source code.  (This alternative is\r
+    allowed only for noncommercial distribution and only if you\r
+    received the program in object code or executable form with such\r
+    an offer, in accord with Subsection b above.)\r
+\r
+The source code for a work means the preferred form of the work for\r
+making modifications to it.  For an executable work, complete source\r
+code means all the source code for all modules it contains, plus any\r
+associated interface definition files, plus the scripts used to\r
+control compilation and installation of the executable.  However, as a\r
+special exception, the source code distributed need not include\r
+anything that is normally distributed (in either source or binary\r
+form) with the major components (compiler, kernel, and so on) of the\r
+operating system on which the executable runs, unless that component\r
+itself accompanies the executable.\r
+\r
+If distribution of executable or object code is made by offering\r
+access to copy from a designated place, then offering equivalent\r
+access to copy the source code from the same place counts as\r
+distribution of the source code, even though third parties are not\r
+compelled to copy the source along with the object code.\r
+\f\r
+  4. You may not copy, modify, sublicense, or distribute the Program\r
+except as expressly provided under this License.  Any attempt\r
+otherwise to copy, modify, sublicense or distribute the Program is\r
+void, and will automatically terminate your rights under this License.\r
+However, parties who have received copies, or rights, from you under\r
+this License will not have their licenses terminated so long as such\r
+parties remain in full compliance.\r
+\r
+  5. You are not required to accept this License, since you have not\r
+signed it.  However, nothing else grants you permission to modify or\r
+distribute the Program or its derivative works.  These actions are\r
+prohibited by law if you do not accept this License.  Therefore, by\r
+modifying or distributing the Program (or any work based on the\r
+Program), you indicate your acceptance of this License to do so, and\r
+all its terms and conditions for copying, distributing or modifying\r
+the Program or works based on it.\r
+\r
+  6. Each time you redistribute the Program (or any work based on the\r
+Program), the recipient automatically receives a license from the\r
+original licensor to copy, distribute or modify the Program subject to\r
+these terms and conditions.  You may not impose any further\r
+restrictions on the recipients' exercise of the rights granted herein.\r
+You are not responsible for enforcing compliance by third parties to\r
+this License.\r
+\r
+  7. If, as a consequence of a court judgment or allegation of patent\r
+infringement or for any other reason (not limited to patent issues),\r
+conditions are imposed on you (whether by court order, agreement or\r
+otherwise) that contradict the conditions of this License, they do not\r
+excuse you from the conditions of this License.  If you cannot\r
+distribute so as to satisfy simultaneously your obligations under this\r
+License and any other pertinent obligations, then as a consequence you\r
+may not distribute the Program at all.  For example, if a patent\r
+license would not permit royalty-free redistribution of the Program by\r
+all those who receive copies directly or indirectly through you, then\r
+the only way you could satisfy both it and this License would be to\r
+refrain entirely from distribution of the Program.\r
+\r
+If any portion of this section is held invalid or unenforceable under\r
+any particular circumstance, the balance of the section is intended to\r
+apply and the section as a whole is intended to apply in other\r
+circumstances.\r
+\r
+It is not the purpose of this section to induce you to infringe any\r
+patents or other property right claims or to contest validity of any\r
+such claims; this section has the sole purpose of protecting the\r
+integrity of the free software distribution system, which is\r
+implemented by public license practices.  Many people have made\r
+generous contributions to the wide range of software distributed\r
+through that system in reliance on consistent application of that\r
+system; it is up to the author/donor to decide if he or she is willing\r
+to distribute software through any other system and a licensee cannot\r
+impose that choice.\r
+\r
+This section is intended to make thoroughly clear what is believed to\r
+be a consequence of the rest of this License.\r
+\f\r
+  8. If the distribution and/or use of the Program is restricted in\r
+certain countries either by patents or by copyrighted interfaces, the\r
+original copyright holder who places the Program under this License\r
+may add an explicit geographical distribution limitation excluding\r
+those countries, so that distribution is permitted only in or among\r
+countries not thus excluded.  In such case, this License incorporates\r
+the limitation as if written in the body of this License.\r
+\r
+  9. The Free Software Foundation may publish revised and/or new versions\r
+of the General Public License from time to time.  Such new versions will\r
+be similar in spirit to the present version, but may differ in detail to\r
+address new problems or concerns.\r
+\r
+Each version is given a distinguishing version number.  If the Program\r
+specifies a version number of this License which applies to it and "any\r
+later version", you have the option of following the terms and conditions\r
+either of that version or of any later version published by the Free\r
+Software Foundation.  If the Program does not specify a version number of\r
+this License, you may choose any version ever published by the Free Software\r
+Foundation.\r
+\r
+  10. If you wish to incorporate parts of the Program into other free\r
+programs whose distribution conditions are different, write to the author\r
+to ask for permission.  For software which is copyrighted by the Free\r
+Software Foundation, write to the Free Software Foundation; we sometimes\r
+make exceptions for this.  Our decision will be guided by the two goals\r
+of preserving the free status of all derivatives of our free software and\r
+of promoting the sharing and reuse of software generally.\r
+\r
+                           NO WARRANTY\r
+\r
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\r
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\r
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\r
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\r
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\r
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\r
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\r
+REPAIR OR CORRECTION.\r
+\r
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\r
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\r
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\r
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\r
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\r
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\r
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\r
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\r
+POSSIBILITY OF SUCH DAMAGES.\r
+\r
+                    END OF TERMS AND CONDITIONS\r
+\f\r
+           How to Apply These Terms to Your New Programs\r
+\r
+  If you develop a new program, and you want it to be of the greatest\r
+possible use to the public, the best way to achieve this is to make it\r
+free software which everyone can redistribute and change under these terms.\r
+\r
+  To do so, attach the following notices to the program.  It is safest\r
+to attach them to the start of each source file to most effectively\r
+convey the exclusion of warranty; and each file should have at least\r
+the "copyright" line and a pointer to where the full notice is found.\r
+\r
+    <one line to give the program's name and a brief idea of what it does.>\r
+    Copyright (C) <year>  <name of author>\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+\r
+\r
+Also add information on how to contact you by electronic and paper mail.\r
+\r
+If the program is interactive, make it output a short notice like this\r
+when it starts in an interactive mode:\r
+\r
+    Gnomovision version 69, Copyright (C) year name of author\r
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\r
+    This is free software, and you are welcome to redistribute it\r
+    under certain conditions; type `show c' for details.\r
+\r
+The hypothetical commands `show w' and `show c' should show the appropriate\r
+parts of the General Public License.  Of course, the commands you use may\r
+be called something other than `show w' and `show c'; they could even be\r
+mouse-clicks or menu items--whatever suits your program.\r
+\r
+You should also get your employer (if you work as a programmer) or your\r
+school, if any, to sign a "copyright disclaimer" for the program, if\r
+necessary.  Here is a sample; alter the names:\r
+\r
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program\r
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.\r
+\r
+  <signature of Ty Coon>, 1 April 1989\r
+  Ty Coon, President of Vice\r
+\r
+This General Public License does not permit incorporating your program into\r
+proprietary programs.  If your program is a subroutine library, you may\r
+consider it more useful to permit linking proprietary applications with the\r
+library.  If this is what you want to do, use the GNU Library General\r
+Public License instead of this License.\r
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..44ab62a
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,3 @@
+2009-01-23  Stanislas Rolland  <typo3@sjbr.ca>
+
+       * Initial upload to TYPO3 Forge
diff --git a/doc/manual.sxw b/doc/manual.sxw
new file mode 100644 (file)
index 0000000..6d33a19
Binary files /dev/null and b/doc/manual.sxw differ
diff --git a/ext_emconf.php b/ext_emconf.php
new file mode 100644 (file)
index 0000000..5d7a7aa
--- /dev/null
@@ -0,0 +1,49 @@
+<?php\r
+\r
+########################################################################\r
+# Extension Manager/Repository config file for ext: "sr_freecap"\r
+#\r
+# Auto generated 23-01-2009 11:30\r
+#\r
+# Manual updates:\r
+# Only the data in the array - anything else is removed by next write.\r
+# "version" and "dependencies" must not be touched!\r
+########################################################################\r
+\r
+$EM_CONF[$_EXTKEY] = array(\r
+       'title' => 'freeCap CAPTCHA',\r
+       'description' => 'A TYPO3 integration of freeCap CAPTCHA.',\r
+       'category' => 'plugin',\r
+       'shy' => 0,\r
+       'version' => '1.1.0',\r
+       'dependencies' => '',\r
+       'conflicts' => '',\r
+       'priority' => '',\r
+       'loadOrder' => '',\r
+       'module' => 'mod1',\r
+       'state' => 'stable',\r
+       'uploadfolder' => 1,\r
+       'createDirs' => '',\r
+       'modify_tables' => '',\r
+       'clearcacheonload' => 0,\r
+       'lockType' => '',\r
+       'author' => 'Stanislas Rolland',\r
+       'author_email' => 'typo3(arobas)sjbr.ca',\r
+       'author_company' => 'SJBR',\r
+       'CGLcompliance' => '',\r
+       'CGLcompliance_note' => '',\r
+       'constraints' => array(\r
+               'depends' => array(\r
+                       'cms' => '',\r
+                       'php' => '5.0.0-0.0.0',\r
+                       'typo3' => '4.0.0-0.0.0',\r
+               ),\r
+               'conflicts' => array(\r
+               ),\r
+               'suggests' => array(\r
+               ),\r
+       ),\r
+       '_md5_values_when_last_written' => 'a:292:{s:11:"COPYING.txt";s:4:"393a";s:12:"ext_icon.gif";s:4:"687c";s:14:"ext_tables.php";s:4:"905b";s:28:"ext_typoscript_constants.txt";s:4:"4377";s:24:"ext_typoscript_setup.txt";s:4:"9973";s:30:"res/words/.ht_de_freecap_words";s:4:"bb43";s:35:"res/words/.ht_default_freecap_words";s:4:"9eb2";s:30:"res/words/.ht_fr_freecap_words";s:4:"71de";s:24:"res/fonts/.anonymous.gdf";s:4:"ec47";s:40:"res/fonts/.ht_freecap_extended_font1.gdf";s:4:"3665";s:40:"res/fonts/.ht_freecap_extended_font2.gdf";s:4:"6237";s:40:"res/fonts/.ht_freecap_extended_font3.gdf";s:4:"e894";s:40:"res/fonts/.ht_freecap_extended_font4.gdf";s:4:"9c66";s:31:"res/fonts/.ht_freecap_font1.gdf";s:4:"2d89";s:31:"res/fonts/.ht_freecap_font2.gdf";s:4:"da7e";s:31:"res/fonts/.ht_freecap_font3.gdf";s:4:"6f97";s:31:"res/fonts/.ht_freecap_font4.gdf";s:4:"dc3d";s:31:"res/fonts/.ht_freecap_font5.gdf";s:4:"f0ef";s:19:"res/voices/de/0.wav";s:4:"4a9d";s:19:"res/voices/de/1.wav";s:4:"a615";s:19:"res/voices/de/2.wav";s:4:"0bda";s:19:"res/voices/de/3.wav";s:4:"19a7";s:19:"res/voices/de/4.wav";s:4:"5d36";s:19:"res/voices/de/5.wav";s:4:"489b";s:19:"res/voices/de/6.wav";s:4:"12e6";s:19:"res/voices/de/7.wav";s:4:"e21d";s:19:"res/voices/de/8.wav";s:4:"ead7";s:19:"res/voices/de/9.wav";s:4:"30fe";s:19:"res/voices/de/a.wav";s:4:"dcea";s:19:"res/voices/de/b.wav";s:4:"23b5";s:19:"res/voices/de/c.wav";s:4:"18ef";s:19:"res/voices/de/d.wav";s:4:"9238";s:19:"res/voices/de/e.wav";s:4:"14f2";s:19:"res/voices/de/f.wav";s:4:"aa99";s:19:"res/voices/de/g.wav";s:4:"5ea0";s:19:"res/voices/de/h.wav";s:4:"dbac";s:19:"res/voices/de/i.wav";s:4:"dd8a";s:19:"res/voices/de/j.wav";s:4:"c417";s:19:"res/voices/de/k.wav";s:4:"8703";s:19:"res/voices/de/l.wav";s:4:"687c";s:19:"res/voices/de/m.wav";s:4:"79f6";s:19:"res/voices/de/n.wav";s:4:"4ce2";s:19:"res/voices/de/o.wav";s:4:"0cff";s:19:"res/voices/de/p.wav";s:4:"b4f9";s:19:"res/voices/de/q.wav";s:4:"3cae";s:19:"res/voices/de/r.wav";s:4:"8a0c";s:19:"res/voices/de/s.wav";s:4:"9287";s:19:"res/voices/de/t.wav";s:4:"1968";s:19:"res/voices/de/u.wav";s:4:"7888";s:19:"res/voices/de/v.wav";s:4:"e20e";s:19:"res/voices/de/w.wav";s:4:"4d7f";s:19:"res/voices/de/x.wav";s:4:"85e5";s:19:"res/voices/de/y.wav";s:4:"86a5";s:19:"res/voices/de/z.wav";s:4:"d0cf";s:20:"res/voices/de/ß.wav";s:4:"2b6e";s:20:"res/voices/de/ä.wav";s:4:"de30";s:20:"res/voices/de/ö.wav";s:4:"5db4";s:20:"res/voices/de/ü.wav";s:4:"17fb";s:19:"res/voices/fr/0.wav";s:4:"d0c4";s:19:"res/voices/fr/1.wav";s:4:"4d11";s:19:"res/voices/fr/2.wav";s:4:"95a1";s:19:"res/voices/fr/3.wav";s:4:"d706";s:19:"res/voices/fr/4.wav";s:4:"d03d";s:19:"res/voices/fr/5.wav";s:4:"49aa";s:19:"res/voices/fr/6.wav";s:4:"1d18";s:19:"res/voices/fr/7.wav";s:4:"77d3";s:19:"res/voices/fr/8.wav";s:4:"b999";s:19:"res/voices/fr/9.wav";s:4:"fb70";s:19:"res/voices/fr/a.wav";s:4:"0a4d";s:19:"res/voices/fr/b.wav";s:4:"021b";s:19:"res/voices/fr/c.wav";s:4:"a096";s:19:"res/voices/fr/d.wav";s:4:"437b";s:19:"res/voices/fr/e.wav";s:4:"3f25";s:19:"res/voices/fr/f.wav";s:4:"1c04";s:19:"res/voices/fr/g.wav";s:4:"e823";s:19:"res/voices/fr/h.wav";s:4:"3759";s:19:"res/voices/fr/i.wav";s:4:"80cb";s:19:"res/voices/fr/j.wav";s:4:"bc1d";s:19:"res/voices/fr/k.wav";s:4:"c029";s:19:"res/voices/fr/l.wav";s:4:"0592";s:19:"res/voices/fr/m.wav";s:4:"644d";s:19:"res/voices/fr/n.wav";s:4:"c5b8";s:19:"res/voices/fr/o.wav";s:4:"282b";s:19:"res/voices/fr/p.wav";s:4:"e05c";s:19:"res/voices/fr/q.wav";s:4:"9136";s:19:"res/voices/fr/r.wav";s:4:"3fe2";s:19:"res/voices/fr/s.wav";s:4:"547c";s:19:"res/voices/fr/t.wav";s:4:"9514";s:19:"res/voices/fr/u.wav";s:4:"6282";s:19:"res/voices/fr/v.wav";s:4:"5aca";s:19:"res/voices/fr/w.wav";s:4:"ff68";s:19:"res/voices/fr/x.wav";s:4:"4ab5";s:19:"res/voices/fr/y.wav";s:4:"f045";s:19:"res/voices/fr/z.wav";s:4:"2116";s:20:"res/voices/fr/à.wav";s:4:"9788";s:20:"res/voices/fr/â.wav";s:4:"9630";s:20:"res/voices/fr/ä.wav";s:4:"0a4d";s:20:"res/voices/fr/ç.wav";s:4:"be88";s:20:"res/voices/fr/è.wav";s:4:"be97";s:20:"res/voices/fr/é.wav";s:4:"30c0";s:20:"res/voices/fr/ê.wav";s:4:"642e";s:20:"res/voices/fr/ë.wav";s:4:"3c49";s:20:"res/voices/fr/î.wav";s:4:"a810";s:20:"res/voices/fr/ï.wav";s:4:"c732";s:20:"res/voices/fr/ô.wav";s:4:"80e1";s:20:"res/voices/fr/ö.wav";s:4:"9136";s:20:"res/voices/fr/û.wav";s:4:"b097";s:20:"res/voices/fr/ü.wav";s:4:"bad2";s:19:"res/voices/pt/0.wav";s:4:"b932";s:19:"res/voices/pt/1.wav";s:4:"7a87";s:19:"res/voices/pt/2.wav";s:4:"656a";s:19:"res/voices/pt/3.wav";s:4:"7cdb";s:19:"res/voices/pt/4.wav";s:4:"7c14";s:19:"res/voices/pt/5.wav";s:4:"10aa";s:19:"res/voices/pt/6.wav";s:4:"eb25";s:19:"res/voices/pt/7.wav";s:4:"f6e3";s:19:"res/voices/pt/8.wav";s:4:"87f0";s:19:"res/voices/pt/9.wav";s:4:"d301";s:19:"res/voices/pt/a.wav";s:4:"8fc0";s:19:"res/voices/pt/b.wav";s:4:"ad53";s:19:"res/voices/pt/c.wav";s:4:"0b7e";s:19:"res/voices/pt/d.wav";s:4:"8fe5";s:19:"res/voices/pt/e.wav";s:4:"29e7";s:19:"res/voices/pt/f.wav";s:4:"834b";s:19:"res/voices/pt/g.wav";s:4:"7a4c";s:19:"res/voices/pt/h.wav";s:4:"e218";s:19:"res/voices/pt/i.wav";s:4:"cbba";s:19:"res/voices/pt/j.wav";s:4:"e214";s:19:"res/voices/pt/k.wav";s:4:"855b";s:19:"res/voices/pt/l.wav";s:4:"ca9f";s:19:"res/voices/pt/m.wav";s:4:"7713";s:19:"res/voices/pt/n.wav";s:4:"bdbe";s:19:"res/voices/pt/o.wav";s:4:"8d74";s:19:"res/voices/pt/p.wav";s:4:"cc66";s:19:"res/voices/pt/q.wav";s:4:"2502";s:19:"res/voices/pt/r.wav";s:4:"a6d9";s:19:"res/voices/pt/s.wav";s:4:"f20d";s:19:"res/voices/pt/t.wav";s:4:"8e0f";s:19:"res/voices/pt/u.wav";s:4:"ac80";s:19:"res/voices/pt/v.wav";s:4:"7836";s:19:"res/voices/pt/w.wav";s:4:"5457";s:19:"res/voices/pt/x.wav";s:4:"d8aa";s:19:"res/voices/pt/y.wav";s:4:"9ee3";s:19:"res/voices/pt/z.wav";s:4:"0ace";s:20:"res/voices/pt/à.wav";s:4:"8fc0";s:20:"res/voices/pt/á.wav";s:4:"be8b";s:20:"res/voices/pt/ã.wav";s:4:"3613";s:20:"res/voices/pt/ç.wav";s:4:"6fef";s:20:"res/voices/pt/é.wav";s:4:"29e7";s:20:"res/voices/pt/ê.wav";s:4:"b316";s:20:"res/voices/pt/í.wav";s:4:"42c1";s:20:"res/voices/pt/ó.wav";s:4:"4418";s:20:"res/voices/pt/õ.wav";s:4:"3192";s:20:"res/voices/pt/ú.wav";s:4:"4a29";s:19:"res/voices/es/0.wav";s:4:"db49";s:19:"res/voices/es/1.wav";s:4:"853c";s:19:"res/voices/es/2.wav";s:4:"cda1";s:19:"res/voices/es/3.wav";s:4:"f164";s:19:"res/voices/es/4.wav";s:4:"857a";s:19:"res/voices/es/5.wav";s:4:"5ad0";s:19:"res/voices/es/6.wav";s:4:"eb6e";s:19:"res/voices/es/7.wav";s:4:"961a";s:19:"res/voices/es/8.wav";s:4:"237b";s:19:"res/voices/es/9.wav";s:4:"c7d8";s:19:"res/voices/es/a.wav";s:4:"e0a0";s:19:"res/voices/es/b.wav";s:4:"dece";s:19:"res/voices/es/c.wav";s:4:"6905";s:19:"res/voices/es/d.wav";s:4:"e647";s:19:"res/voices/es/e.wav";s:4:"05fb";s:19:"res/voices/es/f.wav";s:4:"fa24";s:19:"res/voices/es/g.wav";s:4:"00fe";s:19:"res/voices/es/h.wav";s:4:"b284";s:19:"res/voices/es/i.wav";s:4:"ec3f";s:19:"res/voices/es/j.wav";s:4:"02c0";s:19:"res/voices/es/k.wav";s:4:"7007";s:19:"res/voices/es/l.wav";s:4:"3ac7";s:19:"res/voices/es/m.wav";s:4:"546b";s:19:"res/voices/es/n.wav";s:4:"12c9";s:19:"res/voices/es/o.wav";s:4:"1582";s:19:"res/voices/es/p.wav";s:4:"99b5";s:19:"res/voices/es/q.wav";s:4:"c53f";s:19:"res/voices/es/r.wav";s:4:"1b97";s:19:"res/voices/es/s.wav";s:4:"72c0";s:19:"res/voices/es/t.wav";s:4:"7962";s:19:"res/voices/es/u.wav";s:4:"e466";s:19:"res/voices/es/v.wav";s:4:"a915";s:19:"res/voices/es/w.wav";s:4:"3d1d";s:19:"res/voices/es/x.wav";s:4:"b80d";s:19:"res/voices/es/y.wav";s:4:"ec3f";s:19:"res/voices/es/z.wav";s:4:"cd9b";s:20:"res/voices/es/á.wav";s:4:"7337";s:20:"res/voices/es/é.wav";s:4:"fa97";s:20:"res/voices/es/í.wav";s:4:"6210";s:20:"res/voices/es/ñ.wav";s:4:"617e";s:20:"res/voices/es/ó.wav";s:4:"c3d8";s:20:"res/voices/es/ú.wav";s:4:"b552";s:20:"res/voices/es/ü.wav";s:4:"dbf4";s:19:"res/voices/it/0.wav";s:4:"89d3";s:19:"res/voices/it/1.wav";s:4:"9b12";s:19:"res/voices/it/2.wav";s:4:"628f";s:19:"res/voices/it/3.wav";s:4:"beaa";s:19:"res/voices/it/4.wav";s:4:"a72b";s:19:"res/voices/it/5.wav";s:4:"ad59";s:19:"res/voices/it/6.wav";s:4:"ea89";s:19:"res/voices/it/7.wav";s:4:"9a02";s:19:"res/voices/it/8.wav";s:4:"9471";s:19:"res/voices/it/9.wav";s:4:"2a43";s:19:"res/voices/it/a.wav";s:4:"e2bf";s:19:"res/voices/it/b.wav";s:4:"f77e";s:19:"res/voices/it/c.wav";s:4:"bf0a";s:19:"res/voices/it/d.wav";s:4:"ea6c";s:19:"res/voices/it/e.wav";s:4:"fd73";s:19:"res/voices/it/f.wav";s:4:"1b01";s:19:"res/voices/it/g.wav";s:4:"e2af";s:19:"res/voices/it/h.wav";s:4:"f3df";s:19:"res/voices/it/i.wav";s:4:"ef14";s:19:"res/voices/it/j.wav";s:4:"4ed2";s:19:"res/voices/it/k.wav";s:4:"f0f2";s:19:"res/voices/it/l.wav";s:4:"1ea5";s:19:"res/voices/it/m.wav";s:4:"eec4";s:19:"res/voices/it/n.wav";s:4:"d94f";s:19:"res/voices/it/o.wav";s:4:"bc95";s:19:"res/voices/it/p.wav";s:4:"6d8d";s:19:"res/voices/it/q.wav";s:4:"fb7c";s:19:"res/voices/it/r.wav";s:4:"4148";s:19:"res/voices/it/s.wav";s:4:"dcb7";s:19:"res/voices/it/t.wav";s:4:"08ad";s:19:"res/voices/it/u.wav";s:4:"2d83";s:19:"res/voices/it/v.wav";s:4:"d807";s:19:"res/voices/it/w.wav";s:4:"c00d";s:19:"res/voices/it/x.wav";s:4:"a27b";s:19:"res/voices/it/y.wav";s:4:"7d90";s:19:"res/voices/it/z.wav";s:4:"0d8f";s:20:"res/voices/it/à.wav";s:4:"3bfc";s:20:"res/voices/it/è.wav";s:4:"6a5b";s:20:"res/voices/it/é.wav";s:4:"0664";s:20:"res/voices/it/ò.wav";s:4:"aed2";s:24:"res/voices/default/0.wav";s:4:"e725";s:24:"res/voices/default/1.wav";s:4:"2f6a";s:24:"res/voices/default/2.wav";s:4:"fb53";s:24:"res/voices/default/3.wav";s:4:"a774";s:24:"res/voices/default/4.wav";s:4:"1a97";s:24:"res/voices/default/5.wav";s:4:"24ce";s:24:"res/voices/default/6.wav";s:4:"fe02";s:24:"res/voices/default/7.wav";s:4:"d7b6";s:24:"res/voices/default/8.wav";s:4:"1186";s:24:"res/voices/default/9.wav";s:4:"790c";s:24:"res/voices/default/a.wav";s:4:"7a27";s:24:"res/voices/default/b.wav";s:4:"6931";s:24:"res/voices/default/c.wav";s:4:"6364";s:24:"res/voices/default/d.wav";s:4:"7b55";s:24:"res/voices/default/e.wav";s:4:"9efe";s:24:"res/voices/default/f.wav";s:4:"ed53";s:24:"res/voices/default/g.wav";s:4:"062e";s:24:"res/voices/default/h.wav";s:4:"4b6e";s:24:"res/voices/default/i.wav";s:4:"42aa";s:24:"res/voices/default/j.wav";s:4:"6d64";s:24:"res/voices/default/k.wav";s:4:"bd50";s:24:"res/voices/default/l.wav";s:4:"fdf9";s:24:"res/voices/default/m.wav";s:4:"9c18";s:24:"res/voices/default/n.wav";s:4:"ba4a";s:24:"res/voices/default/o.wav";s:4:"6a6f";s:24:"res/voices/default/p.wav";s:4:"41d9";s:24:"res/voices/default/q.wav";s:4:"1b19";s:24:"res/voices/default/r.wav";s:4:"762a";s:24:"res/voices/default/s.wav";s:4:"ba07";s:24:"res/voices/default/t.wav";s:4:"7640";s:24:"res/voices/default/u.wav";s:4:"f861";s:24:"res/voices/default/v.wav";s:4:"ade1";s:24:"res/voices/default/w.wav";s:4:"4c38";s:24:"res/voices/default/x.wav";s:4:"5ad3";s:24:"res/voices/default/y.wav";s:4:"616e";s:24:"res/voices/default/z.wav";s:4:"1d8b";s:20:"res/images/audio.png";s:4:"c244";s:30:"pi2/class.tx_srfreecap_pi2.php";s:4:"7653";s:14:"pi2/freeCap.js";s:4:"eb15";s:17:"pi2/locallang.xml";s:4:"c608";s:15:"pi1/captcha.php";s:4:"1196";s:30:"pi1/class.tx_srfreecap_pi1.php";s:4:"6f93";s:18:"pi1/freecap141.php";s:4:"b203";s:17:"pi1/locallang.xml";s:4:"aacb";s:14:"doc/manual.sxw";s:4:"3ef7";s:37:"mod1/class.tx_srfreecap_fontmaker.php";s:4:"f772";s:14:"mod1/clear.gif";s:4:"cc11";s:13:"mod1/conf.php";s:4:"e939";s:18:"mod1/fontmaker.php";s:4:"a4eb";s:14:"mod1/index.php";s:4:"a293";s:18:"mod1/locallang.xml";s:4:"fc0b";s:22:"mod1/locallang_mod.xml";s:4:"4220";s:19:"mod1/moduleicon.gif";s:4:"687c";s:20:"pi3/audioCaptcha.php";s:4:"31d0";s:30:"pi3/class.tx_srfreecap_pi3.php";s:4:"42df";}',\r
+);\r
+\r
+?>
\ No newline at end of file
diff --git a/ext_icon.gif b/ext_icon.gif
new file mode 100644 (file)
index 0000000..37abb9f
Binary files /dev/null and b/ext_icon.gif differ
diff --git a/ext_tables.php b/ext_tables.php
new file mode 100644 (file)
index 0000000..d38aba5
--- /dev/null
@@ -0,0 +1,8 @@
+<?php\r
+if (!defined ('TYPO3_MODE')) die ('Access denied.');\r
+\r
+if (TYPO3_MODE == 'BE' && $GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_2']) {\r
+       t3lib_extMgm::addModule('tools', 'txsrfreecapM1', '', t3lib_extMgm::extPath($_EXTKEY).'mod1/');\r
+}\r
+\r
+?>\r
diff --git a/ext_typoscript_constants.txt b/ext_typoscript_constants.txt
new file mode 100644 (file)
index 0000000..77dcc06
--- /dev/null
@@ -0,0 +1,59 @@
+plugin.tx_srfreecap {\r
+\r
+    # cat=plugin.tx_srfreecap/dims/02; type=int+; label= CAPTCHA image height: Height of the generated image.\r
+       imageHeight = 90\r
+\r
+    # cat=plugin.tx_srfreecap/dims/01; type=int+; label= Maximun word length: Maximun length of the randomly generated CAPTCHA string.\r
+       maxWordLength = 5\r
+\r
+    # cat=plugin.tx_srfreecap/color; type=boolean; label= Color of the text: 0=one random colour for all letters, 1=different random colour for each letter.\r
+       textColor = 1\r
+\r
+    # cat=plugin.tx_srfreecap//03; type=options[png,gif,jpg]; label= CAPTCHA image format: Format of the generated image.\r
+       imageFormat = png\r
+\r
+    # cat=plugin.tx_srfreecap/enable/01; type=boolean; label= Use list of words: If enabled, the CAPTCHA string will be selected from a list of words. If not, it will be randomly generated.\r
+       useWordsList = 1\r
+       \r
+    # cat=plugin.tx_srfreecap/enable/02; type=boolean; label= Generate CAPTCHA with numbers only. This option is ignored if Use list of words is enabled.\r
+       generateNumbers = 0\r
+\r
+    # cat=plugin.tx_srfreecap//01; type=int+; label= Maximun attempts: Maximum times a user can refresh the image.\r
+       maxAttempts = 100\r
+\r
+    # cat=plugin.tx_srfreecap//04; type=options[,Transparent,White with grid,White with squiggles,Morphed image blocks]; label= Background type: If not set, will be random selection of possible types.\r
+       backgroundType =\r
+\r
+    # cat=plugin.tx_srfreecap/enable/04; type=boolean; label= Background blurring: If enabled, the background will be blurred. The string should be easier to read.\r
+       backgroundBlur = 1\r
+\r
+    # cat=plugin.tx_srfreecap/enable/05; type=boolean; label= Background morphing: If enabled, the background will be morphed (recommended).\r
+       backgroundMorph = 1\r
+\r
+    # cat=plugin.tx_srfreecap/enable/06; type=boolean; label= Merge string with background: 0=write CAPTCHA string over background, 1=merge CAPTCHA string with non-transparent background.\r
+       mergeWithBackground = 1\r
+\r
+    # cat=plugin.tx_srfreecap//05; type=string; label= Text morphing factor: Morphing factor applied to each character of the CAPTCHA string.\r
+       morphFactor = 1\r
+\r
+    # cat=plugin.tx_srfreecap/file/01; type=file[]; label= Default words list file: All words lists should be in the same directory.\r
+       defaultWordsList = EXT:sr_freecap/res/words/.ht_default_freecap_words\r
+\r
+    # cat=plugin.tx_srfreecap//02; type=options[,formal,informal]; label= Type of salutation to use: Possible values are 'formal' or 'informal'.\r
+       salutation =\r
+\r
+    # cat=plugin.tx_srfreecap/file/02; type=string; label= List of GD font files: Coma-separated list of GD font files located in directory uploads/tx_srfreecap/.\r
+       fontFiles =\r
+\r
+    # cat=plugin.tx_srfreecap/enable/03; type=boolean; label= Accessible output: If enabled, the CAPTCHA will include an audio version.\r
+       accessibleOutput = 0\r
+\r
+    # cat=plugin.tx_srfreecap/enable/07; type=boolean; label= Use site tag: If set, a site tag is added in the background of the CAPTCHA image.\r
+       siteTag = 0\r
+\r
+    # cat=plugin.tx_srfreecap//06; type=string; label= Site tag domain name: Domain name to use in the default site tag.\r
+       siteTagDomain = www.mydomain.org\r
+       \r
+    # cat=plugin.tx_srfreecap//07; type=int+; label= Position of the site tag: 0 = at the top of the CAPTCHA, 1 = at the bottom, 2 = both at the top and at the bottom\r
+       siteTagPosition = 1\r
+}
\ No newline at end of file
diff --git a/ext_typoscript_setup.txt b/ext_typoscript_setup.txt
new file mode 100644 (file)
index 0000000..1414eb5
--- /dev/null
@@ -0,0 +1,40 @@
+plugin.tx_srfreecap_pi1 {\r
+\r
+       imageHeight = {$plugin.tx_srfreecap.imageHeight}\r
+       imageFormat = {$plugin.tx_srfreecap.imageFormat}\r
+\r
+       backgroundType = {$plugin.tx_srfreecap.backgroundType}\r
+       backgroundBlur = {$plugin.tx_srfreecap.backgroundBlur}\r
+       backgroundMorph = {$plugin.tx_srfreecap.backgroundMorph}\r
+\r
+       maxWordLength = {$plugin.tx_srfreecap.maxWordLength}\r
+       useWordsList = {$plugin.tx_srfreecap.useWordsList}\r
+       generateNumbers = {$plugin.tx_srfreecap.generateNumbers}\r
+       \r
+       textColor = {$plugin.tx_srfreecap.textColor}\r
+       mergeWithBackground = {$plugin.tx_srfreecap.mergeWithBackground}\r
+       morphFactor = {$plugin.tx_srfreecap.morphFactor}\r
+       defaultWordsList = {$plugin.tx_srfreecap.defaultWordsList}\r
+       fontFiles = {$plugin.tx_srfreecap.fontFiles}\r
+\r
+       maxAttempts = {$plugin.tx_srfreecap.maxAttempts}\r
+       \r
+       accessibleOutput = {$plugin.tx_srfreecap.accessibleOutput}\r
+       \r
+       siteTag = {$plugin.tx_srfreecap.siteTag}\r
+       siteTagDomain = {$plugin.tx_srfreecap.siteTagDomain}\r
+       siteTagPosition = {$plugin.tx_srfreecap.siteTagPosition}\r
+}\r
+\r
+plugin.tx_srfreecap_pi2 {\r
+\r
+       salutation = {$plugin.tx_srfreecap.salutation}\r
+       accessibleOutput = {$plugin.tx_srfreecap.accessibleOutput}\r
+\r
+       _CSS_DEFAULT_STYLE (\r
+               .tx-srfreecap-pi2-image { margin-left: 1em; }\r
+               .tx-srfreecap-pi2-cant-read { font-size: .9em; color:#35006d; }\r
+               .tx-srfreecap-pi2-cant-read a:link { background-color:transparent; font-weight:bold; text-decoration:none; }\r
+       )\r
+}\r
+\r
diff --git a/mod1/class.tx_srfreecap_fontmaker.php b/mod1/class.tx_srfreecap_fontmaker.php
new file mode 100644 (file)
index 0000000..e12bdf2
--- /dev/null
@@ -0,0 +1,414 @@
+<?php\r
+/***************************************************************\r
+*  Copyright notice\r
+*\r
+*  (c) 2007-2008 Stanislas Rolland <typo3(arobas)sjbr.ca>\r
+*  All rights reserved\r
+*\r
+*  This script is part of the Typo3 project. The Typo3 project is\r
+*  free software; you can redistribute it and/or modify\r
+*  it under the terms of the GNU General Public License as published by\r
+*  the Free Software Foundation; either version 2 of the License, or\r
+*  (at your option) any later version.\r
+*\r
+*  The GNU General Public License can be found at\r
+*  http://www.gnu.org/copyleft/gpl.html.\r
+*\r
+*  This script is distributed in the hope that it will be useful,\r
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*  GNU General Public License for more details.\r
+*\r
+*  This copyright notice MUST APPEAR in all copies of the script!\r
+***************************************************************/\r
+/**\r
+* Module 'GD Font Makers' for the 'sr_freecap' extension.\r
+*\r
+* @author Stanislas Rolland <typo3(arobas)sjbr.ca>\r
+*/\r
+if (!defined('PATH_tslib')) {\r
+       if (@is_dir(PATH_site.'typo3/sysext/cms/tslib/')) {\r
+               define('PATH_tslib', PATH_site.'typo3/sysext/cms/tslib/');\r
+       } elseif (@is_dir(PATH_site.'tslib/')) {\r
+               define('PATH_tslib', PATH_site.'tslib/');\r
+       }\r
+}\r
+require_once(PATH_t3lib.'class.t3lib_scbase.php');\r
+require_once(PATH_t3lib.'class.t3lib_tstemplate.php');\r
+require_once(PATH_t3lib.'class.t3lib_stdgraphic.php');\r
+require_once(PATH_t3lib.'class.t3lib_div.php');\r
+require_once(PATH_tslib.'class.tslib_gifbuilder.php');\r
+require_once(PATH_tslib.'class.tslib_content.php');\r
+\r
+class tx_srfreecap_fontmaker extends t3lib_SCbase {\r
+       var $extKey = 'sr_freecap';\r
+       var $extPrefix = 'tx_srfreecap';\r
+       var $pageinfo;\r
+       \r
+       /**\r
+        * Initialize module\r
+        *\r
+        * @return void\r
+        */\r
+       function init() {\r
+               parent::init();\r
+       }\r
+       \r
+       /**\r
+        * Adds items to the->MOD_MENU array. Used for the function menu selector.\r
+        *\r
+        * @return void\r
+        */\r
+       function menuConfig() {\r
+               global $LANG;\r
+               $this->MOD_MENU = Array (\r
+                       'function' => Array (\r
+                               '1' => $LANG->getLL('function1'),\r
+                               '2' => $LANG->getLL('function2'),\r
+                               '3' => $LANG->getLL('function3'),\r
+                               )\r
+                       );\r
+               parent::menuConfig();\r
+       }\r
+       \r
+       /**\r
+        * Main function of the module. Write the content to $this->content\r
+        *\r
+        * @return void\r
+        */\r
+       function main() {\r
+               global $BE_USER, $LANG, $BACK_PATH, $TYPO3_CONF_VARS;\r
+               \r
+                       // Access check!\r
+                       // The page will show only if there is a valid page and if this page may be viewed by the user\r
+               $this->pageinfo = t3lib_BEfunc::readPageAccess($this->id, $this->perms_clause);\r
+               $access = is_array($this->pageinfo) ? 1 : 0;\r
+               \r
+               if (($this->id && $access) || ($BE_USER->user['admin'] && !$this->id)) {\r
+                       \r
+                               // Draw the header.\r
+                       $this->doc = t3lib_div::makeInstance('mediumDoc');\r
+                       $this->doc->backPath = $BACK_PATH;\r
+                       $this->doc->form = '<form action="" method="post" enctype="multipart/form-data">';\r
+                       \r
+                               // JavaScript\r
+                       $this->doc->JScode = '\r
+                               <script type="text/javascript">\r
+                                       /*<![CDATA[*/\r
+                                       <!--\r
+                                       script_ended = 0;\r
+                                       function jumpToUrl(URL) {\r
+                                       document.location = URL;\r
+                                       }\r
+                                       // -->\r
+                                       /*]]>*/\r
+                                       </script>\r
+                               ';\r
+                       \r
+                       //$headerSection = $this->doc->getHeader('pages', $this->pageinfo, $this->pageinfo['_thePath']).'<br>'.$LANG->php3Lang['labels']['path'].': '.t3lib_div::fixed_lgd_pre($this->pageinfo['_thePath'], 50);\r
+                       \r
+                       $this->content .= $this->doc->startPage($LANG->getLL('title'));\r
+                       $this->content .= $this->doc->header($LANG->getLL('title'));\r
+                       $this->content .= $this->doc->spacer(5);\r
+                       //$this->content .= $this->doc->section('', $this->doc->funcMenu($headerSection, t3lib_BEfunc::getFuncMenu($this->id, 'SET[function]', $this->MOD_SETTINGS['function'], $this->MOD_MENU['function'])));\r
+                       $this->content .= $this->doc->divider(5);\r
+                       \r
+                               // Render content:\r
+                       $this->moduleContent();\r
+                       \r
+                               // ShortCut\r
+                       if ($BE_USER->mayMakeShortcut()) {\r
+                               $this->content .= $this->doc->spacer(20).$this->doc->section('', $this->doc->makeShortcutIcon('id', implode(',', array_keys($this->MOD_MENU)), $this->MCONF['name']));\r
+                       }\r
+                       \r
+                       $this->content .= $this->doc->spacer(10);\r
+               } else {\r
+                               // If no access or if ID == zero\r
+                       $this->doc = t3lib_div::makeInstance('mediumDoc');\r
+                       $this->doc->backPath = $BACK_PATH;\r
+                                \r
+                       $this->content .= $this->doc->startPage($LANG->getLL('title'));\r
+                       $this->content .= $this->doc->header($LANG->getLL('title'));\r
+                       $this->content .= $this->doc->spacer(5);\r
+                       $this->content .= $this->doc->spacer(10);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Prints out the module HTML\r
+        *\r
+        * @return void\r
+        */\r
+       function printContent() {\r
+               global $SOBE;\r
+               \r
+               $this->content .= $this->doc->middle();\r
+               $this->content .= $this->doc->endPage();\r
+               echo $this->content;\r
+       }\r
+       \r
+       /**\r
+        * Generates the module content\r
+        *\r
+        * @return void\r
+        */\r
+       function moduleContent() {\r
+               global $LANG, $TYPO3_DB, $BACK_PATH, $TYPO3_CONF_VARS;\r
+               \r
+                       // get user supplied data\r
+               $charactersToIncludeInFont = intval(t3lib_div::_GP('charactersToIncludeInFont'));\r
+               \r
+               $pixelwidth = intval(t3lib_div::_GP('pixelwidth'));\r
+               $pixelheight = intval(t3lib_div::_GP('pixelheight'));\r
+               if (!$pixelheight) $pixelheight = 50;\r
+               \r
+               $endianness = intval(t3lib_div::_GP('endianness'));\r
+               \r
+               $gdFontFileName = t3lib_div::_GP('gdfontfilename');\r
+               if (!trim($gdFontFileName)) {\r
+                       $gdFontFileName = 'font';\r
+               }\r
+               \r
+               $fontFileName = t3lib_div::_GP('fontfilename');\r
+               if (!trim($fontFileName)) {\r
+                       $fontFileName = 't3lib/fonts/nimbus.ttf';\r
+               }\r
+               $ttfFontFileName = t3lib_div::getFileAbsFileName($fontFileName);\r
+               \r
+               if (!is_file($ttfFontFileName)) {\r
+                       $this->content .= $LANG->getLL('ttfFontFileNotFound') . ' '. $fontFileName;\r
+               } elseif (!empty($pixelwidth)) {\r
+                       if ($charactersToIncludeInFont == 1) {\r
+                               $characters = 'a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z';\r
+                               $numchars = 26;\r
+                               $startCharacter = 'a';\r
+                       } else if ($charactersToIncludeInFont == 2) {\r
+                               $characters = 'a,b,c,d,e,f,g,h,i,j,k,l,m,n,o'\r
+                                       .',p,q,r,s,t,u,v,w,x,y,z,-,-,-,-,-'\r
+                                       .',-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-'\r
+                                       .',-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-'\r
+                                       .',-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-'\r
+                                       .',-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-'\r
+                                       .',-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-'\r
+                                       .',-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,ß'\r
+                                       .',à,á,â,ã,ä,å,æ,ç,è,é,ê,ë,ì,í,î,ï'\r
+                                       .',ð,ñ,ò,ó,ô,õ,ö,-,ø,ù,ú,û,ü,ý,þ,ÿ';\r
+                                       $numchars = 159;\r
+                                       $startCharacter = 'a';\r
+                       } else {\r
+                               $characters = '0,1,2,3,4,5,6,7,8,9';\r
+                               $numchars = 10;\r
+                               $startCharacter = '0';\r
+                       }\r
+                       \r
+                       $PNGImageFile = $this->makeFontImage($characters, $ttfFontFileName, $pixelwidth, $pixelheight);\r
+                       $this->content .= $LANG->getLL('usingFontFile') . ' ' . $fontFileName . $this->doc->spacer(5);\r
+                       $this->content .= $LANG->getLL('pngImageCreated') . ' ' . $PNGImageFile . $this->doc->spacer(5) . '<img src="' . $BACK_PATH . '../' . $PNGImageFile . '" />' . $this->doc->spacer(20);\r
+                       \r
+                       if ($TYPO3_CONF_VARS['GFX']['gdlib_png']) {\r
+                               $image = @ImageCreateFromPNG(PATH_site.$PNGImageFile);\r
+                       } else {\r
+                               $image = @ImageCreateFromGIF(PATH_site.$PNGImageFile);\r
+                       }\r
+                       $fontdata = $this->makeFont($image, $numchars, $startCharacter, $pixelwidth, $pixelheight, $endianness);\r
+                       $gdfFontFileName = $this->buildFontFile($gdFontFileName,$fontdata);\r
+                       ImageDestroy($image);\r
+                       \r
+                       if ($gdfFontFileName) {\r
+                               $this->content .= $LANG->getLL('gdFontFileCreated') . ' ' . $gdfFontFileName;\r
+                       } else {\r
+                               $this->content .= $LANG->getLL('gdFontFileNotCreated') . ' ' . $gdfFontFileName;\r
+                       }\r
+               }\r
+               $this->content .= $this->doc->spacer(20);\r
+               $this->content .= '\r
+                       <table cellspacing="5">\r
+                               <tr><td>' . $LANG->getLL('charactersToIncludeInFont') . '</td><td>\r
+                                       <input id="numbers-only" type="radio" name="charactersToIncludeInFont" value="0" checked="checked" style="margin-right: 3px;" /><label for="numbers-only">' . $LANG->getLL('numbers-only') . '</label>\r
+                                       <br /><input id="ASCII-lowercase-letters" type="radio" name="charactersToIncludeInFont" value="1" style="margin-right: 3px;" /><label for="ASCII-lowercase-letters">' . $LANG->getLL('ASCII-lowercase-letters') . '</label>\r
+                                       <br /><input id="ANSI-extended-ASCII-lowercase-letters" type="radio" name="charactersToIncludeInFont" value="2" style="margin-right: 3px;" /><label for="ANSI-extended-ASCII-lowercase-letters">' . $LANG->getLL('ANSI-extended-ASCII-lowercase-letters') . '</label>\r
+                               </td></tr>\r
+                               <tr><td><label for="pixelwidth">' . $LANG->getLL('characterWidth') . '</label></td><td><input id="pixelwidth" type="text" name="pixelwidth" size="5" /></td></tr>\r
+                               <tr><td><label for="pixelheight">' . $LANG->getLL('characterHeight') . '</label></td><td><input id="pixelheight" type="text" name="pixelheight" size="5" /></td></tr>\r
+                               <tr><td>' . $LANG->getLL('endianness') . '</td><td>\r
+                                       <input id="little-endian" type="radio" name="endianness" value="0" checked="checked" style="margin-right: 3px;" /><label for="little-endian">' . $LANG->getLL('littleEndian') . '</label>\r
+                                       <br /><input id="big-endian" type="radio" name="endianness" value="1" style="margin-right: 3px;" /><label for="big-endian">' . $LANG->getLL('bigEndian') . '</label>\r
+                               </td></tr>\r
+                               <tr><td><label for="fontfilename">' . $LANG->getLL('pathToTTFFile') . '</td><td><input id="fontfilename" type="text" name="fontfilename" size="50" /></td></tr>\r
+                               <tr><td><label for="gdfontfilename">' . $LANG->getLL('gdFontFilePrefix') . '</td><td><input id="gdfontfilename" type="text" name="gdfontfilename" size="25"></td></tr>\r
+                               <tr><td colspan="2"><input type="submit" value="' . htmlspecialchars($LANG->getLL('makeFont')) . '" /></td></tr>\r
+                               </table>\r
+                       ';\r
+               $this->content .= $this->doc->section('', $content, 0, 1);\r
+       }\r
+       \r
+       /**\r
+        * Return a file name built with the label and containing the specified contents\r
+        *\r
+        * @return string               filename\r
+        */\r
+        \r
+       function buildFontFile($label,$contents,$ext='gdf') {\r
+               $relFilename = 'uploads/' . $this->extPrefix . '/' . $label . '_' .  t3lib_div::shortMD5($contents) . '.' . $ext;\r
+               $absFilename = PATH_site . $relFilename;\r
+               if (t3lib_div::writeFile($absFilename,$contents))       {\r
+                       return $relFilename;\r
+               } else {\r
+                       return FALSE;\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Outputs an image of a specified background color displaying a list of characters with specified font size, file and color\r
+        *\r
+        * @param       string          $text: text to display on he image\r
+        * @param       integer         $size: specified font size\r
+        * @param       string          $font: specified font file name\r
+        * @param       string          $color: specified font color\r
+        * @param       string          $bgColor: specified background color\r
+        * @param       string          $align: left or right alignment of text\r
+        * @param       string          $width: width of each character\r
+        * @param       string          $height: height of the image\r
+        * @return      array           image file info array\r
+        */\r
+       function makeFontImage($characters, $font, $width = 35, $height = 50) {\r
+               \r
+               $size = intval($height*.8);\r
+               $vertOffset = intval($height*.7);\r
+               $color = '#000000';\r
+               $bgColor = 'white';\r
+               $align = 'left';\r
+               \r
+               $charactersArray = explode(',', $characters);\r
+               $charactersCount = count($charactersArray);\r
+               \r
+               $gifObjArray = array();\r
+               $gifObjArray['backColor'] = $bgColor;\r
+               $gifObjArray['transparentBackground'] = 0;\r
+               $gifObjArray['reduceColors'] = '';\r
+               $gifObjArray['maxWidth'] = ($charactersCount*$width)+1; \r
+               $gifObjArray['XY'] = ($charactersCount*$width) .','.$height;\r
+               \r
+               for ($ic = 1; $ic < $charactersCount+1; $ic++) {\r
+                       $gifObjArray[$ic.'0'] = 'TEXT';\r
+                       $gifObjArray[$ic.'0.']['text'] = $charactersArray[$ic-1];\r
+                       \r
+                       $bbox = imagettfbbox($size, 0, $font, $charactersArray[$ic-1]);\r
+                       $hOffset = intval(($width - ($bbox[4] - $bbox[6]))/2);\r
+                       $vOffset = intval(($width - ($bbox[7] - $bbox[1]))/2);\r
+                       \r
+                       $gifObjArray[$ic.'0.']['niceText'] = 0;\r
+                       $gifObjArray[$ic.'0.']['antiAlias'] = 1;\r
+                       $gifObjArray[$ic.'0.']['align'] = $align;\r
+                       $gifObjArray[$ic.'0.']['fontSize'] = $size;\r
+                       $gifObjArray[$ic.'0.']['fontFile'] = $font;\r
+                       $gifObjArray[$ic.'0.']['fontColor'] = $color;\r
+                       $gifObjArray[$ic.'0.']['maxWidth'] = $width;\r
+                       $gifObjArray[$ic.'0.']['offset'] = (($ic-1)*$width+$hOffset).','.$vertOffset;\r
+               }\r
+               \r
+               $gifCreator = t3lib_div::makeInstance('tx_srfreecap_gifbuilder');\r
+               $theImage='';\r
+               $gifCreator->init();\r
+               if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib'])        {\r
+                       $gifCreator->start($gifObjArray,array());\r
+                       return $gifCreator->gifBuild();\r
+               } else {\r
+                       return FALSE;\r
+               }\r
+       }\r
+       \r
+/************************************************************\\r
+*\r
+*              GD Fontmaker Copyright 2005 Howard Yeend\r
+*              www.puremango.co.uk\r
+*\r
+*    This file is part of GD Fontmaker.\r
+*\r
+*    GD Fontmaker is free software; you can redistribute it and/or modify\r
+*    it under the terms of the GNU General Public License as published by\r
+*    the Free Software Foundation; either version 2 of the License, or\r
+*    (at your option) any later version.\r
+*\r
+*    GD Fontmaker is distributed in the hope that it will be useful,\r
+*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*    GNU General Public License for more details.\r
+*\r
+*    You should have received a copy of the GNU General Public License\r
+*    along with GD Fontmaker; if not, write to the Free Software\r
+*    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+*\r
+*\r
+\************************************************************/\r
+       \r
+       function makeFont($image,$numchars,$startchar,$pixelwidth,$pixelheight,$endianness=0) {\r
+               \r
+               $startchar = ord($startchar);\r
+               \r
+                       // encode this at start of font\r
+               if ($endianness) {\r
+                               // big-endian\r
+                       $fontdata = chr(0).chr(0).chr(0).chr($numchars).chr(0).chr(0).chr(0).chr($startchar).chr(0).chr(0).chr(0).chr($pixelwidth).chr(0).chr(0).chr(0).chr($pixelheight);\r
+               } else {\r
+                               // little-endian\r
+                       $fontdata = chr($numchars).chr(0).chr(0).chr(0).chr($startchar).chr(0).chr(0).chr(0).chr($pixelwidth).chr(0).chr(0).chr(0).chr($pixelheight).chr(0).chr(0).chr(0);\r
+               }\r
+                       // loop through each pixel of each character of the PNG\r
+                       // (we know the dimensions of the characters because the user told us what they were)\r
+               $y = 0;\r
+               $x = 0;\r
+               $start_x = 0;\r
+               for ($c=0; $c<$numchars*$pixelwidth ; $c+=$pixelwidth)  {\r
+                       for ($y=0 ; $y<$pixelheight ; $y++)     {\r
+                               for($x=$c ; $x<$c+$pixelwidth ; $x++)   {\r
+                                               // get colour of this pixel\r
+                                       $rgb = ImageColorAt($image, $x, $y);\r
+\r
+                                       if ($rgb==0)    {\r
+                                                       // it's black; font data\r
+                                               $fontdata .= chr(255);\r
+                                       } else {\r
+                                                       // it's not black; background\r
+                                                       $fontdata .= chr(0);\r
+                                       }\r
+                                       $i++;\r
+                               }\r
+                       }\r
+               }\r
+                return $fontdata;\r
+       }\r
+}\r
+\r
+class tx_srfreecap_gifbuilder extends tslib_gifbuilder {\r
+       \r
+       /**\r
+        * Returns the reference to a "resource" in TypoScript.\r
+        *\r
+        * @param       string          The resource value.\r
+        * @return      string          Returns the relative filepath\r
+        * @access private\r
+        * @see t3lib_TStemplate::getFileName()\r
+        */\r
+       function checkFile($file)       {\r
+               return $file;\r
+       }\r
+       \r
+       /**\r
+        * Writes the input GDlib image pointer to file\r
+        *\r
+        * @param       pointer         The GDlib image resource pointer\r
+        * @param       string          The filename to write to\r
+        * @return      mixed           The output of either imageGif, imagePng or imageJpeg based on the filename to write\r
+        * @see maskImageOntoImage(), scale(), output()\r
+        */\r
+       function ImageWrite($destImg, $theImage)        {\r
+               return parent::ImageWrite($destImg, PATH_site.$theImage);\r
+       }\r
+}\r
+\r
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/sr_freecap/mod1/class.tx_srfreecap_fontmaker.php']) {\r
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/sr_freecap/mod1/class.tx_srfreecap_fontmaker.php']);\r
+}\r
+\r
+?>\r
diff --git a/mod1/clear.gif b/mod1/clear.gif
new file mode 100644 (file)
index 0000000..9ed1269
Binary files /dev/null and b/mod1/clear.gif differ
diff --git a/mod1/conf.php b/mod1/conf.php
new file mode 100644 (file)
index 0000000..5122540
--- /dev/null
@@ -0,0 +1,14 @@
+<?php\r
+       // DO NOT REMOVE OR CHANGE THESE 3 LINES:\r
+define('TYPO3_MOD_PATH', 'ext/sr_freecap/mod1/');\r
+$BACK_PATH='../../../';\r
+$MCONF['name'] = 'tools_txsrfreecapM1';\r
+\r
+//$MCONF['script']='frameset.php';\r
+\r
+$MCONF['access'] = 'admin';\r
+$MCONF['script'] = 'index.php';\r
+\r
+$MLANG['default']['tabs_images']['tab'] = 'moduleicon.gif';\r
+$MLANG['default']['ll_ref'] = 'LLL:EXT:sr_freecap/mod1/locallang_mod.xml';\r
+?>\r
diff --git a/mod1/fontmaker.php b/mod1/fontmaker.php
new file mode 100644 (file)
index 0000000..c91eb3c
--- /dev/null
@@ -0,0 +1,135 @@
+<?\r
+if (!defined('freeCap')) die ('Access denied.');\r
+/************************************************************\\r
+*\r
+*              GD Fontmaker Copyright 2005 Howard Yeend\r
+*              www.puremango.co.uk\r
+*\r
+*    This file is part of GD Fontmaker.\r
+*\r
+*    GD Fontmaker is free software; you can redistribute it and/or modify\r
+*    it under the terms of the GNU General Public License as published by\r
+*    the Free Software Foundation; either version 2 of the License, or\r
+*    (at your option) any later version.\r
+*\r
+*    GD Fontmaker is distributed in the hope that it will be useful,\r
+*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*    GNU General Public License for more details.\r
+*\r
+*    You should have received a copy of the GNU General Public License\r
+*    along with GD Fontmaker; if not, write to the Free Software\r
+*    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+*\r
+*\r
+\************************************************************/\r
+\r
+if(!empty($_POST['numchars']))\r
+{\r
+       // create GD image from PNG\r
+       $im = @ImageCreateFromPNG($_FILES['pngfile']['tmp_name']);\r
+       if(!$im)\r
+       {\r
+               exit("Cannot create image!");\r
+       }\r
+\r
+       // get user supplied data\r
+       $numchars = $_POST['numchars'];\r
+       $startchar = ord($_POST['startchar']);\r
+       $pixelwidth = $_POST['pixelwidth'];\r
+       $pixelheight = $_POST['pixelheight'];\r
+\r
+       // encode this at start of font\r
+       $fontdata = chr($numchars).chr(0).chr(0).chr(0).chr($startchar).chr(0).chr(0).chr(0).chr($pixelwidth).chr(0).chr(0).chr(0).chr($pixelheight).chr(0).chr(0).chr(0);\r
+\r
+       // loop through each pixel of each character of the PNG\r
+       // (we know the dimensions of the characters because the user told us what they were)\r
+       $y=0;\r
+       $x=0;\r
+       $start_x=0;\r
+       for($c=0; $c<$numchars*$pixelwidth ; $c+=$pixelwidth)\r
+       {\r
+               for($y=0 ; $y<$pixelheight ; $y++)\r
+               {\r
+                       for($x=$c ; $x<$c+$pixelwidth ; $x++)\r
+                       {\r
+                               // get colour of this pixel\r
+                               $rgb = ImageColorAt($im, $x, $y);\r
+\r
+                               if($rgb==0)\r
+                               {\r
+                                       // it's black; font data\r
+                                       $fontdata .= chr(255);\r
+                               } else {\r
+                                       // it's not black; background\r
+                                       $fontdata .= chr(0);\r
+                               }\r
+                               $i++;\r
+                       }\r
+               }\r
+       }\r
+\r
+       // remove image from memory\r
+       ImageDestroy($im);\r
+\r
+       // let user download font\r
+       header("Pragma: public");\r
+       header("Expires: 0");\r
+       header("Cache-Control: must-revalidate, post-check=0, pre-check=0");\r
+       header("Cache-Control: public");\r
+       header("Content-Description: File Transfer");\r
+       header("Content-Type: application/octet-stream");\r
+       header("Content-Disposition: attachment; filename=font.gdf");\r
+       header("Content-Transfer-Encoding: binary");\r
+       header("Content-Length: ".strlen($fontdata));\r
+       echo $fontdata;\r
+       exit();\r
+}\r
+?>\r
+<html>\r
+<head>\r
+<title>GD fontMaker v1 - www.puremango.co.uk</title>\r
+<style>\r
+body,td{\r
+       font-family: verdana;\r
+       font-size: 12px;\r
+       color: black\r
+       background: white;\r
+}\r
+input{\r
+               font-family: verdana;\r
+               font-size: 12px;\r
+}\r
+</style>\r
+</head>\r
+<body>\r
+<b>GD fontMaker v1 - <a href="http://www.puremango.co.uk" target="_blank">www.puremango.co.uk</a></b><br /><br />\r
+<form action="<?=$_SERVER['PHP_SELF']?>" method="post" enctype="multipart/form-data">\r
+<table>\r
+<tr><td>total number of characters</td><td><input type="text" name="numchars"></td></tr>\r
+<tr><td>starting character</td><td><input type="text" name="startchar"></td></tr>\r
+<tr><td>character width</td><td><input type="text" name="pixelwidth"></td></tr>\r
+<tr><td>character height</td><td><input type="text" name="pixelheight"></td></tr>\r
+<tr><td>PNG image</td><td><input type="file" name="pngfile"></td></tr>\r
+<tr><td colspan="2" align="center"><input type="submit" value="make font"></td></tr>\r
+</table>\r
+This script takes a PNG image as input and creates a GD compatible font from it.<br />\r
+<br />\r
+Usage is best described with an example;<br />\r
+<a href="font.png" target="_blank">This file</a> is a PNG of the Arial font.<br />\r
+Each character is 34 pixels wide by 50 pixels high.<br />\r
+The starting character is 'a', and there are 26 characters in total.<br />\r
+Anything other than pure black will be treated as the background of the PNG; this is useful as it allows you to draw guidelines as in the example PNG<br />\r
+<br />\r
+Characters must be in ASCII code order, which means that the ideal character set is:<br />\r
+(space)!"#$%&'()*+,-./0123456789:;&lt;=&gt;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~<br />\r
+<br />\r
+But if you're lazy like me, you'll be pleased to hear that GD will process any undefined character as a space;<br />\r
+In other words, my example can be used to spell "hi there", even though there is no space defined in the font.<br />\r
+But it can't spell "Hi There" because I didn't include capitals; what it would write is:<br />" i &nbsp;here"<br /><br />\r
+<b>Known Bugs</b><br />\r
+You can't create fonts with characters greater than 255 pixels in either dimension, or with more than 255 characters in total (if you need me to, I can solve this)\r
+\r
+</form>\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/mod1/index.php b/mod1/index.php
new file mode 100644 (file)
index 0000000..8ebc7a9
--- /dev/null
@@ -0,0 +1,52 @@
+<?php\r
+/***************************************************************\r
+*  Copyright notice\r
+*\r
+*  (c) 2006-2008 Stanislas Rolland <typo3(arobas)sjbr.ca>\r
+*  All rights reserved\r
+*\r
+*  This script is part of the Typo3 project. The Typo3 project is\r
+*  free software; you can redistribute it and/or modify\r
+*  it under the terms of the GNU General Public License as published by\r
+*  the Free Software Foundation; either version 2 of the License, or\r
+*  (at your option) any later version.\r
+*\r
+*  The GNU General Public License can be found at\r
+*  http://www.gnu.org/copyleft/gpl.html.\r
+*\r
+*  This script is distributed in the hope that it will be useful,\r
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*  GNU General Public License for more details.\r
+*\r
+*  This copyright notice MUST APPEAR in all copies of the script!\r
+***************************************************************/\r
+/**\r
+* Module 'Font Maker' for the 'sr_freecap' extension.\r
+*\r
+* @author Stanislas Rolland <typo3(arobas)sjbr.ca>\r
+*/\r
+       // initialization of the module\r
+unset($MCONF);\r
+require('conf.php');\r
+require($BACK_PATH.'init.php');\r
+require($BACK_PATH.'template.php');\r
+$LANG->includeLLFile(t3lib_extMgm::extPath('sr_freecap').'mod1/locallang.xml');\r
+require_once(t3lib_extMgm::extPath('sr_freecap').'mod1/class.tx_srfreecap_fontmaker.php');\r
+\r
+$BE_USER->modAccess($MCONF, 1); // This checks permissions and exits if the users has no permission for entry.\r
+\r
+       // Make instance:\r
+$SOBE = t3lib_div::makeInstance('tx_srfreecap_fontmaker');\r
+$SOBE->init();\r
+\r
+       // Include files?\r
+reset($SOBE->include_once);\r
+while (list(, $INC_FILE) = each($SOBE->include_once)) {\r
+       include_once($INC_FILE);\r
+}\r
+\r
+$SOBE->main();\r
+$SOBE->printContent();\r
+\r
+?>\r
diff --git a/mod1/locallang.xml b/mod1/locallang.xml
new file mode 100644 (file)
index 0000000..d6d987d
--- /dev/null
@@ -0,0 +1,310 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>\r
+<T3locallang>\r
+    <meta type="array">\r
+        <description>GD Font Maker for freeCap CAPTCHA</description>\r
+        <type>module</type>\r
+        <csh_table></csh_table>\r
+        <labelContext type="array">\r
+        </labelContext>\r
+    </meta>\r
+    <data type="array">\r
+        <languageKey index="default" type="array">\r
+            <label index="title">Make GD Font for freeCap CAPTCHA</label>\r
+            <label index="charactersToIncludeInFont">Characters included in font:</label>\r
+            <label index="numbers-only">Numbers only (0-9)</label>\r
+           <label index="ASCII-lowercase-letters">ASCII lowercase letters (a-z)</label>\r
+           <label index="ANSI-extended-ASCII-lowercase-letters">ANSI-extended ASCII lowercase letters (a-z,ß-ÿ)</label>\r
+            <label index="characterWidth">Character width:</label>\r
+            <label index="characterHeight">Character height:</label>\r
+            <label index="endianness">Byte order (Endianness):</label>\r
+            <label index="littleEndian">Little-endian</label>\r
+            <label index="bigEndian">Big-endian</label>\r
+            <label index="pathToTTFFile">Path to source TTF font file relative to TYPO3 site:</label>\r
+            <label index="gdFontFilePrefix">Prefix of GD font file name to create:</label>\r
+           <label index="makeFont">Make font</label>\r
+           <label index="usingFontFile">The following TTF font file is used as source:</label>\r
+           <label index="ttfFontFileNotFound">The source TTF font file could not be found:</label>\r
+           <label index="pngImageCreated">The following PNG image was created:</label>\r
+           <label index="gdFontFileCreated">The following GD font file was created from the above image:</label>\r
+           <label index="gdFontFileNotCreated">The following GD font file could not be created:</label>\r
+        </languageKey>\r
+        <languageKey index="dk" type="array">\r
+        </languageKey>\r
+        <languageKey index="de" type="array">\r
+        </languageKey>\r
+        <languageKey index="no" type="array">\r
+        </languageKey>\r
+        <languageKey index="it" type="array">\r
+        </languageKey>\r
+        <languageKey index="fr" type="array">\r
+            <label index="title">Fabrication d'une police de caractères GD pour freeCap CAPTCHA</label>\r
+           <label index="charactersToIncludeInFont">Caractères inclus dans la police:</label>\r
+           <label index="numbers-only">Chiffres seulement (0-9)</label>\r
+           <label index="ASCII-lowercase-letters">Lettres minuscules ASCII (a-z)</label>\r
+           <label index="ANSI-extended-ASCII-lowercase-letters">Lettres minuscules ASCII étendu par ANSI (a-z,ß-ÿ)</label>\r
+            <label index="characterWidth">Largeur des caractères:</label>\r
+            <label index="characterHeight">Hauteur des caractères:</label>\r
+            <label index="endianness">Ordre des octets (endianness):</label>\r
+            <label index="littleEndian">Petit-boutiste</label>\r
+            <label index="bigEndian">Gros-boutiste</label>\r
+            <label index="pathToTTFFile">Chemin jusqu'au fichier de police TTF d'entrée relativement au site TYPO3:</label>\r
+           <label index="gdFontFilePrefix">Préfixe du nom du fichier de police GD à créer:</label>\r
+           <label index="makeFont">Fabriquer la police</label>\r
+           <label index="usingFontFile">Le fichier de police TTF suivant est utilisé en entrée:</label>\r
+           <label index="ttfFontFileNotFound">Le fichier de police TTF d'entrée n'a pas été trouvé:</label>\r
+           <label index="pngImageCreated">L'image PNG suivante a été créée:</label>\r
+           <label index="gdFontFileCreated">Le fichier de police GD suivant a été créé à partir de l'image ci-haut:</label>\r
+           <label index="gdFontFileNotCreated">Le fichier de police GD suivant n'a pas pu être créé:</label>\r
+        </languageKey>\r
+        <languageKey index="es" type="array">\r
+        </languageKey>\r
+        <languageKey index="nl" type="array">\r
+        </languageKey>\r
+        <languageKey index="cz" type="array">\r
+        </languageKey>\r
+        <languageKey index="pl" type="array">\r
+        </languageKey>\r
+        <languageKey index="si" type="array">\r
+        </languageKey>\r
+        <languageKey index="fi" type="array">\r
+        </languageKey>\r
+        <languageKey index="tr" type="array">\r
+        </languageKey>\r
+        <languageKey index="se" type="array">\r
+        </languageKey>\r
+        <languageKey index="pt" type="array">\r
+        </languageKey>\r
+        <languageKey index="ru" type="array">\r
+        </languageKey>\r
+        <languageKey index="ro" type="array">\r
+        </languageKey>\r
+        <languageKey index="ch" type="array">\r
+        </languageKey>\r
+        <languageKey index="sk" type="array">\r
+        </languageKey>\r
+        <languageKey index="lt" type="array">\r
+        </languageKey>\r
+        <languageKey index="is" type="array">\r
+        </languageKey>\r
+        <languageKey index="hr" type="array">\r
+        </languageKey>\r
+        <languageKey index="hu" type="array">\r
+        </languageKey>\r
+        <languageKey index="gl" type="array">\r
+        </languageKey>\r
+        <languageKey index="th" type="array">\r
+        </languageKey>\r
+        <languageKey index="gr" type="array">\r
+        </languageKey>\r
+        <languageKey index="hk" type="array">\r
+        </languageKey>\r
+        <languageKey index="eu" type="array">\r
+        </languageKey>\r
+        <languageKey index="bg" type="array">\r
+        </languageKey>\r
+        <languageKey index="br" type="array">\r
+        </languageKey>\r
+        <languageKey index="et" type="array">\r
+        </languageKey>\r
+        <languageKey index="ar" type="array">\r
+        </languageKey>\r
+        <languageKey index="he" type="array">\r
+        </languageKey>\r
+        <languageKey index="ua" type="array">\r
+        </languageKey>\r
+        <languageKey index="lv" type="array">\r
+        </languageKey>\r
+        <languageKey index="jp" type="array">\r
+        </languageKey>\r
+        <languageKey index="vn" type="array">\r
+        </languageKey>\r
+        <languageKey index="ca" type="array">\r
+        </languageKey>\r
+        <languageKey index="ba" type="array">\r
+        </languageKey>\r
+        <languageKey index="kr" type="array">\r
+        </languageKey>\r
+        <languageKey index="eo" type="array">\r
+        </languageKey>\r
+        <languageKey index="my" type="array">\r
+        </languageKey>\r
+        <languageKey index="hi" type="array">\r
+        </languageKey>\r
+    </data>\r
+    <orig_hash type="array">\r
+        <languageKey index="default" type="array">\r
+        </languageKey>\r
+        <languageKey index="dk" type="array">\r
+        </languageKey>\r
+        <languageKey index="de" type="array">\r
+        </languageKey>\r
+        <languageKey index="no" type="array">\r
+        </languageKey>\r
+        <languageKey index="it" type="array">\r
+        </languageKey>\r
+        <languageKey index="fr" type="array">\r
+        </languageKey>\r
+        <languageKey index="es" type="array">\r
+        </languageKey>\r
+        <languageKey index="nl" type="array">\r
+        </languageKey>\r
+        <languageKey index="cz" type="array">\r
+        </languageKey>\r
+        <languageKey index="pl" type="array">\r
+        </languageKey>\r
+        <languageKey index="si" type="array">\r
+        </languageKey>\r
+        <languageKey index="fi" type="array">\r
+        </languageKey>\r
+        <languageKey index="tr" type="array">\r
+        </languageKey>\r
+        <languageKey index="se" type="array">\r
+        </languageKey>\r
+        <languageKey index="pt" type="array">\r
+        </languageKey>\r
+        <languageKey index="ru" type="array">\r
+        </languageKey>\r
+        <languageKey index="ro" type="array">\r
+        </languageKey>\r
+        <languageKey index="ch" type="array">\r
+        </languageKey>\r
+        <languageKey index="sk" type="array">\r
+        </languageKey>\r
+        <languageKey index="lt" type="array">\r
+        </languageKey>\r
+        <languageKey index="is" type="array">\r
+        </languageKey>\r
+        <languageKey index="hr" type="array">\r
+        </languageKey>\r
+        <languageKey index="hu" type="array">\r
+        </languageKey>\r
+        <languageKey index="gl" type="array">\r
+        </languageKey>\r
+        <languageKey index="th" type="array">\r
+        </languageKey>\r
+        <languageKey index="gr" type="array">\r
+        </languageKey>\r
+        <languageKey index="hk" type="array">\r
+        </languageKey>\r
+        <languageKey index="eu" type="array">\r
+        </languageKey>\r
+        <languageKey index="bg" type="array">\r
+        </languageKey>\r
+        <languageKey index="br" type="array">\r
+        </languageKey>\r
+        <languageKey index="et" type="array">\r
+        </languageKey>\r
+        <languageKey index="ar" type="array">\r
+        </languageKey>\r
+        <languageKey index="he" type="array">\r
+        </languageKey>\r
+        <languageKey index="ua" type="array">\r
+        </languageKey>\r
+        <languageKey index="lv" type="array">\r
+        </languageKey>\r
+        <languageKey index="jp" type="array">\r
+        </languageKey>\r
+        <languageKey index="vn" type="array">\r
+        </languageKey>\r
+        <languageKey index="ca" type="array">\r
+        </languageKey>\r
+        <languageKey index="ba" type="array">\r
+        </languageKey>\r
+        <languageKey index="kr" type="array">\r
+        </languageKey>\r
+        <languageKey index="eo" type="array">\r
+        </languageKey>\r
+        <languageKey index="my" type="array">\r
+        </languageKey>\r
+        <languageKey index="hi" type="array">\r
+        </languageKey>\r
+    </orig_hash>\r
+    <orig_text type="array">\r
+        <languageKey index="default" type="array">\r
+        </languageKey>\r
+        <languageKey index="dk" type="array">\r
+        </languageKey>\r
+        <languageKey index="de" type="array">\r
+        </languageKey>\r
+        <languageKey index="no" type="array">\r
+        </languageKey>\r
+        <languageKey index="it" type="array">\r
+        </languageKey>\r
+        <languageKey index="fr" type="array">\r
+        </languageKey>\r
+        <languageKey index="es" type="array">\r
+        </languageKey>\r
+        <languageKey index="nl" type="array">\r
+        </languageKey>\r
+        <languageKey index="cz" type="array">\r
+        </languageKey>\r
+        <languageKey index="pl" type="array">\r
+        </languageKey>\r
+        <languageKey index="si" type="array">\r
+        </languageKey>\r
+        <languageKey index="fi" type="array">\r
+        </languageKey>\r
+        <languageKey index="tr" type="array">\r
+        </languageKey>\r
+        <languageKey index="se" type="array">\r
+        </languageKey>\r
+        <languageKey index="pt" type="array">\r
+        </languageKey>\r
+        <languageKey index="ru" type="array">\r
+        </languageKey>\r
+        <languageKey index="ro" type="array">\r
+        </languageKey>\r
+        <languageKey index="ch" type="array">\r
+        </languageKey>\r
+        <languageKey index="sk" type="array">\r
+        </languageKey>\r
+        <languageKey index="lt" type="array">\r
+        </languageKey>\r
+        <languageKey index="is" type="array">\r
+        </languageKey>\r
+        <languageKey index="hr" type="array">\r
+        </languageKey>\r
+        <languageKey index="hu" type="array">\r
+        </languageKey>\r
+        <languageKey index="gl" type="array">\r
+        </languageKey>\r
+        <languageKey index="th" type="array">\r
+        </languageKey>\r
+        <languageKey index="gr" type="array">\r
+        </languageKey>\r
+        <languageKey index="hk" type="array">\r
+        </languageKey>\r
+        <languageKey index="eu" type="array">\r
+        </languageKey>\r
+        <languageKey index="bg" type="array">\r
+        </languageKey>\r
+        <languageKey index="br" type="array">\r
+        </languageKey>\r
+        <languageKey index="et" type="array">\r
+        </languageKey>\r
+        <languageKey index="ar" type="array">\r
+        </languageKey>\r
+        <languageKey index="he" type="array">\r
+        </languageKey>\r
+        <languageKey index="ua" type="array">\r
+        </languageKey>\r
+        <languageKey index="lv" type="array">\r
+        </languageKey>\r
+        <languageKey index="jp" type="array">\r
+        </languageKey>\r
+        <languageKey index="vn" type="array">\r
+        </languageKey>\r
+        <languageKey index="ca" type="array">\r
+        </languageKey>\r
+        <languageKey index="ba" type="array">\r
+        </languageKey>\r
+        <languageKey index="kr" type="array">\r
+        </languageKey>\r
+        <languageKey index="eo" type="array">\r
+        </languageKey>\r
+        <languageKey index="my" type="array">\r
+        </languageKey>\r
+        <languageKey index="hi" type="array">\r
+        </languageKey>\r
+    </orig_text>\r
+</T3locallang>
\ No newline at end of file
diff --git a/mod1/locallang_mod.xml b/mod1/locallang_mod.xml
new file mode 100644 (file)
index 0000000..c37b3df
--- /dev/null
@@ -0,0 +1,280 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>\r
+<T3locallang>\r
+    <meta type="array">\r
+        <description>sr_freecap font maker module</description>\r
+        <type>module</type>\r
+        <csh_table></csh_table>\r
+        <labelContext type="array">\r
+        </labelContext>\r
+    </meta>\r
+    <data type="array">\r
+        <languageKey index="default" type="array">\r
+            <label index="mlang_labels_tablabel">GD Font Maker for freeCap CAPTCHA</label>\r
+            <label index="mlang_labels_tabdescr">Makes GD font files for use by freeCap CAPTCHA.</label>\r
+            <label index="mlang_tabs_tab">GD Font Maker</label>\r
+        </languageKey>\r
+        <languageKey index="dk" type="array">\r
+        </languageKey>\r
+        <languageKey index="de" type="array">\r
+        </languageKey>\r
+        <languageKey index="no" type="array">\r
+        </languageKey>\r
+        <languageKey index="it" type="array">\r
+        </languageKey>\r
+        <languageKey index="fr" type="array">\r
+            <label index="mlang_labels_tablabel">Polices de caractères GD pour freeCap CAPTCHA</label>\r
+            <label index="mlang_labels_tabdescr">Ce module permet de fabriquer des polices de caratères GD pour utilisation par freeCap CAPTCHA.</label>\r
+            <label index="mlang_tabs_tab">Polices GD</label>\r
+        </languageKey>\r
+        <languageKey index="es" type="array">\r
+        </languageKey>\r
+        <languageKey index="nl" type="array">\r
+        </languageKey>\r
+        <languageKey index="cz" type="array">\r
+        </languageKey>\r
+        <languageKey index="pl" type="array">\r
+        </languageKey>\r
+        <languageKey index="si" type="array">\r
+        </languageKey>\r
+        <languageKey index="fi" type="array">\r
+        </languageKey>\r
+        <languageKey index="tr" type="array">\r
+        </languageKey>\r
+        <languageKey index="se" type="array">\r
+        </languageKey>\r
+        <languageKey index="pt" type="array">\r
+        </languageKey>\r
+        <languageKey index="ru" type="array">\r
+        </languageKey>\r
+        <languageKey index="ro" type="array">\r
+        </languageKey>\r
+        <languageKey index="ch" type="array">\r
+        </languageKey>\r
+        <languageKey index="sk" type="array">\r
+        </languageKey>\r
+        <languageKey index="lt" type="array">\r
+        </languageKey>\r
+        <languageKey index="is" type="array">\r
+        </languageKey>\r
+        <languageKey index="hr" type="array">\r
+        </languageKey>\r
+        <languageKey index="hu" type="array">\r
+        </languageKey>\r
+        <languageKey index="gl" type="array">\r
+        </languageKey>\r
+        <languageKey index="th" type="array">\r
+        </languageKey>\r
+        <languageKey index="gr" type="array">\r
+        </languageKey>\r
+        <languageKey index="hk" type="array">\r
+        </languageKey>\r
+        <languageKey index="eu" type="array">\r
+        </languageKey>\r
+        <languageKey index="bg" type="array">\r
+        </languageKey>\r
+        <languageKey index="br" type="array">\r
+        </languageKey>\r
+        <languageKey index="et" type="array">\r
+        </languageKey>\r
+        <languageKey index="ar" type="array">\r
+        </languageKey>\r
+        <languageKey index="he" type="array">\r
+        </languageKey>\r
+        <languageKey index="ua" type="array">\r
+        </languageKey>\r
+        <languageKey index="lv" type="array">\r
+        </languageKey>\r
+        <languageKey index="jp" type="array">\r
+        </languageKey>\r
+        <languageKey index="vn" type="array">\r
+        </languageKey>\r
+        <languageKey index="ca" type="array">\r
+        </languageKey>\r
+        <languageKey index="ba" type="array">\r
+        </languageKey>\r
+        <languageKey index="kr" type="array">\r
+        </languageKey>\r
+        <languageKey index="eo" type="array">\r
+        </languageKey>\r
+        <languageKey index="my" type="array">\r
+        </languageKey>\r
+        <languageKey index="hi" type="array">\r
+        </languageKey>\r
+    </data>\r
+    <orig_hash type="array">\r
+        <languageKey index="default" type="array">\r
+        </languageKey>\r
+        <languageKey index="dk" type="array">\r
+        </languageKey>\r
+        <languageKey index="de" type="array">\r
+        </languageKey>\r
+        <languageKey index="no" type="array">\r
+        </languageKey>\r
+        <languageKey index="it" type="array">\r
+        </languageKey>\r
+        <languageKey index="fr" type="array">\r
+        </languageKey>\r
+        <languageKey index="es" type="array">\r
+        </languageKey>\r
+        <languageKey index="nl" type="array">\r
+        </languageKey>\r
+        <languageKey index="cz" type="array">\r
+        </languageKey>\r
+        <languageKey index="pl" type="array">\r
+        </languageKey>\r
+        <languageKey index="si" type="array">\r
+        </languageKey>\r
+        <languageKey index="fi" type="array">\r
+        </languageKey>\r
+        <languageKey index="tr" type="array">\r
+        </languageKey>\r
+        <languageKey index="se" type="array">\r
+        </languageKey>\r
+        <languageKey index="pt" type="array">\r
+        </languageKey>\r
+        <languageKey index="ru" type="array">\r
+        </languageKey>\r
+        <languageKey index="ro" type="array">\r
+        </languageKey>\r
+        <languageKey index="ch" type="array">\r
+        </languageKey>\r
+        <languageKey index="sk" type="array">\r
+        </languageKey>\r
+        <languageKey index="lt" type="array">\r
+        </languageKey>\r
+        <languageKey index="is" type="array">\r
+        </languageKey>\r
+        <languageKey index="hr" type="array">\r
+        </languageKey>\r
+        <languageKey index="hu" type="array">\r
+        </languageKey>\r
+        <languageKey index="gl" type="array">\r
+        </languageKey>\r
+        <languageKey index="th" type="array">\r
+        </languageKey>\r
+        <languageKey index="gr" type="array">\r
+        </languageKey>\r
+        <languageKey index="hk" type="array">\r
+        </languageKey>\r
+        <languageKey index="eu" type="array">\r
+        </languageKey>\r
+        <languageKey index="bg" type="array">\r
+        </languageKey>\r
+        <languageKey index="br" type="array">\r
+        </languageKey>\r
+        <languageKey index="et" type="array">\r
+        </languageKey>\r
+        <languageKey index="ar" type="array">\r
+        </languageKey>\r
+        <languageKey index="he" type="array">\r
+        </languageKey>\r
+        <languageKey index="ua" type="array">\r
+        </languageKey>\r
+        <languageKey index="lv" type="array">\r
+        </languageKey>\r
+        <languageKey index="jp" type="array">\r
+        </languageKey>\r
+        <languageKey index="vn" type="array">\r
+        </languageKey>\r
+        <languageKey index="ca" type="array">\r
+        </languageKey>\r
+        <languageKey index="ba" type="array">\r
+        </languageKey>\r
+        <languageKey index="kr" type="array">\r
+        </languageKey>\r
+        <languageKey index="eo" type="array">\r
+        </languageKey>\r
+        <languageKey index="my" type="array">\r
+        </languageKey>\r
+        <languageKey index="hi" type="array">\r
+        </languageKey>\r
+    </orig_hash>\r
+    <orig_text type="array">\r
+        <languageKey index="default" type="array">\r
+        </languageKey>\r
+        <languageKey index="dk" type="array">\r
+        </languageKey>\r
+        <languageKey index="de" type="array">\r
+        </languageKey>\r
+        <languageKey index="no" type="array">\r
+        </languageKey>\r
+        <languageKey index="it" type="array">\r
+        </languageKey>\r
+        <languageKey index="fr" type="array">\r
+        </languageKey>\r
+        <languageKey index="es" type="array">\r
+        </languageKey>\r
+        <languageKey index="nl" type="array">\r
+        </languageKey>\r
+        <languageKey index="cz" type="array">\r
+        </languageKey>\r
+        <languageKey index="pl" type="array">\r
+        </languageKey>\r
+        <languageKey index="si" type="array">\r
+        </languageKey>\r
+        <languageKey index="fi" type="array">\r
+        </languageKey>\r
+        <languageKey index="tr" type="array">\r
+        </languageKey>\r
+        <languageKey index="se" type="array">\r
+        </languageKey>\r
+        <languageKey index="pt" type="array">\r
+        </languageKey>\r
+        <languageKey index="ru" type="array">\r
+        </languageKey>\r
+        <languageKey index="ro" type="array">\r
+        </languageKey>\r
+        <languageKey index="ch" type="array">\r
+        </languageKey>\r
+        <languageKey index="sk" type="array">\r
+        </languageKey>\r
+        <languageKey index="lt" type="array">\r
+        </languageKey>\r
+        <languageKey index="is" type="array">\r
+        </languageKey>\r
+        <languageKey index="hr" type="array">\r
+        </languageKey>\r
+        <languageKey index="hu" type="array">\r
+        </languageKey>\r
+        <languageKey index="gl" type="array">\r
+        </languageKey>\r
+        <languageKey index="th" type="array">\r
+        </languageKey>\r
+        <languageKey index="gr" type="array">\r
+        </languageKey>\r
+        <languageKey index="hk" type="array">\r
+        </languageKey>\r
+        <languageKey index="eu" type="array">\r
+        </languageKey>\r
+        <languageKey index="bg" type="array">\r
+        </languageKey>\r
+        <languageKey index="br" type="array">\r
+        </languageKey>\r
+        <languageKey index="et" type="array">\r
+        </languageKey>\r
+        <languageKey index="ar" type="array">\r
+        </languageKey>\r
+        <languageKey index="he" type="array">\r
+        </languageKey>\r
+        <languageKey index="ua" type="array">\r
+        </languageKey>\r
+        <languageKey index="lv" type="array">\r
+        </languageKey>\r
+        <languageKey index="jp" type="array">\r
+        </languageKey>\r
+        <languageKey index="vn" type="array">\r
+        </languageKey>\r
+        <languageKey index="ca" type="array">\r
+        </languageKey>\r
+        <languageKey index="ba" type="array">\r
+        </languageKey>\r
+        <languageKey index="kr" type="array">\r
+        </languageKey>\r
+        <languageKey index="eo" type="array">\r
+        </languageKey>\r
+        <languageKey index="my" type="array">\r
+        </languageKey>\r
+        <languageKey index="hi" type="array">\r
+        </languageKey>\r
+    </orig_text>\r
+</T3locallang>
\ No newline at end of file
diff --git a/mod1/moduleicon.gif b/mod1/moduleicon.gif
new file mode 100644 (file)
index 0000000..37abb9f
Binary files /dev/null and b/mod1/moduleicon.gif differ
diff --git a/pi1/captcha.php b/pi1/captcha.php
new file mode 100644 (file)
index 0000000..d76defb
--- /dev/null
@@ -0,0 +1,135 @@
+<?php\r
+/***************************************************************\r
+*  Copyright notice\r
+*\r
+*  (c) 2005-2008 Stanislas Rolland <typo3(arobas)sjbr.ca>\r
+*  All rights reserved\r
+*\r
+*  This script is part of the Typo3 project. The Typo3 project is\r
+*  free software; you can redistribute it and/or modify\r
+*  it under the terms of the GNU General Public License as published by\r
+*  the Free Software Foundation; either version 2 of the License, or\r
+*  (at your option) any later version.\r
+*\r
+*  The GNU General Public License can be found at\r
+*  http://www.gnu.org/copyleft/gpl.html.\r
+*\r
+*  This script is distributed in the hope that it will be useful,\r
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*  GNU General Public License for more details.\r
+*\r
+*  This copyright notice MUST APPEAR in all copies of the script!\r
+***************************************************************/\r
+/**\r
+* This script invokes the freecap CAPTCHA image generation\r
+*\r
+*/\r
+error_reporting (E_ALL ^ E_NOTICE);\r
+define('PATH_thisScript',str_replace('//','/', str_replace('\\','/', (php_sapi_name()=='cgi'||php_sapi_name()=='xcgi'||php_sapi_name()=='isapi' ||php_sapi_name()=='cgi-fcgi')&&((!empty($_SERVER['ORIG_PATH_TRANSLATED'])&&isset($_SERVER['ORIG_PATH_TRANSLATED']))?$_SERVER['ORIG_PATH_TRANSLATED']:$_SERVER['PATH_TRANSLATED'])? ((!empty($_SERVER['ORIG_PATH_TRANSLATED'])&&isset($_SERVER['ORIG_PATH_TRANSLATED']))?$_SERVER['ORIG_PATH_TRANSLATED']:$_SERVER['PATH_TRANSLATED']):((!empty($_SERVER['ORIG_SCRIPT_FILENAME'])&&isset($_SERVER['ORIG_SCRIPT_FILENAME']))?$_SERVER['ORIG_SCRIPT_FILENAME']:$_SERVER['SCRIPT_FILENAME']))));\r
+if (!defined('PATH_site')) define('PATH_site', dirname(dirname(dirname(dirname(dirname(PATH_thisScript))))).'/');\r
+if (!defined('PATH_t3lib')) define('PATH_t3lib', PATH_site.'t3lib/');\r
+define('PATH_typo3conf', PATH_site.'typo3conf/');\r
+define('TYPO3_mainDir', 'typo3/');\r
+if (!defined('PATH_typo3')) define('PATH_typo3', PATH_site.TYPO3_mainDir);\r
+if (!defined('PATH_tslib')) {\r
+       if (@is_dir(PATH_site.'typo3/sysext/cms/tslib/')) {\r
+               define('PATH_tslib', PATH_site.'typo3/sysext/cms/tslib/');\r
+       } elseif (@is_dir(PATH_site.'tslib/')) {\r
+               define('PATH_tslib', PATH_site.'tslib/');\r
+       }\r
+}\r
+define('TYPO3_MODE','FE');\r
+define('TYPO3_OS', stristr(PHP_OS,'win')&&!stristr(PHP_OS,'darwin')?'WIN':'');\r
+\r
+require_once(PATH_t3lib.'class.t3lib_div.php');\r
+require_once(PATH_t3lib.'class.t3lib_extmgm.php');\r
+require_once(PATH_t3lib.'config_default.php');\r
+require_once(PATH_typo3conf.'localconf.php');\r
+require_once(PATH_tslib.'class.tslib_fe.php');\r
+require_once(PATH_t3lib.'class.t3lib_tstemplate.php');\r
+require_once(PATH_t3lib.'class.t3lib_page.php');\r
+require_once(PATH_tslib.'class.tslib_content.php');\r
+require_once(t3lib_extMgm::extPath('sr_freecap').'pi1/class.tx_srfreecap_pi1.php');\r
+require_once(PATH_t3lib.'class.t3lib_userauth.php');\r
+require_once(PATH_tslib.'class.tslib_feuserauth.php');\r
+require_once(PATH_t3lib.'class.t3lib_cs.php');\r
+\r
+if (!defined ('TYPO3_db'))  die ('The configuration file was not included.');\r
+if (isset($_GET['GLOBALS']) || isset($_POST['GLOBALS']) || isset($_FILES['GLOBALS']) || isset($_COOKIE['GLOBALS'])) die('You cannot set the GLOBALS-array from outside this script.');\r
+\r
+require_once(PATH_t3lib.'class.t3lib_db.php');\r
+$TYPO3_DB = t3lib_div::makeInstance('t3lib_DB');\r
+\r
+require_once(PATH_t3lib.'class.t3lib_timetrack.php');\r
+$GLOBALS['TT'] = new t3lib_timeTrack;\r
+\r
+if (t3lib_div::int_from_ver( TYPO3_version ) >= 4003000) {\r
+       // ***********************************\r
+       // Initializing the Caching System\r
+       // ***********************************\r
+       $GLOBALS['TT']->push('Initializing the Caching System','');\r
+               require_once(PATH_t3lib . 'class.t3lib_cache.php');\r
+\r
+               require_once(PATH_t3lib . 'cache/class.t3lib_cache_abstractbackend.php');\r
+               require_once(PATH_t3lib . 'cache/class.t3lib_cache_abstractcache.php');\r
+               require_once(PATH_t3lib . 'cache/class.t3lib_cache_exception.php');\r
+               require_once(PATH_t3lib . 'cache/class.t3lib_cache_factory.php');\r
+               require_once(PATH_t3lib . 'cache/class.t3lib_cache_manager.php');\r
+               require_once(PATH_t3lib . 'cache/class.t3lib_cache_variablecache.php');\r
+\r
+               require_once(PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_classalreadyloaded.php');\r
+               require_once(PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_duplicateidentifier.php');\r
+               require_once(PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_invalidbackend.php');\r
+               require_once(PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_invalidcache.php');\r
+               require_once(PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_invaliddata.php');\r
+               require_once(PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_nosuchcache.php');\r
+\r
+               $typo3CacheManager = t3lib_div::makeInstance('t3lib_cache_Manager');\r
+               $cacheFactoryClass = t3lib_div::makeInstanceClassName('t3lib_cache_Factory');\r
+               $typo3CacheFactory = new $cacheFactoryClass($typo3CacheManager);\r
+\r
+               unset($cacheFactoryClass);\r
+       $GLOBALS['TT']->pull();\r
+}\r
+\r
+// ***********************************\r
+// Creating a $TSFE object\r
+// ***********************************\r
+$TSFEclassName = t3lib_div::makeInstanceClassName('tslib_fe');\r
+$id = t3lib_div::_GET('id');\r
+if (!isset($id)) $id = 0;\r
+$id = htmlspecialchars($id);\r
+$TSFE = new $TSFEclassName($TYPO3_CONF_VARS, $id, '0', 1, '', '','','');\r
+if (t3lib_div::int_from_ver( TYPO3_version ) >= 4003000) {\r
+       $TSFE->initCaches();\r
+}\r
+$TSFE->set_no_cache();\r
+$TSFE->connectToDB();\r
+$TSFE->initFEuser();\r
+$TSFE->determineId();\r
+$TSFE->initTemplate();\r
+$TSFE->tmpl->getFileName_backPath = PATH_site;\r
+\r
+// ******************************************************\r
+// Get config if not already gotten\r
+// After this, we should have a valid config-array ready\r
+// ******************************************************\r
+$TSFE->getConfigArray();\r
+\r
+// *******************************************\r
+// Setting language and locale\r
+// *******************************************\r
+$GLOBALS['TT']->push('Setting language and locale','');\r
+       $TSFE->settingLanguage();\r
+       $TSFE->settingLocale();\r
+$GLOBALS['TT']->pull();\r
+\r
+// *******************************************\r
+// Invoke the freecap plugin\r
+// *******************************************\r
+$freecap = t3lib_div::makeInstance('tx_srfreecap_pi1');\r
+$freecap->cObj = t3lib_div::makeInstance('tslib_cObj');\r
+$conf = $TSFE->tmpl->setup['plugin.'][$freecap->prefixId.'.'];\r
+$freecap->main($conf);\r
+?>
\ No newline at end of file
diff --git a/pi1/class.tx_srfreecap_pi1.php b/pi1/class.tx_srfreecap_pi1.php
new file mode 100644 (file)
index 0000000..1d15cbd
--- /dev/null
@@ -0,0 +1,909 @@
+<?php\r
+/***************************************************************\r
+*  Copyright notice\r
+*\r
+*  (c) 2005-2008 Stanislas Rolland (typo3(arobas)sjbr.ca)\r
+*  All rights reserved\r
+*\r
+*  This script is part of the TYPO3 project. The TYPO3 project is\r
+*  free software; you can redistribute it and/or modify\r
+*  it under the terms of the GNU General Public License as published by\r
+*  the Free Software Foundation; either version 2 of the License, or\r
+*  (at your option) any later version.\r
+*\r
+*  The GNU General Public License can be found at\r
+*  http://www.gnu.org/copyleft/gpl.html.\r
+*  A copy is found in the textfile GPL.txt and important notices to the license\r
+*  from the author is found in LICENSE.txt distributed with these scripts.\r
+*\r
+*\r
+*  This script is distributed in the hope that it will be useful,\r
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*  GNU General Public License for more details.\r
+*\r
+*  This copyright notice MUST APPEAR in all copies of the script!\r
+***************************************************************/\r
+/**\r
+ * Integrates freeCap v1.4.1 into TYPO3 and generates the freeCap CAPTCHA image.\r
+ *\r
+ *\r
+ * @author     Stanislas Rolland       <typo3(arobas)sjbr.ca>\r
+ */\r
+/************************************************************\\r
+*\r
+*              freeCap v1.4.1 Copyright 2005 Howard Yeend\r
+*              www.puremango.co.uk\r
+*\r
+*    This file is part of freeCap.\r
+*\r
+*    freeCap is free software; you can redistribute it and/or modify\r
+*    it under the terms of the GNU General Public License as published by\r
+*    the Free Software Foundation; either version 2 of the License, or\r
+*    (at your option) any later version.\r
+*\r
+*    freeCap is distributed in the hope that it will be useful,\r
+*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*    GNU General Public License for more details.\r
+*\r
+*    You should have received a copy of the GNU General Public License\r
+*    along with freeCap; if not, write to the Free Software\r
+*    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+*\r
+*\r
+\************************************************************/\r
+\r
+require_once(PATH_tslib.'class.tslib_pibase.php');\r
+\r
+class tx_srfreecap_pi1 extends tslib_pibase {\r
+       var $cObj;                              // The backReference to the mother cObj object set at call time\r
+       var $prefixId = 'tx_srfreecap_pi1';     // Same as class name\r
+       var $scriptRelPath = 'pi1/class.tx_srfreecap_pi1.php';  // Path to this script relative to the extension dir.\r
+       var $extKey = 'sr_freecap';             // The extension key.\r
+       var $extPrefix = 'tx_srfreecap';\r
+       var $conf = array();\r
+\r
+       function main($conf) {\r
+               $this->conf = $conf;\r
+               $this->pi_loadLL();\r
+\r
+                       // Get session data\r
+               $this->sessionData = $GLOBALS['TSFE']->fe_user->getKey('ses','tx_'.$this->extKey);\r
+\r
+               //////////////////////////////////////////////////////\r
+               ////// User Defined Vars:\r
+               //////////////////////////////////////////////////////\r
+\r
+               // try to avoid the 'free p*rn' method of CAPTCHA circumvention\r
+               // see www.wikipedia.com/captcha for more info\r
+               $this->site_tags[0] = "To avoid spam, please do NOT enter the text if";\r
+               $this->site_tags[1] = "this site is not puremango.co.uk";\r
+               // or more simply:\r
+               //$site_tags[0] = "for use only on puremango.co.uk";\r
+               // reword or add lines as you please\r
+               // or if you don't want any text:\r
+               $this->site_tags = $this->conf['siteTag'] ? explode('|', sprintf($this->pi_getLL('site_tag'), (isset($this->conf['siteTagDomain']) ? $this->conf['siteTagDomain'] : 'www.typo3.org'))) : null;\r
+               // where to write the above:\r
+               // 0=top\r
+               // 1=bottom\r
+               // 2=both\r
+               $this->tag_pos = isset($this->conf['siteTagPosition']) ? $this->conf['siteTagPosition'] : 1;\r
+\r
+               // which type of hash to use?\r
+               // possible values: "sha1", "md5", "crc32"\r
+               // sha1 supported by PHP4.3.0+\r
+               // md5 supported by PHP3+\r
+               // crc32 supported by PHP4.0.1+\r
+               // store in session so can validate in form processor\r
+               $this->sessionData[$this->extKey . '_hash_func'] = 'md5';\r
+\r
+               // image type:\r
+               // possible values: "jpg", "png", "gif"\r
+               // jpg doesn't support transparency (transparent bg option ends up white)\r
+               // png isn't supported by old browsers (see http://www.libpng.org/pub/png/pngstatus.html)\r
+               // gif may not be supported by your GD Lib.\r
+               $this->output = $this->conf['imageFormat'] ? $this->conf['imageFormat'] : 'png';\r
+               \r
+               // true = generate pseudo-random string, false = use dictionary\r
+               // dictionary is easier to recognise\r
+               // - both for humans and computers, so use random string if you're paranoid.\r
+               $this->use_dict = $this->conf['useWordsList'] ? true : false;\r
+               \r
+               // if your server is NOT set up to deny web access to files beginning ".ht"\r
+               // then you should ensure the dictionary file is kept outside the web directory\r
+               // eg: if www.foo.com/index.html points to c:\website\www\index.html\r
+               // then the dictionary should be placed in c:\website\dict.txt\r
+               // test your server's config by trying to access the dictionary through a web browser\r
+               // you should NOT be able to view the contents.\r
+               // can leave this blank if not using dictionary\r
+               if (!trim($this->conf['defaultWordsList'])) {\r
+                       $this->conf['defaultWordsList'] = 'EXT:sr_freecap/res/words/.ht_default_freecap_words';\r
+               }\r
+               if (is_file(dirname(t3lib_div::getFileAbsFileName($this->conf['defaultWordsList'])) . '/.ht_' . $this->LLkey . '_freecap_words')) {\r
+                       $this->dict_location = dirname(t3lib_div::getFileAbsFileName($this->conf['defaultWordsList'])) . '/.ht_' . $this->LLkey . '_freecap_words';\r
+               } elseif (is_file(dirname(t3lib_div::getFileAbsFileName($this->conf['defaultWordsList'])) . '/.ht_default_freecap_words')) {\r
+                       $this->dict_location = dirname(t3lib_div::getFileAbsFileName($this->conf['defaultWordsList'])) . '/.ht_default_freecap_words';\r
+               }\r
+               \r
+               // used to calculate image width, and for non-dictionary word generation\r
+               $this->max_word_length = $this->conf['maxWordLength'] ? $this->conf['maxWordLength'] : 6;\r
+               \r
+               // text colour\r
+               // 0=one random colour for all letters\r
+               // 1=different random colour for each letter\r
+               if ($this->conf['textColor'] == '0') {\r
+                       $this->col_type = 0;\r
+               } else {\r
+                       $this->col_type = 1;\r
+               }\r
+\r
+               // maximum times a user can refresh the image\r
+               // on a 6500 word dictionary, I think 15-50 is enough to not annoy users and make BF unfeasble.\r
+               // further notes re: BF attacks in "avoid brute force attacks" section, below\r
+               // on the other hand, those attempting OCR will find the ability to request new images\r
+               // very useful; if they can't crack one, just grab an easier target...\r
+               // for the ultra-paranoid, setting it to <5 will still work for most users\r
+               $this->max_attempts = $this->conf['maxAttempts'] ? $this->conf['maxAttempts'] : 50;\r
+               \r
+               // list of fonts to use\r
+               // font size should be around 35 pixels wide for each character.\r
+               // you can use my GD fontmaker script at www.puremango.co.uk to create your own fonts\r
+               // There are other programs to can create GD fonts, but my script allows a greater\r
+               // degree of control over exactly how wide each character is, and is therefore\r
+               // recommended for 'special' uses. For normal use of GD fonts,\r
+               // the GDFontGenerator @ http://www.philiplb.de is excellent for convering ttf to GD\r
+               // the fonts included with freeCap *only* include lowercase alphabetic characters\r
+               // so are not suitable for most other uses\r
+               // to increase security, you really should add other fonts\r
+               if ($this->conf['generateNumbers']) {\r
+                       $this->font_locations = Array('EXT:' . $this->extKey . '/res/fonts/.anonymous.gdf');\r
+               } else {\r
+                       $this->font_locations = Array(\r
+                               'EXT:' . $this->extKey . '/res/fonts/.ht_freecap_font1.gdf',\r
+                               'EXT:' . $this->extKey . '/res/fonts/.ht_freecap_font2.gdf',\r
+                               'EXT:' . $this->extKey . '/res/fonts/.ht_freecap_font3.gdf',\r
+                               'EXT:' . $this->extKey . '/res/fonts/.ht_freecap_font4.gdf',\r
+                               'EXT:' . $this->extKey . '/res/fonts/.ht_freecap_font5.gdf'\r
+                               );\r
+               }\r
+               if ($this->conf['fontFiles']) {\r
+                       $this->font_locations = t3lib_div::trimExplode(',', $this->conf['fontFiles'], 1);\r
+               }\r
+               for ($i = 0; $i < sizeof($this->font_locations); $i++) {\r
+                       if (substr($this->font_locations[$i],0,4)=='EXT:') {\r
+                               $this->font_locations[$i] = t3lib_div::getFileAbsFileName($this->font_locations[$i]);\r
+                       } else {\r
+                               $this->font_locations[$i] = PATH_site.'uploads/'.$this->extPrefix.'/'.$this->font_locations[$i];\r
+                       }\r
+               }\r
+               \r
+               // background:\r
+               // 0=transparent (if jpg, white)\r
+               // 1=white bg with grid\r
+               // 2=white bg with squiggles\r
+               // 3=morphed image blocks\r
+               // 'random' background from v1.3 didn't provide any extra security (according to 2 independent experts)\r
+               // many thanks to http://ocr-research.org.ua and http://sam.zoy.org/pwntcha/ for testing\r
+               // for jpgs, 'transparent' is white\r
+               switch ($this->conf['backgroundType']) {\r
+                       case 'Transparent':\r
+                               $this->bg_type = 0;\r
+                               break;\r
+                       case 'White with grid':\r
+                               $this->bg_type = 1;\r
+                               break;\r
+                       case 'White with squiggles':\r
+                               $this->bg_type = 2;\r
+                               break;\r
+                       case 'Morphed image blocks':\r
+                               $this->bg_type = 3;\r
+                               break;\r
+                       default:\r
+                               $this->bg_type = 2;\r
+                               break;\r
+               }\r
+               \r
+               // text morh factor\r
+               $this->morphFactor = $this->conf['morphFactor'] ? $this->conf['morphFactor'] : 1;\r
+               \r
+               // should we blur the background? (looks nicer, makes text easier to read, takes longer)\r
+               $this->blur_bg = $this->conf['backgroundBlur'] ? true : false;\r
+               \r
+               // for bg_type 3, which images should we use?\r
+               // if you add your own, make sure they're fairly 'busy' images (ie a lot of shapes in them)\r
+               $this->bg_images = Array("../res/images/.ht_freecap_im1.jpg","../res/images/.ht_freecap_im2.jpg","../res/images/.ht_freecap_im3.jpg","../res/images/.ht_freecap_im4.jpg","../res/images/.ht_freecap_im5.jpg");\r
+               \r
+               // for non-transparent backgrounds only:\r
+               // if 0, merges CAPTCHA with bg\r
+               // if 1, write CAPTCHA over bg\r
+               $this->merge_type = $this->conf['mergeWithBackground'] ? 0 : 1;\r
+               \r
+               // should we morph the bg? (recommend yes, but takes a little longer to compute)\r
+               $this->morph_bg = $this->conf['backgroundMorph'] ? true : false;\r
+               \r
+               // you shouldn't need to edit anything below this, but it's extensively commented if you do want to play\r
+               // have fun, and email me with ideas, or improvements to the code (very interested in speed improvements)\r
+               // hope this script saves some spam :-)\r
+               \r
+               // seed random number generator\r
+               // PHP 4.2.0+ doesn't need this, but lower versions will\r
+               $this->seed_func($this->make_seed());\r
+               \r
+                       // read each font and get font character widths\r
+               $this->font_widths = Array();\r
+               for ($i=0 ; $i < sizeof($this->font_locations); $i++)   {\r
+                       $handle = fopen($this->font_locations[$i],"r");\r
+                               // read header of GD font, up to char width\r
+                       $c_wid = fread($handle,12);\r
+                       $this->font_widths[$i] = ord($c_wid{8})+ord($c_wid{9})+ord($c_wid{10})+ord($c_wid{11});\r
+                       fclose($handle);\r
+               }\r
+                       // modify image width depending on maximum possible length of word\r
+                       // you shouldn't need to use words > 6 chars in length really.\r
+               $width = ($this->max_word_length*(array_sum($this->font_widths)/sizeof($this->font_widths))+75);\r
+               $height = $this->conf['imageHeight'] ? $this->conf['imageHeight'] : 90;\r
+               \r
+               $this->im = ImageCreate($width, $height);\r
+               $this->im2 = ImageCreate($width, $height);\r
+               \r
+               //////////////////////////////////////////////////////\r
+               ////// Avoid Brute Force Attacks:\r
+               //////////////////////////////////////////////////////\r
+               \r
+               if (empty($this->sessionData[$this->extKey . '_attempts'])) {\r
+                       $this->sessionData[$this->extKey . '_attempts'] = 1;\r
+               } else {\r
+                       $this->sessionData[$this->extKey . '_attempts']++;\r
+\r
+                       // if more than ($this->max_attempts) refreshes, block further refreshes\r
+                       // can be negated by connecting with new session id\r
+                       // could get round this by storing num attempts in database against IP\r
+                       // could get round that by connecting with different IP (eg, using proxy servers)\r
+                       // in short, there's little point trying to avoid brute forcing\r
+                       // the best way to protect against BF attacks is to ensure the dictionary is not\r
+                       // accessible via the web or use random string option\r
+                       if ($this->sessionData[$this->extKey . '_attempts'] > $this->max_attempts) {\r
+                               $this->sessionData[$this->extKey . '_word_hash'] = false;\r
+                               $string = $this->pi_getLL('max_attempts');\r
+                               $font = 5;\r
+                               $width  = imagefontwidth($font) * strlen($string);\r
+                               $height = imagefontheight($font);\r
+                               $this->im3 = ImageCreate($width+2, $height+20);\r
+                               $bg = ImageColorAllocate($this->im3,255,255,255);\r
+                               ImageColorTransparent($this->im3,$bg);\r
+                               $red = ImageColorAllocate($this->im3, 255, 0, 0);\r
+                               ImageString($this->im3,$font,1,10,$string,$red);\r
+                               $this->sendImage($this->im3);\r
+                               exit();\r
+                       }\r
+               }\r
+               \r
+                       // get word\r
+               $word = $this->getWord();\r
+               \r
+                       // save hash of word for comparison\r
+               // using hash so that if there's an insecurity elsewhere (eg on the form processor),\r
+               // an attacker could only get the hash\r
+               // also, shared servers usually give all users access to the session files\r
+               // echo `ls /tmp`; and echo `more /tmp/someone_elses_session_file`; usually work\r
+               // so even if your site is 100% secure, someone else's site on your server might not be\r
+               // hence, even if attackers can read the session file, they can't get the freeCap word\r
+               // (though most hashes are easy to brute force for simple strings)\r
+               $this->sessionData[$this->extKey . '_word_hash'] = $this->hash_func($word);\r
+               \r
+                       // We use a simple encrypt to prevent the session from being exposed\r
+               if ($this->conf['accessibleOutput'] && in_array('mcrypt', get_loaded_extensions())) {\r
+                       $code = 'accessiblemustbe007';\r
+                       $cyph = $this->easy_crypt($word, $code);\r
+                       $this->sessionData[$this->extKey . '_word_accessible'] = $cyph;\r
+               }\r
+               \r
+                       // Store the session data\r
+               $GLOBALS['TSFE']->fe_user->setKey('ses','tx_'.$this->extKey,$this->sessionData);\r
+               $GLOBALS['TSFE']->storeSessionData();\r
+               \r
+                       // Output image\r
+               $this->buildImage($word, $width, $height);\r
+               \r
+               $this->sendImage($this->im);\r
+               \r
+               // unset all sensetive vars\r
+               // in case someone include()s this file on a shared server\r
+               // you might think this unneccessary, as it exit()s\r
+               // but by using register_shutdown_function\r
+               // on a -very- insecure shared server, they -might- be able to get the word\r
+               unset($word);\r
+               \r
+               exit();\r
+       }\r
+       \r
+               // functions to call for random number generation\r
+               // mt_rand produces 'better' random numbers\r
+               // but if your server doesn't support it, it's fine to use rand instead\r
+               //$this->rand_func = "mt_rand";\r
+               //$this->seed_func = "mt_srand";\r
+       function rand_func($min,$max) {\r
+               return mt_rand($min,$max);\r
+       }\r
+       function seed_func($seed) {\r
+               return mt_srand($seed);\r
+       }\r
+\r
+       function make_seed() {\r
+               // from http://php.net/srand\r
+               list($usec, $sec) = explode(' ', microtime());\r
+               return (float) $sec + ((float) $usec * 100000);\r
+       }\r
+       \r
+       function rand_color() {\r
+               if($this->bg_type==3) {\r
+                       // needs darker colour..\r
+                       return $this->rand_func(10,100);\r
+               } else {\r
+                       return $this->rand_func(60,170);\r
+               }\r
+       }\r
+\r
+       function hash_func($string) {\r
+               return md5($string);\r
+       }\r
+       \r
+       function myImageBlur($im) {\r
+               // w00t. my very own blur function\r
+               // in GD2, there's a gaussian blur function. bunch of bloody show-offs... :-)\r
+\r
+               $width = imagesx($im);\r
+               $height = imagesy($im);\r
+\r
+               $temp_im = ImageCreateTrueColor($width,$height);\r
+               $bg = ImageColorAllocate($temp_im,150,150,150);\r
+\r
+               // preserves transparency if in orig image\r
+               ImageColorTransparent($temp_im,$bg);\r
+\r
+               // fill bg\r
+               ImageFill($temp_im,0,0,$bg);\r
+\r
+               // anything higher than 3 makes it totally unreadable\r
+               // might be useful in a 'real' blur function, though (ie blurring pictures not text)\r
+               $distance = 1;\r
+               // use $distance=30 to have multiple copies of the word. not sure if this is useful.\r
+\r
+               // blur by merging with itself at different x/y offsets:\r
+               ImageCopyMerge($temp_im, $im, 0, 0, 0, $distance, $width, $height-$distance, 70);\r
+               ImageCopyMerge($im, $temp_im, 0, 0, $distance, 0, $width-$distance, $height, 70);\r
+               ImageCopyMerge($temp_im, $im, 0, $distance, 0, 0, $width, $height, 70);\r
+               ImageCopyMerge($im, $temp_im, $distance, 0, 0, 0, $width, $height, 70);\r
+               // remove temp image\r
+               ImageDestroy($temp_im);\r
+\r
+               return $im;\r
+       }\r
+       \r
+       function sendImage($pic) {\r
+               // output image with appropriate headers\r
+               header(base64_decode("WC1DYXB0Y2hhOiBmcmVlQ2FwIDEuNCAtIHd3dy5wdXJlbWFuZ28uY28udWs="));\r
+               switch($this->output) {\r
+                       // add other cases as desired\r
+                       case "jpg":\r
+                               header("Content-Type: image/jpeg");\r
+                               ImageJPEG($pic);\r
+                               break;\r
+                       case "gif":\r
+                               header("Content-Type: image/gif");\r
+                               ImageGIF($pic);\r
+                               break;\r
+                       case "png":\r
+                       default:\r
+                               header("Content-Type: image/png");\r
+                               ImagePNG($pic);\r
+                               break;\r
+               }\r
+               // kill GD images (removes from memory)\r
+               ImageDestroy($this->im);\r
+               ImageDestroy($this->im2);\r
+               if(!empty($this->im3)) {\r
+                       ImageDestroy($this->im3);\r
+               }\r
+               // the below aren't really essential, but might aid an OCR attack if discovered.\r
+               // so we unset them\r
+               unset($this->use_dict);\r
+               unset($this->dict_location);\r
+               unset($this->max_word_length);\r
+               unset($this->bg_type);\r
+               unset($this->bg_images);\r
+               unset($this->merge_type);\r
+               unset($this->morph_bg);\r
+               unset($this->col_type);\r
+               unset($this->max_attempts);\r
+               unset($this->font_locations);\r
+       }\r
+       \r
+       function getWord() {\r
+               \r
+                       // get word\r
+               if($this->use_dict) {\r
+                               // load dictionary and choose random word\r
+                               // keep dictionary in non-web accessible folder, or htaccess it\r
+                               // or modify so word comes from a database; SELECT word FROM words ORDER BY rand() LIMIT 1\r
+                               // took 0.11 seconds when 'words' had 10,000 records\r
+                       \r
+                       $words = @file($this->dict_location);\r
+                       \r
+                       $word = strtolower($words[$this->rand_func(0,sizeof($words)-1)]);\r
+                               // cut off line breaks\r
+                       $word = preg_replace('/['.preg_quote(chr(10).chr(13)).']+/', '', $word);\r
+                               // might be large file so forget it now (frees memory)\r
+                       $words = "";\r
+                       unset($words);\r
+               } else {\r
+                               // based on code originally by breakzero at hotmail dot com\r
+                               // (http://uk.php.net/manual/en/function.rand.php)\r
+                               // generate pseudo-random string\r
+                               // doesn't use ijtf as are easily mistaken\r
+                               \r
+                               // I'm not using numbers because the custom fonts I've created don't support anything other than\r
+                               // lowercase or space (but you can download new fonts or create your own using my GD fontmaker script)\r
+\r
+                       if ($this->conf['generateNumbers']) {\r
+                               $consonants = '123456789';\r
+                               $vowels = '123456789';\r
+                       } else {\r
+                               $consonants = 'bcdghklmnpqrsvwxyz';\r
+                               $vowels = 'aeuo';\r
+                       }\r
+                       $word = "";\r
+\r
+                       $wordlen = $this->rand_func(5,$this->max_word_length);\r
+                       for($i=0 ; $i<$wordlen ; $i++) {\r
+                                       // don't allow to start with 'vowel'\r
+                               if($this->rand_func(0,4)>=2 && $i!=0) {\r
+                                       $word .= $vowels{$this->rand_func(0,strlen($vowels)-1)};\r
+                               } else {\r
+                                       $word .= $consonants{$this->rand_func(0,strlen($consonants)-1)};\r
+                               }\r
+                       }\r
+               }\r
+               return $word;\r
+       }\r
+       \r
+       function buildImage($word, $width, $height) {\r
+               \r
+               // how faded should the bg be? (100=totally gone, 0=bright as the day)\r
+               // to test how much protection the bg noise gives, take a screenshot of the freeCap image\r
+               // and take it into a photo editor. play with contrast and brightness.\r
+               // If you can remove most of the bg, then it's not a good enough percentage\r
+               switch($this->bg_type) {\r
+                       case 0:\r
+                               break;\r
+                       case 1:\r
+                       case 2:\r
+                               $bg_fade_pct = 65;\r
+                               break;\r
+                       case 3:\r
+                               $bg_fade_pct = 50;\r
+                               break;\r
+               }\r
+               // slightly randomise the bg fade\r
+               $bg_fade_pct += $this->rand_func(-2,2);\r
+               \r
+               //////////////////////////////////////////////////////\r
+               ////// Fill BGs and Allocate Colours:\r
+               //////////////////////////////////////////////////////\r
+\r
+               // set tag colour\r
+               // have to do this before any distortion\r
+               // (otherwise colour allocation fails when bg type is 1)\r
+               $tag_col = ImageColorAllocate($this->im,10,10,10);\r
+               $site_tag_col2 = ImageColorAllocate($this->im2,0,0,0);\r
+\r
+               // set debug colours (text colours are set later)\r
+               $debug = ImageColorAllocate($this->im, 255, 0, 0);\r
+               $debug2 = ImageColorAllocate($this->im2, 255, 0, 0);\r
+\r
+               // set background colour (can change to any colour not in possible $text_col range)\r
+               // it doesn't matter as it'll be transparent or coloured over.\r
+               // if you're using bg_type 3, you might want to try to ensure that the color chosen\r
+               // below doesn't appear too much in any of your background images.\r
+               $bg = ImageColorAllocate($this->im, 254, 254, 254);\r
+               $bg2 = ImageColorAllocate($this->im2, 254, 254, 254);\r
+\r
+               // set transparencies\r
+               ImageColorTransparent($this->im,$bg);\r
+               // im2 transparent to allow characters to overlap slightly while morphing\r
+               ImageColorTransparent($this->im2,$bg2);\r
+\r
+               // fill backgrounds\r
+               ImageFill($this->im,0,0,$bg);\r
+               ImageFill($this->im2,0,0,$bg2);\r
+\r
+               if($this->bg_type!=0) {\r
+                       // generate noisy background, to be merged with CAPTCHA later\r
+                       // any suggestions on how best to do this much appreciated\r
+                       // sample code would be even better!\r
+                       // I'm not an OCR expert (hell, I'm not even an image expert; puremango.co.uk was designed in MsPaint)\r
+                       // so the noise models are based around my -guesswork- as to what would make it hard for an OCR prog\r
+                       // ideally, the character obfuscation would be strong enough not to need additional background noise\r
+                       // in any case, I hope at least one of the options given here provide some extra security!\r
+\r
+                       $this->im3 = ImageCreateTrueColor($width,$height);\r
+                       $temp_bg = ImageCreateTrueColor($width*1.5,$height*1.5);\r
+                       $bg3 = ImageColorAllocate($this->im3,255,255,255);\r
+                       ImageFill($this->im3,0,0,$bg3);\r
+                       $temp_bg_col = ImageColorAllocate($temp_bg,255,255,255);\r
+                       ImageFill($temp_bg,0,0,$temp_bg_col);\r
+                       \r
+                       // we draw all noise onto temp_bg\r
+                       // then if we're morphing, merge from temp_bg to im3\r
+                       // or if not, just copy a $widthx$height portion of $temp_bg to $im3\r
+                       // temp_bg is much larger so that when morphing, the edges retain the noise.\r
+                       \r
+                       if($this->bg_type==1) {\r
+                               // grid bg:\r
+                               \r
+                               // draw grid on x\r
+                               for($i=$this->rand_func(6,20) ; $i<$width*2 ; $i+=$this->rand_func(10,25)) {\r
+                                       ImageSetThickness($temp_bg,$this->rand_func(2,6));\r
+                                       $text_r = $this->rand_func(100,150);\r
+                                       $text_g = $this->rand_func(100,150);\r
+                                       $text_b = $this->rand_func(100,150);\r
+                                       $text_colour3 = ImageColorAllocate($temp_bg, $text_r, $text_g, $text_b);\r
+                                       \r
+                                       ImageLine($temp_bg,$i,0,$i,$height*2,$text_colour3);\r
+                               }\r
+                               // draw grid on y\r
+                               for($i=$this->rand_func(6,20) ; $i<$height*2 ; $i+=$this->rand_func(10,25)) {\r
+                                       ImageSetThickness($temp_bg,$this->rand_func(2,6));\r
+                                       $text_r = $this->rand_func(100,150);\r
+                                       $text_g = $this->rand_func(100,150);\r
+                                       $text_b = $this->rand_func(100,150);\r
+                                       $text_colour3 = ImageColorAllocate($temp_bg, $text_r, $text_g, $text_b);\r
+                                       \r
+                                       ImageLine($temp_bg,0,$i,$width*2, $i ,$text_colour3);\r
+                               }\r
+                       } else if($this->bg_type==2) {\r
+                               // draw squiggles!\r
+                               \r
+                               $bg3 = ImageColorAllocate($this->im3,255,255,255);\r
+                               ImageFill($this->im3,0,0,$bg3);\r
+                               ImageSetThickness($temp_bg,4);\r
+\r
+                               for($i=0 ; $i<strlen($word)+1 ; $i++) {\r
+                                       $text_r = $this->rand_func(100,150);\r
+                                       $text_g = $this->rand_func(100,150);\r
+                                       $text_b = $this->rand_func(100,150);\r
+                                       $text_colour3 = ImageColorAllocate($temp_bg, $text_r, $text_g, $text_b);\r
+\r
+                                       $points = Array();\r
+                                       // draw random squiggle for each character\r
+                                       // the longer the loop, the more complex the squiggle\r
+                                       // keep random so OCR can't say "if found shape has 10 points, ignore it"\r
+                                       // each squiggle will, however, be a closed shape, so OCR could try to find\r
+                                       // line terminations and start from there. (I don't think they're that advanced yet..)\r
+                                       for($j=1 ; $j<$this->rand_func(5,10) ; $j++) {\r
+                                               $points[] = $this->rand_func(1*(20*($i+1)),1*(50*($i+1)));\r
+                                               $points[] = $this->rand_func(30,$height+30);\r
+                                       }\r
+\r
+                                       ImagePolygon($temp_bg,$points,intval(sizeof($points)/2),$text_colour3);\r
+                               }\r
+\r
+                       } else if($this->bg_type==3) {\r
+                               // take random chunks of $this->bg_images and paste them onto the background\r
+\r
+                               for($i=0 ; $i<sizeof($this->bg_images) ; $i++) {\r
+                                       // read each image and its size\r
+                                       $temp_im[$i] = ImageCreateFromJPEG($this->bg_images[$i]);\r
+                                       $temp_width[$i] = imagesx($temp_im[$i]);\r
+                                       $temp_height[$i] = imagesy($temp_im[$i]);\r
+                               }\r
+\r
+                               $blocksize = $this->rand_func(20,60);\r
+                               for($i=0 ; $i<$width*2 ; $i+=$blocksize) {\r
+                                       // could randomise blocksize here... hardly matters\r
+                                       for($j=0 ; $j<$height*2 ; $j+=$blocksize) {\r
+                                               $image_index = $this->rand_func(0,sizeof($temp_im)-1);\r
+                                               $cut_x = $this->rand_func(0,$temp_width[$image_index]-$blocksize);\r
+                                               $cut_y = $this->rand_func(0,$temp_height[$image_index]-$blocksize);\r
+                                               ImageCopy($temp_bg, $temp_im[$image_index], $i, $j, $cut_x, $cut_y, $blocksize, $blocksize);\r
+                                       }\r
+                               }\r
+                               for($i=0 ; $i<sizeof($temp_im) ; $i++) {\r
+                                       // remove bgs from memory\r
+                                       ImageDestroy($temp_im[$i]);\r
+                               }\r
+                               \r
+                               // for debug:\r
+                               //sendImage($temp_bg);\r
+                       }\r
+                       \r
+                       // for debug:\r
+                       //sendImage($this->im3);\r
+                       \r
+                       if($this->morph_bg) {\r
+                               // morph background\r
+                               // we do this separately to the main text morph because:\r
+                               // a) the main text morph is done char-by-char, this is done across whole image\r
+                               // b) if an attacker could un-morph the bg, it would un-morph the CAPTCHA\r
+                               // hence bg is morphed differently to text\r
+                               // why do we morph it at all? it might make it harder for an attacker to remove the background\r
+                               // morph_chunk 1 looks better but takes longer\r
+                               // this is a different and less perfect morph than the one we do on the CAPTCHA\r
+                               // occasonally you get some dark background showing through around the edges\r
+                               // it doesn't need to be perfect as it's only the bg.\r
+                               $morph_chunk = $this->rand_func(1,5);\r
+                               $morph_y = 0;\r
+                               for($x=0 ; $x<$width ; $x+=$morph_chunk) {\r
+                                       $morph_chunk = $this->rand_func(1,5);\r
+                                       $morph_y += $this->rand_func(-1,1);\r
+                                       ImageCopy($this->im3, $temp_bg, $x, 0, $x+30, 30+$morph_y, $morph_chunk, $height*2);\r
+                               }\r
+                               \r
+                               ImageCopy($temp_bg, $this->im3, 0, 0, 0, 0, $width, $height);\r
+                               \r
+                               $morph_x = 0;\r
+                               for($y=0 ; $y<=$height; $y+=$morph_chunk) {\r
+                                       $morph_chunk = $this->rand_func(1,5);\r
+                                       $morph_x += $this->rand_func(-1,1);\r
+                                       ImageCopy($this->im3, $temp_bg, $morph_x, $y, 0, $y, $width, $morph_chunk);\r
+                               \r
+                               }\r
+                       } else {\r
+                               // just copy temp_bg onto im3\r
+                               ImageCopy($this->im3,$temp_bg,0,0,30,30,$width,$height);\r
+                       }\r
+                       \r
+                       ImageDestroy($temp_bg);\r
+                       \r
+                       if($this->blur_bg) {\r
+                               $this->myImageBlur($this->im3);\r
+                       }\r
+               }\r
+               \r
+               //////////////////////////////////////////////////////\r
+               ////// Write Word\r
+               //////////////////////////////////////////////////////\r
+               \r
+               // write word in random starting X position\r
+               $word_start_x = $this->rand_func(5,32);\r
+               // y positions jiggled about later\r
+               $word_start_y = 15;\r
+               \r
+               if($this->col_type==0) {\r
+                       $text_r = $this->rand_color();\r
+                       $text_g = $this->rand_color();\r
+                       $text_b = $this->rand_color();\r
+                       $text_colour2 = ImageColorAllocate($this->im2, $text_r, $text_g, $text_b);\r
+               }\r
+               \r
+               // write each char in different font\r
+               for($i=0 ; $i<strlen($word) ; $i++) {\r
+                       if($this->col_type==1) {\r
+                               $text_r = $this->rand_color();\r
+                               $text_g = $this->rand_color();\r
+                               $text_b = $this->rand_color();\r
+                               $text_colour2 = ImageColorAllocate($this->im2, $text_r, $text_g, $text_b);\r
+                       }\r
+                       \r
+                       $j = $this->rand_func(0,sizeof($this->font_locations)-1);\r
+                       $font = ImageLoadFont($this->font_locations[$j]);\r
+                       ImageString($this->im2, $font, $word_start_x+($this->font_widths[$j]*$i), $word_start_y, $word{$i}, $text_colour2);\r
+               }\r
+               // use last pixelwidth\r
+               $font_pixelwidth = $this->font_widths[$j];\r
+\r
+               // for debug:\r
+               //sendImage($this->im2);\r
+               \r
+               //////////////////////////////////////////////////////\r
+               ////// Morph Image:\r
+               //////////////////////////////////////////////////////\r
+               \r
+               // calculate how big the text is in pixels\r
+               // (so we only morph what we need to)\r
+               $word_pix_size = $word_start_x+(strlen($word)*$font_pixelwidth);\r
+               \r
+               // firstly move each character up or down a bit:\r
+               for($i=$word_start_x ; $i<$word_pix_size ; $i+=$font_pixelwidth) {\r
+                       // move on Y axis\r
+                       // deviates at least 4 pixels between each letter\r
+                       $prev_y = $y_pos;\r
+                       do{\r
+                               $y_pos = $this->rand_func(-5,5);\r
+                       } while($y_pos<$prev_y+2 && $y_pos>$prev_y-2);\r
+                       ImageCopy($this->im, $this->im2, $i, $y_pos, $i, 0, $font_pixelwidth, $height);\r
+               \r
+                       // for debug:\r
+                       //ImageRectangle($this->im,$i,$y_pos+10,$i+$font_pixelwidth,$y_pos+70,$debug);\r
+               }\r
+               \r
+               // for debug:\r
+               //sendImage($this->im);\r
+               \r
+               ImageFilledRectangle($this->im2,0,0,$width,$height,$bg2);\r
+\r
+               // randomly morph each character individually on x-axis\r
+               // this is where the main distortion happens\r
+               // massively improved since v1.2\r
+               $y_chunk = 1;\r
+               $morph_factor = $this->morphFactor;\r
+               $morph_x = 0;\r
+               for($j=0 ; $j<strlen($word) ; $j++) {\r
+                       $y_pos = 0;\r
+                       for($i=0 ; $i<=$height; $i+=$y_chunk) {\r
+                               $orig_x = $word_start_x+($j*$font_pixelwidth);\r
+                               // morph x += so that instead of deviating from orig x each time, we deviate from where we last deviated to\r
+                               // get it? instead of a zig zag, we get more of a sine wave.\r
+                               // I wish we could deviate more but it looks crap if we do.\r
+                               $morph_x += $this->rand_func(-$morph_factor,$morph_factor);\r
+                               // had to change this to ImageCopyMerge when starting using ImageCreateTrueColor\r
+                               // according to the manual; "when (pct is) 100 this function behaves identically to imagecopy()"\r
+                               // but this is NOT true when dealing with transparencies...\r
+                               ImageCopyMerge($this->im2, $this->im, $orig_x+$morph_x, $i+$y_pos, $orig_x, $i, $font_pixelwidth, $y_chunk, 100);\r
+               \r
+                               // for debug:\r
+                               //ImageLine($this->im2, $orig_x+$morph_x, $i, $orig_x+$morph_x+1, $i+$y_chunk, $debug2);\r
+                               //ImageLine($this->im2, $orig_x+$morph_x+$font_pixelwidth, $i, $orig_x+$morph_x+$font_pixelwidth+1, $i+$y_chunk, $debug2);\r
+                       }\r
+               }\r
+               \r
+               // for debug:\r
+               //sendImage($this->im2);\r
+               \r
+               ImageFilledRectangle($this->im,0,0,$width,$height,$bg);\r
+               // now do the same on the y-axis\r
+               // (much easier because we can just do it across the whole image, don't have to do it char-by-char)\r
+               $y_pos = 0;\r
+               $x_chunk = 1;\r
+               for($i=0 ; $i<=$width ; $i+=$x_chunk) {\r
+                       // can result in image going too far off on Y-axis;\r
+                       // not much I can do about that, apart from make image bigger\r
+                       // again, I wish I could do 1.5 pixels\r
+                       $y_pos += $this->rand_func(-1,1);\r
+                       ImageCopy($this->im, $this->im2, $i, $y_pos, $i, 0, $x_chunk, $height);\r
+               \r
+                       // for debug:\r
+                       //ImageLine($this->im,$i+$x_chunk,0,$i+$x_chunk,100,$debug);\r
+                       //ImageLine($this->im,$i,$y_pos+25,$i+$x_chunk,$y_pos+25,$debug);\r
+               }\r
+               \r
+               // for debug:\r
+               //sendImage($this->im);\r
+               \r
+               // blur edges:\r
+               // doesn't really add any security, but looks a lot nicer, and renders text a little easier to read\r
+               // for humans (hopefully not for OCRs, but if you know better, feel free to disable this function)\r
+               // (and if you do, let me know why)\r
+               $this->myImageBlur($this->im);\r
+               \r
+               // for debug:\r
+               //sendImage($this->im);\r
+               \r
+               if($this->output!="jpg" && $this->bg_type==0) {\r
+                       // make background transparent\r
+                       ImageColorTransparent($this->im,$bg);\r
+               }\r
+               \r
+               //////////////////////////////////////////////////////\r
+               ////// Try to avoid 'free p*rn' style CAPTCHA re-use\r
+               //////////////////////////////////////////////////////\r
+               // ('*'ed to stop my site coming up for certain keyword searches on google)\r
+               // can obscure CAPTCHA word in some cases..\r
+               // write site tags 'shining through' the morphed image\r
+               ImageFilledRectangle($this->im2,0,0,$width,$height,$bg2);\r
+               if(is_array($this->site_tags)) {\r
+                       $font = 2;\r
+                       $siteTagFontWidth = 6;\r
+                       $siteTagFontHeight = 10;\r
+                       for($i=0 ; $i<sizeof($this->site_tags) ; $i++) {\r
+                               // ensure tags are centered\r
+                               $tag_width = strlen($this->site_tags[$i])*$siteTagFontWidth+8;\r
+                               // write tag is chosen position\r
+                               if($this->tag_pos==0 || $this->tag_pos==2) {\r
+                                       // write at top\r
+                                       ImageString($this->im2, $font, intval($width/2)-intval($tag_width/2)+5, $siteTagFontHeight*$i, $this->site_tags[$i], $site_tag_col2);\r
+                               }\r
+                               if($this->tag_pos==1 || $this->tag_pos==2) {\r
+                                       // write at bottom\r
+                                       ImageString($this->im2, $font, intval($width/2)-intval($tag_width/2)+5, ($height-((sizeof($this->site_tags)*$siteTagFontHeight+4))+($i*$siteTagFontHeight)), $this->site_tags[$i], $site_tag_col2);\r
+                               }\r
+                       }\r
+               }\r
+               ImageCopyMerge($this->im2,$this->im,0,0,0,0,$width,$height,80);\r
+               ImageCopy($this->im,$this->im2,0,0,0,0,$width,$height);\r
+               \r
+               //////////////////////////////////////////////////////\r
+               ////// Merge with obfuscated background\r
+               //////////////////////////////////////////////////////\r
+               \r
+               if($this->bg_type!=0) {\r
+                       // merge bg image with CAPTCHA image to create smooth background\r
+                       // fade bg:\r
+                       if ($this->bg_type!=3) {\r
+                               $temp_im = ImageCreateTrueColor($width,$height);\r
+                               $white = ImageColorAllocate($temp_im,255,255,255);\r
+                               ImageFill($temp_im,0,0,$white);\r
+                               ImageCopyMerge($this->im3,$temp_im,0,0,0,0,$width,$height,$bg_fade_pct);\r
+                               // for debug:\r
+                               //sendImage($this->im3);\r
+                               ImageDestroy($temp_im);\r
+                               $c_fade_pct = 50;\r
+                       } else {\r
+                               $c_fade_pct = $bg_fade_pct;\r
+                       }\r
+               \r
+                       // captcha over bg:\r
+                       // might want to not blur if using this method\r
+                       // otherwise leaves white-ish border around each letter\r
+                       if ($this->merge_type == 1) {\r
+                               ImageCopyMerge($this->im3,$this->im,0,0,0,0,$width,$height,100);\r
+                               ImageCopy($this->im,$this->im3,0,0,0,0,$width,$height);\r
+                       } else {\r
+                               // bg over captcha:\r
+                               ImageCopyMerge($this->im,$this->im3,0,0,0,0,$width,$height,$c_fade_pct);\r
+                       }\r
+               }\r
+               unset($bg_fade_pct);\r
+               // for debug:\r
+               //sendImage($this->im);\r
+       }\r
+       \r
+       /**\r
+        * Returns the localized label of the LOCAL_LANG key, $key, in utf-8 for gd (in fact gd is limited to Latin2)\r
+        * Notice that for debugging purposes prefixes for the output values can be set with the internal vars ->LLtestPrefixAlt and ->LLtestPrefix\r
+        *\r
+        * @param       string          The key from the LOCAL_LANG array for which to return the value.\r
+        * @param       string          Alternative string to return IF no value is found set for the key, neither for the local language nor the default.\r
+        * @param       boolean         If true, the output label is passed through htmlspecialchars()\r
+        * @return      string          The value from LOCAL_LANG.\r
+        */\r
+       function pi_getLL($key,$alt='',$hsc=FALSE) {\r
+               if (isset($this->LOCAL_LANG[$this->LLkey][$key])) {\r
+                       $word = $this->LOCAL_LANG[$this->LLkey][$key];\r
+                       if ($this->LOCAL_LANG_charset[$this->LLkey][$key]) {\r
+                               $word = $GLOBALS['TSFE']->csConv($word, $this->LOCAL_LANG_charset[$this->LLkey][$key], 'utf-8');\r
+                       }\r
+               } elseif ($this->altLLkey && isset($this->LOCAL_LANG[$this->altLLkey][$key]))   {\r
+                       $word = $this->LOCAL_LANG[$this->altLLkey][$key];\r
+                       if ($this->LOCAL_LANG_charset[$this->altLLkey][$key]) {\r
+                               $word = $GLOBALS['TSFE']->csConv($word, $this->LOCAL_LANG_charset[$this->altLLkey][$key], 'utf-8');\r
+                       }\r
+               } elseif (isset($this->LOCAL_LANG['default'][$key]))    {\r
+                       $word = $this->LOCAL_LANG['default'][$key];\r
+               } else {\r
+                       $word = $this->LLtestPrefixAlt.$alt;\r
+               }\r
+                       // Don't know why the label is twice encoded...\r
+               $word = utf8_decode($word);\r
+               $output = $this->LLtestPrefix.$word;\r
+               if ($hsc) $output = htmlspecialchars($output);\r
+               return $output;\r
+       }\r
+       \r
+       /**\r
+        * Encodes a string.\r
+        * Returns an array with the string as the first element and the initialization vector as the second element\r
+        */\r
+       function easy_crypt($string, $key)      {\r
+               $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_CBC), MCRYPT_RAND);\r
+               $string = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $string, MCRYPT_MODE_CBC, $iv);\r
+               \r
+               return array(base64_encode($string), base64_encode($iv));\r
+       }\r
+       \r
+       /**\r
+        * Decodes a string\r
+        * The first argument is an array as returned by easy_encrypt()\r
+        */\r
+       function easy_decrypt($cyph_arr, $key){\r
+               return trim(mcrypt_decrypt(MCRYPT_BLOWFISH, $key, base64_decode($cyph_arr[0]), MCRYPT_MODE_CBC, base64_decode($cyph_arr[1])));\r
+       }\r
+       \r
+}\r
+\r
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/sr_freecap/pi1/class.tx_srfreecap_pi1.php'])  {\r
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/sr_freecap/pi1/class.tx_srfreecap_pi1.php']);\r
+}\r
+\r
+?>\r
diff --git a/pi1/freecap141.php b/pi1/freecap141.php
new file mode 100644 (file)
index 0000000..f67dab9
--- /dev/null
@@ -0,0 +1,818 @@
+<?\r
+if (!defined('freeCap')) die ('Access denied.');\r
+/************************************************************\\r
+*\r
+*              freeCap v1.4.1 Copyright 2005 Howard Yeend\r
+*              www.puremango.co.uk\r
+*\r
+*    This file is part of freeCap.\r
+*\r
+*    freeCap is free software; you can redistribute it and/or modify\r
+*    it under the terms of the GNU General Public License as published by\r
+*    the Free Software Foundation; either version 2 of the License, or\r
+*    (at your option) any later version.\r
+*\r
+*    freeCap is distributed in the hope that it will be useful,\r
+*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*    GNU General Public License for more details.\r
+*\r
+*    You should have received a copy of the GNU General Public License\r
+*    along with freeCap; if not, write to the Free Software\r
+*    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+*\r
+*\r
+\************************************************************/\r
+\r
+session_start();\r
+\r
+//////////////////////////////////////////////////////\r
+////// User Defined Vars:\r
+//////////////////////////////////////////////////////\r
+\r
+// try to avoid the 'free p*rn' method of CAPTCHA circumvention\r
+// see www.wikipedia.com/captcha for more info\r
+$site_tags[0] = "To avoid spam, please do NOT enter the text if";\r
+$site_tags[1] = "this site is not puremango.co.uk";\r
+// or more simply:\r
+//$site_tags[0] = "for use only on puremango.co.uk";\r
+// reword or add lines as you please\r
+// or if you don't want any text:\r
+$site_tags = null;\r
+\r
+// where to write the above:\r
+// 0=top\r
+// 1=bottom\r
+// 2=both\r
+$tag_pos = 1;\r
+\r
+// functions to call for random number generation\r
+// mt_rand produces 'better' random numbers\r
+// but if your server doesn't support it, it's fine to use rand instead\r
+$rand_func = "mt_rand";\r
+$seed_func = "mt_srand";\r
+\r
+// which type of hash to use?\r
+// possible values: "sha1", "md5", "crc32"\r
+// sha1 supported by PHP4.3.0+\r
+// md5 supported by PHP3+\r
+// crc32 supported by PHP4.0.1+\r
+$hash_func = "sha1";\r
+// store in session so can validate in form processor\r
+$_SESSION['hash_func'] = $hash_func;\r
+\r
+// image type:\r
+// possible values: "jpg", "png", "gif"\r
+// jpg doesn't support transparency (transparent bg option ends up white)\r
+// png isn't supported by old browsers (see http://www.libpng.org/pub/png/pngstatus.html)\r
+// gif may not be supported by your GD Lib.\r
+$output = "png";\r
+\r
+// 0=generate pseudo-random string, 1=use dictionary\r
+// dictionary is easier to recognise\r
+// - both for humans and computers, so use random string if you're paranoid.\r
+$use_dict = 1;\r
+// if your server is NOT set up to deny web access to files beginning ".ht"\r
+// then you should ensure the dictionary file is kept outside the web directory\r
+// eg: if www.foo.com/index.html points to c:\website\www\index.html\r
+// then the dictionary should be placed in c:\website\dict.txt\r
+// test your server's config by trying to access the dictionary through a web browser\r
+// you should NOT be able to view the contents.\r
+// can leave this blank if not using dictionary\r
+$dict_location = "./.ht_freecap_words";\r
+\r
+// used to calculate image width, and for non-dictionary word generation\r
+$max_word_length = 6;\r
+\r
+// text colour\r
+// 0=one random colour for all letters\r
+// 1=different random colour for each letter\r
+$col_type = 1;\r
+\r
+// maximum times a user can refresh the image\r
+// on a 6500 word dictionary, I think 15-50 is enough to not annoy users and make BF unfeasble.\r
+// further notes re: BF attacks in "avoid brute force attacks" section, below\r
+// on the other hand, those attempting OCR will find the ability to request new images\r
+// very useful; if they can't crack one, just grab an easier target...\r
+// for the ultra-paranoid, setting it to <5 will still work for most users\r
+$max_attempts = 20;\r
+\r
+// list of fonts to use\r
+// font size should be around 35 pixels wide for each character.\r
+// you can use my GD fontmaker script at www.puremango.co.uk to create your own fonts\r
+// There are other programs to can create GD fonts, but my script allows a greater\r
+// degree of control over exactly how wide each character is, and is therefore\r
+// recommended for 'special' uses. For normal use of GD fonts,\r
+// the GDFontGenerator @ http://www.philiplb.de is excellent for convering ttf to GD\r
+\r
+// the fonts included with freeCap *only* include lowercase alphabetic characters\r
+// so are not suitable for most other uses\r
+// to increase security, you really should add other fonts\r
+$font_locations = Array("./.ht_freecap_font1.gdf","./.ht_freecap_font2.gdf","./.ht_freecap_font3.gdf","./.ht_freecap_font4.gdf","./.ht_freecap_font5.gdf");\r
+\r
+// background:\r
+// 0=transparent (if jpg, white)\r
+// 1=white bg with grid\r
+// 2=white bg with squiggles\r
+// 3=morphed image blocks\r
+// 'random' background from v1.3 didn't provide any extra security (according to 2 independent experts)\r
+// many thanks to http://ocr-research.org.ua and http://sam.zoy.org/pwntcha/ for testing\r
+// for jpgs, 'transparent' is white\r
+$bg_type = 2;\r
+// should we blur the background? (looks nicer, makes text easier to read, takes longer)\r
+$blur_bg = false;\r
+// for bg_type 3, which images should we use?\r
+// if you add your own, make sure they're fairly 'busy' images (ie a lot of shapes in them)\r
+$bg_images = Array("./.ht_freecap_im1.jpg","./.ht_freecap_im2.jpg","./.ht_freecap_im3.jpg","./.ht_freecap_im4.jpg","./.ht_freecap_im5.jpg");\r
+// for non-transparent backgrounds only:\r
+       // if 0, merges CAPTCHA with bg\r
+       // if 1, write CAPTCHA over bg\r
+       $merge_type = 0;\r
+       // should we morph the bg? (recommend yes, but takes a little longer to compute)\r
+       $morph_bg = true;\r
+\r
+// you shouldn't need to edit anything below this, but it's extensively commented if you do want to play\r
+// have fun, and email me with ideas, or improvements to the code (very interested in speed improvements)\r
+// hope this script saves some spam :-)\r
+\r
+\r
+\r
+//////////////////////////////////////////////////////\r
+////// Create Images + initialise a few things\r
+//////////////////////////////////////////////////////\r
+\r
+// seed random number generator\r
+// PHP 4.2.0+ doesn't need this, but lower versions will\r
+$seed_func(make_seed());\r
+\r
+// how faded should the bg be? (100=totally gone, 0=bright as the day)\r
+// to test how much protection the bg noise gives, take a screenshot of the freeCap image\r
+// and take it into a photo editor. play with contrast and brightness.\r
+// If you can remove most of the bg, then it's not a good enough percentage\r
+switch($bg_type)\r
+{\r
+       case 0:\r
+               break;\r
+       case 1:\r
+       case 2:\r
+               $bg_fade_pct = 65;\r
+               break;\r
+       case 3:\r
+               $bg_fade_pct = 50;\r
+               break;\r
+}\r
+// slightly randomise the bg fade\r
+$bg_fade_pct += $rand_func(-2,2);\r
+\r
+// read each font and get font character widths\r
+$font_widths = Array();\r
+for($i=0 ; $i<sizeof($font_locations) ; $i++)\r
+{\r
+       $handle = fopen($font_locations[$i],"r");\r
+       // read header of GD font, up to char width\r
+       $c_wid = fread($handle,11);\r
+       $font_widths[$i] = ord($c_wid{8})+ord($c_wid{9})+ord($c_wid{10})+ord($c_wid{11});\r
+       fclose($handle);\r
+}\r
+\r
+// modify image width depending on maximum possible length of word\r
+// you shouldn't need to use words > 6 chars in length really.\r
+$width = ($max_word_length*(array_sum($font_widths)/sizeof($font_widths))+75);\r
+$height = 90;\r
+\r
+$im = ImageCreate($width, $height);\r
+$im2 = ImageCreate($width, $height);\r
+\r
+\r
+\r
+//////////////////////////////////////////////////////\r
+////// Avoid Brute Force Attacks:\r
+//////////////////////////////////////////////////////\r
+if(empty($_SESSION['freecap_attempts']))\r
+{\r
+       $_SESSION['freecap_attempts'] = 1;\r
+} else {\r
+       $_SESSION['freecap_attempts']++;\r
+\r
+       // if more than ($max_attempts) refreshes, block further refreshes\r
+       // can be negated by connecting with new session id\r
+       // could get round this by storing num attempts in database against IP\r
+       // could get round that by connecting with different IP (eg, using proxy servers)\r
+       // in short, there's little point trying to avoid brute forcing\r
+       // the best way to protect against BF attacks is to ensure the dictionary is not\r
+       // accessible via the web or use random string option\r
+       if($_SESSION['freecap_attempts']>$max_attempts)\r
+       {\r
+               $_SESSION['freecap_word_hash'] = false;\r
+\r
+               $bg = ImageColorAllocate($im,255,255,255);\r
+               ImageColorTransparent($im,$bg);\r
+\r
+               $red = ImageColorAllocate($im, 255, 0, 0);\r
+               // depending on how rude you want to be :-)\r
+               //ImageString($im,5,0,20,"bugger off you spamming bastards!",$red);\r
+               ImageString($im,5,15,20,"service no longer available",$red);\r
+\r
+               sendImage($im);\r
+       }\r
+}\r
+\r
+\r
+\r
+\r
+\r
+//////////////////////////////////////////////////////\r
+////// Functions:\r
+//////////////////////////////////////////////////////\r
+function make_seed() {\r
+// from http://php.net/srand\r
+    list($usec, $sec) = explode(' ', microtime());\r
+    return (float) $sec + ((float) $usec * 100000);\r
+}\r
+\r
+function rand_color() {\r
+       global $bg_type,$rand_func;\r
+       if($bg_type==3)\r
+       {\r
+               // needs darker colour..\r
+               return $rand_func(10,100);\r
+       } else {\r
+               return $rand_func(60,170);\r
+       }\r
+}\r
+\r
+function myImageBlur($im)\r
+{\r
+       // w00t. my very own blur function\r
+       // in GD2, there's a gaussian blur function. bunch of bloody show-offs... :-)\r
+\r
+       $width = imagesx($im);\r
+       $height = imagesy($im);\r
+\r
+       $temp_im = ImageCreateTrueColor($width,$height);\r
+       $bg = ImageColorAllocate($temp_im,150,150,150);\r
+\r
+       // preserves transparency if in orig image\r
+       ImageColorTransparent($temp_im,$bg);\r
+\r
+       // fill bg\r
+       ImageFill($temp_im,0,0,$bg);\r
+\r
+       // anything higher than 3 makes it totally unreadable\r
+       // might be useful in a 'real' blur function, though (ie blurring pictures not text)\r
+       $distance = 1;\r
+       // use $distance=30 to have multiple copies of the word. not sure if this is useful.\r
+\r
+       // blur by merging with itself at different x/y offsets:\r
+       ImageCopyMerge($temp_im, $im, 0, 0, 0, $distance, $width, $height-$distance, 70);\r
+       ImageCopyMerge($im, $temp_im, 0, 0, $distance, 0, $width-$distance, $height, 70);\r
+       ImageCopyMerge($temp_im, $im, 0, $distance, 0, 0, $width, $height, 70);\r
+       ImageCopyMerge($im, $temp_im, $distance, 0, 0, 0, $width, $height, 70);\r
+       // remove temp image\r
+       ImageDestroy($temp_im);\r
+\r
+       return $im;\r
+}\r
+\r
+function sendImage($pic)\r
+{\r
+       // output image with appropriate headers\r
+       global $output,$im,$im2,$im3;\r
+       header(base64_decode("WC1DYXB0Y2hhOiBmcmVlQ2FwIDEuNCAtIHd3dy5wdXJlbWFuZ28uY28udWs="));\r
+       switch($output)\r
+       {\r
+               // add other cases as desired\r
+               case "jpg":\r
+                       header("Content-Type: image/jpeg");\r
+                       ImageJPEG($pic);\r
+                       break;\r
+               case "gif":\r
+                       header("Content-Type: image/gif");\r
+                       ImageGIF($pic);\r
+                       break;\r
+               case "png":\r
+               default:\r
+                       header("Content-Type: image/png");\r
+                       ImagePNG($pic);\r
+                       break;\r
+       }\r
+\r
+       // kill GD images (removes from memory)\r
+       ImageDestroy($im);\r
+       ImageDestroy($im2);\r
+       ImageDestroy($pic);\r
+       if(!empty($im3))\r
+       {\r
+               ImageDestroy($im3);\r
+       }\r
+       exit();\r
+}\r
+\r
+\r
+\r
+\r
+//////////////////////////////////////////////////////\r
+////// Choose Word:\r
+//////////////////////////////////////////////////////\r
+if($use_dict==1)\r
+{\r
+       // load dictionary and choose random word\r
+       $words = @file($dict_location);\r
+       $word = strtolower($words[$rand_func(0,sizeof($words)-1)]);\r
+       // cut off line endings/other possible odd chars\r
+       $word = ereg_replace("[^a-z]","",$word);\r
+       // might be large file so forget it now (frees memory)\r
+       $words = "";\r
+       unset($words);\r
+} else {\r
+       // based on code originally by breakzero at hotmail dot com\r
+       // (http://uk.php.net/manual/en/function.rand.php)\r
+       // generate pseudo-random string\r
+       // doesn't use ijtf as are easily mistaken\r
+\r
+       // I'm not using numbers because the custom fonts I've created don't support anything other than\r
+       // lowercase or space (but you can download new fonts or create your own using my GD fontmaker script)\r
+       $consonants = 'bcdghklmnpqrsvwxyz';\r
+       $vowels = 'aeuo';\r
+       $word = "";\r
+\r
+       $wordlen = $rand_func(5,$max_word_length);\r
+\r
+       for($i=0 ; $i<$wordlen ; $i++)\r
+       {\r
+               // don't allow to start with 'vowel'\r
+               if($rand_func(0,4)>=2 && $i!=0)\r
+               {\r
+                       $word .= $vowels{$rand_func(0,strlen($vowels)-1)};\r
+               } else {\r
+                       $word .= $consonants{$rand_func(0,strlen($consonants)-1)};\r
+               }\r
+       }\r
+}\r
+\r
+// save hash of word for comparison\r
+// using hash so that if there's an insecurity elsewhere (eg on the form processor),\r
+// an attacker could only get the hash\r
+// also, shared servers usually give all users access to the session files\r
+// echo `ls /tmp`; and echo `more /tmp/someone_elses_session_file`; usually work\r
+// so even if your site is 100% secure, someone else's site on your server might not be\r
+// hence, even if attackers can read the session file, they can't get the freeCap word\r
+// (though most hashes are easy to brute force for simple strings)\r
+$_SESSION['freecap_word_hash'] = $hash_func($word);\r
+\r
+\r
+\r
+\r
+//////////////////////////////////////////////////////\r
+////// Fill BGs and Allocate Colours:\r
+//////////////////////////////////////////////////////\r
+\r
+// set tag colour\r
+// have to do this before any distortion\r
+// (otherwise colour allocation fails when bg type is 1)\r
+$tag_col = ImageColorAllocate($im,10,10,10);\r
+$site_tag_col2 = ImageColorAllocate($im2,0,0,0);\r
+\r
+// set debug colours (text colours are set later)\r
+$debug = ImageColorAllocate($im, 255, 0, 0);\r
+$debug2 = ImageColorAllocate($im2, 255, 0, 0);\r
+\r
+// set background colour (can change to any colour not in possible $text_col range)\r
+// it doesn't matter as it'll be transparent or coloured over.\r
+// if you're using bg_type 3, you might want to try to ensure that the color chosen\r
+// below doesn't appear too much in any of your background images.\r
+$bg = ImageColorAllocate($im, 254, 254, 254);\r
+$bg2 = ImageColorAllocate($im2, 254, 254, 254);\r
+\r
+// set transparencies\r
+ImageColorTransparent($im,$bg);\r
+// im2 transparent to allow characters to overlap slightly while morphing\r
+ImageColorTransparent($im2,$bg2);\r
+\r
+// fill backgrounds\r
+ImageFill($im,0,0,$bg);\r
+ImageFill($im2,0,0,$bg2);\r
+\r
+if($bg_type!=0)\r
+{\r
+       // generate noisy background, to be merged with CAPTCHA later\r
+       // any suggestions on how best to do this much appreciated\r
+       // sample code would be even better!\r
+       // I'm not an OCR expert (hell, I'm not even an image expert; puremango.co.uk was designed in MsPaint)\r
+       // so the noise models are based around my -guesswork- as to what would make it hard for an OCR prog\r
+       // ideally, the character obfuscation would be strong enough not to need additional background noise\r
+       // in any case, I hope at least one of the options given here provide some extra security!\r
+\r
+       $im3 = ImageCreateTrueColor($width,$height);\r
+       $temp_bg = ImageCreateTrueColor($width*1.5,$height*1.5);\r
+       $bg3 = ImageColorAllocate($im3,255,255,255);\r
+       ImageFill($im3,0,0,$bg3);\r
+       $temp_bg_col = ImageColorAllocate($temp_bg,255,255,255);\r
+       ImageFill($temp_bg,0,0,$temp_bg_col);\r
+\r
+       // we draw all noise onto temp_bg\r
+       // then if we're morphing, merge from temp_bg to im3\r
+       // or if not, just copy a $widthx$height portion of $temp_bg to $im3\r
+       // temp_bg is much larger so that when morphing, the edges retain the noise.\r
+\r
+       if($bg_type==1)\r
+       {\r
+               // grid bg:\r
+\r
+               // draw grid on x\r
+               for($i=$rand_func(6,20) ; $i<$width*2 ; $i+=$rand_func(10,25))\r
+               {\r
+                       ImageSetThickness($temp_bg,$rand_func(2,6));\r
+                       $text_r = $rand_func(100,150);\r
+                       $text_g = $rand_func(100,150);\r
+                       $text_b = $rand_func(100,150);\r
+                       $text_colour3 = ImageColorAllocate($temp_bg, $text_r, $text_g, $text_b);\r
+\r
+                       ImageLine($temp_bg,$i,0,$i,$height*2,$text_colour3);\r
+               }\r
+               // draw grid on y\r
+               for($i=$rand_func(6,20) ; $i<$height*2 ; $i+=$rand_func(10,25))\r
+               {\r
+                       ImageSetThickness($temp_bg,$rand_func(2,6));\r
+                       $text_r = $rand_func(100,150);\r
+                       $text_g = $rand_func(100,150);\r
+                       $text_b = $rand_func(100,150);\r
+                       $text_colour3 = ImageColorAllocate($temp_bg, $text_r, $text_g, $text_b);\r
+\r
+                       ImageLine($temp_bg,0,$i,$width*2, $i ,$text_colour3);\r
+               }\r
+       } else if($bg_type==2) {\r
+               // draw squiggles!\r
+\r
+               $bg3 = ImageColorAllocate($im3,255,255,255);\r
+               ImageFill($im3,0,0,$bg3);\r
+               ImageSetThickness($temp_bg,4);\r
+\r
+               for($i=0 ; $i<strlen($word)+1 ; $i++)\r
+               {\r
+                       $text_r = $rand_func(100,150);\r
+                       $text_g = $rand_func(100,150);\r
+                       $text_b = $rand_func(100,150);\r
+                       $text_colour3 = ImageColorAllocate($temp_bg, $text_r, $text_g, $text_b);\r
+\r
+                       $points = Array();\r
+                       // draw random squiggle for each character\r
+                       // the longer the loop, the more complex the squiggle\r
+                       // keep random so OCR can't say "if found shape has 10 points, ignore it"\r
+                       // each squiggle will, however, be a closed shape, so OCR could try to find\r
+                       // line terminations and start from there. (I don't think they're that advanced yet..)\r
+                       for($j=1 ; $j<$rand_func(5,10) ; $j++)\r
+                       {\r
+                               $points[] = $rand_func(1*(20*($i+1)),1*(50*($i+1)));\r
+                               $points[] = $rand_func(30,$height+30);\r
+                       }\r
+\r
+                       ImagePolygon($temp_bg,$points,intval(sizeof($points)/2),$text_colour3);\r
+               }\r
+\r
+       } else if($bg_type==3) {\r
+               // take random chunks of $bg_images and paste them onto the background\r
+\r
+               for($i=0 ; $i<sizeof($bg_images) ; $i++)\r
+               {\r
+                       // read each image and its size\r
+                       $temp_im[$i] = ImageCreateFromJPEG($bg_images[$i]);\r
+                       $temp_width[$i] = imagesx($temp_im[$i]);\r
+                       $temp_height[$i] = imagesy($temp_im[$i]);\r
+               }\r
+\r
+               $blocksize = $rand_func(20,60);\r
+               for($i=0 ; $i<$width*2 ; $i+=$blocksize)\r
+               {\r
+                       // could randomise blocksize here... hardly matters\r
+                       for($j=0 ; $j<$height*2 ; $j+=$blocksize)\r
+                       {\r
+                               $image_index = $rand_func(0,sizeof($temp_im)-1);\r
+                               $cut_x = $rand_func(0,$temp_width[$image_index]-$blocksize);\r
+                               $cut_y = $rand_func(0,$temp_height[$image_index]-$blocksize);\r
+                               ImageCopy($temp_bg, $temp_im[$image_index], $i, $j, $cut_x, $cut_y, $blocksize, $blocksize);\r
+                       }\r
+               }\r
+               for($i=0 ; $i<sizeof($temp_im) ; $i++)\r
+               {\r
+                       // remove bgs from memory\r
+                       ImageDestroy($temp_im[$i]);\r
+               }\r
+\r
+               // for debug:\r
+               //sendImage($temp_bg);\r
+       }\r
+\r
+       // for debug:\r
+       //sendImage($im3);\r
+\r
+       if($morph_bg)\r
+       {\r
+               // morph background\r
+               // we do this separately to the main text morph because:\r
+               // a) the main text morph is done char-by-char, this is done across whole image\r
+               // b) if an attacker could un-morph the bg, it would un-morph the CAPTCHA\r
+               // hence bg is morphed differently to text\r
+               // why do we morph it at all? it might make it harder for an attacker to remove the background\r
+               // morph_chunk 1 looks better but takes longer\r
+\r
+               // this is a different and less perfect morph than the one we do on the CAPTCHA\r
+               // occasonally you get some dark background showing through around the edges\r
+               // it doesn't need to be perfect as it's only the bg.\r
+               $morph_chunk = $rand_func(1,5);\r
+               $morph_y = 0;\r
+               for($x=0 ; $x<$width ; $x+=$morph_chunk)\r
+               {\r
+                       $morph_chunk = $rand_func(1,5);\r
+                       $morph_y += $rand_func(-1,1);\r
+                       ImageCopy($im3, $temp_bg, $x, 0, $x+30, 30+$morph_y, $morph_chunk, $height*2);\r
+               }\r
+\r
+               ImageCopy($temp_bg, $im3, 0, 0, 0, 0, $width, $height);\r
+\r
+               $morph_x = 0;\r
+               for($y=0 ; $y<=$height; $y+=$morph_chunk)\r
+               {\r
+                       $morph_chunk = $rand_func(1,5);\r
+                       $morph_x += $rand_func(-1,1);\r
+                       ImageCopy($im3, $temp_bg, $morph_x, $y, 0, $y, $width, $morph_chunk);\r
+\r
+               }\r
+       } else {\r
+               // just copy temp_bg onto im3\r
+               ImageCopy($im3,$temp_bg,0,0,30,30,$width,$height);\r
+       }\r
+\r
+       ImageDestroy($temp_bg);\r
+\r
+       if($blur_bg)\r
+       {\r
+               myImageBlur($im3);\r
+       }\r
+}\r
+// for debug:\r
+//sendImage($im3);\r
+\r
+\r
+\r
+\r
+//////////////////////////////////////////////////////\r
+////// Write Word\r
+//////////////////////////////////////////////////////\r
+\r
+// write word in random starting X position\r
+$word_start_x = $rand_func(5,32);\r
+// y positions jiggled about later\r
+$word_start_y = 15;\r
+\r
+if($col_type==0)\r
+{\r
+       $text_r = rand_color();\r
+       $text_g = rand_color();\r
+       $text_b = rand_color();\r
+       $text_colour2 = ImageColorAllocate($im2, $text_r, $text_g, $text_b);\r
+}\r
+\r
+// write each char in different font\r
+for($i=0 ; $i<strlen($word) ; $i++)\r
+{\r
+       if($col_type==1)\r
+       {\r
+               $text_r = rand_color();\r
+               $text_g = rand_color();\r
+               $text_b = rand_color();\r
+               $text_colour2 = ImageColorAllocate($im2, $text_r, $text_g, $text_b);\r
+       }\r
+\r
+       $j = $rand_func(0,sizeof($font_locations)-1);\r
+       $font = ImageLoadFont($font_locations[$j]);\r
+       ImageString($im2, $font, $word_start_x+($font_widths[$j]*$i), $word_start_y, $word{$i}, $text_colour2);\r
+}\r
+// use last pixelwidth\r
+$font_pixelwidth = $font_widths[$j];\r
+\r
+// for debug:\r
+//sendImage($im2);\r
+\r
+\r
+\r
+\r
+\r
+//////////////////////////////////////////////////////\r
+////// Morph Image:\r
+//////////////////////////////////////////////////////\r
+\r
+// calculate how big the text is in pixels\r
+// (so we only morph what we need to)\r
+$word_pix_size = $word_start_x+(strlen($word)*$font_pixelwidth);\r
+\r
+// firstly move each character up or down a bit:\r
+for($i=$word_start_x ; $i<$word_pix_size ; $i+=$font_pixelwidth)\r
+{\r
+       // move on Y axis\r
+       // deviates at least 4 pixels between each letter\r
+       $prev_y = $y_pos;\r
+       do{\r
+               $y_pos = $rand_func(-5,5);\r
+       } while($y_pos<$prev_y+2 && $y_pos>$prev_y-2);\r
+       ImageCopy($im, $im2, $i, $y_pos, $i, 0, $font_pixelwidth, $height);\r
+\r
+       // for debug:\r
+       //ImageRectangle($im,$i,$y_pos+10,$i+$font_pixelwidth,$y_pos+70,$debug);\r
+}\r
+\r
+// for debug:\r
+//sendImage($im);\r
+\r
+ImageFilledRectangle($im2,0,0,$width,$height,$bg2);\r
+\r
+// randomly morph each character individually on x-axis\r
+// this is where the main distortion happens\r
+// massively improved since v1.2\r
+$y_chunk = 1;\r
+$morph_factor = 1;\r
+$morph_x = 0;\r
+for($j=0 ; $j<strlen($word) ; $j++)\r
+{\r
+       $y_pos = 0;\r
+       for($i=0 ; $i<=$height; $i+=$y_chunk)\r
+       {\r
+               $orig_x = $word_start_x+($j*$font_pixelwidth);\r
+               // morph x += so that instead of deviating from orig x each time, we deviate from where we last deviated to\r
+               // get it? instead of a zig zag, we get more of a sine wave.\r
+               // I wish we could deviate more but it looks crap if we do.\r
+               $morph_x += $rand_func(-$morph_factor,$morph_factor);\r
+               // had to change this to ImageCopyMerge when starting using ImageCreateTrueColor\r
+               // according to the manual; "when (pct is) 100 this function behaves identically to imagecopy()"\r
+               // but this is NOT true when dealing with transparencies...\r
+               ImageCopyMerge($im2, $im, $orig_x+$morph_x, $i+$y_pos, $orig_x, $i, $font_pixelwidth, $y_chunk, 100);\r
+\r
+               // for debug:\r
+               //ImageLine($im2, $orig_x+$morph_x, $i, $orig_x+$morph_x+1, $i+$y_chunk, $debug2);\r
+               //ImageLine($im2, $orig_x+$morph_x+$font_pixelwidth, $i, $orig_x+$morph_x+$font_pixelwidth+1, $i+$y_chunk, $debug2);\r
+       }\r
+}\r
+\r
+// for debug:\r
+//sendImage($im2);\r
+\r
+ImageFilledRectangle($im,0,0,$width,$height,$bg);\r
+// now do the same on the y-axis\r
+// (much easier because we can just do it across the whole image, don't have to do it char-by-char)\r
+$y_pos = 0;\r
+$x_chunk = 1;\r
+for($i=0 ; $i<=$width ; $i+=$x_chunk)\r
+{\r
+       // can result in image going too far off on Y-axis;\r
+       // not much I can do about that, apart from make image bigger\r
+       // again, I wish I could do 1.5 pixels\r
+       $y_pos += $rand_func(-1,1);\r
+       ImageCopy($im, $im2, $i, $y_pos, $i, 0, $x_chunk, $height);\r
+\r
+       // for debug:\r
+       //ImageLine($im,$i+$x_chunk,0,$i+$x_chunk,100,$debug);\r
+       //ImageLine($im,$i,$y_pos+25,$i+$x_chunk,$y_pos+25,$debug);\r
+}\r
+\r
+// for debug:\r
+//sendImage($im);\r
+\r
+// blur edges:\r
+// doesn't really add any security, but looks a lot nicer, and renders text a little easier to read\r
+// for humans (hopefully not for OCRs, but if you know better, feel free to disable this function)\r
+// (and if you do, let me know why)\r
+myImageBlur($im);\r
+\r
+// for debug:\r
+//sendImage($im);\r
+\r
+if($output!="jpg" && $bg_type==0)\r
+{\r
+       // make background transparent\r
+       ImageColorTransparent($im,$bg);\r
+}\r
+\r
+\r
+\r
+\r
+\r
+//////////////////////////////////////////////////////\r
+////// Try to avoid 'free p*rn' style CAPTCHA re-use\r
+//////////////////////////////////////////////////////\r
+// ('*'ed to stop my site coming up for certain keyword searches on google)\r
+\r
+// can obscure CAPTCHA word in some cases..\r
+\r
+// write site tags 'shining through' the morphed image\r
+ImageFilledRectangle($im2,0,0,$width,$height,$bg2);\r
+if(is_array($site_tags))\r
+{\r
+       for($i=0 ; $i<sizeof($site_tags) ; $i++)\r
+       {\r
+               // ensure tags are centered\r
+               $tag_width = strlen($site_tags[$i])*6;\r
+               // write tag is chosen position\r
+               if($tag_pos==0 || $tag_pos==2)\r
+               {\r
+                       // write at top\r
+                       ImageString($im2, 2, intval($width/2)-intval($tag_width/2), (10*$i), $site_tags[$i], $site_tag_col2);\r
+               }\r
+               if($tag_pos==1 || $tag_pos==2)\r
+               {\r
+                       // write at bottom\r
+                       ImageString($im2, 2, intval($width/2)-intval($tag_width/2), ($height-34+($i*10)), $site_tags[$i], $site_tag_col2);\r
+               }\r
+       }\r
+}\r
+ImageCopyMerge($im2,$im,0,0,0,0,$width,$height,80);\r
+ImageCopy($im,$im2,0,0,0,0,$width,$height);\r
+// for debug:\r
+//sendImage($im);\r
+\r
+\r
+\r
+\r
+//////////////////////////////////////////////////////\r
+////// Merge with obfuscated background\r
+//////////////////////////////////////////////////////\r
+\r
+if($bg_type!=0)\r
+{\r
+       // merge bg image with CAPTCHA image to create smooth background\r
+\r
+       // fade bg:\r
+       if($bg_type!=3)\r
+       {\r
+               $temp_im = ImageCreateTrueColor($width,$height);\r
+               $white = ImageColorAllocate($temp_im,255,255,255);\r
+               ImageFill($temp_im,0,0,$white);\r
+               ImageCopyMerge($im3,$temp_im,0,0,0,0,$width,$height,$bg_fade_pct);\r
+               // for debug:\r
+               //sendImage($im3);\r
+               ImageDestroy($temp_im);\r
+               $c_fade_pct = 50;\r
+       } else {\r
+               $c_fade_pct = $bg_fade_pct;\r
+       }\r
+\r
+       // captcha over bg:\r
+       // might want to not blur if using this method\r
+       // otherwise leaves white-ish border around each letter\r
+       if($merge_type==1)\r
+       {\r
+               ImageCopyMerge($im3,$im,0,0,0,0,$width,$height,100);\r
+               ImageCopy($im,$im3,0,0,0,0,$width,$height);\r
+       } else {\r
+               // bg over captcha:\r
+               ImageCopyMerge($im,$im3,0,0,0,0,$width,$height,$c_fade_pct);\r
+       }\r
+}\r
+// for debug:\r
+//sendImage($im);\r
+\r
+\r
+//////////////////////////////////////////////////////\r
+////// Write tags, remove variables and output!\r
+//////////////////////////////////////////////////////\r
+\r
+// tag it\r
+// feel free to remove/change\r
+// but if it's not essential I'd appreciate you leaving it\r
+// after all, I've put a lot of work into this and am giving it away for free\r
+// the least you could do is give me credit (or buy me stuff from amazon!)\r
+// but I understand that in professional environments, your boss might not like this tag\r
+// so that's cool.\r
+$tag_str = "freeCap v1.41 - puremango.co.uk";\r
+// for debug:\r
+//$tag_str = "[".$word."]";\r
+\r
+// ensure tag is right-aligned\r
+$tag_width = strlen($tag_str)*6;\r
+// write tag\r
+ImageString($im, 2, $width-$tag_width, $height-13, $tag_str, $tag_col);\r
+\r
+// unset all sensetive vars\r
+// in case someone include()s this file on a shared server\r
+// you might think this unneccessary, as it exit()s\r
+// but by using register_shutdown_function\r
+// on a -very- insecure shared server, they -might- be able to get the word\r
+unset($word);\r
+// the below aren't really essential, but might aid an OCR attack if discovered.\r
+// so we unset them\r
+unset($use_dict);\r
+unset($dict_location);\r
+unset($max_word_length);\r
+unset($bg_type);\r
+unset($bg_images);\r
+unset($merge_type);\r
+unset($bg_fade_pct);\r
+unset($morph_bg);\r
+unset($col_type);\r
+unset($max_attempts);\r
+unset($font_locations);\r
+\r
+\r
+// output final image :-)\r
+sendImage($im);\r
+// (sendImage also destroys all used images)\r
+?>
\ No newline at end of file
diff --git a/pi1/locallang.xml b/pi1/locallang.xml
new file mode 100644 (file)
index 0000000..3308ae8
--- /dev/null
@@ -0,0 +1,293 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>\r
+<T3locallang>\r
+    <meta type="array">\r
+        <description>Language labels for tx_srfreecap_pi1</description>\r
+        <type>module</type>\r
+        <csh_table></csh_table>\r
+        <labelContext type="array">\r
+        </labelContext>\r
+    </meta>\r
+    <data type="array">\r
+        <languageKey index="default" type="array">\r
+            <label index="max_attempts">Sorry, service is interrupted.</label>\r
+           <label index="site_tag">Please do NOT enter the text|if this site is not %1$s</label>\r
+        </languageKey>\r
+        <languageKey index="dk" type="array">\r
+            <label index="max_attempts">Beklager, tjenesten er ude af drift.</label>\r
+        </languageKey>\r
+        <languageKey index="de" type="array">\r
+            <label index="max_attempts">Entschuldigung, der Service ist unterbrochen.</label>\r
+        </languageKey>\r
+        <languageKey index="no" type="array">\r
+        </languageKey>\r
+        <languageKey index="it" type="array">\r
+            <label index="max_attempts">Spiacente, servizio interrotto.</label>\r
+        </languageKey>\r
+        <languageKey index="fr" type="array">\r
+            <label index="max_attempts">Désolé, le service est interrompu.</label>\r
+           <label index="site_tag">Pour éviter le SPAM, n'entrez pas le mot|si le site n'est pas %1$s</label>\r
+        </languageKey>\r
+        <languageKey index="es" type="array">\r
+           <label index="max_attempts">Lo sentimos, el servicio está interrumpido.</label>\r
+        </languageKey>\r
+        <languageKey index="nl" type="array">\r
+            <label index="max_attempts">Service is onderbroken.</label>\r
+        </languageKey>\r
+        <languageKey index="cz" type="array">\r
+        </languageKey>\r
+        <languageKey index="pl" type="array">\r
+        </languageKey>\r
+        <languageKey index="si" type="array">\r
+        </languageKey>\r
+        <languageKey index="fi" type="array">\r
+            <label index="max_attempts">Pahoittelut, palvelu keskeytettiin.</label>\r
+        </languageKey>\r
+        <languageKey index="tr" type="array">\r
+        </languageKey>\r
+        <languageKey index="se" type="array">\r
+        </languageKey>\r
+        <languageKey index="pt" type="array">\r
+           <label index="max_attempts">Desculpe, o serviço foi suspenso.</label>\r
+        </languageKey>\r
+        <languageKey index="ru" type="array">\r
+        </languageKey>\r
+        <languageKey index="ro" type="array">\r
+        </languageKey>\r
+        <languageKey index="ch" type="array">\r
+        </languageKey>\r
+        <languageKey index="sk" type="array">\r
+        </languageKey>\r
+        <languageKey index="lt" type="array">\r
+        </languageKey>\r
+        <languageKey index="is" type="array">\r
+        </languageKey>\r
+        <languageKey index="hr" type="array">\r
+        </languageKey>\r
+        <languageKey index="hu" type="array">\r
+        </languageKey>\r
+        <languageKey index="gl" type="array">\r
+        </languageKey>\r
+        <languageKey index="th" type="array">\r
+        </languageKey>\r
+        <languageKey index="gr" type="array">\r
+        </languageKey>\r
+        <languageKey index="hk" type="array">\r
+        </languageKey>\r
+        <languageKey index="eu" type="array">\r
+        </languageKey>\r
+        <languageKey index="bg" type="array">\r
+        </languageKey>\r
+        <languageKey index="br" type="array">\r
+            <label index="max_attempts">Desculpe, o serviço foi interrompido.</label>\r
+        </languageKey>\r
+        <languageKey index="et" type="array">\r
+        </languageKey>\r
+        <languageKey index="ar" type="array">\r
+        </languageKey>\r
+        <languageKey index="he" type="array">\r
+        </languageKey>\r
+        <languageKey index="ua" type="array">\r
+        </languageKey>\r
+        <languageKey index="lv" type="array">\r
+        </languageKey>\r
+        <languageKey index="jp" type="array">\r
+        </languageKey>\r
+        <languageKey index="vn" type="array">\r
+        </languageKey>\r
+        <languageKey index="ca" type="array">\r
+        </languageKey>\r
+        <languageKey index="ba" type="array">\r
+        </languageKey>\r
+        <languageKey index="kr" type="array">\r
+        </languageKey>\r
+        <languageKey index="eo" type="array">\r
+        </languageKey>\r
+        <languageKey index="my" type="array">\r
+        </languageKey>\r
+        <languageKey index="hi" type="array">\r
+        </languageKey>\r
+    </data>\r
+    <orig_hash type="array">\r
+        <languageKey index="default" type="array">\r
+            <label index="max_attempts" type="integer">148562863</label>\r
+        </languageKey>\r
+        <languageKey index="dk" type="array">\r
+            <label index="max_attempts" type="integer">148562863</label>\r
+        </languageKey>\r
+        <languageKey index="de" type="array">\r
+            <label index="max_attempts" type="integer">148562863</label>\r
+        </languageKey>\r
+        <languageKey index="no" type="array">\r
+        </languageKey>\r
+        <languageKey index="it" type="array">\r
+        </languageKey>\r
+        <languageKey index="fr" type="array">\r
+            <label index="max_attempts" type="integer">148562863</label>\r
+        </languageKey>\r
+        <languageKey index="es" type="array">\r
+        </languageKey>\r
+        <languageKey index="nl" type="array">\r
+            <label index="max_attempts" type="integer">148562863</label>\r
+        </languageKey>\r
+        <languageKey index="cz" type="array">\r
+        </languageKey>\r
+        <languageKey index="pl" type="array">\r
+        </languageKey>\r
+        <languageKey index="si" type="array">\r
+        </languageKey>\r
+        <languageKey index="fi" type="array">\r
+            <label index="max_attempts" type="integer">148562863</label>\r
+        </languageKey>\r
+        <languageKey index="tr" type="array">\r
+        </languageKey>\r
+        <languageKey index="se" type="array">\r
+        </languageKey>\r
+        <languageKey index="pt" type="array">\r
+        </languageKey>\r
+        <languageKey index="ru" type="array">\r
+        </languageKey>\r
+        <languageKey index="ro" type="array">\r
+        </languageKey>\r
+        <languageKey index="ch" type="array">\r
+        </languageKey>\r
+        <languageKey index="sk" type="array">\r
+        </languageKey>\r
+        <languageKey index="lt" type="array">\r
+        </languageKey>\r
+        <languageKey index="is" type="array">\r
+        </languageKey>\r
+        <languageKey index="hr" type="array">\r
+        </languageKey>\r
+        <languageKey index="hu" type="array">\r
+        </languageKey>\r
+        <languageKey index="gl" type="array">\r
+        </languageKey>\r
+        <languageKey index="th" type="array">\r
+        </languageKey>\r
+        <languageKey index="gr" type="array">\r
+        </languageKey>\r
+        <languageKey index="hk" type="array">\r
+        </languageKey>\r
+        <languageKey index="eu" type="array">\r
+        </languageKey>\r
+        <languageKey index="bg" type="array">\r
+        </languageKey>\r
+        <languageKey index="br" type="array">\r
+            <label index="max_attempts" type="integer">148562863</label>\r
+        </languageKey>\r
+        <languageKey index="et" type="array">\r
+        </languageKey>\r
+        <languageKey index="ar" type="array">\r
+        </languageKey>\r
+        <languageKey index="he" type="array">\r
+        </languageKey>\r
+        <languageKey index="ua" type="array">\r
+        </languageKey>\r
+        <languageKey index="lv" type="array">\r
+        </languageKey>\r
+        <languageKey index="jp" type="array">\r
+        </languageKey>\r
+        <languageKey index="vn" type="array">\r
+        </languageKey>\r
+        <languageKey index="ca" type="array">\r
+        </languageKey>\r
+        <languageKey index="ba" type="array">\r
+        </languageKey>\r
+        <languageKey index="kr" type="array">\r
+        </languageKey>\r
+        <languageKey index="eo" type="array">\r
+        </languageKey>\r
+        <languageKey index="my" type="array">\r
+        </languageKey>\r
+        <languageKey index="hi" type="array">\r
+        </languageKey>\r
+    </orig_hash>\r
+    <orig_text type="array">\r
+        <languageKey index="default" type="array">\r
+        </languageKey>\r
+        <languageKey index="dk" type="array">\r
+        </languageKey>\r
+        <languageKey index="de" type="array">\r
+        </languageKey>\r
+        <languageKey index="no" type="array">\r
+        </languageKey>\r
+        <languageKey index="it" type="array">\r
+        </languageKey>\r
+        <languageKey index="fr" type="array">\r
+        </languageKey>\r
+        <languageKey index="es" type="array">\r
+        </languageKey>\r
+        <languageKey index="nl" type="array">\r
+        </languageKey>\r
+        <languageKey index="cz" type="array">\r
+        </languageKey>\r
+        <languageKey index="pl" type="array">\r
+        </languageKey>\r
+        <languageKey index="si" type="array">\r
+        </languageKey>\r
+        <languageKey index="fi" type="array">\r
+        </languageKey>\r
+        <languageKey index="tr" type="array">\r
+        </languageKey>\r
+        <languageKey index="se" type="array">\r
+        </languageKey>\r
+        <languageKey index="pt" type="array">\r
+        </languageKey>\r
+        <languageKey index="ru" type="array">\r
+        </languageKey>\r
+        <languageKey index="ro" type="array">\r
+        </languageKey>\r
+        <languageKey index="ch" type="array">\r
+        </languageKey>\r
+        <languageKey index="sk" type="array">\r
+        </languageKey>\r
+        <languageKey index="lt" type="array">\r
+        </languageKey>\r
+        <languageKey index="is" type="array">\r
+        </languageKey>\r
+        <languageKey index="hr" type="array">\r
+        </languageKey>\r
+        <languageKey index="hu" type="array">\r
+        </languageKey>\r
+        <languageKey index="gl" type="array">\r
+        </languageKey>\r
+        <languageKey index="th" type="array">\r
+        </languageKey>\r
+        <languageKey index="gr" type="array">\r
+        </languageKey>\r
+        <languageKey index="hk" type="array">\r
+        </languageKey>\r
+        <languageKey index="eu" type="array">\r
+        </languageKey>\r
+        <languageKey index="bg" type="array">\r
+        </languageKey>\r
+        <languageKey index="br" type="array">\r
+        </languageKey>\r
+        <languageKey index="et" type="array">\r
+        </languageKey>\r
+        <languageKey index="ar" type="array">\r
+        </languageKey>\r
+        <languageKey index="he" type="array">\r
+        </languageKey>\r
+        <languageKey index="ua" type="array">\r
+        </languageKey>\r
+        <languageKey index="lv" type="array">\r
+        </languageKey>\r
+        <languageKey index="jp" type="array">\r
+        </languageKey>\r
+        <languageKey index="vn" type="array">\r
+        </languageKey>\r
+        <languageKey index="ca" type="array">\r
+        </languageKey>\r
+        <languageKey index="ba" type="array">\r
+        </languageKey>\r
+        <languageKey index="kr" type="array">\r
+        </languageKey>\r
+        <languageKey index="eo" type="array">\r
+        </languageKey>\r
+        <languageKey index="my" type="array">\r
+        </languageKey>\r
+        <languageKey index="hi" type="array">\r
+        </languageKey>\r
+    </orig_text>\r
+</T3locallang>
\ No newline at end of file
diff --git a/pi2/class.tx_srfreecap_pi2.php b/pi2/class.tx_srfreecap_pi2.php
new file mode 100644 (file)
index 0000000..683f187
--- /dev/null
@@ -0,0 +1,164 @@
+<?php\r
+/***************************************************************\r
+*  Copyright notice\r
+*\r
+*  (c) 2005-2008 Stanislas Rolland <typo3(arobas)sjbr.ca>\r
+*  All rights reserved\r
+*\r
+*  This script is part of the TYPO3 project. The TYPO3 project is\r
+*  free software; you can redistribute it and/or modify\r
+*  it under the terms of the GNU General Public License as published by\r
+*  the Free Software Foundation; either version 2 of the License, or\r
+*  (at your option) any later version.\r
+*\r
+*  The GNU General Public License can be found at\r
+*  http://www.gnu.org/copyleft/gpl.html.\r
+*  A copy is found in the textfile GPL.txt and important notices to the license\r
+*  from the author is found in LICENSE.txt distributed with these scripts.\r
+*\r
+*\r
+*  This script is distributed in the hope that it will be useful,\r
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*  GNU General Public License for more details.\r
+*\r
+*  This copyright notice MUST APPEAR in all copies of the script!\r
+***************************************************************/\r
+/**\r
+ * Integrates freeCap v1.4 into TYPO3 and checks the freeCap CAPTCHA word.\r
+ *\r
+ *\r
+ * @author     Stanislas Rolland       <typo3(arobas)sjbr.ca>\r
+ */\r
+/************************************************************\\r
+*\r
+*              freeCap v1.4 Copyright 2005 Howard Yeend\r
+*              www.puremango.co.uk\r
+*\r
+*    This file is part of freeCap.\r
+*\r
+*    freeCap is free software; you can redistribute it and/or modify\r
+*    it under the terms of the GNU General Public License as published by\r
+*    the Free Software Foundation; either version 2 of the License, or\r
+*    (at your option) any later version.\r
+*\r
+*    freeCap is distributed in the hope that it will be useful,\r
+*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*    GNU General Public License for more details.\r
+*\r
+*    You should have received a copy of the GNU General Public License\r
+*    along with freeCap; if not, write to the Free Software\r
+*    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+*\r
+*\r
+\************************************************************/\r
+\r
+require_once(PATH_tslib.'class.tslib_pibase.php');\r
+\r
+class tx_srfreecap_pi2 extends tslib_pibase {\r
+       var $prefixId = 'tx_srfreecap_pi2';\r
+       var $scriptRelPath = 'pi2/class.tx_srfreecap_pi2.php';  // Path to this script relative to the extension dir.\r
+       var $extKey = 'sr_freecap';             // The extension key.\r
+       var $conf = array();\r
+       \r
+       function makeCaptcha() {\r
+               global $TSFE;\r
+               \r
+               $this->tslib_pibase();\r
+               \r
+                       //Make sure that labels in locallang.php may be overridden\r
+               $this->conf = $TSFE->tmpl->setup['plugin.'][$this->prefixId.'.'];\r
+               $this->pi_loadLL();\r
+               $this->pi_USER_INT_obj = 1;  // Disable caching\r
+               \r
+               $L = t3lib_div::_GP('L');\r
+               if (isset($L)) {\r
+                       $L = htmlspecialchars($L);\r
+               }\r
+               $fakeId = t3lib_div::shortMD5(uniqid (rand()),5);\r
+               $TSFE->additionalHeaderData[$this->extKey] .= '<script type="text/javascript" src="'. t3lib_extMgm::siteRelPath($this->extKey) . 'pi2/freeCap.js"></script>';           \r
+               $audioURL = t3lib_extMgm::siteRelPath($this->extKey).'pi3/audioCaptcha.php?id=' . $GLOBALS['TSFE']->id . (isset($L)?'&amp;L='.$L:'');\r
+               \r
+               $markerArray = array();\r
+               $markerArray['###'. strtoupper($this->extKey) . '_IMAGE###'] = '<img ' . $this->pi_classParam('image') . ' id="tx_srfreecap_pi2_captcha_image_'.$fakeId.'" src="'.t3lib_extMgm::siteRelPath($this->extKey).'pi1/captcha.php?id=' . $TSFE->id . (isset($L)?'&amp;L='.$L:'') . '" alt="' . $this->pi_getLL('altText') . '" style="vertical-align: middle; "/>';\r
+               $markerArray['###'. strtoupper($this->extKey) . '_NOTICE###'] = $this->pi_getLL('notice') . ' ' . $this->pi_getLL('explain');\r
+               $markerArray['###'. strtoupper($this->extKey) . '_CANT_READ###'] = '<span ' . $this->pi_classParam('cant-read') . '>' . $this->pi_getLL('cant_read1');\r
+               $markerArray['###'. strtoupper($this->extKey) . '_CANT_READ###'] .= ' <a href="#" onclick="this.blur();newFreeCap(\''.$fakeId.'\', \''.$this->pi_getLL('noImageMessage').'\');return false;">' . $this->pi_getLL('click_here') . '</a>';\r
+               $markerArray['###'. strtoupper($this->extKey) . '_CANT_READ###'] .= $this->pi_getLL('cant_read2') . '</span>';\r
+               if ($this->conf['accessibleOutput']  && in_array('mcrypt', get_loaded_extensions())) {\r
+                       $markerArray['###'. strtoupper($this->extKey) . '_ACCESSIBLE###'] .= '<img alt="' . $this->pi_getLL('click_here_accessible') . '" title="' . $this->pi_getLL('click_here_accessible') . '" src="'.t3lib_extMgm::siteRelPath($this->extKey).'res/images/audio.png" onClick="playCaptcha(\''.$fakeId.'\', \''.$audioURL.'\', \''.$this->pi_getLL('noPlayMessage').'\');" style="cursor: pointer;"'.$this->pi_classParam('image-accessible').' /><div '.$this->pi_classParam('accessible').' id="tx_srfreecap_pi2_captcha_playAudio_'.$fakeId.'"></div>';\r
+               } else {\r
+                       $markerArray['###'. strtoupper($this->extKey) . '_ACCESSIBLE###'] .= '';\r
+               }\r
+               return $markerArray;\r
+       }\r
+       \r
+       /**\r
+        * Check the word that was entered against the hashed value\r
+        *\r
+        * @param       string          $word: hte word that was entered\r
+        * @return      boolean         true, if the word entered matches the hashes value\r
+        */\r
+       function checkWord($word) {\r
+                       // Load session data\r
+               $this->sessionData = $GLOBALS['TSFE']->fe_user->getKey('ses','tx_'.$this->extKey);\r
+               if (!empty($this->sessionData[$this->extKey . '_word_hash']) && !empty($word)) {\r
+                       // all freeCap words are lowercase.\r
+                       // font #4 looks uppercase, but trust me, it's not...\r
+                       if ($this->sessionData[$this->extKey . '_hash_func'] == 'md5') {\r
+                               if (md5(strtolower(utf8_decode($word))) == $this->sessionData[$this->extKey . '_word_hash']) {\r
+                                       // reset freeCap session vars\r
+                                       // cannot stress enough how important it is to do this\r
+                                       // defeats re-use of known image with spoofed session id\r
+                                       $this->sessionData[$this->extKey . '_attempts'] = 0;\r
+                                       $this->sessionData[$this->extKey . '_word_hash'] = false;\r
+                                       return true;\r
+                               }\r
+                       }\r
+               }\r
+               return false;\r
+       }\r
+\r
+       /**\r
+        * From the 'salutationswitcher' extension.\r
+        *\r
+        * @author      Oliver Klee <typo-coding@oliverklee.de>\r
+        */\r
+           // list of allowed suffixes\r
+       var $allowedSuffixes = array('formal', 'informal');\r
+       \r
+       /**\r
+        * Returns the localized label of the LOCAL_LANG key, $key\r
+        * In $this->conf['salutation'], a suffix to the key may be set (which may be either 'formal' or 'informal').\r
+        * If a corresponding key exists, the formal/informal localized string is used instead.\r
+        * If the key doesn't exist, we just use the normal string.\r
+        *\r
+        * Example: key = 'greeting', suffix = 'informal'. If the key 'greeting_informal' exists, that string is used.\r
+        * If it doesn't exist, we'll try to use the string with the key 'greeting'.\r
+        *\r
+        * Notice that for debugging purposes prefixes for the output values can be set with the internal vars ->LLtestPrefixAlt and ->LLtestPrefix\r
+        *\r
+        * @param    string        The key from the LOCAL_LANG array for which to return the value.\r
+        * @param    string        Alternative string to return IF no value is found set for the key, neither for the local language nor the default.\r
+        * @param    boolean        If true, the output label is passed through htmlspecialchars()\r
+        * @return    string        The value from LOCAL_LANG.\r
+        */\r
+       function pi_getLL($key, $alt = '', $hsc = FALSE) {\r
+                       // If the suffix is allowed and we have a localized string for the desired salutation, we'll take that.\r
+               if (isset($this->conf['salutation']) && in_array($this->conf['salutation'], $this->allowedSuffixes, 1)) {\r
+                       $expandedKey = $key.'_'.$this->conf['salutation'];\r
+                       if (isset($this->LOCAL_LANG[$this->LLkey][$expandedKey])) {\r
+                               $key = $expandedKey;\r
+                       }\r
+               }\r
+               return parent::pi_getLL($key, $alt, $hsc);\r
+       }\r
+\r
+}\r
+\r
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/sr_freecap/pi2/class.tx_srfreecap_pi2.php']) {\r
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/sr_freecap/pi2/class.tx_srfreecap_pi2.php']);\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/pi2/freeCap.js b/pi2/freeCap.js
new file mode 100644 (file)
index 0000000..f9acb7f
--- /dev/null
@@ -0,0 +1,79 @@
+/***************************************************************\r
+*  Copyright notice\r
+*\r
+*  (c) 2007-2008 Stanislas Rolland <typo3(arobas)sjbr.ca>\r
+*  All rights reserved\r
+*\r
+*  This script is part of the TYPO3 project. The TYPO3 project is\r
+*  free software; you can redistribute it and/or modify\r
+*  it under the terms of the GNU General Public License as published by\r
+*  the Free Software Foundation; either version 2 of the License, or\r
+*  (at your option) any later version.\r
+*\r
+*  The GNU General Public License can be found at\r
+*  http://www.gnu.org/copyleft/gpl.html.\r
+*  A copy is found in the textfile GPL.txt and important notices to the license\r
+*  from the author is found in LICENSE.txt distributed with these scripts.\r
+*\r
+*\r
+*  This script is distributed in the hope that it will be useful,\r
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*  GNU General Public License for more details.\r
+*\r
+*\r
+*  This copyright notice MUST APPEAR in all copies of the script!\r
+***************************************************************/\r
+/*\r
+ * Javascript functions for TYPO3 plugin freeCap (sr_freecap)\r
+ *\r
+ * TYPO3 CVS ID: $Id$\r
+ */\r
+\r
+/*\r
+ * Loads a new freeCap image\r
+ *\r
+ * @param      string          id: identifier used to uniiquely identify the image\r
+ *\r
+ * @return     void\r
+ */\r
+function newFreeCap(id, noImageMessage) {\r
+       if (document.getElementById) {\r
+                       // extract image name from image source (i.e. cut off ?randomness)\r
+               var theImage = document.getElementById("tx_srfreecap_pi2_captcha_image_"+id);\r
+               var parts = theImage.src.split("&amp");\r
+                       // add ?(random) to prevent browser/isp caching\r
+                       // parts[0] should be id=page_id\r
+                       // parts[1] should be L=sys_language_uid\r
+               theImage.src = parts[0] + "&amp;" + parts[1] + "&amp;set=" + Math.round(Math.random()*100000);\r
+       } else {\r
+               alert(noImageMessage ? noImageMessage : "Sorry, we cannot autoreload a new image. Submit the form and a new image will be loaded.");\r
+       }\r
+}\r
+\r
+/*\r
+ * Plays the audio captcha\r
+ *\r
+ * @param      string          id: identifier used to uniquely identify the wav file\r
+ * @param      string          wavURL: url of the wave file generating script\r
+ *\r
+ * @return     void\r
+ */\r
+function playCaptcha(id, wavURL, noPlayMessage) {\r
+       if (document.getElementById) {\r
+               var theAudio = document.getElementById("tx_srfreecap_pi2_captcha_playAudio_"+id);\r
+               var wavURLForOpera = wavURL + "&amp;nocache=" + Math.random();\r
+               theAudio.innerHTML = '<object type="audio/x-wav" data="' + wavURLForOpera + '" style="visibility: hidden;" height="0">'\r
+                       + '<param name="type" value="audio/x-wav" />'\r
+                       + '<param name="src" value="' + wavURLForOpera + '" />'\r
+                       + '<param name="filename" value="' + wavURLForOpera + '" />'\r
+                       + '<param name="autoplay" value="true" />'\r
+                       + '<param name="autoStart" value="1" />'\r
+                       + '<param name="hidden" value="true" />'\r
+                       + '<param name="controller" value="false" />'\r
+                       + 'alt : <a href="' + wavURLForOpera + '">' + (noPlayMessage ? noPlayMessage : 'Sorry, we cannot play the word of the image.') + '</a>'\r
+                       + '</object>';\r
+       } else {\r
+               alert(noPlayMessage ? noPlayMessage : "Sorry, we cannot play the word of the image.");\r
+       }\r
+}\r
diff --git a/pi2/locallang.xml b/pi2/locallang.xml
new file mode 100644 (file)
index 0000000..6dc4869
--- /dev/null
@@ -0,0 +1,438 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>\r
+<T3locallang>\r
+    <meta type="array">\r
+        <description>Language labels for tx_srfreecap_pi2</description>\r
+        <type>module</type>\r
+        <csh_table></csh_table>\r
+        <labelContext type="array">\r
+        </labelContext>\r
+    </meta>\r
+    <data type="array">\r
+        <languageKey index="default" type="array">\r
+            <label index="altText">CAPTCHA image for SPAM prevention</label>\r
+            <label index="notice">Please enter here the word as displayed in the picture.</label>\r
+            <label index="notice_informal">Please enter here the word as displayed in the picture.</label>\r
+            <label index="explain">This is to prevent spamming.</label>\r
+            <label index="cant_read1">If you can't read the word,</label>\r
+            <label index="cant_read1_informal">If you can't read the word,</label>\r
+            <label index="click_here">click here</label>\r
+            <label index="click_here_informal">click here</label>\r
+           <label index="click_here_accessible">Click here for audio version of the word to enter.</label>\r
+           <label index="click_here_accessible_informal">Click here for audio version of the word to enter.</label>\r
+            <label index="cant_read2">.</label>\r
+           <label index="noImageMessage">Sorry, we cannot autoreload a new image. Submit the form and a new image will be loaded.</label>\r
+           <label index="noPlayMessage">Sorry, we cannot play the word of the image.</label>\r
+        </languageKey>\r
+        <languageKey index="dk" type="array">\r
+            <label index="altText">CAPTCHA billede for SPAM beskyttelse</label>\r
+            <label index="notice">Indtast venligst det ord der er vist på billedet.</label>\r
+            <label index="notice_informal">Indtast venligst det ord der er vist på billedet.</label>\r
+            <label index="explain">Dette er for at beskytte imod misbrug.</label>\r
+            <label index="cant_read1">Hvis du ikke kan læse ordet,</label>\r
+            <label index="cant_read1_informal">Hvis du ikke kan læse ordet,</label>\r
+            <label index="click_here">tryk her</label>\r
+            <label index="click_here_informal">tryk her</label>\r
+            <label index="cant_read2">.</label>\r
+        </languageKey>\r
+        <languageKey index="de" type="array">\r
+            <label index="altText">CAPTCHA Bild zum Spamschutz</label>\r
+            <label index="notice">Bitte geben Sie hier das Wort ein, das im Bild angezeigt wird.</label>\r
+            <label index="notice_informal">Gib hier das Wort ein, das im Bild angezeigt wird.</label>\r
+            <label index="explain">Dies dient der Spamvermeidung</label>\r
+            <label index="cant_read1">Wenn Sie das Wort nicht lesen können,</label>\r
+            <label index="cant_read1_informal">Wenn du das Wort nicht lesen kannst,</label>\r
+            <label index="click_here">bitte hier klicken</label>\r
+            <label index="click_here_informal">hier klicken</label>\r
+            <label index="cant_read2">.</label>\r
+        </languageKey>\r
+        <languageKey index="no" type="array">\r
+        </languageKey>\r
+        <languageKey index="it" type="array">\r
+            <label index="altText">Immagine CAPTCHA per prevenire lo SPAM</label>\r
+            <label index="notice">Per favore, inserisci la parola che vedi nell'immagine seguente.</label>\r
+            <label index="notice_informal">Inserisci la parola che vedi nell'immagine seguente.</label>\r
+            <label index="explain">Questo serve per prevenire lo SPAM.</label>\r
+            <label index="cant_read1">Se non riesci a leggere la parola,</label>\r
+            <label index="cant_read1_informal">Se non riesci a leggere la parola,</label>\r
+            <label index="click_here">clicca qui</label>\r
+            <label index="click_here_informal">clicca qui</label>\r
+            <label index="cant_read2">.</label>\r
+        </languageKey>\r
+        <languageKey index="fr" type="array">\r
+            <label index="altText">Image CAPTCHA pour prévenir l'utilisation abusive</label>\r
+            <label index="notice">Veuillez entrer ici le mot ou le nombre tel qu'il apparaît dans l'image.</label>\r
+            <label index="notice_informal">Entre ici le mot ou le nombre tel qu'il apparaît dans l'image.</label>\r
+            <label index="explain">Ceci vise à prévenir les abus.</label>\r
+            <label index="cant_read1">Si vous ne pouvez lire toutes les lettres ou chiffres,</label>\r
+            <label index="cant_read1_informal">Si tu ne peux pas lire toutes les lettres ou chiffres,</label>\r
+            <label index="click_here">cliquez ici</label>\r
+            <label index="click_here_informal">clique ici</label>\r
+           <label index="click_here_accessible">Cliquez ici pour une version audio du mot ou du nombre à entrer</label>\r
+           <label index="click_here_accessible_informal">Clique ici pour une version audio du mot ou du nombre à entrer</label>\r
+            <label index="cant_read2">.</label>\r
+           <label index="noImageMessage">Désolé, nous ne pouvons présenter une nouvelle image. Envoyez le formulaire et une nouvelle image sera présentée.</label>\r
+           <label index="noImageMessage_informal">Désolé, nous ne pouvons présenter une nouvelle image. Envoie le formulaire et une nouvelle image sera présentée.</label>\r
+           <label index="noPlayMessage">Désolé, nous ne pouvons jouer le mot ou le nombre à entrer.</label>\r
+        </languageKey>\r
+        <languageKey index="es" type="array">\r
+            <label index="altText">Imagen CAPTCHA para prevenir el uso abusivo</label>\r
+            <label index="notice">Por favor introduzca la palabra tal como aparece en la imagen.</label>\r
+            <label index="notice_informal">Por favor introduce la palabra tal como aparece en la imagen.</label>\r
+            <label index="explain">Esto es para prevenir los abusos.</label>\r
+            <label index="cant_read1">Si no puede leer toda las letras,</label>\r
+            <label index="cant_read1_informal">Si no puedes leer todas las letras,</label>\r
+            <label index="click_here">haga clic aquí</label>\r
+            <label index="click_here_informal">haz clic aquí</label>\r
+            <label index="cant_read2">.</label>\r
+        </languageKey>\r
+        <languageKey index="nl" type="array">\r
+            <label index="altText">CAPTCHA afbeelding om SPAM tegen te gaan</label>\r
+            <label index="notice">Voer hier het woord in zoals getoond in de afbeelding.</label>\r
+            <label index="notice_informal">Voer hier het woord in zoals getoond in de afbeelding.</label>\r
+            <label index="explain">Dit is om spam tegen te gaan.</label>\r
+            <label index="cant_read1">Als je het woord niet kunt lezen,</label>\r
+            <label index="cant_read1_informal">Als je het woord niet kunt lezen,</label>\r
+            <label index="click_here">klik hier</label>\r
+            <label index="click_here_informal">klik hier</label>\r
+            <label index="cant_read2">.</label>\r
+        </languageKey>\r
+        <languageKey index="cz" type="array">\r
+        </languageKey>\r
+        <languageKey index="pl" type="array">\r
+        </languageKey>\r
+        <languageKey index="si" type="array">\r
+        </languageKey>\r
+        <languageKey index="fi" type="array">\r
+            <label index="altText">CAPTCHA kuva roskapostin välttämiseksi</label>\r
+            <label index="notice">Kirjoita tähän kuvassa näkyvä sana.</label>\r
+            <label index="notice_informal">Kirjoita tähän kuvassa näkyvä sana</label>\r
+            <label index="explain">(varmistamme ettei viesti tule haittaohjelmasta).</label>\r
+            <label index="cant_read1">Jos et saa sanasta selvää,</label>\r
+            <label index="cant_read1_informal">Jos et saa sanasta selvää,</label>\r
+            <label index="click_here">klikkaa tästä uusi kuva</label>\r
+            <label index="click_here_informal">klikkaa tästä uusi kuva</label>\r
+            <label index="cant_read2">.</label>\r
+        </languageKey>\r
+        <languageKey index="tr" type="array">\r
+        </languageKey>\r
+        <languageKey index="se" type="array">\r
+        </languageKey>\r
+        <languageKey index="pt" type="array">\r
+               <label index="altText">Imagem CAPTCHA para prevenir &quot;spam&quot;</label>\r
+               <label index="notice">Por favor introduza aqui a palavra escrita na imagem.</label>\r
+               <label index="notice_informal">Por favor introduza aqui a palavra escrita na imagem.</label>\r
+               <label index="explain">Esta verificação previne a ocorrência de &quot;spam&quot;.</label>\r
+               <label index="cant_read1">Se não consegue ler a palavra,</label>\r
+               <label index="cant_read1_informal">Se não consegue ler a palavra,</label>\r
+               <label index="click_here">clique aqui para gerar uma nova</label>\r
+               <label index="click_here_informal">clique aqui para gerar uma nova</label>\r
+               <label index="click_here_accessible">Clique aqui para ouvir uma versão audio do código a digitar.</label>\r
+               <label index="click_here_accessible_informal">Clique aqui para ouvir uma versão audio do código a digitar.</label>\r
+               <label index="cant_read2">.</label>\r
+        </languageKey>\r
+        <languageKey index="ru" type="array">\r
+        </languageKey>\r
+        <languageKey index="ro" type="array">\r
+        </languageKey>\r
+        <languageKey index="ch" type="array">\r
+        </languageKey>\r
+        <languageKey index="sk" type="array">\r
+        </languageKey>\r
+        <languageKey index="lt" type="array">\r
+        </languageKey>\r
+        <languageKey index="is" type="array">\r
+        </languageKey>\r
+        <languageKey index="hr" type="array">\r
+        </languageKey>\r
+        <languageKey index="hu" type="array">\r
+        </languageKey>\r
+        <languageKey index="gl" type="array">\r
+        </languageKey>\r
+        <languageKey index="th" type="array">\r
+        </languageKey>\r
+        <languageKey index="gr" type="array">\r
+        </languageKey>\r
+        <languageKey index="hk" type="array">\r
+        </languageKey>\r
+        <languageKey index="eu" type="array">\r
+        </languageKey>\r
+        <languageKey index="bg" type="array">\r
+        </languageKey>\r
+        <languageKey index="br" type="array">\r
+            <label index="altText">Imagem CAPTCHA para prevenção de SPAM</label>\r
+            <label index="notice">Por favor digite a palavra exibida na imagem.</label>\r
+            <label index="notice_informal">Por favor digite a palavra exibida na imagem.</label>\r
+            <label index="explain">Isto serve para prevenir lixo eletrônico.</label>\r
+            <label index="cant_read1">Se você não conseguir ler a palavra,</label>\r
+            <label index="cant_read1_informal">Se você não conseguir ler a palavra,</label>\r
+            <label index="click_here">clique aqui</label>\r
+            <label index="click_here_informal">clique aqui</label>\r
+            <label index="cant_read2">.</label>\r
+        </languageKey>\r
+        <languageKey index="et" type="array">\r
+        </languageKey>\r
+        <languageKey index="ar" type="array">\r
+        </languageKey>\r
+        <languageKey index="he" type="array">\r
+        </languageKey>\r
+        <languageKey index="ua" type="array">\r
+        </languageKey>\r
+        <languageKey index="lv" type="array">\r
+        </languageKey>\r
+        <languageKey index="jp" type="array">\r
+        </languageKey>\r
+        <languageKey index="vn" type="array">\r
+        </languageKey>\r
+        <languageKey index="ca" type="array">\r
+        </languageKey>\r
+        <languageKey index="ba" type="array">\r
+        </languageKey>\r
+        <languageKey index="kr" type="array">\r
+        </languageKey>\r
+        <languageKey index="eo" type="array">\r
+        </languageKey>\r
+        <languageKey index="my" type="array">\r
+        </languageKey>\r
+        <languageKey index="hi" type="array">\r
+        </languageKey>\r
+    </data>\r
+    <orig_hash type="array">\r
+        <languageKey index="default" type="array">\r
+            <label index="altText" type="integer">147175052</label>\r
+            <label index="notice" type="integer">42390561</label>\r
+            <label index="notice_informal" type="integer">42390561</label>\r
+            <label index="explain" type="integer">42597147</label>\r
+            <label index="cant_read1" type="integer">252707028</label>\r
+            <label index="cant_read1_informal" type="integer">252707028</label>\r
+            <label index="click_here" type="integer">172927260</label>\r
+            <label index="click_here_informal" type="integer">172927260</label>\r
+            <label index="cant_read2" type="integer">84250394</label>\r
+        </languageKey>\r
+        <languageKey index="dk" type="array">\r
+            <label index="altText" type="integer">147175052</label>\r
+            <label index="notice" type="integer">42390561</label>\r
+            <label index="notice_informal" type="integer">42390561</label>\r
+            <label index="explain" type="integer">42597147</label>\r
+            <label index="cant_read1" type="integer">252707028</label>\r
+            <label index="cant_read1_informal" type="integer">252707028</label>\r
+            <label index="click_here" type="integer">172927260</label>\r
+            <label index="click_here_informal" type="integer">172927260</label>\r
+            <label index="cant_read2" type="integer">84250394</label>\r
+        </languageKey>\r
+        <languageKey index="de" type="array">\r
+            <label index="altText" type="integer">147175052</label>\r
+            <label index="notice" type="integer">42390561</label>\r
+            <label index="notice_informal" type="integer">42390561</label>\r
+            <label index="explain" type="integer">42597147</label>\r
+            <label index="cant_read1" type="integer">252707028</label>\r
+            <label index="cant_read1_informal" type="integer">252707028</label>\r
+            <label index="click_here" type="integer">172927260</label>\r
+            <label index="click_here_informal" type="integer">172927260</label>\r
+            <label index="cant_read2" type="integer">84250394</label>\r
+        </languageKey>\r
+        <languageKey index="no" type="array">\r
+        </languageKey>\r
+        <languageKey index="it" type="array">\r
+        </languageKey>\r
+        <languageKey index="fr" type="array">\r
+            <label index="altText" type="integer">147175052</label>\r
+            <label index="notice" type="integer">42390561</label>\r
+            <label index="notice_informal" type="integer">42390561</label>\r
+            <label index="explain" type="integer">42597147</label>\r
+            <label index="cant_read1" type="integer">252707028</label>\r
+            <label index="cant_read1_informal" type="integer">252707028</label>\r
+            <label index="click_here" type="integer">172927260</label>\r
+            <label index="click_here_informal" type="integer">172927260</label>\r
+            <label index="cant_read2" type="integer">84250394</label>\r
+        </languageKey>\r
+        <languageKey index="es" type="array">\r
+        </languageKey>\r
+        <languageKey index="nl" type="array">\r
+            <label index="altText" type="integer">147175052</label>\r
+            <label index="notice" type="integer">42390561</label>\r
+            <label index="notice_informal" type="integer">42390561</label>\r
+            <label index="explain" type="integer">42597147</label>\r
+            <label index="cant_read1" type="integer">252707028</label>\r
+            <label index="cant_read1_informal" type="integer">252707028</label>\r
+            <label index="click_here" type="integer">172927260</label>\r
+            <label index="click_here_informal" type="integer">172927260</label>\r
+            <label index="cant_read2" type="integer">84250394</label>\r
+        </languageKey>\r
+        <languageKey index="cz" type="array">\r
+        </languageKey>\r
+        <languageKey index="pl" type="array">\r
+        </languageKey>\r
+        <languageKey index="si" type="array">\r
+        </languageKey>\r
+        <languageKey index="fi" type="array">\r
+            <label index="altText" type="integer">147175052</label>\r
+            <label index="notice" type="integer">42390561</label>\r
+            <label index="notice_informal" type="integer">42390561</label>\r
+            <label index="explain" type="integer">42597147</label>\r
+            <label index="cant_read1" type="integer">252707028</label>\r
+            <label index="cant_read1_informal" type="integer">252707028</label>\r
+            <label index="click_here" type="integer">172927260</label>\r
+            <label index="click_here_informal" type="integer">172927260</label>\r
+            <label index="cant_read2" type="integer">84250394</label>\r
+        </languageKey>\r
+        <languageKey index="tr" type="array">\r
+        </languageKey>\r
+        <languageKey index="se" type="array">\r
+        </languageKey>\r
+        <languageKey index="pt" type="array">\r
+        </languageKey>\r
+        <languageKey index="ru" type="array">\r
+        </languageKey>\r
+        <languageKey index="ro" type="array">\r
+        </languageKey>\r
+        <languageKey index="ch" type="array">\r
+        </languageKey>\r
+        <languageKey index="sk" type="array">\r
+        </languageKey>\r
+        <languageKey index="lt" type="array">\r
+        </languageKey>\r
+        <languageKey index="is" type="array">\r
+        </languageKey>\r
+        <languageKey index="hr" type="array">\r
+        </languageKey>\r
+        <languageKey index="hu" type="array">\r
+        </languageKey>\r
+        <languageKey index="gl" type="array">\r
+        </languageKey>\r
+        <languageKey index="th" type="array">\r
+        </languageKey>\r
+        <languageKey index="gr" type="array">\r
+        </languageKey>\r
+        <languageKey index="hk" type="array">\r
+        </languageKey>\r
+        <languageKey index="eu" type="array">\r
+        </languageKey>\r
+        <languageKey index="bg" type="array">\r
+        </languageKey>\r
+        <languageKey index="br" type="array">\r
+            <label index="altText" type="integer">147175052</label>\r
+            <label index="notice" type="integer">42390561</label>\r
+            <label index="notice_informal" type="integer">42390561</label>\r
+            <label index="explain" type="integer">42597147</label>\r
+            <label index="cant_read1" type="integer">252707028</label>\r
+            <label index="cant_read1_informal" type="integer">252707028</label>\r
+            <label index="click_here" type="integer">172927260</label>\r
+            <label index="click_here_informal" type="integer">172927260</label>\r
+            <label index="cant_read2" type="integer">84250394</label>\r
+        </languageKey>\r
+        <languageKey index="et" type="array">\r
+        </languageKey>\r
+        <languageKey index="ar" type="array">\r
+        </languageKey>\r
+        <languageKey index="he" type="array">\r
+        </languageKey>\r
+        <languageKey index="ua" type="array">\r
+        </languageKey>\r
+        <languageKey index="lv" type="array">\r
+        </languageKey>\r
+        <languageKey index="jp" type="array">\r
+        </languageKey>\r
+        <languageKey index="vn" type="array">\r
+        </languageKey>\r
+        <languageKey index="ca" type="array">\r
+        </languageKey>\r
+        <languageKey index="ba" type="array">\r
+        </languageKey>\r
+        <languageKey index="kr" type="array">\r
+        </languageKey>\r
+        <languageKey index="eo" type="array">\r
+        </languageKey>\r
+        <languageKey index="my" type="array">\r
+        </languageKey>\r
+        <languageKey index="hi" type="array">\r
+        </languageKey>\r
+    </orig_hash>\r
+    <orig_text type="array">\r
+        <languageKey index="default" type="array">\r
+        </languageKey>\r
+        <languageKey index="dk" type="array">\r
+        </languageKey>\r
+        <languageKey index="de" type="array">\r
+        </languageKey>\r
+        <languageKey index="no" type="array">\r
+        </languageKey>\r
+        <languageKey index="it" type="array">\r
+        </languageKey>\r
+        <languageKey index="fr" type="array">\r
+        </languageKey>\r
+        <languageKey index="es" type="array">\r
+        </languageKey>\r
+        <languageKey index="nl" type="array">\r
+        </languageKey>\r
+        <languageKey index="cz" type="array">\r
+        </languageKey>\r
+        <languageKey index="pl" type="array">\r
+        </languageKey>\r
+        <languageKey index="si" type="array">\r
+        </languageKey>\r
+        <languageKey index="fi" type="array">\r
+        </languageKey>\r
+        <languageKey index="tr" type="array">\r
+        </languageKey>\r
+        <languageKey index="se" type="array">\r
+        </languageKey>\r
+        <languageKey index="pt" type="array">\r
+        </languageKey>\r
+        <languageKey index="ru" type="array">\r
+        </languageKey>\r
+        <languageKey index="ro" type="array">\r
+        </languageKey>\r
+        <languageKey index="ch" type="array">\r
+        </languageKey>\r
+        <languageKey index="sk" type="array">\r
+        </languageKey>\r
+        <languageKey index="lt" type="array">\r
+        </languageKey>\r
+        <languageKey index="is" type="array">\r
+        </languageKey>\r
+        <languageKey index="hr" type="array">\r
+        </languageKey>\r
+        <languageKey index="hu" type="array">\r
+        </languageKey>\r
+        <languageKey index="gl" type="array">\r
+        </languageKey>\r
+        <languageKey index="th" type="array">\r
+        </languageKey>\r
+        <languageKey index="gr" type="array">\r
+        </languageKey>\r
+        <languageKey index="hk" type="array">\r
+        </languageKey>\r
+        <languageKey index="eu" type="array">\r
+        </languageKey>\r
+        <languageKey index="bg" type="array">\r
+        </languageKey>\r
+        <languageKey index="br" type="array">\r
+        </languageKey>\r
+        <languageKey index="et" type="array">\r
+        </languageKey>\r
+        <languageKey index="ar" type="array">\r
+        </languageKey>\r
+        <languageKey index="he" type="array">\r
+        </languageKey>\r
+        <languageKey index="ua" type="array">\r
+        </languageKey>\r
+        <languageKey index="lv" type="array">\r
+        </languageKey>\r
+        <languageKey index="jp" type="array">\r
+        </languageKey>\r
+        <languageKey index="vn" type="array">\r
+        </languageKey>\r
+        <languageKey index="ca" type="array">\r
+        </languageKey>\r
+        <languageKey index="ba" type="array">\r
+        </languageKey>\r
+        <languageKey index="kr" type="array">\r
+        </languageKey>\r
+        <languageKey index="eo" type="array">\r
+        </languageKey>\r
+        <languageKey index="my" type="array">\r
+        </languageKey>\r
+        <languageKey index="hi" type="array">\r
+        </languageKey>\r
+    </orig_text>\r
+</T3locallang>
\ No newline at end of file
diff --git a/pi3/audioCaptcha.php b/pi3/audioCaptcha.php
new file mode 100644 (file)
index 0000000..a12ec2d
--- /dev/null
@@ -0,0 +1,136 @@
+<?php\r
+/***************************************************************\r
+*  Copyright notice\r
+*\r
+*  (c) 2008 Stanislas Rolland <typo3(arobas)sjbr.ca>\r
+*  All rights reserved\r
+*\r
+*  This script is part of the Typo3 project. The Typo3 project is\r
+*  free software; you can redistribute it and/or modify\r
+*  it under the terms of the GNU General Public License as published by\r
+*  the Free Software Foundation; either version 2 of the License, or\r
+*  (at your option) any later version.\r
+*\r
+*  The GNU General Public License can be found at\r
+*  http://www.gnu.org/copyleft/gpl.html.\r
+*\r
+*  This script is distributed in the hope that it will be useful,\r
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*  GNU General Public License for more details.\r
+*\r
+*  This copyright notice MUST APPEAR in all copies of the script!\r
+***************************************************************/\r
+/**\r
+ * This script invokes SysTurn speech generation\r
+ *\r
+ */\r
+\r
+error_reporting (E_ALL ^ E_NOTICE);\r
+define('PATH_thisScript',str_replace('//','/', str_replace('\\','/', (php_sapi_name()=='cgi'||php_sapi_name()=='xcgi'||php_sapi_name()=='isapi' ||php_sapi_name()=='cgi-fcgi')&&((!empty($_SERVER['ORIG_PATH_TRANSLATED'])&&isset($_SERVER['ORIG_PATH_TRANSLATED']))?$_SERVER['ORIG_PATH_TRANSLATED']:$_SERVER['PATH_TRANSLATED'])? ((!empty($_SERVER['ORIG_PATH_TRANSLATED'])&&isset($_SERVER['ORIG_PATH_TRANSLATED']))?$_SERVER['ORIG_PATH_TRANSLATED']:$_SERVER['PATH_TRANSLATED']):((!empty($_SERVER['ORIG_SCRIPT_FILENAME'])&&isset($_SERVER['ORIG_SCRIPT_FILENAME']))?$_SERVER['ORIG_SCRIPT_FILENAME']:$_SERVER['SCRIPT_FILENAME']))));\r
+if (!defined('PATH_site')) define('PATH_site', dirname(dirname(dirname(dirname(dirname(PATH_thisScript))))).'/');\r
+if (!defined('PATH_t3lib')) define('PATH_t3lib', PATH_site.'t3lib/');\r
+define('PATH_typo3conf', PATH_site.'typo3conf/');\r
+define('TYPO3_mainDir', 'typo3/');\r
+if (!defined('PATH_typo3')) define('PATH_typo3', PATH_site.TYPO3_mainDir);\r
+if (!defined('PATH_tslib')) {\r
+       if (@is_dir(PATH_site.'typo3/sysext/cms/tslib/')) {\r
+               define('PATH_tslib', PATH_site.'typo3/sysext/cms/tslib/');\r
+       } elseif (@is_dir(PATH_site.'tslib/')) {\r
+               define('PATH_tslib', PATH_site.'tslib/');\r
+       }\r
+}\r
+define('TYPO3_MODE','FE');\r
+define('TYPO3_OS', stristr(PHP_OS,'win')&&!stristr(PHP_OS,'darwin')?'WIN':'');\r
+\r
+require_once(PATH_t3lib.'class.t3lib_div.php');\r
+require_once(PATH_t3lib.'class.t3lib_extmgm.php');\r
+require_once(PATH_t3lib.'config_default.php');\r
+require_once(PATH_typo3conf.'localconf.php');\r
+require_once(PATH_tslib.'class.tslib_fe.php');\r
+require_once(PATH_t3lib.'class.t3lib_tstemplate.php');\r
+require_once(PATH_t3lib.'class.t3lib_page.php');\r
+require_once(PATH_tslib.'class.tslib_content.php');\r
+require_once(t3lib_extMgm::extPath('sr_freecap').'pi3/class.tx_srfreecap_pi3.php');\r
+require_once(PATH_t3lib.'class.t3lib_userauth.php');\r
+require_once(PATH_tslib.'class.tslib_feuserauth.php');\r
+require_once(PATH_t3lib.'class.t3lib_cs.php');\r
+\r
+if (!defined ('TYPO3_db'))  die ('The configuration file was not included.');\r
+if (isset($_GET['GLOBALS']) || isset($_POST['GLOBALS']) || isset($_FILES['GLOBALS']) || isset($_COOKIE['GLOBALS'])) die('You cannot set the GLOBALS-array from outside this script.');\r
+\r
+require_once(PATH_t3lib.'class.t3lib_db.php');\r
+$TYPO3_DB = t3lib_div::makeInstance('t3lib_DB');\r
+\r
+require_once(PATH_t3lib.'class.t3lib_timetrack.php');\r
+$GLOBALS['TT'] = new t3lib_timeTrack;\r
+\r
+if (t3lib_div::int_from_ver( TYPO3_version ) >= 4003000) {\r
+       // ***********************************\r
+       // Initializing the Caching System\r
+       // ***********************************\r
+       $GLOBALS['TT']->push('Initializing the Caching System','');\r
+               require_once(PATH_t3lib . 'class.t3lib_cache.php');\r
+\r
+               require_once(PATH_t3lib . 'cache/class.t3lib_cache_abstractbackend.php');\r
+               require_once(PATH_t3lib . 'cache/class.t3lib_cache_abstractcache.php');\r
+               require_once(PATH_t3lib . 'cache/class.t3lib_cache_exception.php');\r
+               require_once(PATH_t3lib . 'cache/class.t3lib_cache_factory.php');\r
+               require_once(PATH_t3lib . 'cache/class.t3lib_cache_manager.php');\r
+               require_once(PATH_t3lib . 'cache/class.t3lib_cache_variablecache.php');\r
+\r
+               require_once(PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_classalreadyloaded.php');\r
+               require_once(PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_duplicateidentifier.php');\r
+               require_once(PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_invalidbackend.php');\r
+               require_once(PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_invalidcache.php');\r
+               require_once(PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_invaliddata.php');\r
+               require_once(PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_nosuchcache.php');\r
+\r
+               $typo3CacheManager = t3lib_div::makeInstance('t3lib_cache_Manager');\r
+               $cacheFactoryClass = t3lib_div::makeInstanceClassName('t3lib_cache_Factory');\r
+               $typo3CacheFactory = new $cacheFactoryClass($typo3CacheManager);\r
+\r
+               unset($cacheFactoryClass);\r
+       $GLOBALS['TT']->pull();\r
+}\r
+\r
+// ***********************************\r
+// Creating a $TSFE object\r
+// ***********************************\r
+$TSFEclassName = t3lib_div::makeInstanceClassName('tslib_fe');\r
+$id = t3lib_div::_GET('id');\r
+if (!isset($id)) $id = 0;\r
+$id = htmlspecialchars($id);\r
+$TSFE = new $TSFEclassName($TYPO3_CONF_VARS, $id, '0', 1, '', '','','');\r
+if (t3lib_div::int_from_ver( TYPO3_version ) >= 4003000) {\r
+       $TSFE->initCaches();\r
+}\r
+$TSFE->set_no_cache();\r
+$TSFE->connectToDB();\r
+$TSFE->initFEuser();\r
+$TSFE->determineId();\r
+$TSFE->initTemplate();\r
+$TSFE->tmpl->getFileName_backPath = PATH_site;\r
+\r
+// ******************************************************\r
+// Get config if not already gotten\r
+// After this, we should have a valid config-array ready\r
+// ******************************************************\r
+$TSFE->getConfigArray();\r
+\r
+// *******************************************\r
+// Setting language and locale\r
+// *******************************************\r
+$GLOBALS['TT']->push('Setting language and locale','');\r
+       $TSFE->settingLanguage();\r
+       $TSFE->settingLocale();\r
+$GLOBALS['TT']->pull();\r
+\r
+// *******************************************\r
+// Invoke the freecap plugin\r
+// *******************************************\r
+$freecap = t3lib_div::makeInstance('tx_srfreecap_pi3');\r
+$freecap->cObj = t3lib_div::makeInstance('tslib_cObj');\r
+$conf = $TSFE->tmpl->setup['plugin.'][$freecap->prefixId.'.'];\r
+$freecap->main($conf);\r
+?>
\ No newline at end of file
diff --git a/pi3/class.tx_srfreecap_pi3.php b/pi3/class.tx_srfreecap_pi3.php
new file mode 100644 (file)
index 0000000..65c91aa
--- /dev/null
@@ -0,0 +1,170 @@
+<?php\r
+/***************************************************************\r
+*  Copyright notice\r
+*\r
+*  (c) 2007-2008 Stanislas Rolland (typo3(arobas)sjbr.ca)\r
+*  All rights reserved\r
+*\r
+*  This script is part of the TYPO3 project. The TYPO3 project is\r
+*  free software; you can redistribute it and/or modify\r
+*  it under the terms of the GNU General Public License as published by\r
+*  the Free Software Foundation; either version 2 of the License, or\r
+*  (at your option) any later version.\r
+*\r
+*  The GNU General Public License can be found at\r
+*  http://www.gnu.org/copyleft/gpl.html.\r
+*  A copy is found in the textfile GPL.txt and important notices to the license\r
+*  from the author is found in LICENSE.txt distributed with these scripts.\r
+*\r
+*\r
+*  This script is distributed in the hope that it will be useful,\r
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*  GNU General Public License for more details.\r
+*\r
+*  This copyright notice MUST APPEAR in all copies of the script!\r
+***************************************************************/\r
+/**\r
+ * Renders a wav audio version of the CAPTCHA\r
+ *\r
+ * @author     Stanislas Rolland       <typo3(arobas)sjbr.ca>\r
+ */\r
+require_once(PATH_tslib.'class.tslib_pibase.php');\r
+\r
+class tx_srfreecap_pi3 extends tslib_pibase {\r
+       public $cObj;                                                   // The backReference to the mother cObj object set at call time\r
+       public $prefixId = 'tx_srfreecap_pi3';                          // Same as class name\r
+       public $scriptRelPath = 'pi3/class.tx_srfreecap_pi3.php';       // Path to this script relative to the extension dir.\r
+       public $extKey = 'sr_freecap';                                  // The extension key.\r
+       public $conf = array();\r
+       private $voicesDir;\r
+       \r
+       function main($conf) {\r
+               $this->conf = $conf;\r
+                       // Load session data\r
+               $this->sessionData = $GLOBALS['TSFE']->fe_user->getKey('ses','tx_'.$this->extKey);\r
+               $this->voicesDir = $this->getVoicesDir();\r
+               $this->output($this->getWord());\r
+               exit();\r
+       }\r
+       \r
+       /**\r
+        * Gets the directory of wav files based on configured language\r
+        *\r
+        * @return      void\r
+        */\r
+       function getVoicesDir() {\r
+               global $TSFE;\r
+               $voicesDir = t3lib_extMgm::extPath('sr_freecap') . '/res/voices/' . $TSFE->lang . '/';\r
+               if (!is_dir($voicesDir)) {\r
+                       $voicesDir = t3lib_extMgm::extPath('sr_freecap') . '/res/voices/default/';\r
+               }\r
+               return $voicesDir;\r
+       }\r
+       \r
+       /**\r
+        * Gets the word that was stored in session data\r
+        *\r
+        * @return      string          the retrieved and decoded word\r
+        */\r
+       function getWord() {\r
+               $code = 'accessiblemustbe007';\r
+               $dec_string = $this->easy_decrypt($this->sessionData[$this->extKey . '_word_accessible'], $code);\r
+               return implode("-", str_split($dec_string));\r
+       }\r
+       \r
+       /**\r
+        * Decodes a string\r
+        *\r
+        * @param       array           $cyph_arr: an array as returned by easy_encrypt() (see class.tx_srfreecap_pi1.php)\r
+        *\r
+        * @return      string          the decoded string\r
+        */\r
+       function easy_decrypt($cyph_arr, $key){\r
+               return trim(mcrypt_decrypt(MCRYPT_BLOWFISH, $key, base64_decode($cyph_arr[0]), MCRYPT_MODE_CBC, base64_decode($cyph_arr[1])));\r
+       }\r
+\r
+       /**\r
+        * Outputs the wav file\r
+        *\r
+        * @param       string          $word: the word to be spelled and played\r
+        *\r
+        * @return      void\r
+        */\r
+       function output($word) {\r
+               $output = $this->generate($word);\r
+               header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');\r
+               header('Pragma: no-cache');\r
+               header('Cache-Control: no-cache, no-store, must-revalidate');\r
+               header('Content-Type: audio/x-wav');\r
+               header('Content-Length: ' . strlen($output));\r
+               echo $output;\r
+       }\r
+       \r
+       /**\r
+        * Builds an array of letter rendering wav files\r
+        *\r
+        * @param       string          $word: the word to be spelled and played\r
+        *\r
+        * @return      array           array of wav file names\r
+       &