From 03995d3bc642a4a15ef3a370e509671c895d58a3 Mon Sep 17 00:00:00 2001 From: Jeena Date: Mon, 7 Oct 2013 14:46:08 +0200 Subject: [PATCH] exported from svn --- .htaccess | 24 + LICENSE.txt | 340 +++++ README.txt | 41 + admin/auth.php | 13 + admin/blog.func.php | 355 +++++ admin/categories.php | 79 + admin/change.php | 60 + admin/comments.php | 217 +++ admin/export-rss2.php | 13 + admin/index.php | 75 + admin/login.php | 76 + admin/logout.php | 9 + admin/media/select-picture.php | 54 + admin/media/select-teaser.php | 43 + admin/media/upload-picture.php | 88 ++ admin/media/upload-teaser.php | 92 ++ admin/new.php | 103 ++ admin/plugin.php | 53 + admin/settings.php | 33 + admin/update.php | 35 + archive.php | 138 ++ error404.php | 15 + img/JLOG_edit.png | Bin 0 -> 139 bytes img/JLOG_rss-full.png | Bin 0 -> 387 bytes img/JLOG_rss-summary.png | Bin 0 -> 394 bytes img/JLOG_trash.png | Bin 0 -> 117 bytes index.php | 107 ++ lang/lang-admin.de.inc.php | 246 +++ lang/lang-admin.en.inc.php | 246 +++ lang/lang-admin.it.inc.php | 241 +++ lang/lang-admin.pl.inc.php | 241 +++ lang/lang-admin.sv.inc.php | 241 +++ lang/lang.de.inc.php | 121 ++ lang/lang.en.inc.php | 122 ++ lang/lang.it.inc.php | 121 ++ lang/lang.pl.inc.php | 122 ++ lang/lang.sv.inc.php | 121 ++ learn_bb.php | 27 + log.php | 308 ++++ page.php | 45 + personal/css/admin.css | 28 + personal/css/ielte6.css | 34 + personal/css/img/Browse.plb | Bin 0 -> 6037 bytes personal/css/img/banner-ielte6.jpg | Bin 0 -> 38700 bytes personal/css/img/banner.jpg | Bin 0 -> 41411 bytes personal/css/img/body.png | Bin 0 -> 161 bytes personal/css/img/border.png | Bin 0 -> 76 bytes personal/css/img/cheese.png | Bin 0 -> 624 bytes personal/css/img/footer.png | Bin 0 -> 2498 bytes personal/css/img/pokal.png | Bin 0 -> 21125 bytes personal/css/popup.css | 34 + personal/css/print.css | 19 + personal/css/screen.css | 213 +++ personal/template.tpl | 40 + plugins/.htaccess | 2 + plugins/CommentCloser.jplug.php | 126 ++ plugins/MiniAntispam.jplug.php | 38 + scripts/JlogUpdater.php | 149 ++ scripts/bbcode.php | 172 +++ scripts/categories.class.php | 250 ++++ scripts/comments.php | 141 ++ scripts/database.class.php | 71 + scripts/do_template.php | 121 ++ scripts/general.func.php | 313 ++++ scripts/ixr-library.inc.php | 817 ++++++++++ scripts/javascripts.js | 332 +++++ scripts/jlogHTTP_Request.php | 1832 +++++++++++++++++++++++ scripts/jlogPlugins.class.php | 83 ++ scripts/mail.class.php | 279 ++++ scripts/prepend.inc.php | 91 ++ scripts/settings.class.php | 533 +++++++ scripts/stringparser.class.php | 1544 +++++++++++++++++++ scripts/stringparser_bbcode.class.php | 1979 +++++++++++++++++++++++++ scripts/update.php | 135 ++ scripts/update/102To110.php | 66 + scripts/update/110To111.php | 14 + scripts/update/111To112.php | 28 + scripts/update/112To113.php | 15 + scripts/update/Example.php | 42 + scripts/url_syntax.php | 248 ++++ scripts/version.inc.php | 31 + search.php | 94 ++ setup.php | 315 ++++ stop.php | 27 + xmlrpc.php | 244 +++ 85 files changed, 14765 insertions(+) create mode 100644 .htaccess create mode 100644 LICENSE.txt create mode 100644 README.txt create mode 100644 admin/auth.php create mode 100644 admin/blog.func.php create mode 100644 admin/categories.php create mode 100644 admin/change.php create mode 100644 admin/comments.php create mode 100644 admin/export-rss2.php create mode 100644 admin/index.php create mode 100644 admin/login.php create mode 100644 admin/logout.php create mode 100644 admin/media/select-picture.php create mode 100644 admin/media/select-teaser.php create mode 100644 admin/media/upload-picture.php create mode 100644 admin/media/upload-teaser.php create mode 100644 admin/new.php create mode 100644 admin/plugin.php create mode 100644 admin/settings.php create mode 100644 admin/update.php create mode 100644 archive.php create mode 100644 error404.php create mode 100644 img/JLOG_edit.png create mode 100644 img/JLOG_rss-full.png create mode 100644 img/JLOG_rss-summary.png create mode 100644 img/JLOG_trash.png create mode 100644 index.php create mode 100644 lang/lang-admin.de.inc.php create mode 100644 lang/lang-admin.en.inc.php create mode 100644 lang/lang-admin.it.inc.php create mode 100644 lang/lang-admin.pl.inc.php create mode 100644 lang/lang-admin.sv.inc.php create mode 100644 lang/lang.de.inc.php create mode 100644 lang/lang.en.inc.php create mode 100644 lang/lang.it.inc.php create mode 100644 lang/lang.pl.inc.php create mode 100644 lang/lang.sv.inc.php create mode 100644 learn_bb.php create mode 100644 log.php create mode 100644 page.php create mode 100644 personal/css/admin.css create mode 100644 personal/css/ielte6.css create mode 100644 personal/css/img/Browse.plb create mode 100644 personal/css/img/banner-ielte6.jpg create mode 100644 personal/css/img/banner.jpg create mode 100644 personal/css/img/body.png create mode 100644 personal/css/img/border.png create mode 100644 personal/css/img/cheese.png create mode 100644 personal/css/img/footer.png create mode 100644 personal/css/img/pokal.png create mode 100644 personal/css/popup.css create mode 100644 personal/css/print.css create mode 100644 personal/css/screen.css create mode 100644 personal/template.tpl create mode 100644 plugins/.htaccess create mode 100644 plugins/CommentCloser.jplug.php create mode 100644 plugins/MiniAntispam.jplug.php create mode 100644 scripts/JlogUpdater.php create mode 100644 scripts/bbcode.php create mode 100644 scripts/categories.class.php create mode 100644 scripts/comments.php create mode 100644 scripts/database.class.php create mode 100644 scripts/do_template.php create mode 100644 scripts/general.func.php create mode 100644 scripts/ixr-library.inc.php create mode 100644 scripts/javascripts.js create mode 100644 scripts/jlogHTTP_Request.php create mode 100644 scripts/jlogPlugins.class.php create mode 100644 scripts/mail.class.php create mode 100644 scripts/prepend.inc.php create mode 100644 scripts/settings.class.php create mode 100644 scripts/stringparser.class.php create mode 100644 scripts/stringparser_bbcode.class.php create mode 100644 scripts/update.php create mode 100644 scripts/update/102To110.php create mode 100644 scripts/update/110To111.php create mode 100644 scripts/update/111To112.php create mode 100644 scripts/update/112To113.php create mode 100644 scripts/update/Example.php create mode 100644 scripts/url_syntax.php create mode 100644 scripts/version.inc.php create mode 100644 search.php create mode 100644 setup.php create mode 100644 stop.php create mode 100644 xmlrpc.php diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..0f1f401 --- /dev/null +++ b/.htaccess @@ -0,0 +1,24 @@ + + RewriteEngine On + + # catches all cathegories + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule "^cat/([a-z0-9_\-\.,]+)/?([0-9]{0,4})/?$" archive.php?cat=$1&y=$2 [QSA] + + # catches all archive links, month and year + RewriteRule "^archive$" archive.php [QSA] + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule "^([0-9]{4})/?([0-9]{0,2})/?$" archive.php?y=$1&m=$2 [QSA] + + # cathes all permalinks + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule "^([0-9]{4})/?([0-9]{2})/?([a-z0-9_\-\./,]+)$" log.php?y=$1&m=$2&url=$3 [QSA] + + # catches all pages + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule "^([a-z0-9_\-\./,]+)$" page.php?url=$1 [QSA] + diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..45645b4 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..d89e983 --- /dev/null +++ b/README.txt @@ -0,0 +1,41 @@ +### Weblogsystem Jlog +### Programmiert von Jeena Paradies, Dennis Riehle, Robert Bienert +### Mailingliste: +### Projektseite: +### Hilfe zur Installation: +### + +Dieses Programm steht unter der GPL. Eine Kopie der Lizenz habe ich als +Textdatei (Englisch LICENSE.txt) dem Paket beigefügt. + +Wir sehen es sehr gerne wenn sich Leute im Rahmen ihrer Möglichkeiten am +Projekt beteiligen. Insbesondere durch: + +1) Rückmeldungen über Fehler in der Software +2) Mitarbeit an der Software selbst, Plugins oder Programmiertips +3) Mitarbeit an der Dokumentation (siehe Wiki) + + +### Dankeschön an andere Programmierer + +Dieses Programm nutzt zum Auszeichnen der vom Benutzer eingegebenen +Daten die BBCode-Parserklasse für PHP + von Christian Seiler, +welche auch unter der GPL steht. + +Die Komunikation über XML-RPC übernimmt die IXR-Library + Sie steht zwar unter der Artistic +Licence, aber ich bekam vom Autor persönlich die Erlaubnis sie zu nutzen, +danke an dieser Stelle noch einmal an Simon Willison: »You have my +permission to use IXR in your software, re-licensing it if necessary. Thanks +for asking, and sorry the original license didn't work for you. I'll +consider changing the license to something more compatible (BSD probably) +in the future. Cheers, Simon« + +Um über HTTP Dateien zu holen wird HTTP_Request von PEAR mit allen +Abhängigkeiten verwendet zu finden unter: + + +Außerdem nutzt es in veränderter Form das Sessionbasierte Loginsystem +von Benjamin Wilfing, erhältlich unter: + diff --git a/admin/auth.php b/admin/auth.php new file mode 100644 index 0000000..a80d8a9 --- /dev/null +++ b/admin/auth.php @@ -0,0 +1,13 @@ + 23 OR + $minute < 0 OR $minute > 59 OR + $second < 0 OR $second > 59 + ) $errors[] = $l['admin']['false_date']; +*/ + if($form_input['section'] == 'page') { + $sql = "SELECT id FROM ".JLOG_DB_CONTENT." WHERE url = '".$f['url']."';"; + } + else { + $sql = "SELECT id FROM ".JLOG_DB_CONTENT." WHERE + YEAR(date) = ".date("Y", $f['date'])." AND + MONTH(date) = ".date("m", $f['date'])." AND + url = '".$f['url']."';"; + } + + $check_url = new Query($sql); + + if($check_url->error()) { + echo "
\n";
+         echo $check_url->getError();
+         echo "
\n"; + die(); + } + + if($check_url->numRows() > 0) { + $c = $check_url->fetch(); + if($c['id'] != $form_input['id'] AND $form_input['section'] != 'page') $errors[] = $l['admin']['url_duplicate']; + elseif($c['id'] != $form_input['id'] AND $form_input['section'] == 'page') $errors[] = $l['admin']['url_duplicate_page']; + } + } + + if(strlen(trim($form_input['teaserpic']) > 0) AND !is_file(JLOG_BASEPATH.'img'.DIRECTORY_SEPARATOR."t_".$form_input['teaserpic'])) { + $errors[] = $l['admin']['false_teaserpic']; + } + + if($form_input['teaserpiconblog'] == "1" AND strlen(trim($form_input['teaserpic'])) == 0) $errors[] = $l['admin']['no_teaserpic_uploaded']; + + if(strlen(trim($form_input['teaser'])) < 1) $errors[] = $l['admin']['no_teaser']; + if(strlen(trim($form_input['content'])) < 1) $errors[] = $l['admin']['no_content']; + + return $errors; +} + +// Eingabeformular +function form_output($form_input) { + $form_input = array_htmlspecialchars($form_input); +global $l, $categories, $plugins; + + if($form_input['teaserpiconblog'] == 1) $form_input['teaserpiconblog_check'] = "checked='checked'"; + if($form_input['section'] == 'page') $page = " checked='checked'"; + else $weblog = " checked='checked'"; + if($form_input['allowcomments'] === '0') $form_input['comments_check'] = "checked='checked'"; + if($form_input['allowpingback'] === '0') $form_input['pingback_check'] = "checked='checked'"; + + $o = " +
+
".$l['admin']['metadata']." +


+   +

+


+

+


+

+


+

+


+

+".$categories->output_select($form_input['categories'])." + +


+

+ +
+ +
".$l['admin']['contentdata']." + +



+

+ +

+ + + + ".add_session_id_input_tag()." +

+
+
+ + "; + + ### Plugin Hook + $o = $plugins->callHook('adminForm', $o, $form_input); + + return $o; +} + +function preview_output($form_input) { +global $l, $bbcode, $categories; + + // get data from _post + if(empty($form_input['date'])) $form_input['date'] = time(); + $output = "

".$l['admin']['preview']."

\n
".do_entry($form_input, NULL, $section)."
"; + + return $output; +} + +function insert_blog($form_input) { +global $l, $plugins; + + if($form_input['allowcomments'] != "0") $form_input['allowcomments'] = "1"; + if($form_input['allowpingback'] != "0") $form_input['allowpingback'] = "1"; + + $form_input = escape_for_mysql($form_input); + $sql = "INSERT INTO ".JLOG_DB_CONTENT." ( + topic, + url, + section, + date, + teaser, + teaserpic, + teaserpiconblog, + keywords, + content, + comments, + allowpingback ) + VALUES ( + '".$form_input['topic']."', + '".$form_input['url']."', + '".$form_input['section']."', + NOW(), + '".$form_input['teaser']."', + '".$form_input['teaserpic']."', + '".$form_input['teaserpiconblog']."', + '".$form_input['keywords']."', + '".$form_input['content']."', + '".$form_input['allowcomments']."', + '".$form_input['allowpingback']."' );"; + + $writeblog = new Query($sql); + $id = mysql_insert_id(); + if($writeblog->error()) { + echo "
\n";
+        echo $writeblog->getError();
+        echo "
\n"; + die(); + } + + if(is_array($form_input['categories']) AND $form_input['categories']['0'] != 'no_categories') { + $sql = "INSERT INTO ".JLOG_DB_CATASSIGN." ( cat_id, content_id ) + VALUES \n"; + foreach($form_input['categories'] AS $category) { + if(++$i > 1) $sql .= ",\n"; + $sql .= "( '".$category."', '".$id."')"; + } + $sql .= ";"; + + $catassign = new Query($sql); + if($catassign->error()) { + echo "
\n";
+        echo $catassign->getError();
+        echo "
\n"; + die(); + } + } + + ### Plugin Hook + $plugins->callHook('insertEntry', $id, $form_input); + return $id; +} + +function get_blog($id) { +global $l, $categories; + + $sql = 'SELECT id, url, topic, UNIX_TIMESTAMP(date) AS date, ' . + 'teaser, teaserpic, teaserpiconblog, keywords, ' . + 'content, comments, allowpingback, section FROM ' . + JLOG_DB_CONTENT . ' WHERE id = \'' . $id . + '\' LIMIT 1;'; + + $blog = new Query($sql); + if($blog->error()) { + echo "
\n";
+        echo $blog->getError();
+        echo "
\n"; + die(); + } + $form_input = $blog->fetch(); + + $form_input['categories'] = $categories->get_assigned_categories($form_input['id']); + + return $form_input; +} + +function update_blog($form_input) { +global $l, $plugins; + + if($form_input['allowcomments'] != "0") $form_input['allowcomments'] = "1"; + if($form_input['allowpingback'] != "0") $form_input['allowpingback'] = "1"; + + $form_input = escape_for_mysql($form_input); + $sql = "UPDATE ".JLOG_DB_CONTENT." SET + topic = '".$form_input['topic']."', + url = '".$form_input['url']."', + section = '".$form_input['section']."', + teaser = '".$form_input['teaser']."', + teaserpic = '".$form_input['teaserpic']."', + teaserpiconblog = '".$form_input['teaserpiconblog']."', + keywords = '".$form_input['keywords']."', + content = '".$form_input['content']."', + comments = '".$form_input['allowcomments']."', + allowpingback = '".$form_input['allowpingback']."' + WHERE id = '".$form_input['id']."' LIMIT 1;"; + + + $updateblog = new Query($sql); + if($updateblog->error()) { + echo "
\n";
+        echo $updateblog->getError();
+        echo "
\n"; + die(); + } + + if(is_array($form_input['categories'])) { + $sql = "DELETE FROM ".JLOG_DB_CATASSIGN." WHERE content_id = '".$form_input['id']."';"; + $trashcatassign = new Query($sql); + if($trashcatassign->error()) { + echo "
\n";
+        echo $trashcatassign->getError();
+        echo "
\n"; + die(); + } + + if(is_array($form_input['categories']) AND $form_input['categories']['0'] != 'no_categories') { + $sql = "INSERT INTO ".JLOG_DB_CATASSIGN." ( cat_id, content_id ) + VALUES \n"; + foreach($form_input['categories'] AS $category) { + if(++$i > 1) $sql .= ",\n"; + $sql .= "( '".$category."', '".$form_input['id']."')"; + } + $sql .= ";"; + + $catassign = new Query($sql); + if($catassign->error()) { + echo "
\n";
+            echo $catassign->getError();
+            echo "
\n"; + die(); + } + } + } + + ### Plugin Hook + $plugins->callHook('updateEntry', $form_input['id'], $form_input); + + return $l['admin']['data_updated']; +} + +function trash_blog($id) { +global $l; + + $sql = "DELETE FROM ".JLOG_DB_CONTENT." WHERE id = '".escape_for_mysql($id)."' LIMIT 1"; + + $trashblog = new Query($sql); + if($trashblog->error()) { + echo "
\n";
+        echo $trashblog->getError();
+        echo "
\n"; + die(); + } + return $l['admin']['postleted']; +} + +/** + * add PHPSESSID GET parameter if cookies are not allowed + **/ +function add_session_id_to_url($url="") { + if(empty($_COOKIE[session_name()])) { + if(strpos($url, "?") === false) $url .= "?"; + else $url .= "&"; + $url .= session_name() . "=" . htmlspecialchars(session_id()); + } + return $url; +} + +/** + * add PHPSESSID -Tag if cookies are not allowed + */ +function add_session_id_input_tag() { + if(empty($_COOKIE[session_name()])) { + return ""; + } +} + +// output the administration menu +function output_admin_menu() { +global $l, $plugins; + $o = '

+ '.$l['admin']['menu_home'].' | + '.$l['admin']['menu_categories'].' | + '.$l['admin']['menu_comments'].' | + '.$l['admin']['menu_settings'].' | + '.$l['admin']['menu_plugins'].' | + '.$l['admin']['menu_logout'].' +

'; + + ### Plugin Hook + $o = $plugins->callHook('adminMenu', $o); + + return $o; +} + + +// eof diff --git a/admin/categories.php b/admin/categories.php new file mode 100644 index 0000000..504579b --- /dev/null +++ b/admin/categories.php @@ -0,0 +1,79 @@ +".$l['admin']['cat_title']."\n"; + + switch ($get['action']) { + + case 'new': + if(isset($form_input['form_submit'])) { + if(!is_array($errors = $categories->validate($form_input))) { + $categories->new_cat($form_input); + $categories->get_categories(); + $c['main'] .= "

»» ".$l['admin']['cat_new']."

+ ".$categories->output_whole_list_admin(); + } + else { + $c['main'] .= error_output($errors); + $c['main'] .= $categories->output_form($form_input, 'new', $l['admin']['cat_new']); + } + } + else $c['main'] .= $categories->output_form('', 'new', $l['admin']['cat_new']); + break; + + case 'change': + if(isset($form_input['form_submit'])) { + if(!is_array($errors = $categories->validate($form_input))) { + $categories->change_cat($form_input); + $categories->get_categories(); + $c['main'] .= "

".$l['admin']['cat_new_ok']."

".$categories->output_whole_list_admin(); + } + else { + $c['main'] .= error_output($errors); + $c['main'] .= $categories->output_form($form_input, 'new', $l['admin']['cat_new']); + } + } + else { + $form_input['name'] = $categories->get($get['id'], 'name'); + $form_input['id'] = $get['id']; + $form_input['url'] = $categories->get($get['id'], 'url'); + $form_input['description'] = $categories->get($get['id'], 'description'); + + $c['main'] .= $categories->output_form($form_input, 'change', $l['admin']['cat_change']); + } + break; + + case 'trash': + if($form_input['form_submit'] == $l['admin']['yes']) { + $categories->trash_cat($form_input['id']); + $categories->get_categories(); + $c['main'] .= "

".$l['admin']['cat_trash_ok']." + ".$l['admin']['cat_admincenter']."

"; + } + else { + $c['main'] .= "
+

".$l['admin']['cat_really_trash']."

+

".$categories->link($get['id'])."

+

+ + ".add_session_id_input_tag()." + ".$l['admin']['no']."

+
"; + } + break; + + default: + $c['main'] .= "

»» ".$l['admin']['cat_new']."

+ ".$categories->output_whole_list_admin(); + } + +require(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'do_template.php'); +echo $body; +?> diff --git a/admin/change.php b/admin/change.php new file mode 100644 index 0000000..f936d62 --- /dev/null +++ b/admin/change.php @@ -0,0 +1,60 @@ +".$l['admin']['change_headline'].""; + +if($get['action'] == "trash" AND $post['trash'] == $l['admin']['yes']) { + $c['main'] .= "

".trash_blog($get['id'])."

"; + include_once(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'update.php'); +} +elseif ($get['action'] == "trash" AND empty($post['trash'])) { + $c['main'] .= " +
+

".$l['admin']['rearly_delete']." + ".add_session_id_input_tag()." + ".$l['admin']['no']."

+
"; + $form_input = get_blog($get['id']); + $c['main'] .= preview_output($form_input); + $c['title'] = $l['admin']['delete_blogentry']; +} + +else { + if(isset($get['id'])) $form_input = get_blog($get['id']); + elseif (isset($_POST)) $form_input = $post; + else $c['main'] .= $l['admin']['error_occurred']; + + if($post['form_submitted'] == $l['admin']['preview']) { + $c['main'] .= error_output(check_input($form_input)); + $c['main'] .= preview_output($form_input); + $c['main'] .= form_output($form_input); + } + elseif($post['form_submitted'] == $l['admin']['publish']) { + // Put data to database + if(!check_input($form_input)) { + $c['main'] .= "

".update_blog($form_input)."

"; + include_once(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'update.php'); + } + else { + // show preview and form + $c['main'] .= error_output(check_input($form_input)); + $c['main'] .= form_output($form_input); + } + } + else { + // show form + $c['main'] .= form_output($form_input); + } +} + +require(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'do_template.php'); +echo $body; +?> diff --git a/admin/comments.php b/admin/comments.php new file mode 100644 index 0000000..1784bed --- /dev/null +++ b/admin/comments.php @@ -0,0 +1,217 @@ +callHook('deleteComment', $get['id']); + + if( trash($get['id'], JLOG_DB_COMMENTS ) == true) { + $c['main'] .= $l['admin']['kill_c_killed']; + include_once(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'update.php'); + } +} +elseif ($get['action'] == 'trash' AND empty($data['trash'])) { +$c['main'] .= " +
+

".$l['admin']['kill_c_sure']." + + ".add_session_id_input_tag()." + ".$l['admin']['no']."

+
"; + + $sql = 'SELECT id, sid, name, city, email, homepage, content, ' . + 'date, reference, mail_by_comment, type FROM ' . + JLOG_DB_COMMENTS." + WHERE id = ".$mysql_id." + ORDER BY id DESC LIMIT 1;"; + + $comment = new Query($sql); + if($comment->error()) { + echo "
\n"; 
+        echo $comment->getError(); 
+        echo "
\n"; + die(); + } + + $daten = $comment->fetch(); + $c['main'] .= "
    ".do_comment($daten, "x")."
"; + +} +elseif($get['action'] == 'change' AND !empty($get['id'])) { + + $l["comments_comment_topic"] = $l['admin']["comments_comment_topic"]; + $l["comments_by"] = $l['admin']["comments_by"]; + $l["comments_name"] = $l['admin']["comments_name"]; + $l["comments_city"] = $l['admin']["comments_city"]; + $l["comments_email"] = $l['admin']["comments_email"]; + $l["comments_homepage"] = $l['admin']["comments_homepage"]; + $l["comments_bbcode"] = $l['admin']["comments_bbcode"]; + $l["comments_send"] = $l['admin']["comments_send"]; + $l["comments_preview"] = $l['admin']["comments_preview"]; + $l["comments_no_sid"] = $l['admin']["comments_no_sid"]; + $l["comments_false_mail"] = $l['admin']["comments_false_mail"]; + $l["comments_notext"] = $l['admin']["comments_notext"]; + $l["comments_false_hp"] = $l['admin']["comments_false_hp"]; + $l["comments_anonym"] = $l['admin']["comments_anonym"]; + $l["comments_permalink"] = $l['admin']["comments_permalink"]; + $l["comments_from"] = $l['admin']["comments_from"]; + $l["comments_posted"] = $l['admin']["comments_posted"]; + $l["comments_entryform"] = $l['admin']["comments_entryform"]; + $l["comments_mail_by_comment"] = $l['admin']["comments_mail_by_comment"]; + $l["comments_thx"] = $l['admin']["comments_thx"]; + $l["comments_preview"] = $l['admin']["comments_preview"]; + $l["comments_send"] = $l['admin']["comments_send"]; + $l["comments_bold"] = $l['admin']["comments_bold"]; + $l["comments_italic"] = $l['admin']["comments_italic"]; + $l["comments_quote"] = $l['admin']["comments_quote"]; + $l["comments_url"] = $l['admin']["comments_url"]; + $l["comments_plz_format_txt"] = $l['admin']["comments_plz_format_txt"]; + $l["comments_url_href"] = $l['admin']["comments_url_href"]; + $l["comments_url_node"] = $l['admin']["comments_url_node"]; + + if($data['form_submitted'] == $l['comments_preview']) { + $c['main'] .= "\n

".$l['admin']['comments_change_h']."

+
    + ".do_comment($data, 1)." +
".com_form_output($data).com_javascript_variables(); + } + elseif($data['form_submitted'] == $l['comments_send']) { + if(count($errors = com_check_errors($data)) > 0) $c['main'] .= "\n

".$l['admin']['comments_change_h']."

\n".error_output($error).com_form_output($data).com_javascript_variables(); + else { + + $data = com_clean_data($data); + +### Plugin Hook + $data = $plugins->callHook('updateComment', $data); + + $data = escape_for_mysql($data); + + $sql = "UPDATE ".JLOG_DB_COMMENTS." + SET + name = '".$data['name']."', + city = '".$data['city']."', + email = '".$data['email']."', + homepage = '".$data['homepage']."', + content = '".$data['content']."', + mail_by_comment = '".$data['mail_by_comment']."' + WHERE id = '".$data['id']."' LIMIT 1;"; + + $updatecomment = new Query($sql); + if($updatecomment->error()) { + echo "
\n"; 
+               echo $updatecomment->getError(); 
+               echo "
\n"; + die(); + } + $c['main'] .= "\n

".$l['admin']['comments_change_h']."

\n".$l['admin']['comments_updated']." ".$l['admin']['comments_admin'].""; + include_once(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'update.php'); + } + } + else { + $sql = 'SELECT id, sid, name, city, email, homepage, content, ' . + 'UNIX_TIMESTAMP(date) AS date, reference, ' . + 'mail_by_comment, type FROM '.JLOG_DB_COMMENTS." + WHERE id = ".$mysql_id." + ORDER BY id DESC LIMIT 1;"; + + $comment = new Query($sql); + if($comment->error()) { + echo "
\n"; 
+            echo $comment->getError(); 
+            echo "
\n"; + die(); + } + + $data = $comment->fetch(); + if(empty($data['name'])) $data['name'] = $l['comments_name']; + if(empty($data['city'])) $data['city'] = $l['comments_city']; + if(empty($data['email'])) $data['email'] = $l['comments_email']; + if(empty($data['homepage'])) $data['homepage'] = $l['comments_homepage']; + + $c['main'] .= "\n

".$l['admin']['comments_change_h']."

+
    + ".do_comment($data, 1)." +
".com_form_output($data).com_javascript_variables(); + } +} +else { +$yl = new Year_Links($get['y'], JLOG_START_YEAR, add_session_id_to_url(JLOG_PATH."/admin/comments.php"), $l['admin']); + + $c['main'] .= " +

".$l['admin']['kill_c_topic']."

+

".$l['admin']['kill_c_description']."

+

".$yl->get_admin_linklist()."

+ + + + "; + + $sql = "SELECT + ".JLOG_DB_COMMENTS.".id AS id, + ".JLOG_DB_CONTENT.".url AS url, + UNIX_TIMESTAMP(".JLOG_DB_CONTENT.".date) AS reference_date, + UNIX_TIMESTAMP(".JLOG_DB_COMMENTS.".date) AS date, + ".JLOG_DB_COMMENTS.".name AS name, + ".JLOG_DB_CONTENT.".topic AS topic, + ".JLOG_DB_COMMENTS.".email AS email, + ".JLOG_DB_COMMENTS.".type AS type + FROM ".JLOG_DB_COMMENTS.", ".JLOG_DB_CONTENT." + WHERE ".JLOG_DB_COMMENTS.".reference = ".JLOG_DB_CONTENT.".id + AND YEAR(".JLOG_DB_COMMENTS.".date) = '".$yl->get_selected_year()."' + ORDER BY id DESC;"; + + $comments = new Query($sql); + if($comments->error()) { + echo "
\n"; 
+        echo $comments->getError(); 
+        echo "
\n"; + die(); + } + + while ($daten = $comments->fetch()) { + + if(empty($daten['name'])) $daten['name'] = $l['comments_anonym']; + elseif($daten['type'] != 'pingback') $daten['name'] = htmlspecialchars($daten['name'], ENT_QUOTES); + + if(!empty($daten['email'])) { + $email_a = ""; + $email_b = ""; + } + else { + $email_a = ""; + $email_b = ""; + } + $comment = " + + + + + + + + "; + + ### Plugin Hook + $c['main'] .= $plugins->callHook('commentAdminList', $comment, $daten); + + } + + $c['main'] .= " +
".$l['admin']['change']."".$l['admin']['delete']."ID".$l['comments_name']."".$l['comments_posted']."".$l['admin']['kill_c_entry']."
".$l[".$l[".$daten['id']."".$email_a.$daten['name'].$email_b."".strftime(JLOG_DATE_COMMENT, $daten['date'])."".$daten['topic']."
"; +} + +require(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'do_template.php'); +echo $body; +?> diff --git a/admin/export-rss2.php b/admin/export-rss2.php new file mode 100644 index 0000000..d865d6c --- /dev/null +++ b/admin/export-rss2.php @@ -0,0 +1,13 @@ + diff --git a/admin/index.php b/admin/index.php new file mode 100644 index 0000000..39e1a05 --- /dev/null +++ b/admin/index.php @@ -0,0 +1,75 @@ +".$l['admin']['section_weblog']." | ".$l['admin']['section_page'].""; + $where = "section = 'page'"; + } + else { + $show_section = "".$l['admin']['section_weblog']." | ".$l['admin']['section_page'].""; + $where = "YEAR(date) = '".escape_for_mysql($yl->get_selected_year()) + ."' AND section = 'weblog'"; + $year_menu = "

".$yl->get_admin_linklist()."

\n"; + + } + + + + $c['meta']['title'] = $l['admin']['index_headline']; + + $c['main'] .= output_admin_menu()." +

".$l['admin']['admin_headline']."

+

»» ".$l['admin']['new_post']."

+

".$l['admin']['section_show'].": ".$show_section."

".$year_menu." + + + + + + + "; + + $sql = "SELECT + id, + date as mysql_date, + UNIX_TIMESTAMP(date) AS date, + topic + FROM ".JLOG_DB_CONTENT." + WHERE ".$where." + ORDER BY mysql_date DESC;"; + + $blog = new Query($sql); + if($blog->error()) { + echo "
\n";
+        echo $blog->getError();
+        echo "
\n"; + die(); + } + + while ($daten = $blog->fetch()) { + $list = " + + + + + + "; + + ### Plugin Hook + $c['main'] .= $plugins->callHook('adminList', $list, $daten); + } + + $c['main'] .= " +
".$l['admin']['change']."".$l['admin']['delete']."".$l['admin']['date']."".$l['admin']['headline']."
".$l[".$l[".strftime(JLOG_DATE_SUBCURRENT, $daten['date'])."".htmlspecialchars($daten['topic'], ENT_QUOTES)."
+"; + +require(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'do_template.php'); +echo $body; + +// eof \ No newline at end of file diff --git a/admin/login.php b/admin/login.php new file mode 100644 index 0000000..10912ec --- /dev/null +++ b/admin/login.php @@ -0,0 +1,76 @@ + +### autor: Benjamin Wilfing +### email: benjamin.wilfing@selfhtml.org +### homepage: +### +### adapted for Jlog by Jeena Paradies + +ini_set("session.use_trans_sid", false); + +define("JLOG_ADMIN", true); +define("JLOG_LOGIN", true); +require_once('..'.DIRECTORY_SEPARATOR.'scripts'.DIRECTORY_SEPARATOR.'prepend.inc.php'); +require(JLOG_BASEPATH.'admin'.DIRECTORY_SEPARATOR.'blog.func.php'); + +$false_password = ""; +$get = strip($_GET); +$post = strip($_POST); + +### Plugin Hook +$dispatch_login = $plugins->callHook('dispatchLogin', true); + +if ($_SERVER['REQUEST_METHOD'] == 'POST' AND $dispatch_login) { + session_start(); + $passwort = $post['password']; + $url = !empty($post['url']) ? $post['url'] : ''; + $hostname = $_SERVER['HTTP_HOST']; + $path = dirname($_SERVER['SCRIPT_NAME']) . '/'; + + if (strpos($url, "\n") !== false or strpos($url, "\r") !== false) { + die('Somebody tried to hack Jlog with Response-Splitting.'); + } + + if (md5($passwort) == JLOG_ADMIN_PASSWORD) { + $_SESSION['logged_in'] = true; + session_regenerate_id(); // neue SID + + if ($_SERVER['SERVER_PROTOCOL'] == 'HTTP/1.1') { + if (php_sapi_name() == 'cgi') header('Status: 303 See Other'); + else header('HTTP/1.1 303 See Other'); + } + + if ($path == $url) $url = $path . 'new.php'; + if (!empty($url)) $path = $url; + + header('Location: ' . add_session_id_to_url("http://".$hostname.$path)); + exit; + } + else { + $false_password = "

".$l['admin']['login_false_pw']."

\n"; + } +} +else { + setcookie("cookieallowed", "true", time() + 180); +} + +$c['meta']['title'] = $l['admin']['login_headline']; +$c['main'] = ' +

'.$l['admin']['login_headline'].'

+ ' . $false_password . ' +
+

+ +

+

+

+
+'; + +### Plugin Hook +$c["main"] = $plugins->callHook('loginForm', $c["main"]); + + +require_once(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'do_template.php'); +echo $body; + diff --git a/admin/logout.php b/admin/logout.php new file mode 100644 index 0000000..491255d --- /dev/null +++ b/admin/logout.php @@ -0,0 +1,9 @@ + diff --git a/admin/media/select-picture.php b/admin/media/select-picture.php new file mode 100644 index 0000000..a0ef43f --- /dev/null +++ b/admin/media/select-picture.php @@ -0,0 +1,54 @@ + + + + +<?php echo $l['admin']['pic_choose_old'] ?> + + + + + +

+ +

+
+


+

+


+

+

+
+\n"; + } + } +} +?> + + diff --git a/admin/media/select-teaser.php b/admin/media/select-teaser.php new file mode 100644 index 0000000..74e6b95 --- /dev/null +++ b/admin/media/select-teaser.php @@ -0,0 +1,43 @@ + + + + +<?php echo $l['admin']['pic_choose_old_teaser'] ?> + + + + +

+ "; + } +} + +?> + + diff --git a/admin/media/upload-picture.php b/admin/media/upload-picture.php new file mode 100644 index 0000000..0705ecf --- /dev/null +++ b/admin/media/upload-picture.php @@ -0,0 +1,88 @@ + + + + +<?php echo $l['admin']['pic_upload_header'] ?> + + + + + +

+ $max_file_size) $errors[] = $l['admin']['pic_to_big']." (".number_format($_FILES['probe']['size']/1000,0,",","")." KB)"; + + + if(empty($errors)) { + $nr = 0; + switch(true) + { + case preg_match('~.jpg|jpeg~i', $e): + for(;;) { $nr++; if (!file_exists($up_dir.$nr.".jpg")) break; } + $filename = $nr.".jpg"; + break; + case preg_match('~.gif~i', $e): + for(;;) { $nr++; if (!file_exists($up_dir.$nr.".gif")) break; } + $filename = $nr.".gif"; + break; + case preg_match('~.png~i', $e): + for(;;) { $nr++; if (!file_exists($up_dir.$nr.".png")) break; } + $filename = $nr.".png"; + break; + } + + if(empty($errors)) { + if(!move_uploaded_file($_FILES['probe']['tmp_name'], $up_dir.$filename)) $errors[] = $l['admin']['pic_error']; + else chmod($up_dir.$filename, 0664); + } + } + if (empty($errors)) { + ?> +

+

+
+


+

+


+

+

+
+ +

+
+ + +

+ +
+ + + diff --git a/admin/media/upload-teaser.php b/admin/media/upload-teaser.php new file mode 100644 index 0000000..c18c68c --- /dev/null +++ b/admin/media/upload-teaser.php @@ -0,0 +1,92 @@ + + + + +<?php echo $l['admin']['pic_upload_teaser'] ?> + + + + +

+ $max_file_size) $errors[] = $l['admin']['pic_to_big']." (".number_format($_FILES['probe']['size']/1000,0,",","")." KB)"; + + if(empty($errors)) { + $nr = 0; + switch(true) + { + case preg_match('~.jpg|jpeg~i', $e): + for(;;) { $nr++; if (!file_exists($up_dir."t_".$nr.".jpg")) break; } + $filename = "t_".$nr.".jpg"; + break; + case preg_match('~.gif~i', $e): + for(;;) { $nr++; if (!file_exists($up_dir."t_".$nr.".gif")) break; } + $filename = "t_".$nr.".gif"; + break; + case preg_match('~.png~i', $e): + for(;;) { $nr++; if (!file_exists($up_dir."t_".$nr.".png")) break; } + $filename = "t_".$nr.".png"; + break; + } + + + $imginfo = getimagesize($_FILES['probe']['tmp_name']); + + if($imginfo[1] > 150 AND $imginfo[0] > 150 ) { + $errors[] = $l['admin']['pic_height_widht']; + } + elseif($imginfo[0] > 150 ) { + $errors[] = $l['admin']['pic_width']; + } + elseif($imginfo[1] > 150 ) { + $errors[] = $l['admin']['pic_height']; + } + if(empty($errors)) { + if(!move_uploaded_file($_FILES['probe']['tmp_name'], $up_dir.$filename)) $errors[] = $l['admin']['pic_error']; + else chmod($up_dir.$filename, 0664); + } + } + if (empty($errors)) { + ?> +

+ +

+ +

+
+ + +

+ +
+ + + diff --git a/admin/new.php b/admin/new.php new file mode 100644 index 0000000..5e81395 --- /dev/null +++ b/admin/new.php @@ -0,0 +1,103 @@ +".$l['admin']['new_post'].""; + $form_input = strip($_POST); + $form_input['date'] = strftime("%Y-%m-%d %H:%M:%s"); + +if($_POST['form_submitted'] == $l['admin']['preview']) { + $c['main'] .= error_output(check_input($form_input)); + $c['main'] .= preview_output($form_input); + $c['main'] .= form_output($form_input); +} +elseif($_POST['form_submitted'] == $l['admin']['publish']) { + // Put data to database + if(!check_input($form_input)) { + if($id = insert_blog($form_input)) { + $c['main'] .= "

".$l['admin']['entry_saved']."

"; + include_once(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'update.php'); + + // ping blog services and pingback + if($form_input['section'] == 'weblog') { + $blogservices = explode("\n", str_replace("\r", "\n", str_replace("\r\n", "\n", JLOG_BLOGSERVICES))); + foreach($blogservices as $blogservice) { + if(strlen($blogservice) > 0) $pingresult[] = doPing(trim($blogservice)); + } + // if(is_array($pingresult)) $c['main'] .= "\n
    ".join($pingresult)."\n
"; + + if($form_input['allowpingback'] != '0') { + $blogentryForURL = get_blog($id); + require_once(JLOG_BASEPATH.'xmlrpc.php'); + $pingback = new Jlog_SendPingback($bbcode->parse($form_input['content']), blog($blogentryForURL['date'], $blogentryForURL['url']), " -- Jlog v".JLOG_SOFTWARE_VERSION); + + $responces = array(); + $responces = $pingback->doPingbacks(); + +/* Die Ergebnisse der Pings verwirren den User nur habe ich mittlerweile festgestellt. + + if(count($responces) > 0) { + $c['main'] .= "
    "; + foreach($responces as $responce) { + $c['main'] .= "\n
  • ".$responce."
  • "; + } + $c['main'] .= "\n
"; + } +*/ + + } + } + } + } + else { + // show preview and form + $c['main'] .= error_output(check_input($form_input)); + $c['main'] .= form_output($form_input); + } +} +else { + // show form + $c['main'] .= form_output($form_input); +} + +require(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'do_template.php'); +echo $body; + +// verschiedene Dienste anpingen bei neuem Eintrag + +function doPing($url) { + $blog_title = JLOG_WEBSITE; + $blog_url = JLOG_PATH; + $timeout = 30; //Sekunden + $url = parse_url($url); + + $fp = @fsockopen($url['host'], 80, $errno, $errstr, $timeout); + if(!$fp) { + $response = 'Fehler: '.$errstr.' ('.$errno.')
Es konnte keine Verbindung hergestellt werden'; + } else { + $data_string = ' + + weblogUpdates.ping + + '.$blog_title.' + '.$blog_url.' + + '; + $data_header = "POST ".$url['path']." HTTP/1.0\r\n". + "Host: $host\r\n". + "Content-Type: text/xml\r\n". + "User-Agent: qxm XML-RPC Client\r\n". + "Content-Length: ".strlen($data_string)."\r\n\r\n"; + fputs($fp, $data_header); + fputs($fp, $data_string); + unset($response); + fclose($fp); + } + if(isset($response)) return '
  • '.$url['host'].' '.$response.'
  • '; +} + +// eof diff --git a/admin/plugin.php b/admin/plugin.php new file mode 100644 index 0000000..7478a4f --- /dev/null +++ b/admin/plugin.php @@ -0,0 +1,53 @@ +".$pluginName."\n"; + } + } + closedir($handle); + + if(!empty($availablePlugins)) { + $availablePlugins = "
      \n".$availablePlugins."
    \n"; + $title = $l['admin']['plugins_headline']; + } + + else { + $availablePlugins = "

    ".$l['admin']['plugins_not_avaliable']."

    "; + $title = $l['admin']['plugins_h_not_avaliable']; + } + + } + } + else { + $title = $get['jplug']; + $availablePlugins = "

    ".$l['admin']['plugin_no_content']."

    "; + } + + + + $c['meta']['title'] = $title; + $c['main'] .= "

    ".$title."

    \n"; + + $c['main'] .= $plugins->callHook('adminContent', $availablePlugins); + + +require(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'do_template.php'); +echo $body; +?> diff --git a/admin/settings.php b/admin/settings.php new file mode 100644 index 0000000..d7d672a --- /dev/null +++ b/admin/settings.php @@ -0,0 +1,33 @@ +".$l['admin']['m_title'].""; + + $settings = new Settings($l); + if($_POST) { + $settings->importDataByArray(strip($_POST)); + if(count($errors = $settings->validate()) == 0) { + if(count($errors = $settings->do_settings()) == 0) { + $c['main'] .= $l['admin']['m_settings_ok']; + } + + } + if(count($errors) > 0) { + $c['main'] .= error_output($errors); + $c['main'] .= $settings->form_output(); + } + } + else { + $settings->importDataByConstants(); + $c['main'] .= $settings->form_output(); + } +require_once(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'update.php'); +require(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'do_template.php'); +echo $body; +?> diff --git a/admin/update.php b/admin/update.php new file mode 100644 index 0000000..e95f556 --- /dev/null +++ b/admin/update.php @@ -0,0 +1,35 @@ + Jlog 1.1.0 + + define("JLOG_ADMIN", true); + define("JLOG_UPDATE", true); + + // load prepend.inc.php + require_once('..'.DIRECTORY_SEPARATOR.'scripts'.DIRECTORY_SEPARATOR.'prepend.inc.php'); + + include(JLOG_BASEPATH.'lang'.DIRECTORY_SEPARATOR.'lang.'.JLOG_LANGUAGE.'.inc.php'); + include(JLOG_BASEPATH.'lang'.DIRECTORY_SEPARATOR.'lang-admin.'.JLOG_LANGUAGE.'.inc.php'); + + // Rendering + $c['meta']['title'] = "Update"; + //$c['main'] = sprintf("

    Update von %s auf %s

    ", JLOG_INSTALLED_VERSION, JLOG_SOFTWARE_VERSION); + + require_once(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'JlogUpdater.php'); + $updater = new JlogUpdater(); + + if ($updater->isUp2Date()) { + $c['main'] = '

    Das Update auf ' . JLOG_INSTALLED_VERSION . ' wurde bereits erfolgreich durchgeführt.

    '; + } + else if (!isset($_POST['update'])) { + $c['main'] = $updater->prepareForm($l); + } + else { + $c['main'] = $updater->performUpdate($l); + + // Ready :-) + require(JLOG_BASEPATH."scripts".DIRECTORY_SEPARATOR."update.php"); + } + +require(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'do_template.php'); +echo $body; +?> \ No newline at end of file diff --git a/archive.php b/archive.php new file mode 100644 index 0000000..c41a209 --- /dev/null +++ b/archive.php @@ -0,0 +1,138 @@ +get($categories->get_id($get['cat']), 'name'); + $c['main'] .= "

    ".$l['content_categories_header']." ".$categories->get($categories->get_id($get['cat']), 'name')." ".$yl->get_selected_year()."

    "; + $c['main'] .= "

    ".$categories->get($categories->get_id($get['cat']), 'description')."

    "; + + $sql_archive = " + SELECT + ".JLOG_DB_CONTENT.".*, + ".JLOG_DB_CONTENT.".date as mysql_date, + DATE_FORMAT(".JLOG_DB_CONTENT.".date, '%c') AS month, + DATE_FORMAT(".JLOG_DB_CONTENT.".date, '%Y') AS year, + UNIX_TIMESTAMP(".JLOG_DB_CONTENT.".date) AS date + FROM ".JLOG_DB_CONTENT." + LEFT JOIN ".JLOG_DB_CATASSIGN." + ON ".JLOG_DB_CONTENT.".id = ".JLOG_DB_CATASSIGN.".content_id + WHERE ".JLOG_DB_CATASSIGN.".cat_id = '".escape_for_mysql($categories->get_id($get['cat']))."' + AND YEAR(".JLOG_DB_CONTENT.".date) = '".escape_for_mysql($yl->get_selected_year())."' + ORDER BY mysql_date DESC;"; + + $c['main'] .= "

    ".$yl->get_linklist()."

    "; + + } + elseif(empty($get['y'])) { + $c['meta']['title'] = $l['content_archive_header']; + $c['main'] = "

    ".$c['meta']['title']."

    "; + + $sql_archive = "SELECT id, url, topic, + date as mysql_date, + DATE_FORMAT(date, '%c') AS month, + DATE_FORMAT(".JLOG_DB_CONTENT.".date, '%Y') AS year, + UNIX_TIMESTAMP(date) AS date, + teaser, teaserpic, teaserpiconblog, keywords, content, + comments, allowpingback, section + FROM ".JLOG_DB_CONTENT." + WHERE section = 'weblog' + ORDER BY mysql_date DESC + LIMIT ".$p.", ".$amount.";"; + + $sql_count = "SELECT count(*) AS count FROM ".JLOG_DB_CONTENT." WHERE section = 'weblog'"; + + $count_query = new Query($sql_count); + if($count_query->error()) { + echo "
    \n";
    +                echo $count_query->getError();
    +                echo "
    \n"; + die(); + } + $_count = $count_query->fetch(); + $count_query->free(); + $count = $_count['count']; + } + else { + if(!empty($get['m'])) $where_month = " AND MONTH(date) = '".escape_for_mysql($get['m'])."'"; + $c['meta']['title'] = $l['content_archive_header']; + $c['main'] = "

    ".$c['meta']['title']." ".$yl->get_selected_year()."

    "; + + $sql_archive = "SELECT id, url, topic, + date as mysql_date, + DATE_FORMAT(date, '%c') AS month, + DATE_FORMAT(".JLOG_DB_CONTENT.".date, '%Y') AS year, + UNIX_TIMESTAMP(date) AS date, + teaser, teaserpic, teaserpiconblog, keywords, content, + comments, allowpingback, section + FROM ".JLOG_DB_CONTENT.$where_from." + WHERE + YEAR(date) = '".escape_for_mysql($yl->get_selected_year())."' + ".$where_month." + AND section = 'weblog' + ORDER BY mysql_date;"; + + $c['main'] .= "

    ".$yl->get_linklist()."

    "; + } + + $cc = count_comments(); + + $archive = new Query($sql_archive); + if($archive->error()) { + echo "
    \n";
    +        echo $archive->getError();
    +        echo "
    \n"; + die(); + } + +$months = array_flip($l['months']); + +if($archive->numRows() > 0) { + // initialise variables to keep track of last posts month and year + $last_month = false; + $last_year = false; + + while ($daten = $archive->fetch()) { + if(empty($daten)) break 1; + + // did we already reach a new month or year? + if (($last_month != $daten['month']) OR ($last_year != $daten['year'])) { + if ($last_month) { $c['main'] .= " \n"; } + $c['main'] .= "

    ".array_search($daten['month'], $months)." ".$daten['year']."

    \n"; + $c['main'] .= "
    \n"; + // set last month and year to values of current post + $last_month = $daten['month']; + $last_year = $daten['year']; + } + $c['main'] .= do_teaser($daten, $cc, "

    ", "

    "); + } + if(empty($get['y'])) { + $c['main'] .= "

    "; + if(($p - $amount) >= 0) { + $c['main'] .= "<— ".$l['content_archive_preview'].""; + $c['meta']['aditionalheader'] .= ' '."\n"; + } + if((($p - $amount) >= 0) && (($p + $amount) < $count)) $c['main'] .= " | "; + if(($p + $amount) < $count) { + $c['main'] .= "".$l['content_archive_next']." —>"; + $c['meta']['aditionalheader'] .= ' '."\n"; + } + $c['main'] .= "

    "; + } + $c['main'] .= "
    \n"; +} + + +require(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'do_template.php'); +echo $body; +?> diff --git a/error404.php b/error404.php new file mode 100644 index 0000000..bd031d8 --- /dev/null +++ b/error404.php @@ -0,0 +1,15 @@ +".$l['err404_topic']."\n

    ".$l['err404_message']."

    "; + $c['main'] .= '
    +

    +

    +
    '; + +require(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'do_template.php'); +echo $body; +?> diff --git a/img/JLOG_edit.png b/img/JLOG_edit.png new file mode 100644 index 0000000000000000000000000000000000000000..e2b8f68e1c1ee3b35cbe893f6be046808f96c05b GIT binary patch literal 139 zcmeAS@N?(olHy`uVBq!ia0vp^{6H+g$P6Su&)Dt`q}T#{LR|m<{|{t_9=coyq!>$r z{DK)Ap4~_Ta*RD)978H@B~Pe7prCM|pt1QOBeyf7a5JlLGmkK{yl}IHaC3ohbAoVl igK#s0u*k{(%nTbl+2(AnH+>1z&fw|l=d#Wzp$P!29w%%7 literal 0 HcmV?d00001 diff --git a/img/JLOG_rss-full.png b/img/JLOG_rss-full.png new file mode 100644 index 0000000000000000000000000000000000000000..d72c71d13fbda5f5ab57b419f30b8b83d8a9849e GIT binary patch literal 387 zcmV-}0et?6P)gwvN!`VY_rH-n~(B10${QcqK;r;#o z{{H?}eyxb5#{K{Qo3hKlzrTo$cmMzZ0GR*(m;g35HkdZcHkixX#j-DWHDzk4tS0HP6e%m~yC6##+1GCl&m)(!n=8+GU2p6VcP8xb;OD z`c%E=bK@QjjZzNJ&Evp12*#iy_O|?fW!{j|g hf4=)SeC$6bR5!P#QU4#{(5wIe002ovPDHLkV1fa))jI$H literal 0 HcmV?d00001 diff --git a/img/JLOG_rss-summary.png b/img/JLOG_rss-summary.png new file mode 100644 index 0000000000000000000000000000000000000000..61b1715e64e91cbf8287107b31de292053b4122c GIT binary patch literal 394 zcmV;50d@X~P)gwvN!`VY_rH-n~(B10${QcqK;r;#o z{{H?}eyxb5#{K{Qo3hKlzrTo$cmMzZ0GR*(m;g35HkdZcHkixXONXUM((tx5<5l=epB$l%;hPgh$kJHz(|#$_3aoAbd#z3j_0e1oGZFV=6)VdFzDpjtGl-cNU{f9IO2y| o-~+xTM=tvP-GAZN{&SYr1w$=Rzf@fKTmS$707*qoM6N<$g6i$q+W-In literal 0 HcmV?d00001 diff --git a/img/JLOG_trash.png b/img/JLOG_trash.png new file mode 100644 index 0000000000000000000000000000000000000000..29fbe6bc7891b5417412ad38a7738077a9dd4dde GIT binary patch literal 117 zcmeAS@N?(olHy`uVBq!ia0vp^{6H+g$P6Su&)Dt`q}T#{LR|m<{|{t_9=coyq!>$r z{DK)Ap4~_Ta%4SS978H@B`4%1B-kJL@L!(8a)Uv|ss}C(k-y~`w2yM#6yPha0xD$i MboFyt=akR{0Ns`%ZvX%Q literal 0 HcmV?d00001 diff --git a/index.php b/index.php new file mode 100644 index 0000000..d2453e8 --- /dev/null +++ b/index.php @@ -0,0 +1,107 @@ +error()) { + echo "
    \n";
    +        echo $blog->getError();
    +        echo "
    \n"; + die(); + } + +$number_of = $blog->numRows(); + +// -- ganze Posts ausgeben +$i_orginal = 0; +while (++$i_orginal <= JLOG_MAX_BLOG_ORGINAL) { + $cd = array(); + $cd = $blog->fetch(); + $c['meta']['date'] = $cd['metadate']; + if(empty($cd)) break 1; + $c['main'] .= do_entry($cd, $cc); +} + +// -- Teaser ausgeben +$i = 0; +while (++$i <= JLOG_MAX_BLOG_BIG) { + $cd = $blog->fetch(); + if(empty($c['meta']['date'])) $c['meta']['date'] = $cd['metadate']; + if(empty($cd)) break 1; + $c['main'] .= do_teaser($cd, $cc); +} + +if((JLOG_MAX_BLOG_BIG > 0) AND ($number_of > (JLOG_MAX_BLOG_BIG + JLOG_MAX_BLOG_ORGINAL))) $c['main'] .= "\n
    "; + +if($number_of > JLOG_MAX_BLOG_BIG + JLOG_MAX_BLOG_ORGINAL) $c['main'] .= "\n
      "; + +// -- Liste mit alten Beiträgen ausgeben +$linklist = false; +while ($cd = $blog->fetch()) { + if(empty($c['meta']['date'])) $c['meta']['date'] = $cd['metadate']; + ++$i; + $linklist = true; + + $tmp_comments = ""; + if(isset($cc[$cd['id']]) AND $cc[$cd['id']] != 0) $tmp_comments = " (".$cc[$cd['id']].")"; + + $c['main'] .= " +
    • ".strftime(JLOG_DATE_SUBCURRENT, $cd['date'])." ".htmlspecialchars($cd['topic'], ENT_QUOTES)."".$tmp_comments."
    • "; + } + +if($linklist) $c['main'] .= "\n
    \n
    "; + +// -- Link zum Archiv + $c['main'] .= " + "; + +// -- Daten in Template einfügen und ausgeben -- +require(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'do_template.php'); +echo $body; + +// eof diff --git a/lang/lang-admin.de.inc.php b/lang/lang-admin.de.inc.php new file mode 100644 index 0000000..711a1a2 --- /dev/null +++ b/lang/lang-admin.de.inc.php @@ -0,0 +1,246 @@ + "Inhalte", +"menu_categories" => "Kategorien", +"menu_comments" => "Kommentare", +"menu_settings" => "Einstellungen", +"menu_plugins" => "Plugins", +"menu_logout" => "Ausloggen", +"new_post" => "Neuen Eintrag erstellen", +"index_headline" => "Admincenter", +"change_headline" => "Alten Weblogeintrag ändern", +"go" => "los", +"admin_headline" => "Administrationscenter", +"change" => "Ändern", +"delete" => "Löschen", +"date" => "Datum", +"headline" => "Überschrift", +"metadata" => "Metadaten", +"contentdata" => "Inhalt des Eintrages", +"url" => "URL für permanenten Link (nur 0-9 a-z -.,_/)", +"keywords" => "Schlüsselwörter, Keywords", +"categories" => "Kategorie (Mehrfachauswahl mit [Strg], bzw. Apfel Taste)", +"no_categories" => "keine", +"preview" => "Vorschau", +"publish" => "Veröffentlichen", +"submit" => "Absenden", +"cancel" => "Abbrechen", +"no_headline" => "Überschrift fehlt", +"no_url" => "URL fehlt", +"false_url_letters" => "Der URL darf nur Kleinbuchstaben (a-z), Zahlen (0-9) und diese Zeichen enthalten: -.,_/", +"url_duplicate" => "Während eines Monats darf ein URL nur ein einziges mal vorkommen sonst kann das Blog sie nicht auseinanderhalten", +"url_duplicate_page" => "Pages müssen unikate URLs haben, das heißt, dass jede page einen anderen URL haben muss", +"false_teaserpic" => "Die Angabe des Bildes für die Zusammenfassung stimmt nicht, ein solches Bild wurde nicht hochgeladen", +"no_teaserpic_uploaded" => "Das Bild für die Zusammenfassung kann nicht im Blog angezeigt werden wenn es nicht hochgeladen wurde", +"no_teaser" => "Zusammenfassung fehlt", +"no_content" => "Inhalt fehlt", +"pic_for_teaser" => "Ein Bild für die Zusammenfassung (max 150px):", +"pic_upload" => "Bild hochladen", +"pic_choose" => "Bild auswählen", +"show_tpic_on_archive" => "Dieses Bild auch auf der richtigen Blogseite anzeigen.", +"teaser" => "Zusammenfassung", +"contentpic_choose" => "Ein Bild für den Inhalt:", +"content" => "Inhalt des Beitrags", +"howto_bbcode" => "Wie nutze ich BBCode?", +"content_choose_year" => "Das Jahr wählen:", + +"content_bold" => "fett", +"content_italic" => "kursiv", +"content_quote" => "Zitat", +"content_url" => "Link", +"content_plz_format_txt" => "Bitte gebe den zu formatierenden Text ein:", +"content_input_on_pos" => "Einfügen an Position", +"content_url_href" => "Linkziel eingeben:", +"content_url_node" => "Linktext eingeben:", +"content_list" => "Liste", +"content_headline" => "Überschrift", + +"section" => "Art des Beitrages", +"section_show" => "Art der Beiträge zeigen", +"section_weblog" => "weblog", +"section_page" => "page", + +"entry_saved" => "Eintrag gespeichert.", +"data_updated" => "Daten aktualisiert.", +"post_deleted" => "Der Blogeintrag wurde gelöscht.", +"index_topic" => "Letzte Weblogbeiträge", + +"yes" => "Ja", +"no" => "Nein", +"rearly_delete" => "Diesen Eintrag wirklich löschen?", +"delete_blogentry" => "Eintrag löschen", +"postdeleted" => "Eintrag gelöscht", +"error_occurred" => "Ein Fehler ist aufgetreten", + +"can_not_open" => "Kann Datei nicht öffnen", +"can_not_write" => "Kann in Datei nicht schreiben", +"no_wrtitenable" => "Die Datei ist nicht beschreibbar", +"rss_ok" => "RSS und Aktuelles erfolgreich aktualisiert.", +"master_ok" => "Setupdatei erfolgreich aktualisiert.", + +"pic_choose_old" => "Älteres Bild auswählen", +"pic_choose_old_teaser" => "Älteres Teaserbild auswählen", +"pic_upload_header" => "Bild hochladen", +"pic_upload_teaser" => "Teaserbild hochladen", +"pic_error" => "Fehler beim Hochladen bitte Administrator benachrichtigen", +"pic_uploaded" => "Bild wurde hochgeladen", +"pic_insert" => "Bild einfügen", +"pic_instructions" => "Nur PNG, GIF oder JPEG Bilder hochladen. Die Dateigröße darf 300 kB nicht überschreiten.", +"pic_upload" => "Hochladen", +"pic_class" => "CSS Klasse falls benötigt", +"pic_alt" => "Alternativtext", + +"pic_height_widht" => "Bild ist zu hoch und zu breit", +"pic_width" => "Bild ist zu breit", +"pic_height" => "Bild ist zu hoch", +"pic_instr_teaser" => "Nur PNG, GIF oder JPEG Bilder hochladen, die nicht breiter oder höher als 150px sind und 60 kB nicht überschreiten.", +"pic_bad_type" => "Falsches Format", +"pic_to_big" => "Das Bild ist zu groß", + +"kill_c_topic" => "Kommentare administrieren", +"kill_c_killed" => "Kommentar erfolgreich gelöscht.", +"kill_c_sure" => "Diesen Kommentar wirklich löschen?", +"kill_c_h2" => "Unwiederbringlich löschen", +"kill_c_description" => "Achtung, wenn ein Kommentar hier gelöscht wird ist er unwiederbringlich verloren!", +"kill_c_entry" => "Weblogeintrag", +"kill_c_email" => "Diesen Kommentar löschen", +"comments_change_h" => "Kommentar ändern", +"comments_anonym" => "Anonym", +"comments_mail_txt" => "Neuer Kommentar auf ".JLOG_WEBSITE."\nDer Titel war: ", +"comments_posted" => "schrieb am", +"comments_mailsubject" => "Kommentar auf ".JLOG_WEBSITE, +"comments_comment_topic" => "Kommentare", +"comments_by" => "Kommentar von", +"comments_name" => "Name", +"comments_city" => "Stadt / Land", +"comments_email" => "E-Mail", +"comments_homepage" => "http://", +"comments_bbcode" => "Wie benutze ich", +"comments_send" => "Absenden", +"comments_preview" => "Vorschau", +"comments_no_sid" => "Es scheint eine Manipulation vorzuliegen", +"comments_false_mail" => "Die E-Mail Adresse sieht nicht richtig aus", +"comments_notext" => "Es wurde kein Text eingegeben", +"comments_false_hp" => "Die URL zur Homepage scheint falsch zu sein", +"comments_permalink" => "Permanenter link zu diesem Kommentar", +"comments_from" => "aus", +"comments_posted" => "schrieb am", +"comments_entryform" => "Kommentar ändern", +"comments_mail_by_comment" => "Bei Kommentar benachrichtigen", +"comments_thx" => "Der Kommentar wurde geändert", +"comments_preview" => "Vorschau", +"comments_send" => "Senden", +"comments_bold" => "fett", +"comments_italic" => "kursiv", +"comments_quote" => "Zitat", +"comments_url" => "Link", +"comments_plz_format_txt" => "Bitte gebe den zu formatierenden Text ein:", +"comments_url_href" => "Linkziel eingeben:", +"comments_url_node" => "Linktext eingeben:", +"comments_updated" => "Der Kommentar wurde geändert. Zurück zum", +"comments_admin" => "Kommentar Administrationscenter", +"comments_closed" => "Kommentare für diesen Beitrag schließen", + +"m_writenable" => "beschreibbar", +"m_title" => "Haupteinstellungen des Weblogs", +"m_clean_url" => "Saubere URLs (mod_rewrite) verwenden? Beispiel: http://example.com/2005/01/firefox", +"m_metadata" => "Metadaten", +"m_language" => "Sprache des Weblogs", +"m_website" => "Der Name des Weblogs", +"m_publisher" => "Name des Verfassers der Einträge", +"m_admin_password" => "Administrationscenter Passwort", +"m_admin_password_again" => "Passwort bestätigen", +"m_admin_password_admin" => "(leer lassen falls unverändert)", +"m_email" => "E-Mail des Betreibers des Weblogs", +"m_description" => "Eine Kurze Beschreibung des Weblogs", +"m_bs" => "Weblogdienste bei neuem Eintrag benachrichtigen, die den eigenen Eintrag in ihre Suchmaschinen aufnehmen (für jeden eine Zeile)", +"m_bs_weblogs_com" => "weblogs.com", +"m_bs_technorati_com" => "technorati.com", +"m_bs_blogg_de" => "blogg.de", +"m_behavior" => "Verhalten des Weblogs", +"m_max_blog_orginal" => "Anzahl der Einträge, die vollständig auf der Startseite erscheinen", +"m_max_blog_big" => "Anzahl der Einträge, deren Beschreibung auf der Startseite erscheinen", +"m_max_blog_small" => "Anzahl der Einträge, deren Datum und Name auf der Startseite erscheinen", +"m_sub_current" => "Anzahl der Einträge, deren Datum und Name in der Subnavigation, die auf jeder Seite erscheint, erscheinen", +"m_info_by_comment" => "Benachrichtigung des Betreibers des Weblogs bei neuem Kommentar", +"m_database" => "Datenbank", +"m_db" => "Datenbankname", +"m_db_url" => "Datenbank Hostname, in der Regel localhost", +"m_db_user" => "Datenbank Username", +"m_db_pwd" => "Datenbank Passwort", +"m_db_prefix" => "Kürzel, das Tabellennamen vorangestellt wird", +"m_date" => "Format des Datums wie bei der PHP-Funktion strftime()", +"m_date_posting" => "Format für den Eintrag", +"m_date_comment" => "Format für die Kommentare", +"m_date_subcurrent" => "Format für die Subnavigation", +"m_settings_ok" => "Die Einstellungen wurden gespeichert.", + +"e_path" => "Die angegebene URL scheint nicht zu stimmen", +"e_basepath" => "Das angegebene Verzeichnis existiert nicht", +"e_website" => "Bitte Namen des Weblogs eingeben", +"e_publisher" => "Bitte Namen des Betreibers eingeben", +"e_admin_password" => "Bitte Administrationscenter Passwort eingeben", +"e_admin_password_again" => "Bitte Administrationscenter Passwort bestätigen", +"e_email" => "E-Mail Adresse des Betreibers scheint falsch zu sein", +"e_description" => "Bitte eine Beschreibung des Weblogs eingeben", +"e_max_blog_orginal" => "Anzahl der Einträge, die vollständig auf der Startseite erscheinen muss eine Zahl größer oder gleich Null sein", +"e_max_blog_big" => "Anzahl der Einträge, deren Beschreibung auf der Startseite erscheinen muss eine Zahl größer oder gleich Null sein", +"e_max_blog_small" => "Anzahl der Einträge, deren Datum und Name auf der Startseite erscheinen muss eine Zahl größer oder gleich Null sein", +"e_sub_current" => "Anzahl der Einträge, deren Datum und Name in der Subnavigation erscheinen muss eine Zahl größer oder gleich Null sein", +"e_start_year" => "Das versteckte Jahresfeld ist leer", +"e_db" => "Bitte Namen der Datenbank eingeben", +"e_db_url" => "Bitte Datenbank Hostname eingeben", +"e_db_user" => "Bitte Datenbank Benutzernamen eingeben", +"e_db_prefix" => "Das Kürzel, welches als Prefix für die Tabellennamen verwendet werden soll, darf nur aus alphanumerischen Zeichen bestehen. Sie können die Angabe auch leer lassen.", +"e_db_occurred" => "Datenbankfehler", +"e_db_is" => "Es ist ein Fehler auf ".JLOG_PATH." aufgetreten. Der Fehler lautet:", + +"s_phpv_tolow" => "Die PHP Version ist zu alt, bitte auf eine neuere upgraden, bzw. deinen Provider danach fragen", +"s_mysqlv_tolow" => "Die MySQL Version ist zu alt, bitte auf eine neuere upgraden, bzw. deinen Provider danach fragen", +"s_personal_not_wrtbl" => "Das Verzeichnis 'personal' ist nicht beschreibbar. (Chmod 777)", +"s_img_not_wrtbl" => "Das Verzeichnis 'img' ist nicht beschreibbar. (Chmod 777)", +"s_tables_ok" => "Tabellen in der Datenbank angelegt.", +"s_ready_head" => "Setup erfolgreich beendet", +"s_ready" => "Glückwunsch! Nun kannst du im Administrations Center den ersten Eintrag machen.", +"s_ready_menu_admin" => "Zum Administrations Center", +"s_ready_menu_home" => "Auf die Startseite", +"s_problem_fwrite" => "Probleme beim Erstellen notwendiger Dateien", +"s_problem_chmod" => "Probleme beim Setzen der Schreibrechte", +"s_problem_fwrite" => "Probleme beim notwendigem Schreiben in Dateien", +"s_personal_ok" => "Dateien im Verzeichnis 'personal' angelegt", +"s_install" => "Installieren", + +"login_headline" => "Geschützter Bereich", +"login_password" => "Passwort eingeben:", +"login_send" => "Einloggen", +"login_cookies" => "Hinweis! Cookies müssen aktiv sein.", +"login_false_pw" => "Es wurde ein falsches Passwort eingegeben.", + +"cat_name" => "Name der Kategorie", +"cat_url" => "URL im Kategoriearchiv (nur a-z 0-9 _-,. )", +"cat_description" => "Beschreibung der Kategorie, die im Archiv auftaucht", +"cat_new" => "Neue Kategorie anlegen", +"cat_title" => "Kategorien Verwaltung", +"cat_noname" => "Die Kategorie muss einen Namen haben", +"cat_change" => "Die Kategoriedaten ändern", +"cat_new_ok" => "Neue Kategorie angelegt", +"cat_really_trash" => "Folgende Kategorie wirklich löschen? (Alle Informationen gehen verloren)", +"cat_trash_ok" => "Kategorie erfolgreich gelöscht. Zurück zum", +"cat_admincenter" => "Kategorie Administrationscenter", +"cat_duplicate" => "Eine andere Kategorie hat diesen URL schon besetzt.", + +"update_start" => 'Update starten!', +"update_successfull_part" => 'Das Update wurde erfolgreich ausgeführt.', +"update_successfull" => "Alle Updates wurden erfolgreich durchgeführt. Viel Spaß!", +"update_failure" => "Ein Update ist fehlgeschlagen.", +"pingback_closed" => "Pingbacks für diesen Eintrag schließen.", + +"plugin_no_content" => "Das Plugin muss nicht administriert werden.", +"plugins_h_not_avaliable" => "Keine Plugins", +"plugins_not_avaliable" => "Es wurden keine Plugins gefunden.", +"plugins_headline" => "Plugin Administration", + +// Do not change the folowing line +); +// eof \ No newline at end of file diff --git a/lang/lang-admin.en.inc.php b/lang/lang-admin.en.inc.php new file mode 100644 index 0000000..85ca46e --- /dev/null +++ b/lang/lang-admin.en.inc.php @@ -0,0 +1,246 @@ + "Contents", +"menu_categories" => "Categories", +"menu_comments" => "Comments", +"menu_settings" => "Settings", +"menu_plugins" => "Plugins", +"menu_logout" => "Log out", +"new_post" => "Write a new entry", +"index_headline" => "Administration Center", +"change_headline" => "Edit an old entry", +"go" => "Go", +"admin_headline" => "Administration Center", +"change" => "Edit", +"delete" => "Delete", +"date" => "Date", +"headline" => "Headline", +"metadata" => "Metadata", +"contentdata" => "Entry contents", +"url" => "URL for permanent Link (only 0-9 a-z _-,./ )", +"keywords" => "Keywords", +"categories" => "Category (Select more than one category with the help of the [Ctrl] key or the Apple key)", +"no_categories" => "none", +"preview" => "Preview", +"publish" => "Publish", +"submit" => "Submit", +"cancel" => "Cancel", +"no_headline" => "Entry headline is missing.", +"no_url" => "Entry URL is missing.", +"false_url_letters" => "The entry URL may consist of lower case letters, numbers and this characters _-.,/", +"url_duplicate" => "During one month one certain URL may occur only once as Jlog would be confused by two entries bearing one and the same name.", +"url_duplicate_page" => "Pages must have unique URLs, that is to say that every page must have a different URL.", +"false_teaserpic" => "The declaration of the teaser picture is wrong as the specified picture has not been uploaded to the server.", +"no_teaserpic_uploaded" => "The teaser picture cannot be shown in the blog if it has not been uploaded to the server.", +"no_teaser" => "Entry teaser is missing.", +"no_content" => "Entry content is missing.", +"pic_for_teaser" => "A picture to be shown next to the teaser (max. 150px):", +"pic_upload" => "Upload the picture", +"pic_choose" => "Select a picture", +"show_tpic_on_archive" => "Show this picture on the actual entry page, too.", +"teaser" => "Teaser", +"contentpic_choose" => "A picture to be shown next to the entry content:", +"content" => "Entry content", +"howto_bbcode" => "How to use BBCode?", +"content_choose_year" => "Choose Year:", + +"content_bold" => "bold", +"content_italic" => "italic", +"content_quote" => "Quote", +"content_url" => "Link", +"content_plz_format_txt" => "Please enter the text to be formatted:", +"content_input_on_pos" => "Paste at position", +"content_url_href" => "Enter link location:", +"content_url_node" => "Enter link text:", +"content_list" => "List", +"content_headline" => "Headline", + +"section" => "Type of entry:", +"section_show" => "Show types of entries", +"section_weblog" => "Weblog", +"section_page" => "Page", + +"entry_saved" => "Your entry has been saved.", +"data_updated" => "The data have been updated.", +"post_deleted" => "The blog entry has been deleted.", +"index_topic" => "Latest weblog entries", + +"yes" => "Yes", +"no" => "No", +"rearly_delete" => "Do you really want do delete this entry?", +"delete_blogentry" => "Delete entry", +"postdeleted" => "The entry has been deleted.", +"error_occurred" => "An error occured.", + +"can_not_open" => "Cannot open specified file.", +"can_not_write" => "Cannot write in specified file.", +"no_wrtitenable" => "The specified file is not writable.", +"rss_ok" => "RSS feed and News page have been successfully updated.", +"master_ok" => "The setup file has been successfully updated.", + +"pic_choose_old" => "Select an older picture", +"pic_choose_old_teaser" => "Select an older teaser picture", +"pic_upload_header" => "Upload picture", +"pic_upload_teaser" => "Upload teaser picture", +"pic_error" => "Upload error, please notify your server administrator.", +"pic_uploaded" => "Picture has been uploaded.", +"pic_insert" => "Paste a picture", +"pic_instructions" => "Upload only PNG, GIF or JPEG pictures. File size may not exceed 300 kB.", +"pic_upload" => "Upload", +"pic_class" => "CSS Class, if needed", +"pic_alt" => "Alternative text", + +"pic_height_widht" => "Picture is too high and too wide.", +"pic_width" => "Picture is too wide.", +"pic_height" => "Picture is too high.", +"pic_instr_teaser" => "Upload only PNG, GIF or JPEG pictures not being wider or higher than 150px and not exceeding file sizes of 60 kB.", +"pic_bad_type" => "Wrong format", +"pic_to_big" => "The picture is too big.", + +"kill_c_topic" => "Adminster comments", +"kill_c_killed" => "The comment has successfully been deleted.", +"kill_c_sure" => "Do you really want to delete this comment?", +"kill_c_h2" => "Delete irretrievably", +"kill_c_description" => "Attention: Once a comment is deleted from this list, it will be irretrievably lost!", +"kill_c_entry" => "Weblog entry", +"kill_c_email" => "Delete this comment", +"comments_change_h" => "Edit this comment", +"comments_anonym" => "Anonymous", +"comments_mail_txt" => "New comment on ".JLOG_WEBSITE."\nIts headline is:", +"comments_posted" => "wrote on", +"comments_mailsubject" => "Comment on ".JLOG_WEBSITE, +"comments_comment_topic" => "Comments", +"comments_by" => "Comment of", +"comments_name" => "Name", +"comments_city" => "City / Country", +"comments_email" => "E-mail", +"comments_homepage" => "http://", +"comments_bbcode" => "How to use", +"comments_send" => "Submit", +"comments_preview" => "Preview", +"comments_no_sid" => "Some spoofing seems to be on the go.", +"comments_false_mail" => "Your e-mail address does not look correct.", +"comments_notext" => "No text was entered.", +"comments_false_hp" => "The homepage URL seems to be wrong.", +"comments_permalink" => "Permanent link to this comment", +"comments_from" => "from", +"comments_posted" => "wrote on", +"comments_entryform" => "Edit this comment", +"comments_mail_by_comment" => "Notify me about comments", +"comments_thx" => "The comment has been edited.", +"comments_preview" => "Preview", +"comments_send" => "Submit", +"comments_bold" => "bold", +"comments_italic" => "italic", +"comments_quote" => "Quote", +"comments_url" => "Link", +"comments_plz_format_txt" => "Please enter the text to be formatted:", +"comments_url_href" => "Enter link location:", +"comments_url_node" => "Enter link text:", +"comments_updated" => "The comment has been edited. Back to", +"comments_admin" => "Comment Administration Center", +"comments_closed" => "Disable the comment function for this entry", + +"m_writenable" => "writeable", +"m_title" => "Weblog main settings", +"m_clean_url" => "Shall clean URLs (mod_rewrite) be used? Example: http://example.com/2005/01/firefox", +"m_metadata" => "Metadata", +"m_language" => "Language of your weblog", +"m_website" => "Weblog name", +"m_publisher" => "Name of the author of the entries", +"m_admin_password" => "Administration Center password", +"m_admin_password_again" => "Confirm password", +"m_admin_password_admin" => "(keep empty to not change it)", +"m_email" => "E-mail address of the owner of the weblog", +"m_description" => "A short description of the weblog", +"m_bs" => "Notify weblog services about new entries to make them add your entries to their search engine (one per line)", +"m_bs_weblogs_com" => "weblogs.com", +"m_bs_technorati_com" => "technorati.com", +"m_bs_blogg_de" => "blogg.de", +"m_behavior" => "Weblog behavior", +"m_max_blog_orginal" => "Number of entries that are shown completely on the weblog main page", +"m_max_blog_big" => "Number of entries that are announced by their description on the weblog main page", +"m_max_blog_small" => "Number of entries that are announced by their headline and date on the weblog main page", +"m_sub_current" => "Number of entries that are announced by their headline and date in the sub-navigation on every page of the weblog", +"m_info_by_comment" => "Notify the owner of the weblog about new comments", +"m_database" => "Database", +"m_db" => "Name of database", +"m_db_url" => "Hostname of database, usually localhost", +"m_db_user" => "Username of database", +"m_db_pwd" => "Password of database", +"m_db_prefix" => "Short identification code to be prefixed to table names", +"m_date" => "Date format (a format string like the one of the PHP function strftime())", +"m_date_posting" => "for postings", +"m_date_comment" => "for comments", +"m_date_subcurrent" => "for the subnavigation", +"m_settings_ok" => "Your settings have been saved.", + +"e_path" => "The specified URL seems to be wrong.", +"e_basepath" => "The specified directory does not exist.", +"e_website" => "Please enter the name of the weblog.", +"e_publisher" => "Please enter the name of the owner of the weblog.", +"e_admin_password" => "Please enter the password that is required to access the Administration Center.", +"e_admin_password_again" => "Please confirm the password of the Administration Center.", +"e_email" => "The e-mail address of the owner of the weblog seems to be wrong.", +"e_description" => "Please enter a description of the weblog.", +"e_max_blog_orginal" => "Number of entries that are shown completely on the weblog main page must be a number greater than or equal to zero.", +"e_max_blog_big" => "Number of entries that are announced by their description on the weblog main page must be a number greater than or equal to zero.", +"e_max_blog_small" => "Number of entries that are announced by their headline and date on the weblog main page must be a number greater than or equal to zero.", +"e_sub_current" => "Number of entries that are announced by their headline and date in the sub-navigation on every page of the weblog must be a number greater than or equal to zero.", +"e_start_year" => "The hidden year field is empty.", +"e_db" => "Please enter the name of the database.", +"e_db_url" => "Please enter the hostname of the database.", +"e_db_user" => "Please enter the username of the database.", +"e_db_prefix" => "The prefix for table names must not contain anything but alpha-numeric characters. However, you can leave option empty.", +"e_db_occurred" => "Database error", +"e_db_is" => "A error occured in ".JLOG_PATH.". It is:", + +"s_phpv_tolow" => "Your PHP version is too old, please upgrade to a newer one or ask your server administrator to do this.", +"s_mysqlv_tolow" => "Your MySQL version is too old, please upgrade to a newer one or ask your server administrator to do this.", +"s_personal_not_wrtbl" => "The directory 'personal' is not writeable. (Chmod 777)", +"s_img_not_wrtbl" => "The directory 'img' is not writeable. (Chmod 777)", +"s_tables_ok" => "Tables have been created in the database.", +"s_ready_head" => "Setup has been successfully finished.", +"s_ready" => "Congratulations! You can start writing your first blog entry in the Administration Center.", +"s_ready_menu_admin" => "To the Administration Center", +"s_ready_menu_home" => "To the weblog main page", +"s_problem_fwrite" => "Problems occured during the Creation of required files.", +"s_problem_chmod" => "Problems occured while setting write permissions.", +"s_problem_fwrite" => "Problems occured during required writing access to files.", +"s_personal_ok" => "Files in the directory 'personal' have been created.", +"s_install" => "Install", + +"login_headline" => "Protected area", +"login_password" => "Enter password:", +"login_send" => "Log in", +"login_cookies" => "Please note: Cookies must be activated in your browser!", +"login_false_pw" => "Wrong password entered.", + +"cat_name" => "Category name", +"cat_url" => "URL in category archive (only a-z 0-9 _-,. )", +"cat_description" => "Category descriptiom that occurs in the archive", +"cat_new" => "Create new category", +"cat_title" => "Categories management", +"cat_noname" => "The category must have a name.", +"cat_change" => "Edit category data", +"cat_new_ok" => "The new category has been created.", +"cat_really_trash" => "Do you really want to delete the following category? (All information will be lost.)", +"cat_trash_ok" => "The category has successfully been deleted. Back to", +"cat_admincenter" => "Categories Administration Center", +"cat_duplicate" => "Another category is already using this URL.", + +"update_start" => 'Perform update!', +"update_successfull_part" => 'This update has been performed successfully.', +"update_successfull" => "All updates have been performed. Have fun!", +"update_failure" => "Ein Update ist fehlgeschlagen.", +"pingback_closed" => "Close pingbacks for this entry.", + +"plugin_no_content" => "There is no need to administrate this plugin.", +"plugins_h_not_avaliable" => "No plugins available", +"plugins_not_avaliable" => "I couldn't find any plugins.", +"plugins_headline" => "Plugin Administration", + +// Do not change the folowing line! +); +// eof \ No newline at end of file diff --git a/lang/lang-admin.it.inc.php b/lang/lang-admin.it.inc.php new file mode 100644 index 0000000..c0bff8a --- /dev/null +++ b/lang/lang-admin.it.inc.php @@ -0,0 +1,241 @@ + "Contenuti", +"menu_categories" => "Categorie", +"menu_comments" => "Commenti", +"menu_settings" => "Settaggi", +"menu_plugins" => "Plugins", +"menu_logout" => "Log out", +"new_post" => "Scrivi una nuova nota", +"index_headline" => "Administration Center", +"change_headline" => "Modifica una vecchia nota", +"go" => "Vai", +"admin_headline" => "Centro d'amministrazione", +"change" => "Modifica", +"delete" => "Cancella", +"date" => "Data", +"headline" => "Titolo", +"metadata" => "Metadata", +"contentdata" => "Contenuti della nota", +"url" => "URL per Link permanenti (only 0-9 a-z _-,. )", +"keywords" => "Parola chiave", +"categories" => "Categoria (seleziona piu di una categoria con help file di [Ctrl] tasto or the Apple tasto)", +"no_categories" => "nessuna", +"preview" => "Anteprima", +"publish" => "Pubblica", +"submit" => "Inoltrare", +"cancel" => "Cancella", +"no_headline" => "Inseerisci il titolo se mancante.", +"no_url" => "Inserisci URL se mancante.", +"false_url_letters" => "Il nuovo URL deve contenere lettere minuscole, numeri e questi caratteri _-.,/", +"url_duplicate" => "Derante un mese gli URL in Jlog devono avere tutti nomi diversi per evitare che il sistema si confonda.", +"url_duplicate_page" => "La pagina deve avere un solo URLs,in questo modo ogni pagina ha un diverso URL.", +"false_teaserpic" => "L’immagine introduttiva non esiste,l’immagine non é stata salvata nel server.", +"no_teaserpic_uploaded" => "L’immagine introduttiva non puo essere mostrata nel blog se non e stata salvata nel server.", +"no_teaser" => "L'introduzzione manca.", +"no_content" => "Inserisci cintenuto perche mancante.", +"pic_for_teaser" => "Un immagine sara visualizzata nella prossima introduzione (max. 150px):", +"pic_upload" => "Upload immagine", +"pic_choose" => "Seleziona una immagine", +"show_tpic_on_archive" => "Mostra questa immagine anche nell'attuale nota.", +"teaser" => "Introduzione", +"contentpic_choose" => "L'immagine sara visualizzata nella nuova categoria:", +"content" => "Contenuti nota", +"howto_bbcode" => "Come usare BBCode?", +"content_choose_year" => "Sciegli l'anno:", + +"content_bold" => "Grassetto", +"content_italic" => "Corsivo", +"content_quote" => "Citazione", +"content_url" => "Link", +"content_plz_format_txt" => "Perfavore sciegliere il testo per cambiare lo stile:", +"content_input_on_pos" => "Incolla", +"content_url_href" => "Inserisci dove si trova il link:", +"content_url_node" => "Inserisci link testo:", +"content_list" => "Lista", +"content_headline" => "Titolo", + +"section" => "Tipo di nota:", +"section_show" => "Mostra tipi di note", +"section_weblog" => "Weblog", +"section_page" => "Pagina", + +"entry_saved" => "La tua nota e stata salvata .", +"data_updated" => "I dati sono stati updated.", +"post_deleted" => "La nota deve essere cancellata.", +"index_topic" => "Ultima nota nel weblog", + +"yes" => "Si", +"no" => "No", +"rearly_delete" => "Vuoi veramente cancellare questa nota?", +"delete_blogentry" => "Cancella nota", +"postdeleted" => "La nota e stata cancellata.", +"error_occurred" => "Errore in corso.", + +"can_not_open" => "Impossibile aprire il file specificato.", +"can_not_write" => "Impossibile scrivere il file specificato.", +"no_wrtitenable" => "Non si puo scrivere questo file.", +"rss_ok" => "RSS feed e News page sono state aggiornate con successo.", +"master_ok" => "Il file di setup e stato aggiornato con successo.", + +"pic_choose_old" => "Selezionare foto precedenti", +"pic_choose_old_teaser" => "Select an older teaser picture", +"pic_upload_header" => "Aggiorna immagini", +"pic_upload_teaser" => "Upload teaser picture", +"pic_error" => "Errore di aggiornamento, per favore notificarlo all'aministratore del server.", +"pic_uploaded" => "Le immagini sono state aggiornate.", +"pic_insert" => "Incolla una immagine", +"pic_instructions" => "Aggiornare solo immagini PNG, GIF or JPEG. La dimensione del file non deve essere superiore a 300 kB.", +"pic_upload" => "Aggiorna", +"pic_class" => "CSS Class, se necessario", +"pic_alt" => "Testi alternativi", + +"pic_height_widht" => "L'immagine e troppo larga e alta.", +"pic_width" => "L'immagine e troppo larga.", +"pic_height" => "L'immagine e troppo alta.", +"pic_instr_teaser" => "Aggiorna solo immagini in PNG, GIF or JPEG non devono essere alte o larghe piu di 150px e non devono eccedere oltre 60 kB.", +"pic_bad_type" => "Formato non valido", +"pic_to_big" => "L'immagine e troppo grande.", + +"kill_c_topic" => "Commenti dell'amministratore", +"kill_c_killed" => "Il commento e stato cancellato.", +"kill_c_sure" => "Vuoi veramente cancellare questo commento?", +"kill_c_h2" => "Cancellazione irreversibile", +"kill_c_description" => "Attenzione: Un commento e stato cancellato dalla lista, sara perso per sempre!", +"kill_c_entry" => "Nota Weblog", +"kill_c_email" => "Cancella questo commento", +"comments_change_h" => "Modifica questo commento", +"comments_anonym" => "Anonimo", +"comments_mail_txt" => "Nuovo commento in ".JLOG_WEBSITE."\nIts il titolo e:", +"comments_posted" => "scrivi", +"comments_mailsubject" => "Commento on ".JLOG_WEBSITE, +"comments_comment_topic" => "Commenti", +"comments_by" => "Commento off", +"comments_name" => "Nome", +"comments_city" => "Citta / Paese", +"comments_email" => "E-mail", +"comments_homepage" => "http://", +"comments_bbcode" => "Come si usa", +"comments_send" => "Inoltra", +"comments_preview" => "Anteprima", +"comments_no_sid" => "Stai scherzando?.", +"comments_false_mail" => "L'indirizzo e-mail non e corretto.", +"comments_notext" => "Non e presente nessun testo.", +"comments_false_hp" => "Homepage URL sembra errato.", +"comments_permalink" => "Link permanente per questo commento", +"comments_from" => "da", +"comments_posted" => "scrivi", +"comments_entryform" => "Modifica questo commento", +"comments_mail_by_comment" => "Tienimi informato su questo commento", +"comments_thx" => "Il commento é stato creato con successo.", +"comments_preview" => "Anteprima", +"comments_send" => "Inoltra", +"comments_bold" => "Grassetto", +"comments_italic" => "Corsivo", +"comments_quote" => "Quote", +"comments_url" => "Link", +"comments_plz_format_txt" => "Perfavore sciegliere il testo per cambiare lo stile:", +"comments_url_href" => "Inserire la locazione del link:", +"comments_url_node" => "Inserire link text:", +"comments_updated" => "Il commento e stato creato. Indietro", +"comments_admin" => "Commento Administration Center", +"comments_closed" => "Disabilita i commenti per questa nota", + +"m_writenable" => "writeable", +"m_title" => "Weblog settaggi", +"m_clean_url" => "Pulire URLs (mod_rewrite) usati? Esempio: http://example.com/2005/01/firefox", +"m_metadata" => "Metadata", +"m_language" => "Lingua del vostro weblog", +"m_website" => "Nome Weblog", +"m_publisher" => "Nome dell'autore della nota", +"m_admin_password" => "Administration Center password", +"m_admin_password_again" => "Conferma password", +"m_admin_password_admin" => "(lascia vuoto per non cambiarla)", +"m_email" => "E-mail del proprietario del weblog", +"m_description" => "Piccola descrizione del weblog", +"m_bs" => "Notifica quando si aggiungono nuove note (uno per riga)", +"m_bs_weblogs_com" => "weblogs.com", +"m_bs_technorati_com" => "technorati.com", +"m_bs_blogg_de" => "blogg.de", +"m_behavior" => "Carattere weblog", +"m_max_blog_orginal" => "Il numero delle note si strova nella pagina principale", +"m_max_blog_big" => "Numero di note con descrizione presenti nella pagina principale del weblog", +"m_max_blog_small" => "Numero di note con titolo e data presenti nella pagina principale del weblog", +"m_sub_current" => "Numero di note che sono introdotte da titolo e data ipresenti nelle altre pagine del weblog", +"m_info_by_comment" => "Avvisa il proprietario della nota quando ci sono nuovi commenti ", +"m_database" => "Database", +"m_db" => "Nome database", +"m_db_url" => "Hostname del database, solitamente localhost", +"m_db_user" => "Username del database", +"m_db_pwd" => "Password del database", +"m_db_prefix" => "Codice identificazione per prefissi in table names", +"m_date" => "Forma data (a format string like the one of the PHP function strftime())", +"m_date_posting" => "per affissioni", +"m_date_comment" => "per commenti", +"m_date_subcurrent" => "per la subnavigation", +"m_settings_ok" => "I tuoi settaggi sono stati salvati.", + +"e_path" => "Specificare URL perche non corretto.", +"e_basepath" => "Specificare directory non esiste.", +"e_website" => "Perfavore inserire il nome weblog.", +"e_publisher" => "Perfavore inserire il nome del propietario del weblog.", +"e_admin_password" => "Inserire la password necessaria per avere accesso all'Administration Center.", +"e_admin_password_again" => "Confermare password per Administration Center.", +"e_email" => "L'e-mail del propietario del weblog non e corretto.", +"e_description" => "Inserire descrizione del weblog.", +"e_max_blog_orginal" => "Il numero di note e visualizzato nella pagina principale e deve essere maggiore o uguale a zero.", +"e_max_blog_big" => "Numero di note con descrizione presenti nella pagina principale del weblog deve essere maggiore o uguale a zero.", +"e_max_blog_small" => "Numero di note con titolo e data presenti nella pagina principale del weblog deve essere maggiore o uguale a zero.", +"e_sub_current" => "Numero di note che sono introdotte da titolo e data ipresenti nelle altre pagine del weblog deve essere maggiore o uguale a zero.", +"e_start_year" => "La casella nascosta dell'anno e vuota.", +"e_db" => "Inserire nome database.", +"e_db_url" => "Inserire hostname del database.", +"e_db_user" => "Inserire username del database.", +"e_db_occurred" => "Errore database", +"e_db_is" => "Errore in ".JLOG_PATH.". E:", + +"s_phpv_tolow" => "La tua versione del PHP e troppo vecchia, perfavore aggiornare o chiedere all'aministrator del server.", +"s_mysqlv_tolow" => "La tuaversione del MySQL e troppo vecchia, perfavore aggiornare o chiedere all'aministrator del server.", +"s_personal_not_wrtbl" => "La directory 'personal' non puo essere scritta. (Chmod 777)", +"s_img_not_wrtbl" => "La directory 'img' non puo essere scritta. (Chmod 777)", +"s_tables_ok" => "Le tabelle sono state create nel database.", +"s_ready_head" => "Installazione completata con successo.", +"s_ready" => "Tanti auguri! Puoi iniziare a scrivere a scrivere la tua prima nota in Administration Center.", +"s_ready_menu_admin" => "Per Administration Center", +"s_ready_menu_home" => "Per la pagina principale del weblog", +"s_problem_fwrite" => "Problema durante la creazione del file richiesto.", +"s_problem_chmod" => "Problema durante setting write permissions.", +"s_problem_fwrite" => "Problema durante la scrittura del file.", +"s_personal_ok" => "I file in 'personal' sono stati creati.", +"s_install" => "Installa", + +"login_headline" => "Area protetta", +"login_password" => "Inserisci password:", +"login_send" => "Log in", +"login_cookies" => "Attenzione: I Cookies devono essere attivati nel tuo browser!", + +"cat_name" => "Nome categoria", +"cat_url" => "URL in archivio categorie (only a-z 0-9 _-,. )", +"cat_description" => "Descrizione della categoria richiesta", +"cat_new" => "Crea una nuova categoria", +"cat_title" => "Gestione categorie", +"cat_noname" => "La categoria deve avere un nome.", +"cat_change" => "Modifica data categoria", +"cat_new_ok" => "Una nuova categoria e stata creata.", +"cat_really_trash" => "Vuoi veramente cancellare la seguente categoria? (Tutte le informazioni saranno perse.)", +"cat_trash_ok" => "La categoria e stata cancellata. Indietro", +"cat_admincenter" => "Categorie Administration Center", +"cat_duplicate" => "Un altra categoria sta usando questo URL.", + +"update_successfull" => "Aggiornato con successo. Have fun!", +"pingback_closed" => "Chiudi pingbacks per questa nota.", + +"plugin_no_content" => "Non occorre questo plugin.", +"plugins_h_not_avaliable" => "Plugin non disponibili", +"plugins_not_avaliable" => "Non trovo nessun plugins.", +"plugins_headline" => "Plugin Administration", + +// Do not change the folowing line! +); +// eof \ No newline at end of file diff --git a/lang/lang-admin.pl.inc.php b/lang/lang-admin.pl.inc.php new file mode 100644 index 0000000..cec356c --- /dev/null +++ b/lang/lang-admin.pl.inc.php @@ -0,0 +1,241 @@ + "Zawartosść", +"menu_categories" => "Kategorie", +"menu_comments" => "Komentarze", +"menu_settings" => "Konfiguracja", +"menu_plugins" => "Wtyczki", +"menu_logout" => "Wyloguj Å›iÄ™", +"new_post" => "Napisz nowy watek", +"index_headline" => "Centrum Administracyjne", +"change_headline" => "Edytuj stary watek", +"go" => "Start", +"admin_headline" => "Centrum Administracyjne", +"change" => "Edytuj", +"delete" => "Kasuj", +"date" => "Data", +"headline" => "Nagłówek", +"metadata" => "Metadane", +"contentdata" => "Zawartość watku", +"url" => "URL na permanentny link (tylko 0-9 a-z _-,./ )", +"keywords" => "SÅ‚owa kluczowe", +"categories" => "Kategoria (Wybierz wiÄ™cej niż jednÄ… kategoriÄ™ za pomocÄ… klawisza [Ctrl] albo klawisza Apple)", +"no_categories" => "żadna", +"preview" => "PodglÄ…d", +"publish" => "Publikuj", +"submit" => "Zaloguj", +"cancel" => "Anuluj", +"no_headline" => "Brak nagłówka watku.", +"no_url" => "Brak URL watku.", +"false_url_letters" => "W URL możecz tylko używac a do z i _-.,/", +"url_duplicate" => "W ciÄ…gu jednego miesiÄ…ca okreÅ›lony URL może siÄ™ pojawic tylko raz,", +"url_duplicate_page" => "Strony muszÄ… mieć unikalne URLe, co oznacza że każda strona musi mieć inny URL.", +"false_teaserpic" => "Okreslony obrazek nie zostal zapisany na serwerze.", +"no_teaserpic_uploaded" => "Obrazek skróconego opisu nie moze byc pokazany w blogu jesli nie zoatal zapisany na serwerze.", +"no_teaser" => "Brak skróconego opisu.", +"no_content" => "Brak zawartośći artykuÅ‚u.", +"pic_for_teaser" => "Obrazek który zostanie pokazany przy skróconym opisie (max. 150px):", +"pic_upload" => "SciÄ…gnij obrazek", +"pic_choose" => "Wybierz obrazek", +"show_tpic_on_archive" => "Pokaz ten obrazek rowniez na bieżącej stronie.", +"teaser" => "Skrócony opis", +"contentpic_choose" => "Obrazek który zostanie pokazany przy zawartośći arkykuÅ‚u:", +"content" => "Zawartość artykuÅ‚u", +"howto_bbcode" => "Jak używać BBCode?", +"content_choose_year" => "Wybierz rok:", + +"content_bold" => "wytluszczony", +"content_italic" => "pochyÅ‚y", +"content_quote" => "cytat", +"content_url" => "link", +"content_plz_format_txt" => "Prosze wprowadzic tekst do sformatowania:", +"content_input_on_pos" => "Wklej do", +"content_url_href" => "Wprowadź lokalizacje linku:", +"content_url_node" => "Wprowadź tekst linku:", +"content_list" => "Lista", +"content_headline" => "Naglówek", + +"section" => "Rodzaj watku:", +"section_show" => "Pokaż rodzaje watkuw", +"section_weblog" => "Weblog", +"section_page" => "Strona", + +"entry_saved" => "Twój watek zostaÅ‚ zapisany.", +"data_updated" => "Dane zostaly uaktualnione.", +"post_deleted" => "Watek zostal usuniety.", +"index_topic" => "Ostatnie wejscia na weblog", + +"yes" => "Tak", +"no" => "Nie", +"rearly_delete" => "Czy jestes pewny/a ze chcesz zlikwidowac ten watek?", +"delete_blogentry" => "Zlikwiduj watek", +"postdeleted" => "Watek zostal zlikwidowany.", +"error_occurred" => "Pojawil sie blad.", + +"can_not_open" => "Nie da sie otworzyc tego dokumentu.", +"can_not_write" => "Cannot write in specified file.", +"no_wrtitenable" => "The specified file is not writable.", +"rss_ok" => "RSS feed and News page zostaly pomyslnie uaktualnione.", +"master_ok" => "setup zostal pomyslnie uaktualniony.", + +"pic_choose_old" => "Wybierz starszy obrazek", +"pic_choose_old_teaser" => "Wybierz starszy obrazek skróconego opisu", +"pic_upload_header" => "WyÅ›lij obrazek", +"pic_upload_teaser" => "WyÅ›lij obrazek skróconego opisu", +"pic_error" => "WyÅ›lij raport o bÅ‚edzie, prosze zawiadomic administratora swojego serwera.", +"pic_uploaded" => "Obrazek zostal wysÅ‚any.", +"pic_insert" => "Wklej obrazek", +"pic_instructions" => "WyÅ›lij tylko obrazki o rozszerzeniu PNG, GIF lub JPEG. Rozmiar dokumentu nie może przekroczyc 300 kB.", +"pic_upload" => "WyÅ›lij", +"pic_class" => "w potżebie klassa CSS", +"pic_alt" => "tekst alternatywny", + +"pic_height_widht" => "Obrazek jest zbyt wysoki i zbyt szeroki.", +"pic_width" => "Obrazek jest zbyt szeroki.", +"pic_height" => "Obrazek jest zbyt wysoki.", +"pic_instr_teaser" => "Wyslij tylko obrazki z rozszerzeniem PNG, GIF lub JPEG, ktore nie sa szersze ani wyzsze niz 150px i rozmiar dokumentu nie przekracza 60 kB.", +"pic_bad_type" => "ZÅ‚y format", +"pic_to_big" => "Obrazek jest zbyt duży.", + +"kill_c_topic" => "Komentarze administratora", +"kill_c_killed" => "Komentarz zostaÅ‚ pomyÅ›lnie usuniety.", +"kill_c_sure" => "Czy jesteÅ› pewny ze chcesz usunąć ten komentarz?", +"kill_c_h2" => "UsuÅ„ calkowicie", +"kill_c_description" => "Uwaga: Gdy komentarz zostanie usuniÄ™ty z listy, nie bÄ™dzie możliwe jego odtworzenie!", +"kill_c_entry" => "Weblog artykół", +"kill_c_email" => "UsuÅ„ ten komentarz", +"comments_change_h" => "Edytuj ten komentarz", +"comments_anonym" => "Anonim", +"comments_mail_txt" => "Nowy komentarz na ".JLOG_WEBSITE."\nJego nagłówek jest:", +"comments_posted" => "pisany", +"comments_mailsubject" => "Komentarz na ".JLOG_WEBSITE, +"comments_comment_topic" => "Komentarze", +"comments_by" => "komentarz od", +"comments_name" => "ImiÄ™", +"comments_city" => "Miejscowość / Kraj", +"comments_email" => "emaila", +"comments_homepage" => "http://", +"comments_bbcode" => "Jak używać", +"comments_send" => "WyÅ›lij", +"comments_preview" => "PodglÄ…d", +"comments_no_sid" => "To wyglÄ…da na manipulacjÄ™.", +"comments_false_mail" => "Twoj adres emaila jest niepoprawny.", +"comments_notext" => "Nie zostaÅ‚ wprowadzony tekst.", +"comments_false_hp" => "URL strony glównej jest bÅ‚edny.", +"comments_permalink" => "Permanentny link do tego komentarza", +"comments_from" => "od", +"comments_posted" => "pisany", +"comments_entryform" => "Edytuj ten komentarz", +"comments_mail_by_comment" => "Powiadom mnie o komentarzach", +"comments_thx" => "Komentarz zostaÅ‚ edytowany.", +"comments_preview" => "PodglÄ…d", +"comments_send" => "WyÅ›lij", +"comments_bold" => "wytluszczony", +"comments_italic" => "pochyÅ‚y", +"comments_quote" => "cytat", +"comments_url" => "link", +"comments_plz_format_txt" => "Prosze wprowadzić tekst do sformatowania:", +"comments_url_href" => "Wprowadź link location:", +"comments_url_node" => "Wprowadź tekst linka:", +"comments_updated" => "Komentarz zostaÅ‚ edytowany. Z powrotem do", +"comments_admin" => "Centrum administrowania komentarzy", +"comments_closed" => "Wyłącz komentaże teko artykuÅ‚u", + +"m_writenable" => "prawo do zapisu", +"m_title" => "Główne ustawienia webloga", +"m_clean_url" => "Używac Å‚adne URL (mod_rewrite)? PrzykÅ‚ad: http://example.com/2005/01/firefox", +"m_metadata" => "Metadane", +"m_language" => "Jezyk twojego webloga", +"m_website" => "Nazwa webloga", +"m_publisher" => "Imie autora watkow", +"m_admin_password" => "Haslo centrum administracyjnego", +"m_admin_password_again" => "Potwierdź hasÅ‚o", +"m_admin_password_admin" => "(zostaw puste abe nie zmieniać)", +"m_email" => "Address emaila wÅ‚aÅ›ciciela tego webloga", +"m_description" => "Krótki opis webloga", +"m_bs" => "Zawiadom serwisy blogowe o nowym artykule aby dodali jego do swoich przeszukiwarek (jeden na linjÄ™)", +"m_bs_weblogs_com" => "weblogs.com", +"m_bs_technorati_com" => "technorati.com", +"m_bs_blogg_de" => "blogg.de", +"m_behavior" => "zachowanie na weblogu", +"m_max_blog_orginal" => "Ile artykuÅ‚uw pokazać na stronie głównej?", +"m_max_blog_big" => "Ile krótkich opisów artykuÅ‚uw pokazać na stronie głównej?", +"m_max_blog_small" => "Ile nagłówkuw z datÄ… artykuÅ‚uw pokazać na stronie głównej?", +"m_sub_current" => "Ile nagłówkuw z datÄ… artykuÅ‚uw pokazać na boku każdej strony webloga?", +"m_info_by_comment" => "Zawiadom wÅ‚asciciela webloga o nowych komentarzach", +"m_database" => "Baza danych", +"m_db" => "Nazwa bazy danych", +"m_db_url" => "Hostname bazy danych, normalnie localhost", +"m_db_user" => "Użytkownik bazy danych", +"m_db_pwd" => "Haslo bazy danych", +"m_db_prefix" => "Krótki prefix nazw tabelów", +"m_date" => "Format daty (jak w funkcji PHP strftime())", +"m_date_posting" => "dla artykuÅ‚uw", +"m_date_comment" => "dla komentarzy", +"m_date_subcurrent" => "dla bocznej nawigacji", +"m_settings_ok" => "Twoje ustawienia zostaly zapisane.", + +"e_path" => "Dany URL jest bÅ‚edny.", +"e_basepath" => "Nie ma danego katalogu.", +"e_website" => "Prosze wprowadzic nazwÄ™ webloga.", +"e_publisher" => "Prosze wprowadzic imiÄ™ wÅ‚aųciciela webloga.", +"e_admin_password" => "Prosze wprowadzic hasÅ‚o dostÄ™pu do centrum administracyjnego.", +"e_admin_password_again" => "Prosze potwierdzic hasÅ‚o centrum administracyjnego.", +"e_email" => "Adres emaila wÅ‚aÅ›ciciela webloga jest bÅ‚edny.", +"e_description" => "Prosze wprowadzic opis webloga.", +"e_max_blog_orginal" => "Ilość artykuÅ‚uw na głównej stronie muÅ›i byci 0 albo wiÄ™cej.", +"e_max_blog_big" => "Ilość skróconegych opisuw na głównej stronie muÅ›i byci 0 albo wiÄ™cej.", +"e_max_blog_small" => "Ilość nagłówkuw z datÄ… na głównej stronie muÅ›i byci 0 albo wiÄ™cej.", +"e_sub_current" => "Ilość nagłówkuw z datÄ… na boku każdej strony muÅ›i byci 0 albo wiÄ™cej.", +"e_start_year" => "Ukryty rok byÅ‚ pusty.", +"e_db" => "Prosze wprowadzic nazwÄ™ bazy danych.", +"e_db_url" => "Prosze wprowadzic the nazwa hosta bazy danych.", +"e_db_user" => "Prosze wprowadzic imie użytkownika bazy danych.", +"e_db_occurred" => "BÅ‚ad bazy danych", +"e_db_is" => "PojawiÅ‚ siÄ™ bÅ‚ad w ".JLOG_PATH.". To jest:", + +"s_phpv_tolow" => "Twoja wersja PHP jest zbyt stara, proszÄ™ zaopatrzyć siÄ™ w nowszÄ… lub poprosić o to administratora serwera.", +"s_mysqlv_tolow" => "Twoja wersja MySQL jest zbyt stara, proszÄ™ zaopatrzyć siÄ™ w nowszÄ… lub poprosić o to administratora serwera.", +"s_personal_not_wrtbl" => "Nie mam prawa pisac do kataloga 'personal'. (Chmod 777)", +"s_img_not_wrtbl" => "Nie mam prawa pisac do kataloga 'img'. (Chmod 777)", +"s_tables_ok" => "Tabely bazy danych zostaÅ‚y ztwożone.", +"s_ready_head" => "Twój nowy weblog zostaÅ‚ utworzony.", +"s_ready" => "Gratulacje! Mozesz zacząć pisac swój pierwszy wpis w centrum administracynym.", +"s_ready_menu_admin" => "Do centrum administracyjnego", +"s_ready_menu_home" => "Do strony glównej weblogu", +"s_problem_chmod" => "Błąd w ciÄ…gu ustawienia prawa pisania.", +"s_problem_fwrite" => "Błąd w ciÄ…gu pisania danych do pliku.", +"s_personal_ok" => "Pliki w katalogu 'personal' zostaÅ‚y utworzona.", +"s_install" => "Instaluj", + +"login_headline" => "Obszar chroniony", +"login_password" => "Wprowadź hasÅ‚o:", +"login_send" => "Zaloguj siÄ™", +"login_cookies" => "Uwaga: Cookie muszÄ… być aktywne w twojej przeglÄ…darce!", +"login_false_pw" => "Wprowadzono zÅ‚e hasÅ‚o.", + +"cat_name" => "Nazwa kategorii", +"cat_url" => "URL archiwie kategorii (tylko a-z 0-9 _-,. )", +"cat_description" => "Opis kategorii które pojawiÅ‚y siÄ™ w archiwum", +"cat_new" => "Stwóz nowÄ… kategorie", +"cat_title" => "Zarzadzanie kategoriami", +"cat_noname" => "Kategoria musi mieć nazwÄ™.", +"cat_change" => "Edytuj dane kategorii", +"cat_new_ok" => "ZostaÅ‚a utworzona nowa kategoria.", +"cat_really_trash" => "Czy jesteÅ› pewny że chcesz usunąć nastÄ™pujacÄ… kategorie? (Wszystkie informacje zostanÄ… stracone.)", +"cat_trash_ok" => "Kategoria zostaÅ‚a pomyÅ„lnie usuniÄ™ta. Z powrotem do", +"cat_admincenter" => "Centrum administracji kategoriami", +"cat_duplicate" => "Inna kategoria już używa tego URL.", + +"update_successfull" => "Uaktualnienie zostaÅ‚o pomyÅ›lnie dokonane. Have fun!", +"pingback_closed" => "Nie dopuÅ›cić pingbacków dla tego artykuÅ‚u.", + +"plugin_no_content" => "Nie potrzeba administrować tego pluginu.", +"plugins_h_not_avaliable" => "Nie ma pluginuw", +"plugins_not_avaliable" => "Nie mozna znalezc zadnych pluginuw.", +"plugins_headline" => "Administracja pluginuw", + +// Do not change the folowing line! +); +// eof \ No newline at end of file diff --git a/lang/lang-admin.sv.inc.php b/lang/lang-admin.sv.inc.php new file mode 100644 index 0000000..1ebde89 --- /dev/null +++ b/lang/lang-admin.sv.inc.php @@ -0,0 +1,241 @@ + "InnehÃ¥ll", +"menu_categories" => "Kategorier", +"menu_comments" => "Kommentarer", +"menu_settings" => "Inställningar", +"menu_plugins" => "Plugins", +"menu_logout" => "Logga ut", +"new_post" => "Skriv ett nytt inlägg", +"index_headline" => "Administrationscenter", +"change_headline" => "Editera ett gammalt inlägg", +"go" => "Go", +"admin_headline" => "Administrationscenter", +"change" => "Editera", +"delete" => "Radera", +"date" => "Datum", +"headline" => "Rubrik", +"metadata" => "Metadata", +"contentdata" => "InnehÃ¥ll", +"url" => "URL för permanent länk (bara 0-9 a-z _-,./ )", +"keywords" => "Nyckelord", +"categories" => "Kategori (Välj flera kategorier med hjälp av [Ctrl] eller Command tangenten)", +"no_categories" => "ingen", +"preview" => "Förhandsgranskning", +"publish" => "Publicera", +"submit" => "Skicka", +"cancel" => "Avbryt", +"no_headline" => "Rubriken fattas.", +"no_url" => "URL fattas.", +"false_url_letters" => "URLen fÃ¥r bara innehÃ¥lla smÃ¥ bokstäver, siffror eller _-.,/", +"url_duplicate" => "Exakt samma webblogginlägg-url fÃ¥r ej förekomma tvÃ¥ gÃ¥nger under samma mÃ¥nad", +"url_duplicate_page" => "Alla sidor-url:er mÃ¥sta vara unika.", +"false_teaserpic" => "Teaserbilden har inte blivit upladdad än.", +"no_teaserpic_uploaded" => "Teaserbilden kan inte visas om den inte är uppladdad.", +"no_teaser" => "Teaser fattas.", +"no_content" => "InnehÃ¥ll fattas.", +"pic_for_teaser" => "Bilden som ska visas i teasern (max 150px):", +"pic_upload" => "Ladda upp bild", +"pic_choose" => "Välj bild", +"show_tpic_on_archive" => "Visa bilden även i bloggen.", +"teaser" => "Teaser", +"contentpic_choose" => "Bilden som visas i innehÃ¥ll:", +"content" => "InnehÃ¥ll", +"howto_bbcode" => "Hur använder man BBCode?", +"content_choose_year" => "Välj Ã¥r:", + +"content_bold" => "fet", +"content_italic" => "kursiv", +"content_quote" => "citera", +"content_url" => "länk", +"content_plz_format_txt" => "Skriv in texten som ska formateras:", +"content_input_on_pos" => "Klistra in vid position:", +"content_url_href" => "Skriv in URLen:", +"content_url_node" => "Skriv in texten:", +"content_list" => "lista", +"content_headline" => "rubrik", + +"section" => "Typ av inlägg:", +"section_show" => "Visa typer av inlägg", +"section_weblog" => "Webblogg", +"section_page" => "Sida", + +"entry_saved" => "Inlägg har sparats.", +"data_updated" => "Datan har uppdaterats.", +"post_deleted" => "Blogginlägg har raderats.", +"index_topic" => "Senaste blogginlägg", + +"yes" => "Ja", +"no" => "Nej", +"rearly_delete" => "Är du säker att du vill radera inlägget?", +"delete_blogentry" => "Radera inlägget", +"error_occurred" => "Ett fel har upstÃ¥tt.", + +"can_not_open" => "Kan inte öppna filen.", +"can_not_write" => "Kan inte spara filen.", +"no_wrtitenable" => "Det gÃ¥r inte att skriva till filen.", +"rss_ok" => "RSS och 'aktuellt' har uppdaterats.", +"master_ok" => "Setupfilen har uppdaterats.", + +"pic_choose_old" => "Välj en gammal bild", +"pic_choose_old_teaser" => "Välj en gammal teaserbild", +"pic_upload_header" => "Ladda upp en bild", +"pic_upload_teaser" => "Ladda upp en teaserbild", +"pic_error" => "Det har uppstÃ¥tt ett fel, kontakta serveradministratören.", +"pic_uploaded" => "Bilden har laddats upp.", +"pic_insert" => "Infoga bilden", +"pic_instructions" => "Endast uppladdning av PNG-, GIF- eller JPEG-bilder. Bilden fÃ¥r inte vara större än 300 kB.", +"pic_upload" => "Ladda upp", +"pic_class" => "CSS klass (vid behov)", +"pic_alt" => "Alternativtext", + +"pic_height_widht" => "Bilden är för bred och för hög.", +"pic_width" => "Bilden är för bred.", +"pic_height" => "Bilden är för hög.", +"pic_instr_teaser" => "Endast uppladdning av PNG-, GIF- eller JPEG-bilder som inte är bredare än 150px och inte större än 60 kB.", +"pic_bad_type" => "Fel bildformat", +"pic_to_big" => "Bilden är för stor.", + +"kill_c_topic" => "Administrera kommentarer", +"kill_c_killed" => "Kommentaren raderades.", +"kill_c_sure" => "Är du säker att du vill radera kommentaren?", +"kill_c_h2" => "Radera", +"kill_c_description" => "Varning! När en kommentar en gÃ¥ng har tagits bort frÃ¥n denna lista, är den oÃ¥terkalleligen raderad.", +"kill_c_entry" => "Webblogg inlägg", +"kill_c_email" => "Radera kommentaren", +"comments_change_h" => "Editera kommentaren", +"comments_anonym" => "Anonym", +"comments_mail_txt" => "Ny kommentar pÃ¥ ".JLOG_WEBSITE."\nRubriken var:", +"comments_posted" => "skriven", +"comments_mailsubject" => "Kommentar pÃ¥ ".JLOG_WEBSITE, + +"comments_comment_topic" => "Kommentarer", +"comments_by" => "Kommentar frÃ¥n", +"comments_name" => "Namn", +"comments_city" => "Stad / Land", +"comments_email" => "e-post", +"comments_homepage" => "http://", +"comments_bbcode" => "Hur använder jag", +"comments_send" => "Skicka", +"comments_preview" => "Förhandsgranskning", +"comments_no_sid" => "Det verkar ha skett en manipulation", +"comments_false_mail" => "E-postadressen ser inte korrekt ut", +"comments_notext" => "Ingen text har skrivits", +"comments_false_hp" => "Kontrollera att rätt URL har angivits", +"comments_anonym" => "Anonym", +"comments_permalink" => "Permanent länk till denna kommentar", +"comments_from" => "frÃ¥n", +"comments_posted" => "skrev den", +"comments_entryform" => "Din kommentar", +"comments_mail_by_comment" => "Underrätta vid kommentar", +"comments_thx" => "Kommentaren blev uppdaterat.", +"comments_preview" => "Förhandsgranskning", +"comments_bold" => "fet", +"comments_italic" => "kursiv", +"comments_quote" => "citera", +"comments_url" => "länk", +"comments_updated" => "Kommentaren har uppdaterats. GÃ¥ tillbaks till", +"comments_admin" => "Kommentar-administationscenter", +"comments_plz_format_txt" => "Vänligen ange texten som ska formateras", +"comments_url_href" => "Ange länkmÃ¥l:", +"comments_url_node" => "Ange länktext:", +"comments_closed" => "Kommentarerna är stängda för detta inlägg.", + +"m_title" => "Huvudinställningar", +"m_clean_url" => "Ska rena URLer (mod_rewrite) användas? Exempel: http://example.com/2005/01/firefox", +"m_metadata" => "Metadata", +"m_language" => "Din webbloggs sprÃ¥k", +"m_website" => "Webbloggs namn", +"m_publisher" => "Författarens namn", +"m_admin_password" => "Administrationcenter lösenord", +"m_admin_password_again" => "Bekräfta lösenordet", +"m_admin_password_admin" => "(lämna blank för att inte ändra)", +"m_email" => "Författarens e-postadress", +"m_description" => "En kort introduktion om bloggen", +"m_bs" => "Notifera webblogg-services om nya inlägg sÃ¥ de kan lägga till den i sin sökmotor (en service per linje)", +"m_bs_weblogs_com" => "weblogs.com", +"m_bs_technorati_com" => "technorati.com", +"m_bs_blogg_de" => "blogg.de", +"m_behavior" => "Webbloggbeteende", +"m_max_blog_orginal" => "Hur mÃ¥nga inlägg ska visas komplett pÃ¥ startsidan?", +"m_max_blog_big" => "Hur mÃ¥nga inlägg ska visas som ingress pÃ¥ startsidan?", +"m_max_blog_small" => "Hur mÃ¥nga inlägg ska visas som en lista med rubrik och datum pÃ¥ startsidan?", +"m_sub_current" => "Hur mÃ¥nga inlägg ska visas i subnavigationen?", +"m_info_by_comment" => "E-post till författaren att en ny kommentar har inkommit", +"m_database" => "Databas", +"m_db" => "Databasens namn", +"m_db_url" => "Databasens hostnamn, oftast localhost", +"m_db_user" => "Databasens användarnamn", +"m_db_pwd" => "Databasens lösenord", +"m_db_prefix" => "Kort identifikation som prefix pÃ¥ tabellnamn i databasen", +"m_date" => "Datumformat (en formatsträng som i PHP-funktionen strftime())", +"m_date_posting" => "för inlägg", +"m_date_comment" => "för kommentarer", +"m_date_subcurrent" => "för subnavigationen", +"m_settings_ok" => "Dina inställningar har sparats.", + +"e_path" => "URLen verkar fel.", +"e_basepath" => "Katalogen existerar inte.", +"e_website" => "Skriv in bloggens namn.", +"e_publisher" => "Skriv in författarens namn.", +"e_admin_password" => "Skriv in lösenordet till administrationscentret.", +"e_admin_password_again" => "Skriv in lösenordet en gÃ¥ng till för att verifiera den.", +"e_email" => "E-postadressen verkar fel.", +"e_description" => "Skriv in en kort beskrivning om bloggen.", +"e_max_blog_orginal" => "Antal av inlägg som ska visas komplett pÃ¥ startsidan mÃ¥sta vara noll eller mer.", +"e_max_blog_big" => "Antal av inlägg som ska visas som ingress pÃ¥ startsidan mÃ¥sta vara noll eller mer.", +"e_max_blog_small" => "Antal av inlägg som ska visas som en lista med rubrik och datum pÃ¥ startsidan mÃ¥sta vara noll eller mer.", +"e_sub_current" => "Antal av inlägg som ska visas som en lista med rubrik och datum i subnavigationen mÃ¥sta vara noll eller mer.", +"e_start_year" => "Gömda fälten för Ã¥ret är tom.", +"e_db" => "Skriv in databasens namn.", +"e_db_url" => "Skriv in databasens hostnamn.", +"e_db_user" => "Skriv in databasens användernamn.", +"e_db_occurred" => "Databas fel", +"e_db_is" => "Ett fel har uppstÃ¥tt pÃ¥ ".JLOG_PATH.". Det är:", + +"s_phpv_tolow" => "Din PHP-version är för gammal, vänligen uppgradera till en nyare eller be din serveradministratör att göra det.", +"s_mysqlv_tolow" => "Din MYSQL-version är för gammal, vänligen uppgradera till en nyare eller be din serveradministratör att göra det.", +"s_personal_not_wrtbl" => "Det gÃ¥r inte att skriva i katalogen 'personal'. (Chmod 777)", +"s_img_not_wrtbl" => "Det gÃ¥r inte att skriva i katalogen 'img'. (Chmod 777)", +"s_tables_ok" => "Tabellerna i databasen har skapats.", +"s_ready_head" => "Bloggen har installerats.", +"s_ready" => "Grattis! Nu kan du börja skriva i administrationscenter", +"s_ready_menu_admin" => "Till administrationscenter", +"s_ready_menu_home" => "Till startsidan", +"s_problem_fwrite" => "Ett problem uppstod medan nödvändiga filer skapades.", +"s_problem_chmod" => "Ett problem uppstod medan rättigheterna till de nödvändiga filerna ändrades.", +"s_personal_ok" => "Filer i katalogen 'personal' skapades.", +"s_install" => "Installera nu!", + +"login_headline" => "Administrationscenter", +"login_password" => "Skriv in ditt lösenord:", +"login_send" => "Logga in", +"login_cookies" => "Notera: Du mÃ¥ste ha cookies pÃ¥ i din webbläsare!", +"login_false_pw" => "Fel lösenord.", + +"cat_name" => "Kategoriens namn", +"cat_url" => "URL i kategoriarkivet (bara a-z 0-9 _-,. )", +"cat_description" => "Kategoribeskrivning som visas i arkivet", +"cat_new" => "Skapa ny kategori", +"cat_title" => "Kategorimanagement", +"cat_noname" => "Kategorien mÃ¥ste ha ett namn.", +"cat_change" => "Ändra kategoriens data", +"cat_new_ok" => "Ny kategori har skapats.", +"cat_really_trash" => "Är du säker att du vill radera kategorien?", +"cat_trash_ok" => "Kategorien blev raderat. Tillbacks till", +"cat_admincenter" => "Kategori administrationscenter", +"cat_duplicate" => "En annan kategori använder redan samma URL.", + +"update_successfull" => "Uppdateringen lyckades. Ha sÃ¥ kul!", +"pingback_closed" => "Avaktivera pingbacks för detta inlägg.", + +"plugin_no_content" => "Man behöver inte administrera pluginet.", +"plugins_h_not_avaliable" => "Inga plugins hittades", +"plugins_not_avaliable" => "Jag kunde inte hitta nÃ¥got plugin.", +"plugins_headline" => "Plugin administration", + +// Do not change the folowing line! +); + +// eof \ No newline at end of file diff --git a/lang/lang.de.inc.php b/lang/lang.de.inc.php new file mode 100644 index 0000000..b614caa --- /dev/null +++ b/lang/lang.de.inc.php @@ -0,0 +1,121 @@ + "Herzlich Willkommen", +"subnav_current" => "Aktuelle Einträge", +"subnav_info" => "Informationen", +"subnav_rss" => "Aktuelles von dieser Seite per RSS Feed. Mehr darüber erfahren Sie auf der Seite von Alp Uçkan.", +"subnav_copyright" => "Alle Rechte vorbehalten.", +"subnav_powered" => "Powered by", + +"content_posted" => "geschrieben am", +"content_more" => "weiterlesen", +"content_more_title" => "Ganzen Eintrag lesen", +"content_permalink" => "permanenter Link zu diesem Eintrag", +"content_posted" => "Eingestellt am", +"content_archive" => "Ältere Weblogeinträge gibt es im", +"content_archivelink" => "Archiv", +"content_archive_header" => "Archivierte Einträge", +"content_categories_header"=> "Kategorie", +"content_skip" => "Zum Hauptinhalt springen.", +"content_choose_year" => "Das Jahr wählen:", +"content_search_header" => "Suche auf der Webseite", +"content_search" => "suchen", +"content_nothing_found" => "Es wurden 0 Ergebnisse gefunden. Vorschläge:
    • Überprüfen Sie die Schreibweise.
    • Suchen Sie mit anderen bzw. weniger Schlüsselwörtern.
    • Entfernen Sie Frage- oder Pluszeichen.
    ", +"content_search_topic" => "Weblog durchsuchen", +"content_from" => "von", +"content_comments" => "Kommentare", +"content_comment_plz" => "kommentieren", +"content_comments_title" => "zu Kommentaren springen", +"content_cat_linklist" => "zugeordnete Kategorien", +"content_cat_link" => "Alle Einträge dieser Kategorie anzeigen", +"content_categorieslist_h" => "Kategorien", +"content_archive_preview" => "Vorherige Seite", +"content_archive_next" => "Nächste Seite", + +"meta_start" => "Zurück zur Startseite", +"meta_search" => "Suche", +"meta_copyright" => "Urheberrecht", + +"comments_comment_topic" => "Kommentare", +"comments_by" => "Kommentar von", +"comments_name" => "Name", +"comments_city" => "Stadt / Land", +"comments_email" => "E-Mail", +"comments_homepage" => "http://", +"comments_bbcode" => "Wie benutze ich", +"comments_send" => "Absenden", +"comments_preview" => "Vorschau", +"comments_no_sid" => "Es scheint eine Manipulation vorzuliegen", +"comments_false_mail" => "Die E-Mail Adresse sieht nicht richtig aus", +"comments_notext" => "Es wurde kein Text eingegeben", +"comments_false_hp" => "Die URL zur Homepage scheint falsch zu sein", +"comments_anonym" => "Anonym", +"comments_permalink" => "Permanenter link zu diesem Kommentar", +"comments_from" => "aus", +"comments_posted" => "schrieb am", +"comments_entryform" => "Dein Kommentar", +"comments_save_data" => "Userdaten in einem Cookie sichern", +"comments_mail_by_comment" => "Bei Kommentar benachrichtigen", +"comments_duplicate" => "Aus versehen wurde das Formular zwei mal abgesandt", +"comments_thx" => "Danke - Der Kommentar wurde gespeichert", +"comments_mailsubject" => "Kommentar auf ".JLOG_WEBSITE, +"comments_mail_txt" => "Neuer Kommentar auf ".JLOG_WEBSITE."\nDer Titel war: ", +"comments_stop_receiving" => "Um die Benachrichtigung bei neuen Kommentaren abzustellen klicken Sie hier:", +"comments_stop_successful" => "Die Benachrichtigung wurde abgestellt.", +"comments_preview" => "Vorschau", +"comments_send" => "Senden", +"comments_show" => "Kommentare anzeigen", +"comments_hide" => "Kommentare verstecken", +"comments_bold" => "fett", +"comments_italic" => "kursiv", +"comments_quote" => "Zitat", +"comments_url" => "Link", +"comments_plz_format_txt" => "Bitte gebe den zu formatierenden Text ein:", +"comments_url_href" => "Linkziel eingeben:", +"comments_url_node" => "Linktext eingeben:", +"comments_closed" => "Die Kommentare sind für diesen Eintrag geschlossen.", +"comments_teaser_closed" => "(Kommentare geschlossen)", +"pingback_topic" => "Pingbacks", + +"db_error" => "Datenbankfehler", +"plz_try_again" => "Bitte versuchen Sie es später noch einmal.", + +"error" => "Fehler", +"err404_topic" => "Fehler 404 - Seite nicht gefunden", +"err404_message" => "Diese Seite existiert leider nicht. Versuchen Sie sie über die Suchfunktion zu finden.", + +"language" => "de-de", +"locale" => array('de_DE.UTF-8', 'de_DE.UTF-8@euro', 'de_DE'), +"date_format" => "%d. %B %Y um %H:%M Uhr", +"date_format_comment" => "%d.%m.%Y", +"date_format_subcurrent" => "%d.%m.%Y", + +"index_topic" => "Startseite", +"bbtitle" => "BBcode nutzen", +"bbxmp" => "
    • Zeilenumbrüche werden automatisch erzeugt und man kann die Codeschnipsel auch kombinieren.
    • +
    • [url]http://example.com[/url]
    • +
    • [url=http://example.com]Beispiellink[/url]
    • +
    • [b]fett[/b]
    • +
    • [i]kursiv[/i]
    • +
    • [quote]Ein zitierter Text welcher aus einer anderen Quelle stammt. Es empfiehlt sich die Quelle auch mit anzugeben.[/quote]

    ", + +// do not change the following line +"months" => array ( +// here you can change the months for the archive +1 => "Januar", +2 => "Februar", +3 => "März", +4 => "April", +5 => "Mai", +6 => "Juni", +7 => "Juli", +8 => "August", +9 => "September", +10 => "Oktober", +11 => "November", +12 => "Dezember" + +// do not change the folowing lines + ) +); ?> diff --git a/lang/lang.en.inc.php b/lang/lang.en.inc.php new file mode 100644 index 0000000..49ce8d6 --- /dev/null +++ b/lang/lang.en.inc.php @@ -0,0 +1,122 @@ + "Welcome", +"subnav_current" => "Recent weblog entries", +"subnav_info" => "Information", +"subnav_rss" => "Recent weblogentries as a RSS feed. Read more about RSS on mezzoblue.com.", +"subnav_copyright" => "All rights reserved.", +"subnav_powered" => "Powered by", + +"content_posted" => "posted on", +"content_more" => "read more", +"content_more_title" => "read the whole entry", +"content_permalink" => "permanent link for this article", +"content_posted" => "Posted on", +"content_archive" => "You can find older weblog entries in the", +"content_archivelink" => "archive", +"content_archive_header" => "Archive", +"content_categories_header"=> "Category", +"content_skip" => "skip to maincontent", +"content_choose_year" => "Choose the year:", +"content_search_header" => "Search the weblog", +"content_search" => "search", +"content_nothing_found" => "We found 0 results. Suggestions:
    • Check your spelling.
    • Try different or fewer keywords.
    • Remove quotation marks or plus signs.
    ", +"content_search_topic" => "Search this weblog", +"content_from" => "from", +"content_comments" => "Comments", +"content_comment_plz" => "comment", +"content_comments_title" => "skip to comments", +"content_cat_linklist" => "assigned categories", +"content_cat_link" => "Show all entries to this category", +"content_categorieslist_h" => "Categories", +"content_archive_preview" => "previous page", +"content_archive_next" => "next page", + +"meta_start" => "back to homepage", +"meta_search" => "Search", +"meta_copyright" => "Copyright", + +"comments_comment_topic" => "Comments", +"comments_by" => "Comment by", +"comments_name" => "name", +"comments_city" => "city / country", +"comments_email" => "email", +"comments_homepage" => "http://", +"comments_bbcode" => "How to use", +"comments_send" => "send", +"comments_preview" => "preview", +"comments_no_sid" => "There must be some manipulation", +"comments_false_mail" => "email address looks wrong", +"comments_notext" => "you have to write some text", +"comments_false_hp" => "Homepage URL looks wrong", +"comments_anonym" => "Anonymous", +"comments_permalink" => "permalink to this comment", +"comments_from" => "from", +"comments_posted" => "wrote on", +"comments_entryform" => "Your comment", +"comments_save_data" => "save userdata in a cookie", +"comments_mail_by_comment" => "mail me in case of a new comment", +"comments_duplicate" => "form was send twice by mistake", +"comments_thx" => "Thanks - Your comment was saved", +"comments_mailsubject" => "New comment on ".JLOG_WEBSITE, +"comments_mail_txt" => "Someone just responded to the entry you subscribed to at: ".JLOG_WEBSITE."\nThe title of the entry was: ", +"comments_stop_receiving" => "To stop receiving notifications for this comment, click here:", +"comments_stop_successful" => "Stopping receiving notifications was successful.", +"comments_preview" => "preview", +"comments_send" => "send", +"comments_show" => "show comments", +"comments_hide" => "hide comments", +"comments_bold" => "bold", +"comments_italic" => "italic", +"comments_quote" => "quote", +"comments_url" => "link", +"comments_plz_format_txt" => "Please enter your Text:", +"comments_url_href" => "enter linktarget:", +"comments_url_node" => "enter linktext:", +"comments_closed" => "Comments are closed for this entry.", +"comments_teaser_closed" => "(Comments closed)", +"pingback_topic" => "Pingbacks", + +"db_error" => "Database error", +"plz_try_again" => "Please try again later.", + +"error" => "Error", +"err404_topic" => "error 404", +"err404_message" => "There is no such page. Please try the search engine on this page.", + +"language" => "en-gb", +"locale" => array( "en_US", "us", "verUS" ), +"date_format" => "%d. %B %Y um %H:%M Uhr", +"date_format_comment" => "%d.%m.%Y", +"date_format_subcurrent" => "%d.%m.%Y", + +"index_topic" => "Homepage and News", +"bbtitle" => "Using BBcode", +"bbxmp" => "

    Linebreakes are automaticly transformed. Notice that you can combine this code snippets.

    +

    [url]http://example.com[/url]

    +

    [url=http://example.com]example link[/url]

    +

    [b]bold[/b]

    +

    [i]italic[/i]

    +

    [quote]A quoted text from an other source. Pleace add the + source as a link.[/quote]

    ", + +// do not change the following line +"months" => array ( +// here you can change the months for the archive +1 => "January", +2 => "February", +3 => "March", +4 => "April", +5 => "May", +6 => "June", +7 => "July", +8 => "August", +9 => "September", +10 => "October", +11 => "November", +12 => "December" + +// do not change the folowing lines + ) +); ?> diff --git a/lang/lang.it.inc.php b/lang/lang.it.inc.php new file mode 100644 index 0000000..692aea7 --- /dev/null +++ b/lang/lang.it.inc.php @@ -0,0 +1,121 @@ + "Benvenuti", +"subnav_current" => "Recenti note nel weblog ", +"subnav_info" => "Informazioni", +"subnav_rss" => "Recenti note nel weblog as a RSS feed. Leggi di più riguardo RSS in mezzoblue.com.", +"subnav_copyright" => "Tutti i diritti sono riservati.", +"subnav_powered" => "Powered by", + +"content_posted" => "Pubblicato il", +"content_more" => "Leggi di più", +"content_more_title" => "Leggi l'intera nota", +"content_permalink" => "Link permanente per questo aricolo", +"content_posted" => "Pubblicato il", +"content_archive" => "Puoi trovare vecchie note weblog in ", +"content_archivelink" => "Archivio", +"content_archive_header" => "Archivio", +"content_categories_header"=> "Categoria", +"content_skip" => "vai ai contenuti principali", +"content_choose_year" => "Sciegli l'anno:", +"content_search_header" => "Cerca il weblog", +"content_search" => "Cerca", +"content_nothing_found" => "Sono stati trovato 0 risultati.Suggerimento:
    • Controlla l'ortografia.
    • Prova con una differente parola chiave.
    • Cancellare virgolette o segno più.
    ", +"content_search_topic" => "Cerca questo weblog", +"content_from" => "da", +"content_comments" => "Commenti", +"content_comment_plz" => "Commenti", +"content_comments_title" => "vai ai commenti", +"content_cat_linklist" => "Categorie assegnate", +"content_cat_link" => "Mostra tutte le note di questa categoria", +"content_categorieslist_h" => "Categorie", +"content_archive_preview" => "Pagina precedente", +"content_archive_next" => "Prossima pagina", + +"meta_start" => "Vai alla homepage", +"meta_search" => "Cerca", +"meta_copyright" => "Copyright", + +"comments_comment_topic" => "Commenti", +"comments_by" => "Commento di", +"comments_name" => "Nome", +"comments_city" => "Città/ Paese", +"comments_email" => "e-mail", +"comments_homepage" => "http://", +"comments_bbcode" => "Come si usa", +"comments_send" => "Invia", +"comments_preview" => "Anteprima", +"comments_no_sid" => "Stai manipolando qualcosa!", +"comments_false_mail" => "L'indirizzo e-mail non è corretto", +"comments_notext" => "Devi scrivere qualcosa", +"comments_false_hp" => "Homepage URL non corretta", +"comments_anonym" => "Anonimo", +"comments_permalink" => "permalink per questo commento", +"comments_from" => "da", +"comments_posted" => "Scritto il", +"comments_entryform" => "Tuo commento", +"comments_save_data" => "Salva userdata in cookie", +"comments_mail_by_comment" => "Inviami una e-mail in caso di nuovi commenti", +"comments_duplicate" => "Nota spedita due volte", +"comments_thx" => "Grazie - Il tuo commento è stato salvato", +"comments_mailsubject" => "Nuovo commento in ".JLOG_WEBSITE, +"comments_mail_txt" => "Qualcuno ha risposto alla tua nota: ".JLOG_WEBSITE."\nIl titolo della nota era: ", +"comments_stop_receiving" => "Per non ricevere piu notifiche riguardo questo commento, clicca qui:", +"comments_stop_successful" => "Notifice annullate con successo.", +"comments_preview" => "Anteprima", +"comments_send" => "Invia", +"comments_show" => "Visualizza commenti", +"comments_hide" => "Nascondi commenti", +"comments_bold" => "Grassetto", +"comments_italic" => "Corsivo", +"comments_quote" => "Cita espressione", +"comments_url" => "link", +"comments_plz_format_txt" => "Perfavore inserire il testo:", +"comments_url_href" => "Inserire linktarget:", +"comments_url_node" => "Inserire linktext:", +"comments_closed" => "I commenti sono chiusi per questa nota.", +"comments_teaser_closed" => "(Commenti stop)", +"pingback_topic" => "Pingbacks", + +"db_error" => "Errore database", +"plz_try_again" => "Riprovare più tardi, grazie.", + +"error" => "Errore", +"err404_topic" => "Errore 404", +"err404_message" => "Non ci sono file riguardanti la ricerca in questa pagina. Perfavore prova a usare il motore di ricerca di questa pagina.", + +"language" => "it-it", +"locale" => array( "it_IT", "it" ), +"date_format" => "%d. %B %Y alle %H:%M", +"date_format_comment" => "%d.%m.%Y", +"date_format_subcurrent" => "%d.%m.%Y", + +"index_topic" => "Homepage e News", +"bbtitle" => "Usare BBcode", +"bbxmp" => "

    Linebreakes sono trasformate automaticamente. Nota che puoi combinare i pezzi del codice.

    +

    [url]http://example.com[/url]

    +

    [url=http://example.com]example link[/url]

    +

    [b]Grassetto[/b]

    +

    [i]Corsivo[/i]

    +

    [quote]La citazione providene da un altra sorgente. Perfavore aggiungi la sorgente .[/quote]

    ", + +// do not change the following line +"months" => array ( +// here you can change the months for the archive +1 => "Gennaio", +2 => "Febbraio", +3 => "Marzo", +4 => "Aprile", +5 => "Maggio", +6 => "Giugno", +7 => "Luglio", +8 => "Agosto", +9 => "Settembre", +10 => "Ottobre", +11 => "Novembre", +12 => "Dicembre" + +// do not change the folowing lines + ) +); ?> diff --git a/lang/lang.pl.inc.php b/lang/lang.pl.inc.php new file mode 100644 index 0000000..94f5ef6 --- /dev/null +++ b/lang/lang.pl.inc.php @@ -0,0 +1,122 @@ + "Witamy", +"subnav_current" => "Ostatnie wartki", +"subnav_info" => "Informacja", +"subnav_rss" => "Ostatnie wartki jako RSS. Przeczytaj wiecej o RSS na mezzoblue.com.", +"subnav_copyright" => "Wszystkie prawa zastrzezone.", +"subnav_powered" => "Powered by", + +"content_more" => "przeczytaj więcej", +"content_more_title" => "przeczytaj cały wartek", +"content_permalink" => "permanentny link dla tego wartku", +"content_posted" => "Pisany", +"content_archive" => "Starsze wartki znajdżesz w", +"content_archivelink" => "archiwum", +"content_archive_header" => "Archiwum", +"content_categories_header"=> "Kategoria", +"content_skip" => "przejdz do tekstu", +"content_choose_year" => "Wybierz rok:", +"content_search_header" => "Przeszukaj weblog", +"content_search" => "szukaj", +"content_nothing_found" => "Znaleziono 0 wyników. Sugestie:
    • Sprawdz czy poprawnie wpisaÅ‚es wyszukiwanÄ… frazÄ™.
    • Wprowadz inne lub mniej słów.
    • UsuÅ„ cudzysłów lub znak plus.
    ", +"content_search_topic" => "Przeszukaj ten weblog", +"content_from" => "od", +"content_comments" => "Komentarze", +"content_comment_plz" => "komentarz", +"content_comments_title" => "przejdź do komentarzy", +"content_cat_linklist" => "przyznaczone kategorie", +"content_cat_link" => "Pokaż wszystkie wartki tej kategori", +"content_categorieslist_h" => "Kategorie", +"content_archive_preview" => "poprzednia strona", +"content_archive_next" => "następna strona", + +"meta_start" => "powrót do strony glównej", +"meta_search" => "Szukaj", +"meta_copyright" => "Prawa autorskie", + +"comments_comment_topic" => "Komentarze", +"comments_by" => "Komentowane przez", +"comments_name" => "imię", +"comments_city" => "miejscowość / kraj", +"comments_email" => "emaila", +"comments_homepage" => "http://", +"comments_bbcode" => "Jak używać", +"comments_send" => "wyślij", +"comments_preview" => "podgląd", +"comments_no_sid" => "Coś jest nie tak, wygląda na manipulacje", +"comments_false_mail" => "adres emaila jest niepoprawny", +"comments_notext" => "trzeba napisac jakiś tekst", +"comments_false_hp" => "URL strony glównej jest niepoprawny", +"comments_anonym" => "Anonim", +"comments_permalink" => "link permanentny do tego komentarza", +"comments_from" => "od", +"comments_posted" => "pisany", +"comments_entryform" => "Twój komentarz", +"comments_save_data" => "zapisz dane uzytkownika w cookie", +"comments_mail_by_comment" => "zawiadom mnie gdy pojawi się nowy komentarz", +"comments_duplicate" => "formularz został wysłany przez pomyłkę", +"comments_thx" => "Dziekujemy - Twój komentarz został zachowany", +"comments_mailsubject" => "Nowy komentarz na ".JLOG_WEBSITE, +"comments_mail_txt" => "Ktoś napisał komentarz na: ".JLOG_WEBSITE."\n Tytół wartku był: ", +"comments_stop_receiving" => "Aby przestać otrzymywać notyfikacje kliknij tutaj:", +"comments_stop_successful" => "Notyfikacje zostaly zatżymane.", +"comments_preview" => "podglad", +"comments_send" => "wyślij", +"comments_show" => "pokaż komentarze", +"comments_hide" => "ukryj komentarze", +"comments_bold" => "bold", # TODO +"comments_italic" => "italic", # TODO +"comments_quote" => "quote", # TODO +"comments_url" => "link", +"comments_plz_format_txt" => "Prosze wprowadzić swój tekst:", +"comments_url_href" => "wprowadź url:", +"comments_url_node" => "wprowadź text:", +"comments_closed" => "Na tym wartku komentarze zostały zamknięte.", +"comments_teaser_closed" => "(Zamknięte komentarze)", +"pingback_topic" => "Pingbaki", + +"db_error" => "Błąd bazy danych", +"plz_try_again" => "Prosze ponownie spróbować później.", + +"error" => "Błąd", +"err404_topic" => "błąd 404", +"err404_message" => "Nie ma takiej strony. Prosze użyć przeglądarki na tej stronie.", + +"language" => "en-gb", +"locale" => array( "en_US", "us", "verUS" ), +"date_format" => "%d. %B %Y um %H:%M Uhr", +"date_format_comment" => "%d.%m.%Y", +"date_format_subcurrent" => "%d.%m.%Y", + +"index_topic" => "Strona glówna", +"bbtitle" => "Urzywanie BBcode", +"bbxmp" => "

    Linebreakes are automaticly transformed. Notice that you can combine this code snippets.

    +

    [url]http://example.com[/url]

    +

    [url=http://example.com]example link[/url]

    +

    [b]bold[/b]

    +

    [i]italic[/i]

    +

    [quote]A quoted text from an other source. Pleace add the + source as a link.[/quote]

    ", + +// do not change the following line +"months" => array ( +// tutaj mozna zmienic miesiace for the archive +1 => "Styczen", +2 => "Luty", +3 => "Marzec", +4 => "Kwiecien", +5 => "Maj", +6 => "Czerwiec", +7 => "Lipiec", +8 => "Śierpień", +9 => "Wrzesień", +10 => "Październik", +11 => "Listopad", +12 => "Grudzień" + +// do not change the folowing lines + ) +); +// eof \ No newline at end of file diff --git a/lang/lang.sv.inc.php b/lang/lang.sv.inc.php new file mode 100644 index 0000000..2213030 --- /dev/null +++ b/lang/lang.sv.inc.php @@ -0,0 +1,121 @@ + "Välkommen", +"subnav_current" => "Aktuella inlägg", +"subnav_info" => "Information", +"subnav_rss" => "Aktuellt från denna sida via RSS Feed. Mer info om detta hittar du på http://susning.nu/RSS.", +"subnav_copyright" => "Alla rättigheter förbehållna", +"subnav_powered" => "Powered by", + +"content_posted" => "skrivet den", +"content_more" => "läs mer", +"content_more_title" => "Läs hela webbloginlägget", +"content_permalink" => "permanent länk till detta webbloginlägg", +"content_posted" => "Inlagt den", +"content_archive" => "Äldre webbloginlägg finns i", +"content_archivelink" => "Arkiv", +"content_archive_header" => "Arkiverade inlägg", +"content_categories_header"=> "Kategori", +"content_skip" => "Hoppa till huvudinnehåll.", +"content_choose_year" => "Välj år:", +"content_search_header" => "Sök på webbsidan", +"content_search" => "sök", +"content_nothing_found" => "Antal träffar: 0. Förslag: :
    • Kontrollera stavningen.
    • Sök med andra eller färre nyckelord.
    • Radera frÃ¥ge- eller plustecken.
    ", +"content_search_topic" => "Sök igenom webblog", +"content_from" => "från", +"content_comments" => "Kommentarer", +"content_comment_plz" => "kommentera", +"content_comments_title" => "hoppa till kommentarer", +"content_cat_linklist" => "tilldelade kategorier", +"content_cat_link" => "Visa alla inlägg ur denna kategori", +"content_categorieslist_h" => "Kategorier", +"content_archive_preview" => "Föregående sida", +"content_archive_next" => "Nästa sida", + +"meta_start" => "Tillbaka till startsidan", +"meta_search" => "Genomsöker", +"meta_copyright" => "Upphovsrätt", + +"comments_comment_topic" => "Kommentarer", +"comments_by" => "Kommentar från", +"comments_name" => "Namn", +"comments_city" => "Stad / Land", +"comments_email" => "E-mail", +"comments_homepage" => "http://", +"comments_bbcode" => "Hur använder jag", +"comments_send" => "Skicka", +"comments_preview" => "Förhandsgranskning", +"comments_no_sid" => "Det verkar ha skett en manipulation", +"comments_false_mail" => "E-mailadressen ser inte korrekt ut", +"comments_notext" => "Ingen text har skrivits", +"comments_false_hp" => "Kontrollera att rätt URL har angivits", +"comments_anonym" => "Anonym", +"comments_permalink" => "Permanent länk till denna kommentar", +"comments_from" => "från", +"comments_posted" => "skrev den", +"comments_entryform" => "Din kommentar", +"comments_save_data" => "Spara användarinställningar", +"comments_mail_by_comment" => "Underrätta vid kommentar", +"comments_duplicate" => "Formuläret skickades av misstag två gånger", +"comments_thx" => "Tack - Kommentaren har sparats", +"comments_mailsubject" => "Kommentar på ".JLOG_WEBSITE, +"comments_mail_txt" => "Ny kommentar på ".JLOG_WEBSITE."\nTiteln var: ", +"comments_stop_receiving" => "För att avaktivera underrättelsen vid nya kommentarer, klicka här:", +"comments_stop_successful" => "Underrättelsen har avaktiverats", +"comments_preview" => "Förhandsgranskning", +"comments_send" => "Skicka", +"comments_show" => "visa kommentarer", +"comments_hide" => "dölj kommentarer", +"comments_bold" => "fet", +"comments_italic" => "kursiv", +"comments_quote" => "citera", +"comments_url" => "länk", +"comments_plz_format_txt" => "Vänligen ange texten som ska formateras", +"comments_url_href" => "Ange länkmål:", +"comments_url_node" => "Ange länktext:", +"comments_closed" => "Kommentarerna är stängda för detta inlägg.", +"comments_teaser_closed" => "(Kommentarer stängda)", +"pingback_topic" => "Pingbacks", + +"db_error" => "Databasfel", +"plz_try_again" => "Var god försök igen senare.", + +"error" => "Error", +"err404_topic" => "Error 404 - Sidan hittades inte", +"err404_message" => "Denna sida existerar tyvärr inte. Försök hitta den genom sökfunktionen.", + +"language" => "sv-se", +"locale" => array('sv_SE', 'sve_sve'), +"date_format" => "%Y-%B-%d kl %H:%M", +"date_format_comment" => "%Y-%m-%d", +"date_format_subcurrent" => "%Y-%m-%d", + +"index_topic" => "Startsida", +"bbtitle" => "Använd BBcode", +"bbxmp" => "
    • Radbrytning sker automatiskt och man kan även kombinera kodstyckena.
    • +
    • [url]http://example.com[/url]
    • +
    • [url=http://example.com]Exempellänk[/url]
    • +
    • [b]fet[/b]
    • +
    • [i]kursiv[/i]
    • +
    • [quote]Ett citat ur en annan källtext. Det rekommenderas att även ange denna.[/quote]

    ", + +// do not change the following line +"months" => array ( +// here you can change the months for the archive +1 => "januari", +2 => "februari", +3 => "mars", +4 => "april", +5 => "maj", +6 => "juni", +7 => "juli", +8 => "august", +9 => "september", +10 => "oktober", +11 => "november", +12 => "december" + +// do not change the folowing lines + ) +); ?> diff --git a/learn_bb.php b/learn_bb.php new file mode 100644 index 0000000..c9abcde --- /dev/null +++ b/learn_bb.php @@ -0,0 +1,27 @@ + + + ".$l['bbtitle']." + + + +

    ".$l['bbtitle']."

    + ".$l['bbxmp']." + + "; +} + +else { + $c['title'] = $l['bbtitle']; + $c['main'] = $l['bbxmp']; + +require(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'do_template.php'); +echo $body; + +} +?> diff --git a/log.php b/log.php new file mode 100644 index 0000000..b0b48f5 --- /dev/null +++ b/log.php @@ -0,0 +1,308 @@ +error()) { + echo "
    \n";
    +        echo $blog->getError();
    +        echo "
    \n"; + die(); + } + + if($blog->numRows() == 0) { + header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found"); + include_once(JLOG_BASEPATH."error404.php"); + exit; + } +} +else { + header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found"); + include_once(JLOG_BASEPATH."error404.php"); + exit; +} + + +$blogentry = $blog->fetch(); + +// get comments from Database + +$sql_comments = "SELECT + id, sid, name, city, email, homepage, + content, UNIX_TIMESTAMP(date) AS date, + reference, mail_by_comment, type + FROM ".JLOG_DB_COMMENTS." + WHERE reference = '".$blogentry['id']."' + ORDER BY date;"; + +$c['meta']['date'] = $blogentry['metadate']; +$c['meta']['description'] = strip_tags($bbcode->parse($blogentry['teaser'])); +$c['meta']['keywords'] = $blogentry['keywords']; +$c['meta']['title'] = $blogentry['topic']; +$c['meta']['pingback'] = true; + +$c['main'] = do_entry($blogentry); + +// Form entry + +$com_form = strip($_POST); +if(!isset($com_form['type'])) $com_form['type'] = ""; +$error = com_check_errors($com_form); + +// Preview +if(isset($com_form['form_submitted']) AND $com_form['form_submitted'] === $l['comments_preview']) { + + $comments = new Query($sql_comments); + if($comments->error()) { + echo "
    \n";
    +        echo $comments->getError();
    +        echo "
    \n"; + die(); + } + + $commentsArray = array(); + $countComments = 0; + while($commentsArray[] = $comments->fetch()); + + foreach($commentsArray as $tmp_comment) if($tmp_comment['type'] != 'pingback') ++$countComments; + + $preview = ""; + if(isset($error)) $preview .= error_output($error); + $clear_form = com_clean_data($com_form); + $clear_form['id'] = ""; + + ### Plugin Hook + $clear_form = $plugins->callHook('previewComment', $clear_form, $blogentry); + + $preview .= "
      + ".do_comment($clear_form, $countComments)." +
    "; + + $c['form_content'] .= $preview; + $c['form_content'] .= com_form_output($com_form).com_javascript_variables(); +} + +// Send data to DB +elseif(isset($com_form['form_submitted']) AND $com_form['form_submitted'] == $l['comments_send'] AND $blogentry['comments'] == 1) { + + if(isset($error)) { + + $c['form_content'] .= error_output($error); + $c['form_content'] .= com_form_output($com_form).com_javascript_variables(); + } + else { + // Send comment + + $com_form = com_clean_data($com_form); + + ### Plugin Hook + $com_form = $plugins->callHook('newComment', $com_form, $blogentry); + + $com = escape_for_mysql($com_form); + if(!isset($com['mail_by_comment'])) $com['mail_by_comment'] = ""; + + $sql = "INSERT INTO ".JLOG_DB_COMMENTS." ( + sid, + name, + city, + email, + homepage, + content, + reference, + mail_by_comment, + date, + type + ) + VALUES ( + '".$com['sid']."', + '".$com['name']."', + '".$com['city']."', + '".$com['email']."', + '".$com['homepage']."', + '".$com['content']."', + '".$blogentry['id']."', + '".$com['mail_by_comment']."', + NOW(), + '".$com['type']."' + )"; + + $newcomment = new Query($sql); + $cid = mysql_insert_id(); + if($newcomment->error()) { + if($newcomment->getErrno() == 1062) { + $errors[] = $l['comments_duplicate']; + $c['form_content'] .= error_output($errors, 'entryform').com_javascript_variables(); + } + else { + echo "
    \n";
    +                 echo $newcomment->getError();
    +                 echo "
    \n"; + die(); + } + } + else { + if(isset($com_form['cookie']) AND $com_form['cookie'] == 1) set_cookie($com_form); + else trash_cookie(); + + include_once(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'update.php'); + + $sql = "SELECT DISTINCT email + FROM ".JLOG_DB_COMMENTS." WHERE reference = '".$blogentry['id']."' AND mail_by_comment = 1"; + $comment_mail = new Query($sql); + + // we are going to send some mail + require_once(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'mail.class.php'); + + if($comment_mail->error()) { + echo "
    \n";
    +                echo $comment_mail->getError();
    +                echo "
    \n"; + die(); + } + elseif( JLOG_INFO_BY_COMMENT ) { + // we need this for some mail texts + require(JLOG_BASEPATH.'lang'.DIRECTORY_SEPARATOR.'lang-admin.'.JLOG_LANGUAGE.'.inc.php'); + + $mail = new Jlog_Mail(); + $mail->setFrom($com_form['email'], $com_form['name']); + $mail->setSubject($l['admin']['comments_mailsubject']." - ".$blogentry['topic']); + + $text = $l['admin']['comments_mail_txt']." »".$blogentry['topic']."«\n- -\n"; + if(!empty($com_form['name'])) $text .= $com_form['name']; + else $text .= $l['admin']['comments_anonym']; + if(!empty($com_form['city'])) $text .= " ".$l['comments_from']." ".$com_form['city']; + $text .= " ".$l['admin']['comments_posted']." ".$date.":\n\n"; + $text .= html_entity_decode(strip_tags($bbcomments->parse($com_form['content']))); + $text .= "\n\n".str_replace ( '&', '&', blog($blogentry['date'], $blogentry['url']))."#c".$cid; + $text .= "\n\n".$l['admin']['kill_c_email']."\n".JLOG_PATH."/admin/comments.php?action=trash&id=".$cid; + $mail->setText($text); + + ### Plugin Hook + $mail = $plugins->callHook('adminMail', $mail, $blogentry, $cid); + $mail->send(JLOG_EMAIL); + } + + $mail = new Jlog_Mail(); + $mail->setSubject($l['comments_mailsubject']." - ".$blogentry['topic']); + $mail->setFrom(JLOG_EMAIL, JLOG_WEBSITE); + + $text = $l['comments_mail_txt']." »".$blogentry['topic']."«\n- -\n"; + if(!empty($com_form['name'])) $text .= $com_form['name']; + else $text .= $l['comments_anonym']; + if(!empty($com_form['city'])) $text .= " ".$l['comments_from']." ".$com_form['city']; + $text .= " ".$l['comments_posted']." ".$date.":\n\n"; + $text .= html_entity_decode(strip_tags($bbcomments->parse($com_form['content']))); + $text .= "\n\n".str_replace ( '&', '&', blog($blogentry['date'], $blogentry['url']))."#c".$cid.""; + $text .= "\n-- \n".$l['comments_stop_receiving']."\n"; + $text .= JLOG_PATH."/stop.php?id=".$blogentry['id']."&email="; + + while ($data = $comment_mail->fetch()) { + if($data['email'] != $com_form['email']) { + // set text for current user + $mail->setText($text . $data['email']); + $mail = $plugins->callHook('commentorMail', $mail, $blogentry); + // send mail + $mail->send(); + } + } + $c['form_content'] .= "

    ".$l['comments_thx']."

    ".com_javascript_variables(); + } + } +} + +// If nothing happens +elseif($blogentry['comments'] == 1) { + $com_form['name'] = $l['comments_name']; + $com_form['city'] = $l['comments_city']; + $com_form['email'] = $l['comments_email']; + $com_form['homepage'] = $l['comments_homepage']; + $com_form['sid'] = new_sid(); + if(isset($_COOKIE["jlog_userdata"])) { + $cookie = unserialize(urldecode($_COOKIE["jlog_userdata"])); + if($cookie != "") $com_form['cookie'] = 1; + if($cookie[0] != "") $com_form['name'] = $cookie[0]; + if($cookie[1] != "") $com_form['city'] = $cookie[1]; + if($cookie[2] != "") $com_form['email'] = $cookie[2]; + if($cookie[3] != "") $com_form['homepage'] = $cookie[3]; + } + $c['form_content'] .= com_form_output($com_form).com_javascript_variables(); +} +else $c['form_content'] .= "

    ".$l['comments_closed']."

    \n".com_javascript_variables(); + + + +// get comments and pingbacks + +$comments = new Query($sql_comments); +if($comments->error()) { + echo "
    \n";
    +    echo $comments->getError();
    +    echo "
    \n"; + die(); +} +$countPingbacks = 0; +$countComments = 0; +$commentsArray = array(); +$no_comments = ""; + +while($tmp_commentsArray = $comments->fetch()) $commentsArray[] = $tmp_commentsArray; +foreach($commentsArray as $tmp_comment) { + if($tmp_comment['type'] == 'pingback') ++$countPingbacks; + else ++$countComments; +} + +if($countPingbacks > 0) { + if($countComments < 1) $no_comments = " class='entryform'"; + $c['main'] .= "\n

    ".$l['pingback_topic']."

    \n
      "; + foreach($commentsArray as $pingback) { + if($pingback['type'] == 'pingback') $c['main'] .= "\n
    1. ".$pingback['name']."
    2. "; + } + $c['main'] .= "\n
    \n"; +} + +if($countComments < 1) $no_comments = " class='entryform'"; +$c['main'] .= "\n

    ".$l['comments_comment_topic']."

    \n"; + +if($countComments > 0) { + $c['main'] .= "
      "; + + $i = 0; + foreach($commentsArray as $data) { + if($data['type'] !== 'pingback') { + ++$i; + $data = com_clean_data($data); + $c['main'] .= do_comment($data, $i); + } + } + + $c['main'] .= "\n
    \n"; +} + +$c['main'] .= $c['form_content']; + +require(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'do_template.php'); +echo $body; + +?> diff --git a/page.php b/page.php new file mode 100644 index 0000000..f2198f3 --- /dev/null +++ b/page.php @@ -0,0 +1,45 @@ +error()) { + echo "
    \n";
    +        echo $blog->getError();
    +        echo "
    \n"; + die(); + } + + if($blog->numRows() == 0) { + header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found"); + include_once(JLOG_BASEPATH."error404.php"); + exit; + } + $daten = $blog->fetch(); + + $c['meta']['date'] = $daten['metadate']; + $c['meta']['description'] = strip_tags($bbcode->parse($daten['teaser'])); + $c['meta']['keywords'] = $daten['keywords']; + $c['meta']['title'] = $daten['topic']; + + $c['main'] = do_entry($daten, NULL, 'page'); + + +require(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'do_template.php'); +echo $body; +?> diff --git a/personal/css/admin.css b/personal/css/admin.css new file mode 100644 index 0000000..51ff90b --- /dev/null +++ b/personal/css/admin.css @@ -0,0 +1,28 @@ +/* -- CSS for the Jlog admincenter v0.2 -- */ +/* -- last edit 15 Dec 2004 -- */ + +#admin { margin: 0; padding: 0; border: 0; } +#admin p { font-weight: normal; } +#admin input, #admin textarea { font-weight: normal; font-family: inherit; font-size: inherit; padding-left: 0.2em; } +#admin input.long { width: 90%; } +#admin input.short { width: 3em; } +#admin input.button { width: auto; margin: 1em; } +#admin textarea { width: 90%; } +#admin form dt { font-weight: normal; margin: 0.5em 0 0 0; } +#admin form dd { margin: 0 0 0 1em; } +#admin form textarea.small { height: 2.7em; } +#admin form textarea.big { height: 15em; } + +#admin table { empty-cells: show; border-spacing: 0; font-size: 1em; } +#admin table tr td, +#admin table tr th { padding: 3px 8px; border-left: 1px dotted #bdaa94; vertical-align: top; } +#admin table tr th { border-bottom: 1px dotted #bdaa94; } +#admin table a, #admin table a img { border: none; background: none; } + +#admin a img.admin { border: none; background: none; } + +#admin h2.preview { color: red; text-align: center; background-color: white; } +#admin .preview { background: #FFF5F7; margin: 0 -10px; padding: 10px; } + +#admin .hide { display: none; } +#admin-menu { position: relative; z-index: 2; } diff --git a/personal/css/ielte6.css b/personal/css/ielte6.css new file mode 100644 index 0000000..2d93510 --- /dev/null +++ b/personal/css/ielte6.css @@ -0,0 +1,34 @@ +/* additional hacks for IE + * btw. IE sucks! ;-) + */ + + #pokal { /* do not display the alpha image */ + display: none; + } + + #container { /* IE max-width and PNG no-alpha hack */ + height: 1%; + width: 750px; + width:expression(document.body.clientWidth>805?"800px":"auto"); + background-image: url(img/banner-ielte6.jpg); + } + + #main { width: 63%; margin: 0 0 0 15px; } + + ul.comments li { + overflow-x: scroll; + } + + #admin table { /* adapting the font size for IE 5.x */ + font-size: 1em; + } + + * html #subnav { /* Box-Model Bug */ + content:"\"; width: 30%; padding: 2em 1.5em; + } + + * html #main { width: 62.5%; margin: 0 0 0 15px; } + + html + body #admin { /* close the hole in IE 5.0 */ + margin: 0; + } diff --git a/personal/css/img/Browse.plb b/personal/css/img/Browse.plb new file mode 100644 index 0000000000000000000000000000000000000000..b5d3fd60c029b707efd2dfbc521d4465586e334e GIT binary patch literal 6037 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 P00IC3|NsC0|NsC0@&2V? literal 0 HcmV?d00001 diff --git a/personal/css/img/banner-ielte6.jpg b/personal/css/img/banner-ielte6.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f357afb81bbd17ec413f0fd4bfeb15f43bf8c9fa GIT binary patch literal 38700 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 literal 0 HcmV?d00001 diff --git a/personal/css/img/banner.jpg b/personal/css/img/banner.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b73ce5bc9a986c53896211da0b7bac3f19d9635d GIT binary patch literal 41411 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 A-2eap literal 0 HcmV?d00001 diff --git a/personal/css/img/body.png b/personal/css/img/body.png new file mode 100644 index 0000000000000000000000000000000000000000..51b09b980a75ce18333e8e9f4dac20e1842fd5b1 GIT binary patch literal 161 zcmeAS@N?(olHy`uVBq!ia0vp^j6lrA#0(@k_T0G%q&Ne7LR=Xb4E{f1_<>&kwWLxx|{ wFjXq+C{Rey)5S4_<9c#NLPA0TLz0RVgO~^t<0kpJQ-G2Tp00i_>zopr0Mo1_761SM literal 0 HcmV?d00001 diff --git a/personal/css/img/border.png b/personal/css/img/border.png new file mode 100644 index 0000000000000000000000000000000000000000..f4fdb83abe4db0606c35aac3d6da463e1d008e0c GIT binary patch literal 76 zcmeAS@N?(olHy`uVBq!ia0vp^%s|Y@!2~3yG&Mg4Qo^1tjv*Y^lXnz8K6ZP1{{H&^ ad<^Q}IZVH1*5(4G89ZJ6T-G@yGywpdV-=DB literal 0 HcmV?d00001 diff --git a/personal/css/img/cheese.png b/personal/css/img/cheese.png new file mode 100644 index 0000000000000000000000000000000000000000..6893ffdd3d8112ce89f6a3fa66c006a86d162c09 GIT binary patch literal 624 zcmV-$0+0QPP)FFu;=;(;E>2#X9x3@>l<#N=mtu5-+)fLt2^-}Nd?x-G*hx+*VNOd}$)YsQn zs?BB_|MW_!QmI6ppP%RK=jSJNc6OH9Y&NMzqmkO}cBzw-lhm)TFRE6n<;OoZVzE%`^*YsTHuEg4 z-ELE-rlvUC@As)XolgDUzd5Ioe?m!;$5Ba=C6pvdmQa%Z-+lptvK5gBT4oCX0000< KMNUMnLSTZ?Q!&*5 literal 0 HcmV?d00001 diff --git a/personal/css/img/footer.png b/personal/css/img/footer.png new file mode 100644 index 0000000000000000000000000000000000000000..d132ed7a1dcadfcf46c26a24ba473cd27220ed51 GIT binary patch literal 2498 zcmV;z2|f0SP)-M(bLe}-rMNv=l=iv$KsGS000S1 zNkl!6^1;#&te}F{}LL@}U z&LF#p7>SICheUkH++bnD4Kvd--CeKQ6W896ZgzVfz1?3`b=Ox_=lcF6gz*G@-@)?j zBw+fMn&aL02&OmUyJ5MTzMbIs8bE5|e3!j(lA2xo$>ot<9C47vfM^rh_|lBhNXscy z!p|+eLMY)lQDFn}4M?x$Yal05Oc1dN(&QwB;M~ zX}PwG0|T8_NI+m)4rrP$$3yyXVHw#UUVhg{gIcvC{RV9pxKz9AgvJd9`|T`ZamD`DiYU-y0V% zJwM+1WB4*ZF+KY2t;;XGeSf)gefn(Nfng!79ArWx4~;1n2d5r>4p|S_imv0Jneo9! zS#ii}RouXK)*WqzY^a8XL}@h6jRNtD1eyrD-y1%fx%pW$!0+}x9q$Ye9u%L_LIj>| zX{e=NK*5oetvJr%bUNR^kqeLPVYY&+%q?s=@$7#v()72;A)t6n|U$Q{Fw2%_O zPG#i^vVq|VwefS(-{wxY1gjV-vNu4A9+X%SYO^Ljy(W-pb10Xr0p|_d)Vtw)r~iA9 z&i-`An|lcTaTH9j&=pD+1!Js0!_9pm0kz}(FI=2Wghe21`QU2kB>7PJ`zRiF zkqP8sY&`JI9$m6b3kf6;QjCf(ELehC%%duPPB%?0oOZ%?2?)|=&7cCi#)FF}q{ok@ z6o_Bk-oa{qnCzfme6P_Mj)p$2UAy*kDUjx1eGj4VG6Ib(^oDEkqVwSwnR<5lOzxar zQszSdbNSYp7NfM(4aDSrDi+d2r?#|^aS?Mj)22Sj<>7E`|C{;2v}84!+iUSZ;SVZQ z7pW^;4?o8|>I@7dR#8w3kbw}5%_4QgQF)gQmGyGAC2Ml0o?BKaKYcu!?B>B!7V>1i z`p)sZcQo^#w2;*>iKb^jEge@G-v7kUVJ0U?hMa`6^B$D&Xfz&$DB08z@Byip$p(v{VZR0QDJzoOLEoxW+@?dMmv7VP8gj4}TqG zba~lBnz-%%bR(L`{b>&|mn_N8wR9~jV+dxxsuF&Vr0WA(u_vt_1Es7{szawFb6GDP zBVJ<%QXszIA&W^IJf8V`zB(MI-@QLBQf=ZP51ql(*J>0x7UWW+3s@UJCzxAVcA#a* z6&2yCWT-=@rZkO2uwo$!4>{~_PwKzN9OKh_Q#f&nVHr$ajRWR^YlRO?DoWD#ocK|u zjta+)%Lyon=Jjkdjgp5N_ikem052{u14dlrI*!;+-^8)#?UX{eX@{)nRjFh`N;VTvzvT< zJ(d-Cx}RpDRX4RY?$*Q4*@Pc9B6${+Py)}@Xqh%8k6R|FWLH`~L^AbB{Xg-`9x{n+ zT&s@y{-3yqG;<2qEBO$#a^{uFCO<_4FbHs#X^vcnPvykq9ruTTN^*8gUW(vnZ6NXgP`Q>DbQ$D z17x-YoV^8*RzbRELqfmX`MzfzyikIp9$l z5-~ufPDhPQF*3@lj@p$Kg4H}Ao;kP}(Z1(M3irmG!F4Zi5!<&5Q|Z-s(4T@RMBf0P&f5XH62u}SEGnKt$x?) z^aCih>_J!hy7)Qy9|1v1t^-zufJ%6GdrgwLJQr#MJOBTXXp~^BDQUS^!zrOQey+$0 zz()E8K}j+pBc3vG0IWisJKZFQrKRO|SZv)Y)7t3uqzJ6ckvNof@Nj8j$m)gLX9z$xq22BwS`dYkbhQ4tpfY~{0i?QbNw8S<;s5{u M07*qoM6N<$g7CzzT>t<8 literal 0 HcmV?d00001 diff --git a/personal/css/img/pokal.png b/personal/css/img/pokal.png new file mode 100644 index 0000000000000000000000000000000000000000..c9814e53f9a9b202ee03d9c1edf5f5ee44a11967 GIT binary patch literal 21125 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 literal 0 HcmV?d00001 diff --git a/personal/css/popup.css b/personal/css/popup.css new file mode 100644 index 0000000..d3196ab --- /dev/null +++ b/personal/css/popup.css @@ -0,0 +1,34 @@ +body { + font-family: Verdana, Arial, Helvetica, sans-serif; + color: black; + font-size: 0.8em; + background-color: #eee; + margin: 0px; + padding: 10px 5%; +} +h1 { + margin: 0px 0px 20px 0px; + font-size: 140%; +} +.caution { + color: red; + font-weight: bold; +} +ul { list-style-type: none; margin: 0; } +ul.error { list-style-type: disc; } +li { margin: 0.5em; } +.error { color: red; } +a { color: brown; } +img { border: none; } +a img { + border: none; + margin: 0 0 0.5em 0; +} +p { margin: 0; padding: 0.5em 0 0.5em 0 } +blockquote { + border: 1px solid #999; + border-left: 3px solid #aaa; + padding: 0 1em 0.3em 1em; + margin: 0; + background: #eee url(/img/anfuehrungszeichen.png) 2% 1px no-repeat; +} diff --git a/personal/css/print.css b/personal/css/print.css new file mode 100644 index 0000000..ec681cd --- /dev/null +++ b/personal/css/print.css @@ -0,0 +1,19 @@ +/* print.css for the default template of Jlog + * see screen.css for more details + */ + +/* -- hide -- */ + #subnav, .skip, .entryform, .hidecomments, #entryform, hr { display: none; } + +/* -- main settings -- */ + body { font-family: Georgia, "Times New Roman", Times, serif; } + h1 { text-align: right; margin-top: 0; } + blockquote { font-style: italic; } + +/* -- links -- */ + a { text-decoration: none; } + #main a:after { font-size: 70%; content:" <"attr(href)">"; } + #main .meta a:after, #main h2 a:after { content:""; } + +/* -- comments -- */ + ul#commentslist { list-style-type: none; } diff --git a/personal/css/screen.css b/personal/css/screen.css new file mode 100644 index 0000000..4b9600e --- /dev/null +++ b/personal/css/screen.css @@ -0,0 +1,213 @@ +/* screen.css for the standard Jlog template. + * + * Author: Jeena Paradies + * License: GPL (see LICENSE.txt in this package) + * + */ + +/* -- main positionering -- */ + body { + font-size: 100.01%; + font-family: verdana, arial, sans-serif; + background: #ffdc6c url(img/body.png); + color: black; + min-width: 500px; + margin: 0 20px; + padding: 0; + text-align: center; + } + #container { + font-size: 0.8em; + text-align: left; + margin: 0 auto; + max-width: 800px; + background: url(img/banner.jpg) no-repeat 0 2.4em white; + border: 1px solid #2B2B2B; + border-top: 0; + position: relative; + } + #main { + margin: 0 0 0 25px; + padding: 190px 0 2em 0; + width: 64.5%; + float: left; + } + + /* Clearfix-Hack */ + #main:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; + } + + #main {display: inline-table;} + + /* Hides from IE-mac \*/ + * html #main {height: 1%;} + #main {display: block;} + /* End hide from IE-mac */ + + /* -- logo -- */ + h1 { + font-size: 2em; + font-weight: normal; + padding: 0 5%; + margin: 0; + background: url(img/cheese.png) right bottom repeat-y white; + } + h1 a:link, h1 a:visited { color: black; text-decoration: none; } + + /* -- pokal -- */ + #pokal { + position: absolute; + left: -21px; + top: 4.5em; + width: 128px; + height: 198px; + background: url(img/pokal.png) no-repeat; + margin: 0; + padding: 0; + } + + /* -- subnavigation -- */ + #subnav { + width: 26%; + margin: 1em 1px 1em 0; + float: right; + margin-top: 165px; + padding: 1% 1% 1% 2%; + font-size: 0.8em; + background: url(img/border.png) repeat-y white; + } + #subnav dt { + font-weight: bold; + margin-top: 1.5em; + } + #subnav dd { + padding: 0.5em; + margin: 0; + line-height: 120%; + } + #subnav ul { + margin: 0; padding: 0; + list-style-type: none; + } + #subnav ul li { margin-bottom: 0.5em; } + .rss img { vertical-align: middle; border: 0; width: 94px; height: 15px; } + + /* -- footer -- */ + #footer { + clear: both; + height: 60px; + background: url(img/footer.png) no-repeat top center; + } + +/* -- basic styles -- */ + .skip { + position: absolute; + left: -999px; + width: 990px; + } + hr { + background-color: #aaa; + color: #aaa; + border: 0 none; + height: 1px; + margin: 1em 0; + clear: both; + } + .error { color: red; } + blockquote { + background: url(img/border.png) repeat-y; + padding: 0 0.5em; + font-style: italic; + } + #searchform { text-align: center; } + .meta.date { margin-top: 0; } + .meta { font-style: italic; font-size: 0.85em; } + .searchword { background: yellow; } + + /* -- pictures -- */ + .fl { float: left; margin: 0 1em 1em 0; } + .fr { float: right; margin: 0 0 1em 1em; } + #main img, dl.img { + border: 1px solid #aaa; + padding: 2px; + max-width: 95%; + } + dl.img dt { padding: 0; margin: 0;} + #main dl.img dt img { margin: 0; padding: 0; max-width: 100%; border: none; } + dl.img dd { margin: 0; padding: 0 0.3em; font-size: 90%; } + .teaser { clear: both; } + + /* -- main link styles -- */ + a:link { color: #18518b; } + a:visited { color: #555; } + a:hover { color: black; } + + /* -- headlines -- */ + h2, h3, h4, h5, h6 { + font-weight: normal; + font-family: verdana, sans-serif; + position: relative; + z-index: 2; + } + h2 { font-size: 1.7em; margin: 0; } + h3 { font-size: 1.2em; } + h4 { font-size: 1.1em; } + h5 { font-size: 1em; } + h6 { font-size: 0.9em; } + h2 a:link, h2 a:visited, + .teaser h3 a:link, .teaser h3 a:visited, + .teaser h4 a:link, .teaser h4 a:visited { text-decoration: none; color: black; } + h2 a:hover, .teaser h3 a:hover, .teaser h4 a:hover { text-decoration: underline; } + .teaser h3, .teaser h4 { margin: 0; } + + /* -- textareas and inputs -- */ + fieldset { border: 1px solid #aaa; padding: 1em; } + legend { padding: 1em; font-weight: bold; } + input.long, input.short, input.userdata, textarea, select { + background: #f7f7f7; + border: 1px solid #bbb; + border-right: 1px solid #d8d8d8; + border-bottom: 1px solid #D8D8D8; + } + +/* -- aditional styles for the home- and searchpage -- */ + .teaser h2 { font-size: 1.3em; } + .teaser h3, .teaser h4 { font-weight: bold; } + .teaserpic { float: right; margin: 0 0 1em 1em; } + .entries , .search li { list-style-type: none; } + .search li { border-top: 1px solid #d8d8d8; padding-top: 1em; } + ul.search { margin: auto 5%; padding-left: 0; } + h2.search { text-align: center; } + .archive { margin-left: 5%; } + .archivenavigation { text-align: center; border-top: 1px dotted #aaa; padding-top: 0.7em; margin-top: 2em; } + +/* -- comments -- */ + p.hidecomments { font-size: 0.75em; text-align: right; line-height: 1px; padding: 0; margin-bottom: 0; } + #preview li { border: solid 1px red; } + ul.comments .meta { font-size: 1.3em; } + ul.comments { list-style-type: none; font-size: 0.9em;} + ul.comments li { + padding: 0 1em 0.5em 1em; + margin: 1em 0; + background: #f7f7f7; + border: 1px solid #ccc; + border-left: 1px solid #d8d8d8; + border-top: 1px solid #D8D8D8; + overflow-x: scroll; + } + ul.comments li p { margin: 0.5em; } + ul.comments a.permalink { + font: normal bold 1.5em monospace; + border-right: 1px solid #d8d8d8; + text-decoration: none; + padding-right: 0.2em; + margin-right: 0.2em; + } + ul.comments a.permalink:hover { text-decoration: underline; } + #pingbackslist { margin-bottom: 3em; } + textarea { width: 90%; min-width: 10em; } diff --git a/personal/template.tpl b/personal/template.tpl new file mode 100644 index 0000000..d07b1c4 --- /dev/null +++ b/personal/template.tpl @@ -0,0 +1,40 @@ + + + + <jlog:title /> - <jlog:website /> + + + + + + +

    +
    +

    + +
    + +
    + +
    + + diff --git a/plugins/.htaccess b/plugins/.htaccess new file mode 100644 index 0000000..4dbcc9b --- /dev/null +++ b/plugins/.htaccess @@ -0,0 +1,2 @@ +Order allow,deny +Deny from All \ No newline at end of file diff --git a/plugins/CommentCloser.jplug.php b/plugins/CommentCloser.jplug.php new file mode 100644 index 0000000..a443d7b --- /dev/null +++ b/plugins/CommentCloser.jplug.php @@ -0,0 +1,126 @@ + + * @author: Robert Bienert + * @version: 1.3 + * @date: 2009-01-04 + * + * Dieses Plugin schliesst nach einer bestimmten, festzulegenden + * Laufzeit die Kommentare eines Artikels. + * + * Konstanten-Praefix: COMMENT_CLOSER + */ + +define('COMMENT_CLOSER_CFG_FILE', JLOG_BASEPATH . 'personal' . + DIRECTORY_SEPARATOR . 'settings.CommentCloser.inc.php'); + +if (@file_exists(COMMENT_CLOSER_CFG_FILE)) + include_once COMMENT_CLOSER_CFG_FILE; + +class CommentCloser extends JlogPlugin { + var $_units = array('SECOND', 'MINUTE', 'HOUR', 'DAY', 'WEEK', + 'MONTH', 'YEAR', + ); + // Dieses Array kann lokalisiert werden: + var $_unit_desc = array('Sekunden', 'Minuten', 'Stunden', + 'Tagen', 'Wochen', 'Monaten', 'Jahren' + ); + + // Konfigurationsoberflaeche + function hook_adminContent($output) { + $lifeTime = defined('COMMENT_CLOSER_LIFETIME') ? + COMMENT_CLOSER_LIFETIME : ''; + $timeUnit = defined('COMMENT_CLOSER_TIMEUNIT') ? + COMMENT_CLOSER_TIMEUNIT : ''; + $self = htmlspecialchars($_SERVER['REQUEST_URI']); + + if (array_key_exists('commclose_do', $_POST)) { + $lifeTime = $_POST['commclose_lifetime']; + $timeUnit = $_POST['commclose_unit']; + // Einheiten pruefen + if (! in_array($timeUnit, $this->_units)) + $timeUnit = ''; + + // keine (negative) Zeit XXX implicit cast + if ($lifeTime + 0 <= 0) + $lifeTime = 0; + + # XXX MySQL bug: WEEK wird bei mir nicht + # erkannt, deshalb manuelles Umrechnen: + if ($timeUnit == 'WEEK') { + $lifeTime *= 7; + $timeUnit = 'DAY'; + } + + $mask = umask(0); + + if (($f = @fopen(COMMENT_CLOSER_CFG_FILE, 'wb'))) + { + @fwrite($f, "'); + @fclose($f); + } + + umask($mask); + } + + $output = << +

    +

    +

    Nach der angegeben Zeit können Beiträge nicht mehr kommentiert werden.

    + +EOT; + + return $output; + } + + // Pruefen auf zu schliessende Beitraege + function hook_onUpdate($data) { + // Kein Schliessen gewuenscht, Plugin nicht konfiguriert + // oder ungueltige Werte gesetzt: + if (!defined('COMMENT_CLOSER_LIFETIME') || + COMMENT_CLOSER_LIFETIME+0 <= 0 || + !defined('COMMENT_CLOSER_TIMEUNIT') || + !in_array(COMMENT_CLOSER_TIMEUNIT, + $this->_units)) + { + return $data; + } + + $q = new Query('UPDATE ' . JLOG_DB_PREFIX . + 'content SET comments=0 ' . + 'WHERE date < DATE_SUB(NOW(), INTERVAL ' . + COMMENT_CLOSER_LIFETIME . ' ' . + COMMENT_CLOSER_TIMEUNIT . + ') AND comments=1'); + # TODO error handling + + return $data; + } +} +?> diff --git a/plugins/MiniAntispam.jplug.php b/plugins/MiniAntispam.jplug.php new file mode 100644 index 0000000..67c5365 --- /dev/null +++ b/plugins/MiniAntispam.jplug.php @@ -0,0 +1,38 @@ + + * @author: Jeena Paradies + * @version: 1.0 + * @date: 2006-05-10 + */ + +class MiniAntispam extends JlogPlugin { + + function hook_commentForm($form) { + $uid = $this->generate_uid(); + $uid_inputs = "\n ".''; + $uid_inputs .= "\n ".''; + + return str_replace("

    ", "

    ".$uid_inputs, $form); + } + + function hook_newComment($form) { + if(empty($form['publickey']) OR $form['publickey'] != $form['privatkey']) { + die("

    Hi spammer

    Please don't spam me."); + } + return $form; + } + + function generate_uid($len = 40) { + $acceptedChars = 'azertyuiopqsdfghjklmwxcvbnAZERTYUIOPQSDFGHJKLMWXCVBN0123456789.,-;_'; + $maxchar = strlen($acceptedChars)-1; + $uid = ''; + mt_srand((double)microtime()*1000000); + + for($i=0; $i < $len; $i++) $uid .= $acceptedChars{ mt_rand(0, $maxchar) }; + + return $uid; + } + +} +?> diff --git a/scripts/JlogUpdater.php b/scripts/JlogUpdater.php new file mode 100644 index 0000000..cf70868 --- /dev/null +++ b/scripts/JlogUpdater.php @@ -0,0 +1,149 @@ + next version in history + * + * @var array + */ + var $versions = array( + '1.0.2' => '1.1.0', + '1.1.0' => '1.1.1', + '1.1.1' => '1.1.2', + '1.1.2' => '1.1.3' + ); + + function JlogUpdater() + { + require_once(JLOG_BASEPATH."scripts".DIRECTORY_SEPARATOR."settings.class.php"); + } + + function getOldVersion() + { + return JLOG_INSTALLED_VERSION; + } + + function getNewVersion() + { + return JLOG_SOFTWARE_VERSION; + } + + function isUp2Date() + { + if (version_compare($this->getOldVersion(), $this->getNewVersion(), '<')) { + return false; + } + return true; + } + + function prepareForm($l) + { + $html = '
    ' + . '

    ' . $l['admin']['e_admin_password'] . ': ' + . '' + . '

    '; + $version = $this->getOldVersion(); + while (isset($this->versions[$version])) { + $class = $this->_loadUpdateClass($version, $this->versions[$version]); + $html .= sprintf("

    Update %s%s

    \n", $version, $this->versions[$version]); + $html .= $class->getForm($l); + $version = $this->versions[$version]; + } + $html .= '

    '; + $html .= '
    '; + return $html; + } + + function performUpdate($l) + { + if (JLOG_AMDIN_PASSWORD !== md5($_POST['jlog_password']) and JLOG_ADMIN_PASSWORD !== md5(utf8_decode($_POST['jlog_password']))) { + return '

    ' . $l['admin']['login_false_pw'] . '

    '; + } + + require_once(JLOG_BASEPATH."scripts".DIRECTORY_SEPARATOR."settings.class.php"); + // read current settings from environment + $settings = new Settings($l); + $settings->importDataByConstants(); + + $error = false; + $html = ''; + $version = $this->getOldVersion(); + while (isset($this->versions[$version])) { + $class = $this->_loadUpdateClass($version, $this->versions[$version]); + $html .= sprintf("

    Update %s%s

    \n", $version, $this->versions[$version]); + $result = $class->performUpdate($l, $settings); + if ($result === true) { + // we know that update class ran successfully + $result = $this->_updateVersionNumber($settings, $this->versions[$version]); + // check if errors occured + if (!empty($result)) { + $this->_renderErrors($result); + break; + } + else { + $html .= '

    ' . $l['admin']['update_successfull_part'] . '

    '; + } + } + else { + $html .= $this->_renderErrors($result); + break; + } + $version = $this->versions[$version]; + } + if ($error) { + $html .= '

    ' . $l['admin']['update_failure'] . '

    '; + } + else { + $html .= '

    ' . $l['admin']['update_successfull'] . '

    '; + } + return $html; + } + + function _getUpdateFile($oldver, $newver) + { + $oldver = str_replace('.', '', $oldver); + $newver = str_replace('.', '', $newver); + return "{$oldver}To{$newver}.php"; + } + + function _getUpdateClass($oldver, $newver) + { + $oldver = str_replace('.', '', $oldver); + $newver = str_replace('.', '', $newver); + return "JlogUpdate_{$oldver}To{$newver}"; + } + + function _loadUpdateClass($oldver, $newver) + { + $file = $this->_getUpdateFile($oldver, $newver); + $class = $this->_getUpdateClass($oldver, $newver); + require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'update' . DIRECTORY_SEPARATOR . $file); + return new $class(); + } + + function _renderErrors($errors) + { + $html = '
      '; + foreach ($errors as $error) { + $html .= '
    • ' . $error . '
    • '; + } + $html .= '
    '; + return $html; + } + + function _updateVersionNumber($settings, $newver) + { + $settings->setValue('jlog_installed_version', $newver); + $settings->setValue('jlog_installed_url', JLOG_SOFTWARE_URL); + $settings->setValue('jlog_installed_phpv', JLOG_SOFTWARE_PHPV); + $settings->setValue('jlog_installed_mysqlv', JLOG_SOFTWARE_MYSQLV); + + // rewrite settings.inc.php + return $settings->do_settings(); + } +} + +// eof \ No newline at end of file diff --git a/scripts/bbcode.php b/scripts/bbcode.php new file mode 100644 index 0000000..d153756 --- /dev/null +++ b/scripts/bbcode.php @@ -0,0 +1,172 @@ +' . $content . ''; + } +} + +// Funktion zum Einbinden von Bildern +function do_bbcode_img ($action, $attributes, $content, $params, $node_object) { + if ($action == 'validate') { + if (isset($attributes['caption'])) { + $node_object->setFlag('paragraph_type', BBCODE_PARAGRAPH_BLOCK_ELEMENT); + if ($node_object->_parent->type() == STRINGPARSER_NODE_ROOT OR + in_array($node_object->_parent->_codeInfo['content_type'], array('block', 'list', 'listitem'))) { + return true; + } + else return false; + } + else return true; + } + $title = empty($attributes["title"]) ? "" : " title='".htmlspecialchars($attributes["title"])."'"; + + if (isset($attributes['class']) AND isset($attributes['caption'])) $class_caption = " class='img ".htmlspecialchars($attributes['class'])."'"; + elseif (isset($attributes['class'])) $class = " class='".htmlspecialchars($attributes['class'])."'"; + elseif (isset($attributes['caption'])) $class_caption = " class='img'"; // bugfix by Sebastian Kochendörfer #215 + + if (strpos($content, "http://") === 0) return "".htmlspecialchars($attributes["; + else { + list($img_width, $img_height, $img_type, $img_attr) = @getimagesize(JLOG_BASEPATH.'/img'.DIRECTORY_SEPARATOR.htmlspecialchars($content)); + $img = "".htmlspecialchars($attributes["; + } + + if(isset($attributes['caption'])) { + return "\n\n
    ".$img."
    \n
    ".htmlspecialchars($attributes['caption'])."
    \n\n"; + } + else return $img; +} + +// Funktion zum Einbinden von HTML Code, welcher vom Browser interpretiert wird +function do_bbcode_html($action, $attributes, $content, $params, $node_object) { + if ($action == 'validate') return true; + return $content; +} + +$bbcode = new StringParser_BBCode (); +$bbcode->addFilter (STRINGPARSER_FILTER_PRE, 'convertlinebreaks'); +$bbcode->addFilter (STRINGPARSER_FILTER_POST, 'special_character'); + +$bbcode->addParser (array ('block', 'inline', 'link', 'listitem'), 'htmlspecialchars'); +$bbcode->addParser (array ('block', 'inline', 'link', 'listitem'), 'nl2br'); +$bbcode->addParser ('list', 'bbcode_stripcontents'); +$bbcode->setRootParagraphHandling (true); + +$bbcode->addCode ('b', 'simple_replace', null, array ('start_tag' => '', 'end_tag' => ''), + 'inline', array ('listitem', 'block', 'inline', 'link'), array ()); + +$bbcode->addCode ('i', 'simple_replace', null, array ('start_tag' => '', 'end_tag' => ''), + 'inline', array ('listitem', 'block', 'inline', 'link'), array ()); + +$bbcode->addCode ('headline', 'simple_replace', null, array('start_tag' => '

    ', 'end_tag' => '

    '), + 'block', array('block'), array('inline', 'link')); + +$bbcode->addCode ('quote', 'simple_replace', null, array('start_tag' => '
    ', 'end_tag' => '
    '), + 'block', array('block', 'listitem'), array('inline', 'link')); + +$bbcode->addCode ('url', 'usecontent?', 'do_bbcode_url', array ('usecontent_param' => 'default'), + 'link', array ('listitem', 'block', 'inline'), array ('link')); + +$bbcode->addCode ('img', 'usecontent', 'do_bbcode_img', array (), + 'image', array ('listitem', 'block', 'inline', 'link'), array ()); + +$bbcode->addCode ('html', 'usecontent', 'do_bbcode_html', array (), + 'html', array ('listitem', 'block', 'inline', 'link'), array ('image')); + +$bbcode->addCode ('list', 'simple_replace', null, array ('start_tag' => '
      ', 'end_tag' => '
    '), + 'list', array ('block', 'listitem'), array ()); + +$bbcode->addCode ('olist', 'simple_replace', null, array ('start_tag' => '
      ', 'end_tag' => '
    '), + 'list', array ('block', 'listitem'), array ()); + +$bbcode->addCode ('*', 'simple_replace', null, array ('start_tag' => '
  • ', 'end_tag' => '
  • '), + 'listitem', array ('list', 'olist' ), array ()); + +$bbcode->setCodeFlag ('*', 'closetag', BBCODE_CLOSETAG_OPTIONAL); +$bbcode->setCodeFlag ('*', 'paragraphs', false); +$bbcode->setCodeFlag ('list', 'paragraph_type', BBCODE_PARAGRAPH_BLOCK_ELEMENT); +$bbcode->setCodeFlag ('list', 'opentag.before.newline', BBCODE_NEWLINE_DROP); +$bbcode->setCodeFlag ('list', 'closetag.after.newline', BBCODE_NEWLINE_DROP); +$bbcode->setCodeFlag ('olist', 'paragraph_type', BBCODE_PARAGRAPH_BLOCK_ELEMENT); +$bbcode->setCodeFlag ('olist', 'opentag.before.newline', BBCODE_NEWLINE_DROP); +$bbcode->setCodeFlag ('olist', 'closetag.before.newline', BBCODE_NEWLINE_DROP); +$bbcode->setCodeFlag ('headline', 'paragraph_type', BBCODE_PARAGRAPH_BLOCK_ELEMENT); +$bbcode->setCodeFlag ('headline', 'opentag.before.newline', BBCODE_NEWLINE_DROP); +$bbcode->setCodeFlag ('headline', 'closetag.after.newline', BBCODE_NEWLINE_DROP); +$bbcode->setCodeFlag ('html', 'opentag.before.newline', BBCODE_NEWLINE_DROP); +$bbcode->setCodeFlag ('html', 'closetag.after.newline', BBCODE_NEWLINE_DROP); +$bbcode->setCodeFlag ('quote', 'paragraph_type', BBCODE_PARAGRAPH_BLOCK_ELEMENT); +$bbcode->setCodeFlag ('quote', 'paragraphs', true); +$bbcode->setCodeFlag ('quote', 'opentag.before.newline', BBCODE_NEWLINE_DROP); +$bbcode->setCodeFlag ('quote', 'closetag.after.newline', BBCODE_NEWLINE_DROP); + +// BBCode for comments +$bbcomments = new StringParser_BBCode (); +$bbcomments->addFilter (STRINGPARSER_FILTER_PRE, 'convertlinebreaks'); +$bbcomments->addFilter (STRINGPARSER_FILTER_POST, 'special_character'); + +$bbcomments->addParser (array ('block', 'inline', 'link'), 'htmlspecialchars'); +$bbcomments->addParser (array ('block', 'inline', 'link'), 'nl2br'); +$bbcomments->setRootParagraphHandling (true); + +$bbcomments->addCode ('b', 'simple_replace', null, array ('start_tag' => '', 'end_tag' => ''), + 'inline', array ('block', 'inline', 'link'), array ()); +$bbcomments->addCode ('i', 'simple_replace', null, array ('start_tag' => '', 'end_tag' => ''), + 'inline', array ('block', 'inline', 'link'), array ()); +$bbcomments->addCode ('url', 'usecontent?', 'do_bbcode_url', array ('usecontent_param' => 'default'), + 'link', array ('block', 'inline'), array ('link')); +$bbcomments->addCode ('quote', 'simple_replace', null, array('start_tag' => '
    ', 'end_tag' => '
    '), + 'block', array('block'), array('inline', 'link')); + +$bbcomments->setCodeFlag ('quote', 'paragraph_type', BBCODE_PARAGRAPH_BLOCK_ELEMENT); +$bbcomments->setCodeFlag ('quote', 'paragraphs', true); +$bbcomments->setCodeFlag ('quote', 'opentag.before.newline', BBCODE_NEWLINE_DROP); +$bbcomments->setCodeFlag ('quote', 'closetag.after.newline', BBCODE_NEWLINE_DROP); + +// eof diff --git a/scripts/categories.class.php b/scripts/categories.class.php new file mode 100644 index 0000000..0adf1e6 --- /dev/null +++ b/scripts/categories.class.php @@ -0,0 +1,250 @@ +l = $l; + + $this->get_categories(); + } + + function get($id, $data) { + return $this->categories[$id][$data]; + } + + function get_id($url) { + foreach($this->categories AS $cat) { + if($cat['url'] == $url) return $cat['id']; + } + + } + + function get_categories() { + if(!defined("JLOG_UPDATE") AND !defined("JLOG_LOGIN")) { + $sql = "SELECT id, name, url, description FROM ".JLOG_DB_CATEGORIES; + $cat = new Query($sql); + if($cat->error()) { + echo "
    \n";
    +                echo $cat->getError();
    +                echo "
    \n"; + die(); + } + while($c = $cat->fetch()) { + $this->categories[$c['id']] = + array('id' => $c['id'], 'name' => $c['name'], 'url' => $c['url'], 'description' => $c['description'] ); + } + } + } + + function get_assigned_categories($id) { + $sql = "SELECT cat_id FROM ".JLOG_DB_CATASSIGN." WHERE content_id = '".$id."'"; + $assigned = new Query($sql); + if($assigned->error()) { + echo "
    \n";
    +            echo $assigned->getError();
    +            echo "
    \n"; + die(); + } + $ids = array(); + while($a = $assigned->fetch()) { + $ids[] = $a['cat_id']; + } + return $ids; + } + + function output_select($catassign) { + // $catassign is an array which contains all assigned ids + + if(count($this->categories) > 0) { + $output = "


    \n" + ." \n

    "; + + return $output; + } + } + + function output_rss($id) { + $ids = $this->get_assigned_categories($id); + if(is_array($ids)) { + foreach($ids AS $i) { + $output .= " ".$this->get($i, 'name')."\n"; + } + } + return $output; + } + + function output_assigned_links($ids) { + if(!is_array($ids)) $ids = $this->get_assigned_categories($ids); + if(is_array($ids)) { + foreach($ids as $id) { + $output .= $this->link($id)." "; + } + } + if(isset($output)) return " » ".$output.""; + } + + function output_whole_list($_before = "
      \n", $_after = "
    \n", $before = "
  • ", $after = "
  • \n") { + if(is_array($this->categories) AND count($this->categories)) { + $output = $_before; + foreach($this->categories AS $id => $tmp) { + $output .= $before.$this->link($id).$after; + } + $output .= $_after; + return $output; + } + else return false; + } + + function link($id) { + if(JLOG_CLEAN_URL) return "".$this->categories[$id]['name'].""; + else return "".$this->categories[$id]['name'].""; + } + + function output_whole_list_admin() { + $output = " + + + + + + "; + + foreach($this->categories AS $id => $tmp) { + $output .= " + + + + + \n"; + } + + $output .= "
    ".$this->l['admin']['change']."".$this->l['admin']['delete']."".$this->l['admin']['cat_name']."
    ".$this->l[".$this->l[".$this->link($id)."
    \n"; + + return $output; + } + + function output_form($form_input = "", $action = 'new', $legend) { + $output = " +
    +
    ".$legend." +


    +

    +


    + +

    +


    +

    +

    + ".$this->l['admin']['cancel']." + ".add_session_id_input_tag()."

    +
    +
    "; + + return $output; + } + + function new_cat($form_input) { + + $form_input = escape_for_mysql($form_input); + + $sql = "INSERT INTO ".JLOG_DB_CATEGORIES." (name, url, description) VALUES + ('".$form_input['name']."', + '".$form_input['url']."', + '".$form_input['description']."');"; + + $new = new Query($sql); + + if($new->error()) { + echo "
    \n";
    +         echo $new->getError();
    +         echo "
    \n"; + die(); + } + } + + function change_cat($form_input) { + + $form_input = escape_for_mysql($form_input); + + $sql = "UPDATE ".JLOG_DB_CATEGORIES." + SET + name = '".$form_input['name']."', + url = '".$form_input['url']."', + description = '".$form_input['description']."' + WHERE + id = '".$form_input['id']."' LIMIT 1;"; + + $change = new Query($sql); + + if($change->error()) { + echo "
    \n";
    +         echo $change->getError();
    +         echo "
    \n"; + die(); + } + } + + function trash_cat($id) { + + $sql = "DELETE FROM ".JLOG_DB_CATEGORIES." WHERE id = '".escape_for_mysql($id)."' LIMIT 1"; + $trash = new Query($sql); + if($trash->error()) { + echo "
    \n";
    +        echo $trash->getError();
    +        echo "
    \n"; + die(); + } + + $sql = "DELETE FROM ".JLOG_DB_CATASSIGN." WHERE cat_id = '".escape_for_mysql($id)."' LIMIT 1"; + $trash = new Query($sql); + if($trash->error()) { + echo "
    \n";
    +        echo $trash->getError();
    +        echo "
    \n"; + die(); + } + + + } + + function validate($form_input) { + if(empty($form_input['name'])) $errors[] = $this->l['admin']['cat_noname']; + + if(empty($form_input['url'])) $errors[] = $this->l['admin']['no_url']; + elseif(!preg_match("/^[a-z0-9\-_\.,]+$/", $form_input['url'])) $errors[] = $this->l['admin']['false_url_letters']; + else { + $sql = "SELECT id FROM ".JLOG_DB_CATEGORIES." WHERE url = '".escape_for_mysql($form_input['url'])."';"; + + $check_url = new Query($sql); + + if($check_url->error()) { + echo "
    \n";
    +             echo $check_url->getError();
    +             echo "
    \n"; + die(); + } + + if($check_url->numRows() > 0) { + $c = $check_url->fetch(); + if($c['id'] != $form_input['id']) $errors[] = $this->l['admin']['cat_duplicate']; + } + } + + return $errors; + } +} +?> diff --git a/scripts/comments.php b/scripts/comments.php new file mode 100644 index 0000000..0b6d0b3 --- /dev/null +++ b/scripts/comments.php @@ -0,0 +1,141 @@ + +
    ".$l['comments_entryform']." +

    + ".$l['comments_bbcode']." + BBcode? + +
    + +

    +

    + +
    + + +

    +

    +  "; + if(defined('JLOG_ADMIN')) $output .= "\n \n"; + else { + $output .= " \n"; + } + $output .= " +

    +

    + + "; + + if(defined("JLOG_ADMIN")) $output .= add_session_id_input_tag(); + + $output .= " +

    +
    + \n + "; + + ### Plugin Hook + $output = $plugins->callHook('commentForm', $output, $com_form); + + return $output; + } + + function com_javascript_variables() { + global $l; + return " + + "; + } + + function com_check_errors($com_form) { + global $l; + if(empty($com_form['sid'])) $errors[] = $l['comments_no_sid']; + if(isset($com_form['email']) AND $com_form['email'] != "" AND !preg_match("/^[^@]+@.+\.\D{2,6}$/", $com_form['email']) AND $com_form['email'] != $l['comments_email']) $errors[] = $l['comments_false_mail']; + if(empty($com_form['content'])) $errors[] = $l['comments_notext']; + if(isset($errors)) return $errors; + } + + function com_clean_data($data) { + global $l; + if(empty($data['name']) OR $data['name'] == $l['comments_name']) $data['name'] = ""; + if(empty($data['city']) OR $data['city'] == $l['comments_city']) $data['city'] = ""; + if(empty($data['email']) OR $data['email'] == $l['comments_email']) $data['email'] = ""; + if(empty($data['homepage']) OR $data['homepage'] == $l['comments_homepage']) $data['homepage'] = ""; + + if(empty($data['date'])) $data['date'] = time(); + + return $data; + } + + function set_cookie($data) { + $userdaten = array( $data['name'], + $data['city'], + $data['email'], + $data['homepage'] ); + $cookielife = time() + 42 * 24 * 60 * 60; + $path = parse_url(JLOG_PATH); + if(!isset($path['path'])) $path['path'] = ""; + setcookie("jlog_userdata", urlencode(serialize($userdaten)), $cookielife, $path['path']."/"); + } + + function trash_cookie() { + $cookielife = time() - 3600; + setcookie("jlog_userdata", '', $cookielife, "/"); + } + + function new_sid() { + list($usec, $sec) = explode(' ', microtime()); + mt_srand((float) $sec + ((float) $usec * 100000)); + return $_SERVER["REMOTE_ADDR"]."-".time()."-".mt_rand(1000,9999); + } + + // Funcitons + + function do_comment($data, $nr) { + global $l, $bbcomments, $plugins; + + $meta = array_htmlspecialchars($data); + $comment = " +
  • +

    "; + if(!empty($meta['homepage'])) $comment .= ""; + if(!empty($meta['name'])) $comment .= $meta['name']; + else $comment .= $l['comments_anonym']; + if(!empty($meta['homepage'])) $comment .= ""; + $comment .= ""; + if(!empty($meta['city'])) $comment .= " ".$l['comments_from']." ".$meta['city']; + $comment .= " ".$l['comments_posted']." ".strftime(JLOG_DATE_COMMENT, $data['date']).":

    \n".$bbcomments->parse($data['content'])."
  • "; + + ### Plugin Hook + $comment = $plugins->callHook('showComment', $comment, $data, $nr); + + return $comment; + } +?> diff --git a/scripts/database.class.php b/scripts/database.class.php new file mode 100644 index 0000000..bf804da --- /dev/null +++ b/scripts/database.class.php @@ -0,0 +1,71 @@ +_sql = trim($sql); + $this->_result = mysql_query($this->_sql); + if(!$this->_result) { + $this->_errno = mysql_errno(); + $this->_error = mysql_error(); + } + } + + //Methoden + function error() + { + // Result-ID in einer tmp-Variablen speichern + $tmp = $this->_result; + // Variable in boolean umwandeln + $tmp = (bool)$tmp; + // Variable invertieren + $tmp = !$tmp; + // und zurückgeben + return $tmp; + } + + function getError() { + if($this->error()) { + $str = "request:\n".$this->_sql."\n"; + $str .= "response:\n".$this->_error."\n"; + $str .= "Errorcode: ".$this->_errno; + } + else $str = "No error."; + return $str; + } + function getErrno() { + return $this->_errno; + } + + function fetch() { + if($this->error()) { + echo "An Error has occurred, please check your MySQL-Query."; + $return = null; + } + else $return = mysql_fetch_assoc($this->_result); + return $return; + } + + function numRows() { + if($this->error()) { + $return = -1; + } + else $return = mysql_num_rows($this->_result); + return $return; + } + + function free() { + // Speicher freimachen + mysql_free_result($this->_result); + } + + } +?> diff --git a/scripts/do_template.php b/scripts/do_template.php new file mode 100644 index 0000000..66b85b6 --- /dev/null +++ b/scripts/do_template.php @@ -0,0 +1,121 @@ +'."\n"; +if(isset($c['meta']['robots'])) $c['meta']['aditionalheader'] .= ' '."\n"; +if(isset($c['meta']['keywords'])) $c['meta']['aditionalheader'] .= ' '."\n"; +if(isset($c['meta']['description'])) $c['meta']['aditionalheader'] .= ' '."\n"; +if(isset($c['meta']['date'])) $c['meta']['aditionalheader'] .= ' '; +if(isset($c['meta']['pingback'])) { + $c['meta']['aditionalheader'] .= "\n".' '; + header("X-Pingback: ".JLOG_PATH."/xmlrpc.php"); +} + +$c['meta']['aditionalheader'] .= +' + + + + + + '; + +// do this on admincenter +if(defined('JLOG_ADMIN')) { + // turn off cashing + header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); + header("Last-Modified: " . gmdate("D, d M Y H:i:s") ." GMT"); + header("Cache-Control: no-cache"); + header("Pragma: no-cache"); + header("Cache-Control: post-check=0, pre-check=0", FALSE); + // include admin.css + $c['meta']['aditionalheader'] .= "\n ".''; + $c['main'] = "
    ".$c['main']."
    "; +} + +$_search = array ( + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" +); + +$_replace = array ( + $l['language'], + htmlspecialchars(JLOG_WEBSITE, ENT_QUOTES), + htmlspecialchars($c['meta']['title']), + $c['meta']['aditionalheader'], + JLOG_PATH, + $l['content_skip'], + $l['meta_start'], + $l['subnav_aboutpage'], + JLOG_DESCRIPTION, + $l['content_search_topic'], + '', // bugfix + $l['content_search'], + $l['content_categorieslist_h'], + $l['subnav_current'], + $c['subnav_current'], + $l['content_archive'], + archive(), + $l['content_archivelink'], + $l['subnav_info'], + $l['subnav_rss'], + "XML - Fullpost XML - Summary", + "© ".date('Y')." ".JLOG_PUBLISHER.", ".$l['subnav_copyright'], + $c['main'], + $l['subnav_powered']." Jlog" +); + +$body = str_replace($_search, $_replace, $_body); + +$jlogTemplateTags = new JLOG_Tags($body); + + if(($categorieslist_tag = $jlogTemplateTags->getTag('categorieslist')) !== false) { + if(strlen($categorieslist_class = $jlogTemplateTags->getAttributeValue('categorieslist', 'class'))>0) $categorieslist_class = ' class="'.$categorieslist_class.'"'; + if( $categorieslist = $categories->output_whole_list("\n ".''."\n")) { + $body = str_replace($categorieslist_tag, $categorieslist, $body ); + } + else $body = str_replace($categorieslist_tag, '', $body ); + } + +$body = $plugins->callHook('body', $body, $jlogTemplateTags); diff --git a/scripts/general.func.php b/scripts/general.func.php new file mode 100644 index 0000000..1a449d2 --- /dev/null +++ b/scripts/general.func.php @@ -0,0 +1,313 @@ +callHook('permalink', $permalink, $date, $url, $section); + + return $permalink; +} + +function archive() { + if(JLOG_CLEAN_URL === true) return JLOG_PATH."/archive"; + else return JLOG_PATH."/archive.php"; +} + +// get year links +class Year_Links { + + function Year_Links($get, $start, $page, $l, $cat="") { + $date = getdate(); + $this->_now = $date['year']; + $this->_start = $start; + $this->_page = $page; + $this->_l = $l; + if(JLOG_CLEAN_URL === true) { + if($cat != "") { + list($tmp, $cat) = explode("=", $cat); + $this->cat = "/cat/".$cat; + } + } + elseif($cat !== "") $this->cat = $cat."&"; + + if($get >= $this->_start OR $get <= $this->_now AND preg_match("[0-9]", $get)) $this->year = $get; + else $this->year = $this->_now; + } + + function get_linklist() { + + for($y = $this->_start; $y <= $this->_now; $y++) { + if($y != $this->_start) $years_links .= " | "; + if($y == $this->year) $years_links .= " ".$y.""; + else { + if(JLOG_CLEAN_URL === true) $years_links .= " ".$y."\n"; + else $years_links .= " cat."y=".$y."'>".$y."\n"; + } + } + + return $this->_l['content_choose_year'].$years_links; + } + + function get_admin_linklist() { + + for($y = $this->_start; $y <= $this->_now; $y++) { + if($y != $this->_start) $years_links .= " | "; + if($y == $this->year) $years_links .= " ".$y.""; + else $years_links .= " ".$y."\n"; + } + + return $this->_l['content_choose_year'].$years_links; + + } + +// get selected year + function get_selected_year() { + return $this->year; + } +} + +// kill Magic Quotes +function strip($_data) { + if (!get_magic_quotes_gpc()) return $_data; + else { + if (is_array($_data)) foreach($_data as $key => $val) $_data[$key] = strip($val); + else $_data = stripslashes($_data); + return $_data; + } +} +// escape input for mysql +function escape_for_mysql($_data) { + if (is_array($_data)) foreach($_data as $key => $val) $_data[$key] = escape_for_mysql($val); + else $_data = mysql_escape_string($_data); + return $_data; +} +// htmlspecialchars a whole array +function array_htmlspecialchars($_data) { + if (is_array($_data)) foreach($_data as $key => $val) $_data[$key] = array_htmlspecialchars($val); + else $_data = htmlspecialchars($_data, ENT_QUOTES); + return $_data; +} +// Fehler ausgeben +function error_output($errors, $id = "", $headline = false) { +global $l; + $error = ""; + if($headline === false) $headline = $l["error"]; + if(isset($errors)) { + if(strlen($headline) > 0) $error = "\n

    ".$headline."

    "; + $error .= "\n
      \n"; + foreach($errors AS $f) $error .= "
    • ".$f."
    • \n"; + $error .= "
    \n"; + } + return $error; +} + +// Aus der Datenbank löschen (wird beim Kommentarlöschen gebraucht) + +function trash($id, $table) { + $sql = "DELETE FROM ".$table." WHERE id = '".$id."' LIMIT 1"; + + $trash = new Query($sql); + if($trash->error()) { + echo "
    \n";
    +        echo $trash->getError();
    +        echo "
    \n"; + die(); + } + return true; +} + +// output a teaser +function do_teaser($data, $cc, $pre = '

    ', $post = '

    ') { +global $l, $bbcode, $categories, $plugins; + + if(empty($data['date_url'])) $data['date_url'] = $data['date']; # fix for search.php + + $output = "\n
    \n"; + if($data['teaserpic'] != "") { + list($img_width, $img_height, $img_type, $img_attr) = @getimagesize(JLOG_BASEPATH.'img'.DIRECTORY_SEPARATOR.'t_'.$data['teaserpic']); + $output .= " \n"; + } + $output .= " ".$pre."".htmlspecialchars($data['topic'], ENT_QUOTES)."".$post." +

    ".$l['content_posted']." ".strftime(JLOG_DATE, $data['date']).$categories->output_assigned_links($data['id'])."

    "; + $output .= $bbcode->parse($data['teaser']); + + $output .="

    ".$l['content_more'].""; + + if($data['section'] == 'weblog') { + if(isset($cc[$data['id']]) AND $cc[$data['id']] != 0) $tmp_comments = " ".$l['content_comments']." (".$cc[$data['id']].")"; + elseif($data['comments'] === '0') $tmp_comments = $l['comments_teaser_closed']; + else $tmp_comments = " ".$l['content_comment_plz'].""; + $output .= " | ".$tmp_comments; + } + $output .= "

    \n
    \n"; + + ### Plugin Hook + $output = $plugins->callHook('doTeaser', $output, $data, $cc, $pre, $post); + + return $output; +} + +function do_entry($data, $cc = NULL, $section = 'weblog', $pre = '

    ', $post = '

    ') { +global $l, $bbcode, $categories, $plugins; + + $output = " +
    + ".$pre."".htmlspecialchars($data['topic'], ENT_QUOTES)."".$post."\n"; + + if($data['teaserpic'] != "" AND $data['teaserpiconblog'] == 1) { + list($img_width, $img_height, $img_type, $img_attr) = @getimagesize(JLOG_BASEPATH.'img'.DIRECTORY_SEPARATOR.'t_'.$data['teaserpic']); + $output .= ""; + } + + if($section == 'weblog' OR ($cat = $categories->output_assigned_links($data['id'])) != "") { + $output .= "

    "; + if($section == 'weblog') $output .= $l['content_posted']." ".strftime(JLOG_DATE, $data['date']); + $output .= $categories->output_assigned_links($data['id'])."

    "; + } + + $output .= $bbcode->parse($data['content']); + $path_parts = pathinfo($_SERVER['SCRIPT_NAME']); + + if($data['section'] == 'weblog' AND $path_parts['basename'] != 'log.php') { + if(isset($cc[$data['id']]) AND $cc[$data['id']] != 0) $tmp_comments = " ".$l['content_comments']." (".$cc[$data['id']].")"; + elseif($data['comments'] === '0') $tmp_comments = $l['comments_teaser_closed']; + else $tmp_comments = "".$l['content_comment_plz'].""; + $output .="

    ".$tmp_comments."

    "; + } + + if($section == 'weblog') $output .= '
    '; + $output .= "
    \n"; + + ### Plugin Hook + $output = $plugins->callHook('doEntry', $output, $data, $cc, $section); + + return $output; +} + +function count_comments() { + // -- Kommentare zählen + $sql = "SELECT reference, COUNT(*) as count FROM ".JLOG_DB_COMMENTS." WHERE type <> 'pingback' GROUP BY reference"; + $comments = new Query($sql); + if($comments->error()) { + echo "
    \n";
    +                echo $comments->getError();
    +             echo "
    \n"; + die(); + } + // -- Anzahl der jeweiligen Kommentare + $com = array(); + while($c = $comments->fetch()) $com[$c['reference']] = $c['count']; + + ### Plugin Hook + global $plugins; + $com = $plugins->callHook('countComments', $com); + + return $com; +} + +if (!function_exists('is_a')) { + function is_a($object, $class) + { + if (!is_object($object)) { + return false; + } + + if (get_class($object) == strtolower($class)) { + return true; + } else { + return is_subclass_of($object, $class); + } + } +} + +if (!function_exists("stripos")) { + function stripos($str,$needle,$offset=0) { + return strpos( strtolower($str), strtolower($needle), $offset ); + } +} + +if(!function_exists('str_ireplace')){ + function str_ireplace($search, $replace, $subject){ + if(is_array($search)){ + array_walk($search, create_function('&$pat, $key', '"/".preg_quote($pat, "/")."/i"')); + } + else{ + $search = '/'.preg_quote($search, '/').'/i'; + } + return preg_replace($search, $replace, $subject); + } +} + +if ( !function_exists('file_put_contents') && !defined('FILE_APPEND') ) { + define('FILE_APPEND', 1); + function file_put_contents($n, $d, $flag = false) { + $mode = ($flag == FILE_APPEND || strtoupper($flag) == 'FILE_APPEND') ? 'a' : 'w'; + $f = @fopen($n, $mode); + if ($f === false) { + return 0; + } else { + if (is_array($d)) $d = implode($d); + $bytes_written = fwrite($f, $d); + fclose($f); + return $bytes_written; + } + } +} + + +function my_serialize_cfg($arg) { + if(is_string($arg)) return "'".preg_replace("/'/","\\'",$arg)."'"; + elseif(is_integer($arg)) return (string)$arg; + elseif(is_float($arg)) return (string)$arg; + elseif(is_null($arg)) return 'NULL'; + elseif(is_bool($arg)) { + if($arg) return 'true'; + else return 'false'; + } + elseif(is_array($arg)) { + $retval = 'Array('; + foreach($arg as $key => $value) { + $retval .= my_serialize_cfg($key).' => '.my_serialize_cfg($value).','; + } + $retval .= ')'; + return $retval; + } + else die("unsupported type! ".gettype($arg)); +} + +class JLOG_Tags { + var $tree = array(); + + function JLOG_Tags($body) { + preg_match_all('/]*)\/?>(<\/(\1):(\2)>)?/ims', $body, $this->tree); + } + + function getTag($tagname) { + if(($tagnr = array_search($tagname, $this->tree[1])) !== false) return $this->tree[0][$tagnr]; + else return false; + } + + function getAttributeValue($tagname, $attribute) { + $pattern = '/(?:^|\s)([a-z]\w+)(?:=)(?:(?:\'([^\']+)\')|(?:"([^"]*)")|([^\s,]+))/i'; + if(($tagnr = array_search($tagname, $this->tree[1])) !== false) { + preg_match_all($pattern, $this->tree[2][ $tagnr ], $matches, PREG_SET_ORDER); + $a = count($matches); + for($i=0;$i<$a;$i++) { + if($matches[$i][1] == $attribute) return $matches[$i][3]; + } + } + else return; + } +} +?> \ No newline at end of file diff --git a/scripts/ixr-library.inc.php b/scripts/ixr-library.inc.php new file mode 100644 index 0000000..26f4b3c --- /dev/null +++ b/scripts/ixr-library.inc.php @@ -0,0 +1,817 @@ + htmlspecialchars) + Site: http://scripts.incutio.com/xmlrpc/ + Manual: http://scripts.incutio.com/xmlrpc/manual.php + Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php +*/ + + +class IXR_Value { + var $data; + var $type; + function IXR_Value ($data, $type = false) { + $this->data = $data; + if (!$type) { + $type = $this->calculateType(); + } + $this->type = $type; + if ($type == 'struct') { + /* Turn all the values in the array in to new IXR_Value objects */ + foreach ($this->data as $key => $value) { + $this->data[$key] = new IXR_Value($value); + } + } + if ($type == 'array') { + for ($i = 0, $j = count($this->data); $i < $j; $i++) { + $this->data[$i] = new IXR_Value($this->data[$i]); + } + } + } + function calculateType() { + if ($this->data === true || $this->data === false) { + return 'boolean'; + } + if (is_integer($this->data)) { + return 'int'; + } + if (is_double($this->data)) { + return 'double'; + } + // Deal with IXR object types base64 and date + if (is_object($this->data) && is_a($this->data, 'IXR_Date')) { + return 'date'; + } + if (is_object($this->data) && is_a($this->data, 'IXR_Base64')) { + return 'base64'; + } + // If it is a normal PHP object convert it in to a struct + if (is_object($this->data)) { + $this->data = get_object_vars($this->data); + return 'struct'; + } + if (!is_array($this->data)) { + return 'string'; + } + /* We have an array - is it an array or a struct ? */ + if ($this->isStruct($this->data)) { + return 'struct'; + } else { + return 'array'; + } + } + function getXml() { + /* Return XML for this value */ + switch ($this->type) { + case 'boolean': + return ''.(($this->data) ? '1' : '0').''; + break; + case 'int': + return ''.$this->data.''; + break; + case 'double': + return ''.$this->data.''; + break; + case 'string': + return ''.htmlspecialchars($this->data).''; + break; + case 'array': + $return = ''."\n"; + foreach ($this->data as $item) { + $return .= ' '.$item->getXml()."\n"; + } + $return .= ''; + return $return; + break; + case 'struct': + $return = ''."\n"; + foreach ($this->data as $name => $value) { + $return .= " $name"; + $return .= $value->getXml()."\n"; + } + $return .= ''; + return $return; + break; + case 'date': + case 'base64': + return $this->data->getXml(); + break; + } + return false; + } + function isStruct($array) { + /* Nasty function to check if an array is a struct or not */ + $expected = 0; + foreach ($array as $key => $value) { + if ((string)$key != (string)$expected) { + return true; + } + $expected++; + } + return false; + } +} + + +class IXR_Message { + var $message; + var $messageType; // methodCall / methodResponse / fault + var $faultCode; + var $faultString; + var $methodName; + var $params; + // Current variable stacks + var $_arraystructs = array(); // The stack used to keep track of the current array/struct + var $_arraystructstypes = array(); // Stack keeping track of if things are structs or array + var $_currentStructName = array(); // A stack as well + var $_param; + var $_value; + var $_currentTag; + var $_currentTagContents; + // The XML parser + var $_parser; + function IXR_Message ($message) { + $this->message = $message; + } + function parse() { + // first remove the XML declaration + $this->message = preg_replace('/<\?xml(.*)?\?'.'>/', '', $this->message); + if (trim($this->message) == '') { + return false; + } + $this->_parser = xml_parser_create(); + // Set XML parser to take the case of tags in to account + xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, false); + // Set XML parser callback functions + xml_set_object($this->_parser, $this); + xml_set_element_handler($this->_parser, 'tag_open', 'tag_close'); + xml_set_character_data_handler($this->_parser, 'cdata'); + if (!xml_parse($this->_parser, $this->message)) { + /* die(sprintf('XML error: %s at line %d', + xml_error_string(xml_get_error_code($this->_parser)), + xml_get_current_line_number($this->_parser))); */ + return false; + } + xml_parser_free($this->_parser); + // Grab the error messages, if any + if ($this->messageType == 'fault') { + $this->faultCode = $this->params[0]['faultCode']; + $this->faultString = $this->params[0]['faultString']; + } + return true; + } + function tag_open($parser, $tag, $attr) { + $this->currentTag = $tag; + switch($tag) { + case 'methodCall': + case 'methodResponse': + case 'fault': + $this->messageType = $tag; + break; + /* Deal with stacks of arrays and structs */ + case 'data': // data is to all intents and puposes more interesting than array + $this->_arraystructstypes[] = 'array'; + $this->_arraystructs[] = array(); + break; + case 'struct': + $this->_arraystructstypes[] = 'struct'; + $this->_arraystructs[] = array(); + break; + } + } + function cdata($parser, $cdata) { + $this->_currentTagContents .= $cdata; + } + function tag_close($parser, $tag) { + $valueFlag = false; + switch($tag) { + case 'int': + case 'i4': + $value = (int)trim($this->_currentTagContents); + $this->_currentTagContents = ''; + $valueFlag = true; + break; + case 'double': + $value = (double)trim($this->_currentTagContents); + $this->_currentTagContents = ''; + $valueFlag = true; + break; + case 'string': + $value = (string)trim($this->_currentTagContents); + $this->_currentTagContents = ''; + $valueFlag = true; + break; + case 'dateTime.iso8601': + $value = new IXR_Date(trim($this->_currentTagContents)); + // $value = $iso->getTimestamp(); + $this->_currentTagContents = ''; + $valueFlag = true; + break; + case 'value': + // "If no type is indicated, the type is string." + if (trim($this->_currentTagContents) != '') { + $value = (string)$this->_currentTagContents; + $this->_currentTagContents = ''; + $valueFlag = true; + } + break; + case 'boolean': + $value = (boolean)trim($this->_currentTagContents); + $this->_currentTagContents = ''; + $valueFlag = true; + break; + case 'base64': + $value = base64_decode($this->_currentTagContents); + $this->_currentTagContents = ''; + $valueFlag = true; + break; + /* Deal with stacks of arrays and structs */ + case 'data': + case 'struct': + $value = array_pop($this->_arraystructs); + array_pop($this->_arraystructstypes); + $valueFlag = true; + break; + case 'member': + array_pop($this->_currentStructName); + break; + case 'name': + $this->_currentStructName[] = trim($this->_currentTagContents); + $this->_currentTagContents = ''; + break; + case 'methodName': + $this->methodName = trim($this->_currentTagContents); + $this->_currentTagContents = ''; + break; + } + if ($valueFlag) { + /* + if (!is_array($value) && !is_object($value)) { + $value = trim($value); + } + */ + if (count($this->_arraystructs) > 0) { + // Add value to struct or array + if ($this->_arraystructstypes[count($this->_arraystructstypes)-1] == 'struct') { + // Add to struct + $this->_arraystructs[count($this->_arraystructs)-1][$this->_currentStructName[count($this->_currentStructName)-1]] = $value; + } else { + // Add to array + $this->_arraystructs[count($this->_arraystructs)-1][] = $value; + } + } else { + // Just add as a paramater + $this->params[] = $value; + } + } + } +} + + +class IXR_Server { + var $data; + var $callbacks = array(); + var $message; + var $capabilities; + function IXR_Server($callbacks = false, $data = false) { + $this->setCapabilities(); + if ($callbacks) { + $this->callbacks = $callbacks; + } + $this->setCallbacks(); + $this->serve($data); + } + function serve($data = false) { + if (!$data) { + global $HTTP_RAW_POST_DATA; + if (!$HTTP_RAW_POST_DATA) { + die('XML-RPC server accepts POST requests only.'); + } + $data = $HTTP_RAW_POST_DATA; + } + $this->message = new IXR_Message($data); + if (!$this->message->parse()) { + $this->error(-32700, 'parse error. not well formed'); + } + if ($this->message->messageType != 'methodCall') { + $this->error(-32600, 'server error. invalid xml-rpc. not conforming to spec. Request must be a methodCall'); + } + $result = $this->call($this->message->methodName, $this->message->params); + // Is the result an error? + if (is_a($result, 'IXR_Error')) { + $this->error($result); + } + // Encode the result + $r = new IXR_Value($result); + $resultxml = $r->getXml(); + // Create the XML + $xml = << + + + + $resultxml + + + + + +EOD; + // Send it + $this->output($xml); + } + function call($methodname, $args) { + if (!$this->hasMethod($methodname)) { + return new IXR_Error(-32601, 'server error. requested method '.$methodname.' does not exist.'); + } + $method = $this->callbacks[$methodname]; + // Perform the callback and send the response + if (count($args) == 1) { + // If only one paramater just send that instead of the whole array + $args = $args[0]; + } + // Are we dealing with a function or a method? + if (substr($method, 0, 5) == 'this:') { + // It's a class method - check it exists + $method = substr($method, 5); + if (!method_exists($this, $method)) { + return new IXR_Error(-32601, 'server error. requested class method "'.$method.'" does not exist.'); + } + // Call the method + $result = $this->$method($args); + } else { + // It's a function - does it exist? + if (!function_exists($method)) { + return new IXR_Error(-32601, 'server error. requested function "'.$method.'" does not exist.'); + } + // Call the function + $result = $method($args); + } + return $result; + } + + function error($error, $message = false) { + // Accepts either an error object or an error code and message + if ($message && !is_object($error)) { + $error = new IXR_Error($error, $message); + } + $this->output($error->getXml()); + } + function output($xml) { + $xml = ''."\n".$xml; + $length = strlen($xml); + header('Connection: close'); + header('Content-Length: '.$length); + header('Content-Type: text/xml'); + header('Date: '.date('r')); + echo $xml; + exit; + } + function hasMethod($method) { + return in_array($method, array_keys($this->callbacks)); + } + function setCapabilities() { + // Initialises capabilities array + $this->capabilities = array( + 'xmlrpc' => array( + 'specUrl' => 'http://www.xmlrpc.com/spec', + 'specVersion' => 1 + ), + 'faults_interop' => array( + 'specUrl' => 'http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php', + 'specVersion' => 20010516 + ), + 'system.multicall' => array( + 'specUrl' => 'http://www.xmlrpc.com/discuss/msgReader$1208', + 'specVersion' => 1 + ), + ); + } + function getCapabilities($args) { + return $this->capabilities; + } + function setCallbacks() { + $this->callbacks['system.getCapabilities'] = 'this:getCapabilities'; + $this->callbacks['system.listMethods'] = 'this:listMethods'; + $this->callbacks['system.multicall'] = 'this:multiCall'; + } + function listMethods($args) { + // Returns a list of methods - uses array_reverse to ensure user defined + // methods are listed before server defined methods + return array_reverse(array_keys($this->callbacks)); + } + function multiCall($methodcalls) { + // See http://www.xmlrpc.com/discuss/msgReader$1208 + $return = array(); + foreach ($methodcalls as $call) { + $method = $call['methodName']; + $params = $call['params']; + if ($method == 'system.multicall') { + $result = new IXR_Error(-32600, 'Recursive calls to system.multicall are forbidden'); + } else { + $result = $this->call($method, $params); + } + if (is_a($result, 'IXR_Error')) { + $return[] = array( + 'faultCode' => $result->code, + 'faultString' => $result->message + ); + } else { + $return[] = array($result); + } + } + return $return; + } +} + +class IXR_Request { + var $method; + var $args; + var $xml; + function IXR_Request($method, $args) { + $this->method = $method; + $this->args = $args; + $this->xml = << + +{$this->method} + + +EOD; + foreach ($this->args as $arg) { + $this->xml .= ''; + $v = new IXR_Value($arg); + $this->xml .= $v->getXml(); + $this->xml .= "\n"; + } + $this->xml .= ''; + } + function getLength() { + return strlen($this->xml); + } + function getXml() { + return $this->xml; + } +} + + +class IXR_Client { + var $server; + var $port; + var $path; + var $useragent; + var $response; + var $message = false; + var $debug = false; + // Storage place for an error message + var $error = false; + function IXR_Client($server, $path = false, $port = 80) { + if (!$path) { + // Assume we have been given a URL instead + $bits = parse_url($server); + $this->server = $bits['host']; + $this->port = isset($bits['port']) ? $bits['port'] : 80; + $this->path = isset($bits['path']) ? $bits['path'] : '/'; + // Make absolutely sure we have a path + if (!$this->path) { + $this->path = '/'; + } + } else { + $this->server = $server; + $this->path = $path; + $this->port = $port; + } + $this->useragent = 'The Incutio XML-RPC PHP Library'; + } + function query() { + $args = func_get_args(); + $method = array_shift($args); + $request = new IXR_Request($method, $args); + $length = $request->getLength(); + $xml = $request->getXml(); + $r = "\r\n"; + $request = "POST {$this->path} HTTP/1.0$r"; + $request .= "Host: {$this->server}$r"; + $request .= "Content-Type: text/xml$r"; + $request .= "User-Agent: {$this->useragent}$r"; + $request .= "Content-length: {$length}$r$r"; + $request .= $xml; + // Now send the request + if ($this->debug) { + echo '
    '.htmlspecialchars($request)."\n
    \n\n"; + } + $fp = @fsockopen($this->server, $this->port); + if (!$fp) { + $this->error = new IXR_Error(-32300, 'transport error - could not open socket'); + return false; + } + fputs($fp, $request); + $contents = ''; + $gotFirstLine = false; + $gettingHeaders = true; + while (!feof($fp)) { + $line = fgets($fp, 4096); + if (!$gotFirstLine) { + // Check line for '200' + if (strstr($line, '200') === false) { + $this->error = new IXR_Error(-32300, 'transport error - HTTP status code was not 200'); + return false; + } + $gotFirstLine = true; + } + if (trim($line) == '') { + $gettingHeaders = false; + } + if (!$gettingHeaders) { + $contents .= trim($line)."\n"; + } + } + if ($this->debug) { + echo '
    '.htmlspecialchars($contents)."\n
    \n\n"; + } + // Now parse what we've got back + $this->message = new IXR_Message($contents); + if (!$this->message->parse()) { + // XML error + $this->error = new IXR_Error(-32700, 'parse error. not well formed'); + return false; + } + // Is the message a fault? + if ($this->message->messageType == 'fault') { + $this->error = new IXR_Error($this->message->faultCode, $this->message->faultString); + return false; + } + // Message must be OK + return true; + } + function getResponse() { + // methodResponses can only have one param - return that + return $this->message->params[0]; + } + function isError() { + return (is_object($this->error)); + } + function getErrorCode() { + return $this->error->code; + } + function getErrorMessage() { + return $this->error->message; + } +} + + +class IXR_Error { + var $code; + var $message; + function IXR_Error($code, $message) { + $this->code = $code; + $this->message = $message; + } + function getXml() { + $xml = << + + + + + faultCode + {$this->code} + + + faultString + {$this->message} + + + + + + +EOD; + return $xml; + } +} + + +class IXR_Date { + var $year; + var $month; + var $day; + var $hour; + var $minute; + var $second; + function IXR_Date($time) { + // $time can be a PHP timestamp or an ISO one + if (is_numeric($time)) { + $this->parseTimestamp($time); + } else { + $this->parseIso($time); + } + } + function parseTimestamp($timestamp) { + $this->year = date('Y', $timestamp); + $this->month = date('Y', $timestamp); + $this->day = date('Y', $timestamp); + $this->hour = date('H', $timestamp); + $this->minute = date('i', $timestamp); + $this->second = date('s', $timestamp); + } + function parseIso($iso) { + $this->year = substr($iso, 0, 4); + $this->month = substr($iso, 4, 2); + $this->day = substr($iso, 6, 2); + $this->hour = substr($iso, 9, 2); + $this->minute = substr($iso, 12, 2); + $this->second = substr($iso, 15, 2); + } + function getIso() { + return $this->year.$this->month.$this->day.'T'.$this->hour.':'.$this->minute.':'.$this->second; + } + function getXml() { + return ''.$this->getIso().''; + } + function getTimestamp() { + return mktime($this->hour, $this->minute, $this->second, $this->month, $this->day, $this->year); + } +} + + +class IXR_Base64 { + var $data; + function IXR_Base64($data) { + $this->data = $data; + } + function getXml() { + return ''.base64_encode($this->data).''; + } +} + + +class IXR_IntrospectionServer extends IXR_Server { + var $signatures; + var $help; + function IXR_IntrospectionServer() { + $this->setCallbacks(); + $this->setCapabilities(); + $this->capabilities['introspection'] = array( + 'specUrl' => 'http://xmlrpc.usefulinc.com/doc/reserved.html', + 'specVersion' => 1 + ); + $this->addCallback( + 'system.methodSignature', + 'this:methodSignature', + array('array', 'string'), + 'Returns an array describing the return type and required parameters of a method' + ); + $this->addCallback( + 'system.getCapabilities', + 'this:getCapabilities', + array('struct'), + 'Returns a struct describing the XML-RPC specifications supported by this server' + ); + $this->addCallback( + 'system.listMethods', + 'this:listMethods', + array('array'), + 'Returns an array of available methods on this server' + ); + $this->addCallback( + 'system.methodHelp', + 'this:methodHelp', + array('string', 'string'), + 'Returns a documentation string for the specified method' + ); + } + function addCallback($method, $callback, $args, $help) { + $this->callbacks[$method] = $callback; + $this->signatures[$method] = $args; + $this->help[$method] = $help; + } + function call($methodname, $args) { + // Make sure it's in an array + if ($args && !is_array($args)) { + $args = array($args); + } + // Over-rides default call method, adds signature check + if (!$this->hasMethod($methodname)) { + return new IXR_Error(-32601, 'server error. requested method "'.$this->message->methodName.'" not specified.'); + } + $method = $this->callbacks[$methodname]; + $signature = $this->signatures[$methodname]; + $returnType = array_shift($signature); + // Check the number of arguments + if (count($args) != count($signature)) { + // print 'Num of args: '.count($args).' Num in signature: '.count($signature); + return new IXR_Error(-32602, 'server error. wrong number of method parameters'); + } + // Check the argument types + $ok = true; + $argsbackup = $args; + for ($i = 0, $j = count($args); $i < $j; $i++) { + $arg = array_shift($args); + $type = array_shift($signature); + switch ($type) { + case 'int': + case 'i4': + if (is_array($arg) || !is_int($arg)) { + $ok = false; + } + break; + case 'base64': + case 'string': + if (!is_string($arg)) { + $ok = false; + } + break; + case 'boolean': + if ($arg !== false && $arg !== true) { + $ok = false; + } + break; + case 'float': + case 'double': + if (!is_float($arg)) { + $ok = false; + } + break; + case 'date': + case 'dateTime.iso8601': + if (!is_a($arg, 'IXR_Date')) { + $ok = false; + } + break; + } + if (!$ok) { + return new IXR_Error(-32602, 'server error. invalid method parameters'); + } + } + // It passed the test - run the "real" method call + return parent::call($methodname, $argsbackup); + } + function methodSignature($method) { + if (!$this->hasMethod($method)) { + return new IXR_Error(-32601, 'server error. requested method "'.$method.'" not specified.'); + } + // We should be returning an array of types + $types = $this->signatures[$method]; + $return = array(); + foreach ($types as $type) { + switch ($type) { + case 'string': + $return[] = 'string'; + break; + case 'int': + case 'i4': + $return[] = 42; + break; + case 'double': + $return[] = 3.1415; + break; + case 'dateTime.iso8601': + $return[] = new IXR_Date(time()); + break; + case 'boolean': + $return[] = true; + break; + case 'base64': + $return[] = new IXR_Base64('base64'); + break; + case 'array': + $return[] = array('array'); + break; + case 'struct': + $return[] = array('struct' => 'struct'); + break; + } + } + return $return; + } + function methodHelp($method) { + return $this->help[$method]; + } +} + + +class IXR_ClientMulticall extends IXR_Client { + var $calls = array(); + function IXR_ClientMulticall($server, $path = false, $port = 80) { + parent::IXR_Client($server, $path, $port); + $this->useragent = 'The Incutio XML-RPC PHP Library (multicall client)'; + } + function addCall() { + $args = func_get_args(); + $methodName = array_shift($args); + $struct = array( + 'methodName' => $methodName, + 'params' => $args + ); + $this->calls[] = $struct; + } + function query() { + // Prepare multicall, then call the parent::query() method + return parent::query('system.multicall', $this->calls); + } +} + +?> diff --git a/scripts/javascripts.js b/scripts/javascripts.js new file mode 100644 index 0000000..5c79bbc --- /dev/null +++ b/scripts/javascripts.js @@ -0,0 +1,332 @@ +// TODO: I'd like to have an extra "js" directory for all JavaScripts +// a theme needs. + +/* + * Jlogs not minified version of JavaScript + */ + +function jlog_bbcode(insText, aTag, eTag) { + if (!insText) { return ''; } + return aTag + insText + eTag; +} + +function jlog_bbcode_link(insText, aTag, eTag) { + var url = new RegExp('^(http://|https://|www.|ftp://|news:|mailto:).'); + var www = new RegExp('^(www.).'); + var mail = new RegExp('^[^@]+@[^@]+\.[a-zA-Z]+$'); + var http = new RegExp('^(http://)$'); + var node, href; + if((url.test(insText)) || (mail.test(insText))) { + href = insText; + if (mail.test(href)) { href = 'mailto:' + insText; } + if (www.test(href)) { href = 'http://' + href; } + node = prompt(jlog_l_comments_url_node); + if((node !== null) && (node !== '')) { insText = '[url=' + href + ']' + node + eTag; } + else if(node === '') { insText = aTag + href + eTag; } + } + else { + node = insText; + if(node === '') { node = prompt(jlog_l_comments_url_node, insText); } + href = prompt(jlog_l_comments_url_href, 'http://'); + if (http.test(href)) { return insText; } + if (www.test(href)) { href = 'http://' + href; } + if(((node !== null) && (node !== '')) && ((href !== null) && (href !== ''))) { + insText = '[url=' + href + ']' + node + eTag; + } + else if((href !== null) && (href !== '')) { insText = aTag + href + eTag; } + } + return insText; +} + + +function jlog_bbcode_list(o_insText, aTag, eTag) { + var insText = o_insText.replace(/(\n|\r|\r\n)(?=(.+))/g, '$1[*]'); + return '[list]\n[*]' + insText + eTag + '\n'; +} + +function jlog_bbcode_insert(aTag, eTag, completeText) { + var input = document.forms.entryform.elements.content; + input.focus(); + var insText; + /* für Internet Explorer und Opera >= 8 */ + if(typeof document.selection != 'undefined') { + /* Einfügen des Formatierungscodes */ + var range = document.selection.createRange(); + insText = range.text; + if (aTag === '[url]') { range.text = jlog_bbcode_link(insText, aTag, eTag); } + else if(eTag === '[/list]') { range.text = jlog_bbcode_list(insText, aTag, eTag); } + else { range.text = jlog_bbcode(insText, aTag, eTag); } + + /* Anpassen der Cursorposition */ + range = document.selection.createRange(); + if (insText.length === 0) { + range.move('character', -eTag.length); + } else { + range.moveStart('character', insText.length); + } + range.select(); + } + /* für neuere auf Gecko basierende Browser */ + else if(typeof input.selectionStart != 'undefined') + { + /* Einfügen des Formatierungscodes */ + var start = input.selectionStart; + var end = input.selectionEnd; + insText = input.value.substring(start, end); + if(aTag === '[url]') { insText = jlog_bbcode_link(insText, aTag, eTag); } + else if(eTag === '[/list]') { insText = jlog_bbcode_list(insText, aTag, eTag); } + else { insText = jlog_bbcode(insText, aTag, eTag); } + + input.value = input.value.substr(0, start) + insText + input.value.substr(end); + + /* Anpassen der Cursorposition */ + var pos; + if (insText.length === 0) { + pos = start + aTag.length + eTag.length; + } else { + pos = start + insText.length; + } + input.selectionStart = pos; + input.selectionEnd = pos; + } + /* für die übrigen Browser */ + else + { + /* Einfügen des Formatierungscodes */ + if(aTag === '[url]') { insText = jlog_bbcode_link('', aTag, eTag); } + else if(eTag === '[/list]') { insText = jlog_bbcode_list('', aTag, eTag); } + else { insText = jlog_bbcode(prompt(jlog_l_comments_plz_format_txt), aTag, eTag); } + input.value += insText; + } +} + +function jlog_bbcode_img(jfilename) { + var jclass = ''; + var jalt = ''; + if ( document.getElementById("class").value !== '') { + jclass = ' class=\"' + document.getElementById("class").value + '\"'; + } + if ( document.getElementById("alt").value !== '') { + jalt = ' alt=\"' + document.getElementById("alt").value + '\"'; + } + var jimg = '[img' + jclass + jalt + ']' + jfilename + '[/img]'; + opener.parent.jlog_insertAtCursor(jimg); + window.close(); +} + +// from http://www.alexking.org/blog/2003/06/02/inserting-at-the-cursor-using-javascript/ +function jlog_insertAtCursor(insText) { + //IE and Opera support + var field = document.forms.entryform.elements.content; + if (document.selection) { + field.focus(); + var sel = document.selection.createRange(); + sel.text = insText; + } + //MOZILLA/NETSCAPE support + else if (field.selectionStart || field.selectionStart == '0') { + var startPos = field.selectionStart; + var endPos = field.selectionEnd; + field.value = field.value.substring(0, startPos) + insText + field.value.substring(endPos, field.value.length); + } else { + field.value += insText; + } +} + +var show = true; + +function jlog_killcomments() { + + var commentslist = document.getElementById("commentslist"); + var pingbacks_header = document.getElementById("pingbacks"); + var pingbacks_list = document.getElementById("pingbackslist"); + + if (show) { + document.getElementById("hidecomments").firstChild.nodeValue = jlog_l_comments_show; + show=false; + if(pingbacks_header) { pingbacks_header.style.display = "none"; } + if(pingbacks_list) { pingbacks_list.style.display = "none"; } + document.getElementById("comments").style.display = "none"; + document.getElementById("entryform").style.display = "none"; + if(commentslist) { commentslist.style.display = "none"; } + } + else { + document.getElementById("hidecomments").firstChild.nodeValue = jlog_l_comments_hide; + show=true; + if(pingbacks_header) { pingbacks_header.style.display = "block"; } + if(pingbacks_list) { pingbacks_list.style.display = "block"; } + document.getElementById("comments").style.display = "block"; + document.getElementById("entryform").style.display = "block"; + if(commentslist) { commentslist.style.display = "block"; } + } +} + +var jlog_bbcode_br; + +function jlog_bbcode_do_button(titel, aTag, eTag) { + var button = document.createElement("input"); + button.onclick = function() { + jlog_bbcode_insert(aTag, eTag); + return false; + }; + button.className = "jlog_bbcode"; + button.type = "button"; + button.value = titel; + jlog_bbcode_br.parentNode.insertBefore(button, jlog_bbcode_br); +} + +/* from http://www.kryogenix.org/code/browser/searchhi/ */ +function jlog_highlightWord(node,word) { + + if (node.hasChildNodes) { + for (var hi_cn=0;hi_cn + * @author Stig Bakken + * @author Tomas V.V.Cox + * @author Greg Beaver + * @copyright 1997-2005 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: PEAR.php,v 1.96 2005/09/21 00:12:35 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 0.1 + */ + +define('PEAR_ERROR_RETURN', 1); +define('PEAR_ERROR_PRINT', 2); +define('PEAR_ERROR_TRIGGER', 4); +define('PEAR_ERROR_DIE', 8); +define('PEAR_ERROR_CALLBACK', 16); + +define('PEAR_ERROR_EXCEPTION', 32); + +define('PEAR_ZE2', (function_exists('version_compare') && + version_compare(zend_version(), "2-dev", "ge"))); + +if (substr(PHP_OS, 0, 3) == 'WIN') { + define('OS_WINDOWS', true); + define('OS_UNIX', false); + define('PEAR_OS', 'Windows'); +} else { + define('OS_WINDOWS', false); + define('OS_UNIX', true); + define('PEAR_OS', 'Unix'); // blatant assumption +} + +if (!defined('PATH_SEPARATOR')) { + if (OS_WINDOWS) { + define('PATH_SEPARATOR', ';'); + } else { + define('PATH_SEPARATOR', ':'); + } +} + +$GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_RETURN; +$GLOBALS['_PEAR_default_error_options'] = E_USER_NOTICE; +$GLOBALS['_PEAR_destructor_object_list'] = array(); +$GLOBALS['_PEAR_shutdown_funcs'] = array(); +$GLOBALS['_PEAR_error_handler_stack'] = array(); + +@ini_set('track_errors', true); + +class PEAR +{ + + var $_debug = false; + var $_default_error_mode = null; + var $_default_error_options = null; + var $_default_error_handler = ''; + var $_error_class = 'PEAR_Error'; + var $_expected_errors = array(); + + function PEAR($error_class = null) + { + $classname = strtolower(get_class($this)); + if ($this->_debug) { + print "PEAR constructor called, class=$classname\n"; + } + if ($error_class !== null) { + $this->_error_class = $error_class; + } + while ($classname && strcasecmp($classname, "pear")) { + $destructor = "_$classname"; + if (method_exists($this, $destructor)) { + global $_PEAR_destructor_object_list; + $_PEAR_destructor_object_list[] = &$this; + if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) { + register_shutdown_function("_PEAR_call_destructors"); + $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true; + } + break; + } else { + $classname = get_parent_class($classname); + } + } + } + + function _PEAR() { + if ($this->_debug) { + printf("PEAR destructor called, class=%s\n", strtolower(get_class($this))); + } + } + + function &getStaticProperty($class, $var) + { + static $properties; + return $properties[$class][$var]; + } + + function registerShutdownFunc($func, $args = array()) + { + $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args); + } + + function isError($data, $code = null) + { + if (is_a($data, 'PEAR_Error')) { + if (is_null($code)) { + return true; + } elseif (is_string($code)) { + return $data->getMessage() == $code; + } else { + return $data->getCode() == $code; + } + } + return false; + } + + function setErrorHandling($mode = null, $options = null) + { + if (isset($this) && is_a($this, 'PEAR')) { + $setmode = &$this->_default_error_mode; + $setoptions = &$this->_default_error_options; + } else { + $setmode = &$GLOBALS['_PEAR_default_error_mode']; + $setoptions = &$GLOBALS['_PEAR_default_error_options']; + } + + switch ($mode) { + case PEAR_ERROR_EXCEPTION: + case PEAR_ERROR_RETURN: + case PEAR_ERROR_PRINT: + case PEAR_ERROR_TRIGGER: + case PEAR_ERROR_DIE: + case null: + $setmode = $mode; + $setoptions = $options; + break; + + case PEAR_ERROR_CALLBACK: + $setmode = $mode; + // class/object method callback + if (is_callable($options)) { + $setoptions = $options; + } else { + trigger_error("invalid error callback", E_USER_WARNING); + } + break; + + default: + trigger_error("invalid error mode", E_USER_WARNING); + break; + } + } + + function expectError($code = '*') + { + if (is_array($code)) { + array_push($this->_expected_errors, $code); + } else { + array_push($this->_expected_errors, array($code)); + } + return sizeof($this->_expected_errors); + } + + function popExpect() + { + return array_pop($this->_expected_errors); + } + + function _checkDelExpect($error_code) + { + $deleted = false; + + foreach ($this->_expected_errors AS $key => $error_array) { + if (in_array($error_code, $error_array)) { + unset($this->_expected_errors[$key][array_search($error_code, $error_array)]); + $deleted = true; + } + + if (0 == count($this->_expected_errors[$key])) { + unset($this->_expected_errors[$key]); + } + } + return $deleted; + } + + function delExpect($error_code) + { + $deleted = false; + + if ((is_array($error_code) && (0 != count($error_code)))) { + foreach($error_code as $key => $error) { + if ($this->_checkDelExpect($error)) { + $deleted = true; + } else { + $deleted = false; + } + } + return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME + } elseif (!empty($error_code)) { + if ($this->_checkDelExpect($error_code)) { + return true; + } else { + return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME + } + } else { + return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME + } + } + + function &raiseError($message = null, + $code = null, + $mode = null, + $options = null, + $userinfo = null, + $error_class = null, + $skipmsg = false) + { + // The error is yet a PEAR error object + if (is_object($message)) { + $code = $message->getCode(); + $userinfo = $message->getUserInfo(); + $error_class = $message->getType(); + $message->error_message_prefix = ''; + $message = $message->getMessage(); + } + + if (isset($this) && isset($this->_expected_errors) && sizeof($this->_expected_errors) > 0 && sizeof($exp = end($this->_expected_errors))) { + if ($exp[0] == "*" || + (is_int(reset($exp)) && in_array($code, $exp)) || + (is_string(reset($exp)) && in_array($message, $exp))) { + $mode = PEAR_ERROR_RETURN; + } + } + if ($mode === null) { + if (isset($this) && isset($this->_default_error_mode)) { + $mode = $this->_default_error_mode; + $options = $this->_default_error_options; + } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) { + $mode = $GLOBALS['_PEAR_default_error_mode']; + $options = $GLOBALS['_PEAR_default_error_options']; + } + } + + if ($error_class !== null) { + $ec = $error_class; + } elseif (isset($this) && isset($this->_error_class)) { + $ec = $this->_error_class; + } else { + $ec = 'PEAR_Error'; + } + if ($skipmsg) { + $a = &new $ec($code, $mode, $options, $userinfo); + return $a; + } else { + $a = &new $ec($message, $code, $mode, $options, $userinfo); + return $a; + } + } + + function &throwError($message = null, + $code = null, + $userinfo = null) + { + if (isset($this) && is_a($this, 'PEAR')) { + $a = &$this->raiseError($message, $code, null, null, $userinfo); + return $a; + } else { + $a = &PEAR::raiseError($message, $code, null, null, $userinfo); + return $a; + } + } + + function staticPushErrorHandling($mode, $options = null) + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + $def_mode = &$GLOBALS['_PEAR_default_error_mode']; + $def_options = &$GLOBALS['_PEAR_default_error_options']; + $stack[] = array($def_mode, $def_options); + switch ($mode) { + case PEAR_ERROR_EXCEPTION: + case PEAR_ERROR_RETURN: + case PEAR_ERROR_PRINT: + case PEAR_ERROR_TRIGGER: + case PEAR_ERROR_DIE: + case null: + $def_mode = $mode; + $def_options = $options; + break; + + case PEAR_ERROR_CALLBACK: + $def_mode = $mode; + if (is_callable($options)) { + $def_options = $options; + } else { + trigger_error("invalid error callback", E_USER_WARNING); + } + break; + + default: + trigger_error("invalid error mode", E_USER_WARNING); + break; + } + $stack[] = array($mode, $options); + return true; + } + + function staticPopErrorHandling() + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + $setmode = &$GLOBALS['_PEAR_default_error_mode']; + $setoptions = &$GLOBALS['_PEAR_default_error_options']; + array_pop($stack); + list($mode, $options) = $stack[sizeof($stack) - 1]; + array_pop($stack); + switch ($mode) { + case PEAR_ERROR_EXCEPTION: + case PEAR_ERROR_RETURN: + case PEAR_ERROR_PRINT: + case PEAR_ERROR_TRIGGER: + case PEAR_ERROR_DIE: + case null: + $setmode = $mode; + $setoptions = $options; + break; + + case PEAR_ERROR_CALLBACK: + $setmode = $mode; + // class/object method callback + if (is_callable($options)) { + $setoptions = $options; + } else { + trigger_error("invalid error callback", E_USER_WARNING); + } + break; + + default: + trigger_error("invalid error mode", E_USER_WARNING); + break; + } + return true; + } + + function pushErrorHandling($mode, $options = null) + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + if (isset($this) && is_a($this, 'PEAR')) { + $def_mode = &$this->_default_error_mode; + $def_options = &$this->_default_error_options; + } else { + $def_mode = &$GLOBALS['_PEAR_default_error_mode']; + $def_options = &$GLOBALS['_PEAR_default_error_options']; + } + $stack[] = array($def_mode, $def_options); + + if (isset($this) && is_a($this, 'PEAR')) { + $this->setErrorHandling($mode, $options); + } else { + PEAR::setErrorHandling($mode, $options); + } + $stack[] = array($mode, $options); + return true; + } + + function popErrorHandling() + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + array_pop($stack); + list($mode, $options) = $stack[sizeof($stack) - 1]; + array_pop($stack); + if (isset($this) && is_a($this, 'PEAR')) { + $this->setErrorHandling($mode, $options); + } else { + PEAR::setErrorHandling($mode, $options); + } + return true; + } + + function loadExtension($ext) + { + if (!extension_loaded($ext)) { + if ((ini_get('enable_dl') != 1) || (ini_get('safe_mode') == 1)) { + return false; + } + if (OS_WINDOWS) { + $suffix = '.dll'; + } elseif (PHP_OS == 'HP-UX') { + $suffix = '.sl'; + } elseif (PHP_OS == 'AIX') { + $suffix = '.a'; + } elseif (PHP_OS == 'OSX') { + $suffix = '.bundle'; + } else { + $suffix = '.so'; + } + return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix); + } + return true; + } + +} + +function _PEAR_call_destructors() +{ + global $_PEAR_destructor_object_list; + if (is_array($_PEAR_destructor_object_list) && + sizeof($_PEAR_destructor_object_list)) + { + reset($_PEAR_destructor_object_list); + if (@PEAR::getStaticProperty('PEAR', 'destructlifo')) { + $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list); + } + while (list($k, $objref) = each($_PEAR_destructor_object_list)) { + $classname = get_class($objref); + while ($classname) { + $destructor = "_$classname"; + if (method_exists($objref, $destructor)) { + $objref->$destructor(); + break; + } else { + $classname = get_parent_class($classname); + } + } + } + $_PEAR_destructor_object_list = array(); + } + + if (is_array($GLOBALS['_PEAR_shutdown_funcs']) AND !empty($GLOBALS['_PEAR_shutdown_funcs'])) { + foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) { + call_user_func_array($value[0], $value[1]); + } + } +} + +class PEAR_Error +{ + + function PEAR_Error($message = 'unknown error', $code = null, + $mode = null, $options = null, $userinfo = null) + { + if ($mode === null) { + $mode = PEAR_ERROR_RETURN; + } + $this->message = $message; + $this->code = $code; + $this->mode = $mode; + $this->userinfo = $userinfo; + if (function_exists("debug_backtrace")) { + if (@!PEAR::getStaticProperty('PEAR_Error', 'skiptrace')) { + $this->backtrace = debug_backtrace(); + } + } + if ($mode & PEAR_ERROR_CALLBACK) { + $this->level = E_USER_NOTICE; + $this->callback = $options; + } else { + if ($options === null) { + $options = E_USER_NOTICE; + } + $this->level = $options; + $this->callback = null; + } + if ($this->mode & PEAR_ERROR_PRINT) { + if (is_null($options) || is_int($options)) { + $format = "%s"; + } else { + $format = $options; + } + printf($format, $this->getMessage()); + } + if ($this->mode & PEAR_ERROR_TRIGGER) { + trigger_error($this->getMessage(), $this->level); + } + if ($this->mode & PEAR_ERROR_DIE) { + $msg = $this->getMessage(); + if (is_null($options) || is_int($options)) { + $format = "%s"; + if (substr($msg, -1) != "\n") { + $msg .= "\n"; + } + } else { + $format = $options; + } + die(sprintf($format, $msg)); + } + if ($this->mode & PEAR_ERROR_CALLBACK) { + if (is_callable($this->callback)) { + call_user_func($this->callback, $this); + } + } + if ($this->mode & PEAR_ERROR_EXCEPTION) { + trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING); + eval('$e = new Exception($this->message, $this->code);throw($e);'); + } + } + + function getMode() { + return $this->mode; + } + + function getCallback() { + return $this->callback; + } + + function getMessage() + { + return ($this->error_message_prefix . $this->message); + } + + function getCode() + { + return $this->code; + } + + function getType() + { + return get_class($this); + } + + function getUserInfo() + { + return $this->userinfo; + } + + function getDebugInfo() + { + return $this->getUserInfo(); + } + + function getBacktrace($frame = null) + { + if (defined('PEAR_IGNORE_BACKTRACE')) { + return null; + } + if ($frame === null) { + return $this->backtrace; + } + return $this->backtrace[$frame]; + } + + function addUserInfo($info) + { + if (empty($this->userinfo)) { + $this->userinfo = $info; + } else { + $this->userinfo .= " ** $info"; + } + } + + function toString() { + $modes = array(); + $levels = array(E_USER_NOTICE => 'notice', + E_USER_WARNING => 'warning', + E_USER_ERROR => 'error'); + if ($this->mode & PEAR_ERROR_CALLBACK) { + if (is_array($this->callback)) { + $callback = (is_object($this->callback[0]) ? + strtolower(get_class($this->callback[0])) : + $this->callback[0]) . '::' . + $this->callback[1]; + } else { + $callback = $this->callback; + } + return sprintf('[%s: message="%s" code=%d mode=callback '. + 'callback=%s prefix="%s" info="%s"]', + strtolower(get_class($this)), $this->message, $this->code, + $callback, $this->error_message_prefix, + $this->userinfo); + } + if ($this->mode & PEAR_ERROR_PRINT) { + $modes[] = 'print'; + } + if ($this->mode & PEAR_ERROR_TRIGGER) { + $modes[] = 'trigger'; + } + if ($this->mode & PEAR_ERROR_DIE) { + $modes[] = 'die'; + } + if ($this->mode & PEAR_ERROR_RETURN) { + $modes[] = 'return'; + } + return sprintf('[%s: message="%s" code=%d mode=%s level=%s '. + 'prefix="%s" info="%s"]', + strtolower(get_class($this)), $this->message, $this->code, + implode("|", $modes), $levels[$this->level], + $this->error_message_prefix, + $this->userinfo); + } + +} + +/** + * HTTP_Request.php code: + */ + +// +-----------------------------------------------------------------------+ +// | Copyright (c) 2002-2003, Richard Heyes | +// | All rights reserved. | +// +-----------------------------------------------------------------------+ + +define('HTTP_REQUEST_METHOD_GET', 'GET', true); +define('HTTP_REQUEST_METHOD_HEAD', 'HEAD', true); +define('HTTP_REQUEST_METHOD_POST', 'POST', true); +define('HTTP_REQUEST_METHOD_PUT', 'PUT', true); +define('HTTP_REQUEST_METHOD_DELETE', 'DELETE', true); +define('HTTP_REQUEST_METHOD_OPTIONS', 'OPTIONS', true); +define('HTTP_REQUEST_METHOD_TRACE', 'TRACE', true); + +define('HTTP_REQUEST_HTTP_VER_1_0', '1.0', true); +define('HTTP_REQUEST_HTTP_VER_1_1', '1.1', true); + +class HTTP_Request { + + var $_url; + var $_method; + var $_http; + var $_requestHeaders; + var $_user; + var $_pass; + var $_sock; + var $_proxy_host; + var $_proxy_port; + var $_proxy_user; + var $_proxy_pass; + var $_postData; + var $_body; + var $_bodyDisallowed = array('TRACE'); + var $_postFiles = array(); + var $_timeout; + var $_response; + var $_allowRedirects; + var $_maxRedirects; + var $_redirects; + var $_useBrackets = true; + var $_listeners = array(); + var $_saveBody = true; + var $_readTimeout = null; + var $_socketOptions = null; + + function HTTP_Request($url = '', $params = array()) + { + $this->_sock = &new Net_Socket(); + $this->_method = HTTP_REQUEST_METHOD_GET; + $this->_http = HTTP_REQUEST_HTTP_VER_1_1; + $this->_requestHeaders = array(); + $this->_postData = array(); + $this->_body = null; + + $this->_user = null; + $this->_pass = null; + + $this->_proxy_host = null; + $this->_proxy_port = null; + $this->_proxy_user = null; + $this->_proxy_pass = null; + + $this->_allowRedirects = false; + $this->_maxRedirects = 3; + $this->_redirects = 0; + + $this->_timeout = null; + $this->_response = null; + + foreach ($params as $key => $value) { + $this->{'_' . $key} = $value; + } + + if (!empty($url)) { + $this->setURL($url); + } + + $this->addHeader('User-Agent', 'PEAR HTTP_Request class ( http://pear.php.net/ )'); + + $this->addHeader('Connection', 'close'); + + if (!empty($this->_user)) { + $this->addHeader('Authorization', 'Basic ' . base64_encode($this->_user . ':' . $this->_pass)); + } + + if (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http && extension_loaded('zlib') && + 0 == (2 & ini_get('mbstring.func_overload'))) { + + $this->addHeader('Accept-Encoding', 'gzip'); + } + } + + function _generateHostHeader() + { + if ($this->_url->port != 80 AND strcasecmp($this->_url->protocol, 'http') == 0) { + $host = $this->_url->host . ':' . $this->_url->port; + + } elseif ($this->_url->port != 443 AND strcasecmp($this->_url->protocol, 'https') == 0) { + $host = $this->_url->host . ':' . $this->_url->port; + + } elseif ($this->_url->port == 443 AND strcasecmp($this->_url->protocol, 'https') == 0 AND strpos($this->_url->url, ':443') !== false) { + $host = $this->_url->host . ':' . $this->_url->port; + + } else { + $host = $this->_url->host; + } + + return $host; + } + + function reset($url, $params = array()) + { + $this->HTTP_Request($url, $params); + } + + function setURL($url) + { + $this->_url = &new Net_URL($url, $this->_useBrackets); + + if (!empty($this->_url->user) || !empty($this->_url->pass)) { + $this->setBasicAuth($this->_url->user, $this->_url->pass); + } + + if (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http) { + $this->addHeader('Host', $this->_generateHostHeader()); + } + } + + function setProxy($host, $port = 8080, $user = null, $pass = null) + { + $this->_proxy_host = $host; + $this->_proxy_port = $port; + $this->_proxy_user = $user; + $this->_proxy_pass = $pass; + + if (!empty($user)) { + $this->addHeader('Proxy-Authorization', 'Basic ' . base64_encode($user . ':' . $pass)); + } + } + + function setBasicAuth($user, $pass) + { + $this->_user = $user; + $this->_pass = $pass; + + $this->addHeader('Authorization', 'Basic ' . base64_encode($user . ':' . $pass)); + } + + function setMethod($method) + { + $this->_method = $method; + } + + function setHttpVer($http) + { + $this->_http = $http; + } + + function addHeader($name, $value) + { + $this->_requestHeaders[strtolower($name)] = $value; + } + + function removeHeader($name) + { + if (isset($this->_requestHeaders[strtolower($name)])) { + unset($this->_requestHeaders[strtolower($name)]); + } + } + + function addQueryString($name, $value, $preencoded = false) + { + $this->_url->addQueryString($name, $value, $preencoded); + } + + function addRawQueryString($querystring, $preencoded = true) + { + $this->_url->addRawQueryString($querystring, $preencoded); + } + + function addPostData($name, $value, $preencoded = false) + { + if ($preencoded) { + $this->_postData[$name] = $value; + } else { + $this->_postData[$name] = $this->_arrayMapRecursive('urlencode', $value); + } + } + + function _arrayMapRecursive($callback, $value) + { + if (!is_array($value)) { + return call_user_func($callback, $value); + } else { + $map = array(); + foreach ($value as $k => $v) { + $map[$k] = $this->_arrayMapRecursive($callback, $v); + } + return $map; + } + } + + function addFile($inputName, $fileName, $contentType = 'application/octet-stream') + { + if (!is_array($fileName) && !is_readable($fileName)) { + return PEAR::raiseError("File '{$fileName}' is not readable"); + } elseif (is_array($fileName)) { + foreach ($fileName as $name) { + if (!is_readable($name)) { + return PEAR::raiseError("File '{$name}' is not readable"); + } + } + } + $this->addHeader('Content-Type', 'multipart/form-data'); + $this->_postFiles[$inputName] = array( + 'name' => $fileName, + 'type' => $contentType + ); + return true; + } + + function addRawPostData($postdata, $preencoded = true) + { + $this->_body = $preencoded ? $postdata : urlencode($postdata); + } + + function setBody($body) + { + $this->_body = $body; + } + + function clearPostData() + { + $this->_postData = null; + } + + function addCookie($name, $value) + { + $cookies = isset($this->_requestHeaders['cookie']) ? $this->_requestHeaders['cookie']. '; ' : ''; + $this->addHeader('Cookie', $cookies . $name . '=' . $value); + } + + function clearCookies() + { + $this->removeHeader('Cookie'); + } + + function sendRequest($saveBody = true) + { + if (!is_a($this->_url, 'Net_URL')) { + return PEAR::raiseError('No URL given.'); + } + + $host = isset($this->_proxy_host) ? $this->_proxy_host : $this->_url->host; + $port = isset($this->_proxy_port) ? $this->_proxy_port : $this->_url->port; + + if (strcasecmp($this->_url->protocol, 'https') == 0 AND function_exists('file_get_contents') AND extension_loaded('openssl')) { + if (isset($this->_proxy_host)) { + return PEAR::raiseError('HTTPS proxies are not supported.'); + } + $host = 'ssl://' . $host; + } + + $magicQuotes = ini_get('magic_quotes_runtime'); + ini_set('magic_quotes_runtime', false); + + $err = $this->_sock->connect($host, $port, null, $this->_timeout, $this->_socketOptions); + PEAR::isError($err) or $err = $this->_sock->write($this->_buildRequest()); + + if (!PEAR::isError($err)) { + if (!empty($this->_readTimeout)) { + $this->_sock->setTimeout($this->_readTimeout[0], $this->_readTimeout[1]); + } + + $this->_notify('sentRequest'); + + $this->_response = &new HTTP_Response($this->_sock, $this->_listeners); + $err = $this->_response->process($this->_saveBody && $saveBody); + } + + ini_set('magic_quotes_runtime', $magicQuotes); + + if (PEAR::isError($err)) { + return $err; + } + + if ( $this->_allowRedirects + AND $this->_redirects <= $this->_maxRedirects + AND $this->getResponseCode() > 300 + AND $this->getResponseCode() < 399 + AND !empty($this->_response->_headers['location'])) { + + $redirect = $this->_response->_headers['location']; + + // Absolute URL + if (preg_match('/^https?:\/\//i', $redirect)) { + $this->_url = &new Net_URL($redirect); + $this->addHeader('Host', $this->_generateHostHeader()); + // Absolute path + } elseif ($redirect{0} == '/') { + $this->_url->path = $redirect; + + // Relative path + } elseif (substr($redirect, 0, 3) == '../' OR substr($redirect, 0, 2) == './') { + if (substr($this->_url->path, -1) == '/') { + $redirect = $this->_url->path . $redirect; + } else { + $redirect = dirname($this->_url->path) . '/' . $redirect; + } + $redirect = Net_URL::resolvePath($redirect); + $this->_url->path = $redirect; + + } else { + if (substr($this->_url->path, -1) == '/') { + $redirect = $this->_url->path . $redirect; + } else { + $redirect = dirname($this->_url->path) . '/' . $redirect; + } + $this->_url->path = $redirect; + } + + $this->_redirects++; + return $this->sendRequest($saveBody); + + } elseif ($this->_allowRedirects AND $this->_redirects > $this->_maxRedirects) { + return PEAR::raiseError('Too many redirects'); + } + + $this->_sock->disconnect(); + + return true; + } + + function getResponseCode() + { + return isset($this->_response->_code) ? $this->_response->_code : false; + } + + function getResponseHeader($headername = null) + { + if (!isset($headername)) { + return isset($this->_response->_headers)? $this->_response->_headers: array(); + } else { + $headername = strtolower($headername); + return isset($this->_response->_headers[$headername]) ? $this->_response->_headers[$headername] : false; + } + } + + function getResponseBody() + { + return isset($this->_response->_body) ? $this->_response->_body : false; + } + + function getResponseCookies() + { + return isset($this->_response->_cookies) ? $this->_response->_cookies : false; + } + + function _buildRequest() + { + $separator = ini_get('arg_separator.output'); + ini_set('arg_separator.output', '&'); + $querystring = ($querystring = $this->_url->getQueryString()) ? '?' . $querystring : ''; + ini_set('arg_separator.output', $separator); + + $host = isset($this->_proxy_host) ? $this->_url->protocol . '://' . $this->_url->host : ''; + $port = (isset($this->_proxy_host) AND $this->_url->port != 80) ? ':' . $this->_url->port : ''; + $path = (empty($this->_url->path)? '/': $this->_url->path) . $querystring; + $url = $host . $port . $path; + + $request = $this->_method . ' ' . $url . ' HTTP/' . $this->_http . "\r\n"; + + if (in_array($this->_method, $this->_bodyDisallowed) || + (HTTP_REQUEST_METHOD_POST != $this->_method && empty($this->_body)) || + (HTTP_REQUEST_METHOD_POST != $this->_method && empty($this->_postData) && empty($this->_postFiles))) { + + $this->removeHeader('Content-Type'); + } else { + if (empty($this->_requestHeaders['content-type'])) { + $this->addHeader('Content-Type', 'application/x-www-form-urlencoded'); + } elseif ('multipart/form-data' == $this->_requestHeaders['content-type']) { + $boundary = 'HTTP_Request_' . md5(uniqid('request') . microtime()); + $this->addHeader('Content-Type', 'multipart/form-data; boundary=' . $boundary); + } + } + + if (!empty($this->_requestHeaders)) { + foreach ($this->_requestHeaders as $name => $value) { + $canonicalName = implode('-', array_map('ucfirst', explode('-', $name))); + $request .= $canonicalName . ': ' . $value . "\r\n"; + } + } + + if (in_array($this->_method, $this->_bodyDisallowed) || + (HTTP_REQUEST_METHOD_POST != $this->_method && empty($this->_body))) { + + $request .= "\r\n"; + + } elseif (HTTP_REQUEST_METHOD_POST == $this->_method && + (!empty($this->_postData) || !empty($this->_postFiles))) { + + if (!isset($boundary)) { + $postdata = implode('&', array_map( + create_function('$a', 'return $a[0] . \'=\' . $a[1];'), + $this->_flattenArray('', $this->_postData) + )); + + } else { + $postdata = ''; + if (!empty($this->_postData)) { + $flatData = $this->_flattenArray('', $this->_postData); + foreach ($flatData as $item) { + $postdata .= '--' . $boundary . "\r\n"; + $postdata .= 'Content-Disposition: form-data; name="' . $item[0] . '"'; + $postdata .= "\r\n\r\n" . urldecode($item[1]) . "\r\n"; + } + } + foreach ($this->_postFiles as $name => $value) { + if (is_array($value['name'])) { + $varname = $name . ($this->_useBrackets? '[]': ''); + } else { + $varname = $name; + $value['name'] = array($value['name']); + } + foreach ($value['name'] as $key => $filename) { + $fp = fopen($filename, 'r'); + $data = fread($fp, filesize($filename)); + fclose($fp); + $basename = basename($filename); + $type = is_array($value['type'])? @$value['type'][$key]: $value['type']; + + $postdata .= '--' . $boundary . "\r\n"; + $postdata .= 'Content-Disposition: form-data; name="' . $varname . '"; filename="' . $basename . '"'; + $postdata .= "\r\nContent-Type: " . $type; + $postdata .= "\r\n\r\n" . $data . "\r\n"; + } + } + $postdata .= '--' . $boundary . "--\r\n"; + } + $request .= 'Content-Length: ' . strlen($postdata) . "\r\n\r\n"; + $request .= $postdata; + + // Explicitly set request body + } elseif (!empty($this->_body)) { + + $request .= 'Content-Length: ' . strlen($this->_body) . "\r\n\r\n"; + $request .= $this->_body; + } + + return $request; + } + + function _flattenArray($name, $values) + { + if (!is_array($values)) { + return array(array($name, $values)); + } else { + $ret = array(); + foreach ($values as $k => $v) { + if (empty($name)) { + $newName = $k; + } elseif ($this->_useBrackets) { + $newName = $name . '[' . $k . ']'; + } else { + $newName = $name; + } + $ret = array_merge($ret, $this->_flattenArray($newName, $v)); + } + return $ret; + } + } + + function attach(&$listener) + { + if (!is_a($listener, 'HTTP_Request_Listener')) { + return false; + } + $this->_listeners[$listener->getId()] =& $listener; + return true; + } + + function detach(&$listener) + { + if (!is_a($listener, 'HTTP_Request_Listener') || + !isset($this->_listeners[$listener->getId()])) { + return false; + } + unset($this->_listeners[$listener->getId()]); + return true; + } + + function _notify($event, $data = null) + { + foreach (array_keys($this->_listeners) as $id) { + $this->_listeners[$id]->update($this, $event, $data); + } + } +} + +class HTTP_Response +{ + + var $_sock; + var $_protocol; + var $_code; + var $_headers; + var $_cookies; + var $_body = ''; + var $_chunkLength = 0; + var $_listeners = array(); + function HTTP_Response(&$sock, &$listeners) + { + $this->_sock =& $sock; + $this->_listeners =& $listeners; + } + + function process($saveBody = true) + { + do { + $line = $this->_sock->readLine(); + if (sscanf($line, 'HTTP/%s %s', $http_version, $returncode) != 2) { + return PEAR::raiseError('Malformed response.'); + } else { + $this->_protocol = 'HTTP/' . $http_version; + $this->_code = intval($returncode); + } + while ('' !== ($header = $this->_sock->readLine())) { + $this->_processHeader($header); + } + } while (100 == $this->_code); + + $this->_notify('gotHeaders', $this->_headers); + + $chunked = isset($this->_headers['transfer-encoding']) && ('chunked' == $this->_headers['transfer-encoding']); + $gzipped = isset($this->_headers['content-encoding']) && ('gzip' == $this->_headers['content-encoding']); + $hasBody = false; + if (!isset($this->_headers['content-length']) || 0 != $this->_headers['content-length']) { + while (!$this->_sock->eof()) { + if ($chunked) { + $data = $this->_readChunked(); + } else { + $data = $this->_sock->read(4096); + } + if ('' == $data) { + break; + } else { + $hasBody = true; + if ($saveBody || $gzipped) { + $this->_body .= $data; + } + $this->_notify($gzipped? 'gzTick': 'tick', $data); + } + } + } + if ($hasBody) { + if ($gzipped) { + $this->_body = gzinflate(substr($this->_body, 10)); + $this->_notify('gotBody', $this->_body); + } else { + $this->_notify('gotBody'); + } + } + return true; + } + + function _processHeader($header) + { + list($headername, $headervalue) = explode(':', $header, 2); + $headername = strtolower($headername); + $headervalue = ltrim($headervalue); + + if ('set-cookie' != $headername) { + if (isset($this->_headers[$headername])) { + $this->_headers[$headername] .= ',' . $headervalue; + } else { + $this->_headers[$headername] = $headervalue; + } + } else { + $this->_parseCookie($headervalue); + } + } + + function _parseCookie($headervalue) + { + $cookie = array( + 'expires' => null, + 'domain' => null, + 'path' => null, + 'secure' => false + ); + + if (!strpos($headervalue, ';')) { + $pos = strpos($headervalue, '='); + $cookie['name'] = trim(substr($headervalue, 0, $pos)); + $cookie['value'] = trim(substr($headervalue, $pos + 1)); + + } else { + $elements = explode(';', $headervalue); + $pos = strpos($elements[0], '='); + $cookie['name'] = trim(substr($elements[0], 0, $pos)); + $cookie['value'] = trim(substr($elements[0], $pos + 1)); + + for ($i = 1; $i < count($elements); $i++) { + if (false === strpos($elements[$i], '=')) { + $elName = trim($elements[$i]); + $elValue = null; + } else { + list ($elName, $elValue) = array_map('trim', explode('=', $elements[$i])); + } + $elName = strtolower($elName); + if ('secure' == $elName) { + $cookie['secure'] = true; + } elseif ('expires' == $elName) { + $cookie['expires'] = str_replace('"', '', $elValue); + } elseif ('path' == $elName || 'domain' == $elName) { + $cookie[$elName] = urldecode($elValue); + } else { + $cookie[$elName] = $elValue; + } + } + } + $this->_cookies[] = $cookie; + } + + function _readChunked() + { + if (0 == $this->_chunkLength) { + $line = $this->_sock->readLine(); + if (preg_match('/^([0-9a-f]+)/i', $line, $matches)) { + $this->_chunkLength = hexdec($matches[1]); + if (0 == $this->_chunkLength) { + $this->_sock->readLine(); + return ''; + } + } else { + return ''; + } + } + $data = $this->_sock->read($this->_chunkLength); + $this->_chunkLength -= strlen($data); + if (0 == $this->_chunkLength) { + $this->_sock->readLine(); + } + return $data; + } + + function _notify($event, $data = null) + { + foreach (array_keys($this->_listeners) as $id) { + $this->_listeners[$id]->update($this, $event, $data); + } + } +} + +/** + * Socket.php + */ + +// +----------------------------------------------------------------------+ +// | PHP Version 4 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2003 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 2.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available at through the world-wide-web at | +// | http://www.php.net/license/2_02.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Authors: Stig Bakken | +// | Chuck Hagenbuch | +// +----------------------------------------------------------------------+ +// +// $Id: Socket.php,v 1.24 2005/02/03 20:40:16 chagenbu Exp $ + + +define('NET_SOCKET_READ', 1); +define('NET_SOCKET_WRITE', 2); +define('NET_SOCKET_ERROR', 3); + +class Net_Socket extends PEAR { + + var $fp = null; + var $blocking = true; + var $persistent = false; + var $addr = ''; + var $port = 0; + var $timeout = false; + var $lineLength = 2048; + + function connect($addr, $port = 0, $persistent = null, $timeout = null, $options = null) + { + if (is_resource($this->fp)) { + @fclose($this->fp); + $this->fp = null; + } + + if (!$addr) { + return $this->raiseError('$addr cannot be empty'); + } elseif (strspn($addr, '.0123456789') == strlen($addr) || + strstr($addr, '/') !== false) { + $this->addr = $addr; + } else { + $this->addr = @gethostbyname($addr); + } + + $this->port = $port % 65536; + + if ($persistent !== null) { + $this->persistent = $persistent; + } + + if ($timeout !== null) { + $this->timeout = $timeout; + } + + $openfunc = $this->persistent ? 'pfsockopen' : 'fsockopen'; + $errno = 0; + $errstr = ''; + if ($options && function_exists('stream_context_create')) { + if ($this->timeout) { + $timeout = $this->timeout; + } else { + $timeout = 0; + } + $context = stream_context_create($options); + $fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $timeout, $context); + } else { + if ($this->timeout) { + $fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $this->timeout); + } else { + $fp = @$openfunc($this->addr, $this->port, $errno, $errstr); + } + } + + if (!$fp) { + return $this->raiseError($errstr, $errno); + } + + $this->fp = $fp; + + return $this->setBlocking($this->blocking); + } + + function disconnect() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + @fclose($this->fp); + $this->fp = null; + return true; + } + + function isBlocking() + { + return $this->blocking; + } + + function setBlocking($mode) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $this->blocking = $mode; + socket_set_blocking($this->fp, $this->blocking); + return true; + } + + function setTimeout($seconds, $microseconds) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return socket_set_timeout($this->fp, $seconds, $microseconds); + } + + function getStatus() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return socket_get_status($this->fp); + } + + function gets($size) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return @fgets($this->fp, $size); + } + + function read($size) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return @fread($this->fp, $size); + } + + function write($data, $blocksize = null) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + if (is_null($blocksize) && !OS_WINDOWS) { + return fwrite($this->fp, $data); + } else { + if (is_null($blocksize)) { + $blocksize = 1024; + } + + $pos = 0; + $size = strlen($data); + while ($pos < $size) { + $written = @fwrite($this->fp, substr($data, $pos, $blocksize)); + if ($written === false) { + return false; + } + $pos += $written; + } + + return $pos; + } + } + + function writeLine($data) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return fwrite($this->fp, $data . "\r\n"); + } + + function eof() + { + return (is_resource($this->fp) && feof($this->fp)); + } + + function readByte() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + return ord(@fread($this->fp, 1)); + } + + function readWord() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $buf = @fread($this->fp, 2); + return (ord($buf[0]) + (ord($buf[1]) << 8)); + } + + function readInt() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $buf = @fread($this->fp, 4); + return (ord($buf[0]) + (ord($buf[1]) << 8) + + (ord($buf[2]) << 16) + (ord($buf[3]) << 24)); + } + + function readString() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $string = ''; + while (($char = @fread($this->fp, 1)) != "\x00") { + $string .= $char; + } + return $string; + } + + function readIPAddress() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $buf = @fread($this->fp, 4); + return sprintf("%s.%s.%s.%s", ord($buf[0]), ord($buf[1]), + ord($buf[2]), ord($buf[3])); + } + + function readLine() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $line = ''; + $timeout = time() + $this->timeout; + while (!feof($this->fp) && (!$this->timeout || time() < $timeout)) { + $line .= @fgets($this->fp, $this->lineLength); + if (substr($line, -1) == "\n") { + return rtrim($line, "\r\n"); + } + } + return $line; + } + + function readAll() + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $data = ''; + while (!feof($this->fp)) { + $data .= @fread($this->fp, $this->lineLength); + } + return $data; + } + + function select($state, $tv_sec, $tv_usec = 0) + { + if (!is_resource($this->fp)) { + return $this->raiseError('not connected'); + } + + $read = null; + $write = null; + $except = null; + if ($state & NET_SOCKET_READ) { + $read[] = $this->fp; + } + if ($state & NET_SOCKET_WRITE) { + $write[] = $this->fp; + } + if ($state & NET_SOCKET_ERROR) { + $except[] = $this->fp; + } + if (false === ($sr = stream_select($read, $write, $except, $tv_sec, $tv_usec))) { + return false; + } + + $result = 0; + if (count($read)) { + $result |= NET_SOCKET_READ; + } + if (count($write)) { + $result |= NET_SOCKET_WRITE; + } + if (count($except)) { + $result |= NET_SOCKET_ERROR; + } + return $result; + } + +} + +/** + * URL.php + */ +// +-----------------------------------------------------------------------+ +// | Copyright (c) 2002-2004, Richard Heyes | +// | All rights reserved. | +// +-----------------------------------------------------------------------+ +// $Id: URL.php,v 1.36 2004/06/19 18:58:50 richard Exp $ + +class Net_URL +{ + + var $url; + var $protocol; + var $username; + var $password; + var $host; + var $port; + var $path; + var $querystring; + var $anchor; + var $useBrackets; + function Net_URL($url = null, $useBrackets = true) + { + $this->__construct($url, $useBrackets); + } + + function __construct($url = null, $useBrackets = true) + { + $HTTP_SERVER_VARS = !empty($_SERVER) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS']; + + $this->useBrackets = $useBrackets; + $this->url = $url; + $this->user = ''; + $this->pass = ''; + $this->host = ''; + $this->port = 80; + $this->path = ''; + $this->querystring = array(); + $this->anchor = ''; + + if (!preg_match('/^[a-z0-9]+:\/\//i', $url)) { + + $this->protocol = (@$HTTP_SERVER_VARS['HTTPS'] == 'on' ? 'https' : 'http'); + + if (!empty($HTTP_SERVER_VARS['HTTP_HOST']) AND preg_match('/^(.*)(:([0-9]+))?$/U', $HTTP_SERVER_VARS['HTTP_HOST'], $matches)) { + $host = $matches[1]; + if (!empty($matches[3])) { + $port = $matches[3]; + } else { + $port = $this->getStandardPort($this->protocol); + } + } + + $this->user = ''; + $this->pass = ''; + $this->host = !empty($host) ? $host : (isset($HTTP_SERVER_VARS['SERVER_NAME']) ? $HTTP_SERVER_VARS['SERVER_NAME'] : 'localhost'); + $this->port = !empty($port) ? $port : (isset($HTTP_SERVER_VARS['SERVER_PORT']) ? $HTTP_SERVER_VARS['SERVER_PORT'] : $this->getStandardPort($this->protocol)); + $this->path = !empty($HTTP_SERVER_VARS['SCRIPT_NAME']) ? $HTTP_SERVER_VARS['SCRIPT_NAME'] : '/'; + $this->querystring = isset($HTTP_SERVER_VARS['QUERY_STRING']) ? $this->_parseRawQuerystring($HTTP_SERVER_VARS['QUERY_STRING']) : null; + $this->anchor = ''; + } + + if (!empty($url)) { + $urlinfo = parse_url($url); + + $this->querystring = array(); + + foreach ($urlinfo as $key => $value) { + switch ($key) { + case 'scheme': + $this->protocol = $value; + $this->port = $this->getStandardPort($value); + break; + + case 'user': + case 'pass': + case 'host': + case 'port': + $this->$key = $value; + break; + + case 'path': + if ($value{0} == '/') { + $this->path = $value; + } else { + $path = dirname($this->path) == DIRECTORY_SEPARATOR ? '' : dirname($this->path); + $this->path = sprintf('%s/%s', $path, $value); + } + break; + + case 'query': + $this->querystring = $this->_parseRawQueryString($value); + break; + + case 'fragment': + $this->anchor = $value; + break; + } + } + } + } + + function getURL() + { + $querystring = $this->getQueryString(); + + $this->url = $this->protocol . '://' + . $this->user . (!empty($this->pass) ? ':' : '') + . $this->pass . (!empty($this->user) ? '@' : '') + . $this->host . ($this->port == $this->getStandardPort($this->protocol) ? '' : ':' . $this->port) + . $this->path + . (!empty($querystring) ? '?' . $querystring : '') + . (!empty($this->anchor) ? '#' . $this->anchor : ''); + + return $this->url; + } + + function addQueryString($name, $value, $preencoded = false) + { + if ($preencoded) { + $this->querystring[$name] = $value; + } else { + $this->querystring[$name] = is_array($value) ? array_map('rawurlencode', $value): rawurlencode($value); + } + } + + function removeQueryString($name) + { + if (isset($this->querystring[$name])) { + unset($this->querystring[$name]); + } + } + + function addRawQueryString($querystring) + { + $this->querystring = $this->_parseRawQueryString($querystring); + } + + function getQueryString() + { + if (!empty($this->querystring)) { + foreach ($this->querystring as $name => $value) { + if (is_array($value)) { + foreach ($value as $k => $v) { + $querystring[] = $this->useBrackets ? sprintf('%s[%s]=%s', $name, $k, $v) : ($name . '=' . $v); + } + } elseif (!is_null($value)) { + $querystring[] = $name . '=' . $value; + } else { + $querystring[] = $name; + } + } + $querystring = implode(ini_get('arg_separator.output'), $querystring); + } else { + $querystring = ''; + } + + return $querystring; + } + + function _parseRawQuerystring($querystring) + { + $parts = preg_split('/[' . preg_quote(ini_get('arg_separator.input'), '/') . ']/', $querystring, -1, PREG_SPLIT_NO_EMPTY); + $return = array(); + + foreach ($parts as $part) { + if (strpos($part, '=') !== false) { + $value = substr($part, strpos($part, '=') + 1); + $key = substr($part, 0, strpos($part, '=')); + } else { + $value = null; + $key = $part; + } + if (substr($key, -2) == '[]') { + $key = substr($key, 0, -2); + if (@!is_array($return[$key])) { + $return[$key] = array(); + $return[$key][] = $value; + } else { + $return[$key][] = $value; + } + } elseif (!$this->useBrackets AND !empty($return[$key])) { + $return[$key] = (array)$return[$key]; + $return[$key][] = $value; + } else { + $return[$key] = $value; + } + } + + return $return; + } + + function resolvePath($path) + { + $path = explode('/', str_replace('//', '/', $path)); + + for ($i=0; $i 1 OR ($i == 1 AND $path[0] != '') ) ) { + unset($path[$i]); + unset($path[$i-1]); + $path = array_values($path); + $i -= 2; + + } elseif ($path[$i] == '..' AND $i == 1 AND $path[0] == '') { + unset($path[$i]); + $path = array_values($path); + $i--; + + } else { + continue; + } + } + + return implode('/', $path); + } + + function getStandardPort($scheme) + { + switch (strtolower($scheme)) { + case 'http': return 80; + case 'https': return 443; + case 'ftp': return 21; + case 'imap': return 143; + case 'imaps': return 993; + case 'pop3': return 110; + case 'pop3s': return 995; + default: return null; + } + } + + function setProtocol($protocol, $port = null) + { + $this->protocol = $protocol; + $this->port = is_null($port) ? $this->getStandardPort() : $port; + } + +} + + +?> diff --git a/scripts/jlogPlugins.class.php b/scripts/jlogPlugins.class.php new file mode 100644 index 0000000..578f87c --- /dev/null +++ b/scripts/jlogPlugins.class.php @@ -0,0 +1,83 @@ +get = strip($_GET); + + if(is_dir($plugindirectory)) { + $handle = opendir($plugindirectory); + while( false !== ( $file = readdir ($handle) ) ) { + if(substr($file, -10) === '.jplug.php') { + include_once $plugindirectory.$file; + $this->register( substr($file, 0, -10) ); + } + } + closedir($handle); + + } + } + + function register($plugin) { + $this->plugins[] = new $plugin; + } + + // Aufruf $JLogPluginManagerInstanz->callHook('eins', $param1[, $param2, ...]); + // $param1 = Pflicht-Parameter, alle anderen optional + function callHook($hook) { + $hook = 'hook_' . $hook; + + $parameters = func_get_args(); + array_shift($parameters); // $hook entfernen + if (!isset($parameters[0])) + die('fatal error - no parameters'); + + $hookresult = $parameters[0]; + + foreach ($this->plugins as $plugin) { + $parameters[0] = $hookresult; + if($hook == 'hook_adminTitle' OR $hook == 'hook_adminContent') { + if(strtolower($this->get['jplug']) === strtolower(get_class($plugin))) + $hookresult = call_user_func_array(array($plugin, $hook), $parameters); + } + else $hookresult = call_user_func_array(array($plugin, $hook), $parameters); + } + return $hookresult; + } +} +?> diff --git a/scripts/mail.class.php b/scripts/mail.class.php new file mode 100644 index 0000000..f673538 --- /dev/null +++ b/scripts/mail.class.php @@ -0,0 +1,279 @@ +_from = 'no-reply@' . $_SERVER['SERVER_NAME']; + $this->_subject = 'Kein Betreff - No Subject'; + $this->addHeader('MIME-Version', '1.0'); + $this->addHeader('Content-Type', 'text/plain; charset=UTF-8'); + $this->addHeader('Content-Transfer-Encoding', '8bit'); + $this->addHeader('X-Mailer', 'Jlog with PHP ' . phpversion()); + } + + /** + * setFrom() - sets from value + * + * @access public + * @param string $email + * @param string $name + * @return void + */ + function setFrom($email, $name) + { + if (!empty($email) and !empty($name)) { + $this->_from = "$name <$email>"; + } + } + + /** + * getFrom() - gets from value + * + * @access public + * @return string + */ + function getFrom() + { + return $this->_from; + } + + /** + * setSubject() - sets subject + * + * @access public + * @param string $text + * @return void + */ + function setSubject($text) + { + if (strlen($text) > 0) { + $this->_subject = $text; + } + } + + /** + * getSubject() - gets subject + * + * @access public + * @return string + */ + function getSubject() + { + return $this->_subject; + } + + /** + * setText() - sets content of email + * + * @access public + * @param string $text + * @return void + */ + function setText($text) + { + $this->_text = $text; + } + + /** + * appendText() - appends content to the email + * + * @access public + * @param string $text + * @return void + */ + function appendText($text) + { + $this->_text .= $text; + } + + /** + * getText() - gets content of email + * + * @access public + * @return string + */ + function getText() + { + return $this->_text; + } + + /** + * addHeader() - adds an additional header + * + * Adds a header, by replacing any earlier headers of the same name. + * If no value is passed, the key is interpreted as a header line and + * split into key and value. + * + * @access public + * @param string $key + * @param string $value + * @return void + */ + function addHeader($key, $value = null) + { + if ($value === null) { + $data = explode(':', $key, 1); + if (count($data) !== 2) return false; + $key = $data[0]; + $value = $data[1]; + } + if (strlen($key) < 1 or strlen($value) < 1) return false; + $this->_header[$key] = $value; + } + + /** + * unsetHeader() - deletes a header + * + * @access public + * @param string $key + * @return void + */ + function unsetHeader($key) + { + if (isset($this->_header[$key])) unset($this->_header[$key]); + } + + /** + * getHeader() - gets a header + * + * @access public + * @return string|null + */ + function getHeader($key) + { + if (isset($this->_header[$key])) return $this->_header[$key]; + return null; + } + + /** + * getHeaders() - gets all headers + * + * @access public + * @return array + */ + function getHeaders() + { + return $this->_header; + } + + /** + * getCleanHeaderString() - gets sanitized header string + * + * @access public + * @return string + */ + function getCleanHeaderString() + { + $headers = ''; + foreach ($this->_header as $key => $value) { + // remove all non alpha-numeric chars, except for dash + $key = preg_replace('/[^a-zA-Z0-9-]/', '', $key); + // remove line breaks to prevent header injection + $value = str_replace(array("\r", "\n"), '', $value); + // add header + $headers .= "$key: $value\r\n"; + } + return $headers; + } + + /** + * dropMail() - sets drop mail flag + * + * Sets a flag that causes the send() method to skip sending this + * email, so that this mail is actualy dropped. + * + * @access public + * @return void + */ + function dropMail() + { + $this->_dropped = true; + } + + /** + * send() - sends mail + * + * @access public + * @param string $to + * @return boolean + */ + function send($to) + { + if ($this->_dropped) return false; + + $this->addHeader('From', $this->_from); + + $safe_mode = strtolower(ini_get('safe_mode')); + if ($safe_mode == 1 or $safe_mode == 'on' or $safe_mode == 'yes') { + @mail($to, $this->_subject, $this->_text, $this->getCleanHeaderString()); + } + else { + @mail($to, $this->_subject, $this->_text, $this->getCleanHeaderString(), "-f".JLOG_EMAIL); + } + return true; + } +} + +// eof diff --git a/scripts/prepend.inc.php b/scripts/prepend.inc.php new file mode 100644 index 0000000..dcf0280 --- /dev/null +++ b/scripts/prepend.inc.php @@ -0,0 +1,91 @@ +".$l['db_error']."
    ".$l['plz_try_again']."."); +} +// select our database +$select = @mysql_select_db(JLOG_DB); +if ($connect == FALSE) { + mail(JLOG_EMAIL, $l['admin']['e_db'], $l['admin']['e_db_is']."\n".mysql_error()); + die("".$l['db_error']."
    ".$l['plz_try_again']."."); +} +// do some settings +@mysql_query("SET NAMES utf8"); +@mysql_query("SET sql_mode=''"); + +// some more code that needs to run for every page - however, this +// code requires an established connection to the database +setlocale(LC_TIME, $l['locale']); +require_once(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'categories.class.php'); +require_once(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'jlogPlugins.class.php'); +$plugins = new JlogPluginManager(JLOG_BASEPATH.'plugins'.DIRECTORY_SEPARATOR); + +// call hooks for bbcode plugins +$bbcode = $plugins->callHook('bbcode', $bbcode); +$bbcomments = $plugins->callHook('bbcomments', $bbcomments); + +// eof \ No newline at end of file diff --git a/scripts/settings.class.php b/scripts/settings.class.php new file mode 100644 index 0000000..5eed38f --- /dev/null +++ b/scripts/settings.class.php @@ -0,0 +1,533 @@ +l = $l; + } + + /** + * getValue() - reads configuration data + * + * This procedure returns the value for then configuration option + * specified by $key or an array of all options if $key is not + * specified or false + * + * @access public + * @param string|boolean $key + * @return mixed + */ + function getValue($key = false) { + if($key === false) return $this->d; + else return $this->d[strtolower($key)]; + } + + /** + * setValue() - sets configuration data + * + * @access public + * @param string|boolean $key + * @param mixed $value + * @return mixed + */ + function setValue($key, $value) { + $this->d[strtolower($key)] = $value; + } + + /** + * importDataByConstants() + * + * imports data from global constats starting with JLOG_ prefix + * + * @access public + * @return void + */ + function importDataByConstants() { + # no return + // this is a blacklist of constats which are not to be written in settings.inc.php + $search = array( + 'JLOG_ADMIN', + 'JLOG_DB_CONTENT', + 'JLOG_DB_COMMENTS', + 'JLOG_DB_CATASSIGN', + 'JLOG_DB_CATEGORIES', + 'JLOG_DB_ATTRIBUTES', + 'JLOG_UPDATE', + 'JLOG_LOGIN', + 'JLOG_SOFTWARE_VERSION', + 'JLOG_SOFTWARE_URL', + 'JLOG_SOFTWARE_PHPV', + 'JLOG_SOFTWARE_MYSQLV', + 'JLOG_ADMIN_PASSWORD_AGAIN' + ); + + // get all needed constants and put it into the class + $constants = get_defined_constants(); + foreach($constants as $key => $value) { + if(!in_array($key, $search) AND strpos($key, "JLOG_") !== false) { + $this->setValue($key, $value); + } + } + } + + /** + * importDataByArray() - sets configuration data + * + * Sets configuration data according to $d. If working in + * non-exclusive mode (the default), $d is merged into the current + * configuration, otherwise the current configuration is discared + * and $d is set as the new configuration. + * + * @access public + * @param array $d + * @param boolean $exclusiv + * @return void + */ + function importDataByArray($d = false, $exclusiv = false) { + + // get the data from users $d array and put it into the class + if($d !== false) { + if($exclusiv) $this->d = $d; + else $this->d = array_merge($this->d, $d); + } + + if(JLOG_ADMIN === true) { + $this->d['jlog_db'] = JLOG_DB; + $this->d['jlog_db_url'] = JLOG_DB_URL; + $this->d['jlog_db_user'] = JLOG_DB_USER; + $this->d['jlog_db_pwd'] = JLOG_DB_PWD; + $this->d['jlog_db_prefix'] = JLOG_DB_PREFIX; + $this->d['jlog_start_year'] = JLOG_START_YEAR; + $this->d['jlog_path'] = JLOG_PATH; + $this->d['jlog_basepath'] = JLOG_BASEPATH; + if($this->d['jlog_admin_password'] == '') { + $this->jlog_admin_password = JLOG_ADMIN_PASSWORD; + } + else { + $this->d['jlog_admin_password'] = md5($this->d['jlog_admin_password']); + $this->d['jlog_admin_password_again'] = md5($this->d['jlog_admin_password_again']); + } + $this->d['jlog_installed_version'] = JLOG_INSTALLED_VERSION; + $this->d['jlog_installed_url'] = JLOG_INSTALLED_URL; + $this->d['jlog_installed_phpv'] = JLOG_INSTALLED_PHPV; + $this->d['jlog_installed_mysqlv'] = JLOG_INSTALLED_MYSQLV; + } + else { + $this->d['jlog_admin_password'] = md5($this->d['jlog_admin_password']); + $this->d['jlog_admin_password_again'] = md5($this->d['jlog_admin_password_again']); + } + + if((defined('JLOG_SETUP') AND JLOG_SETUP === true)) + { + $this->d['jlog_installed_version'] = JLOG_SOFTWARE_VERSION; + $this->d['jlog_installed_url'] = JLOG_SOFTWARE_URL; + $this->d['jlog_installed_phpv'] = JLOG_SOFTWARE_PHPV; + $this->d['jlog_installed_mysqlv'] = JLOG_SOFTWARE_MYSQLV; + } + } + + /** + * importSuggestedData() - preallocates configuration data + * + * Initialises the configuration with useful settings during + * the installation process. + * + * @access public + * @return void + */ + function importSuggestedData() { + // suggest some data for setup + $this->setValue('jlog_path', $this->getSuggestPath()); + $this->setValue('jlog_basepath', dirname(dirname( __FILE__ )).DIRECTORY_SEPARATOR); + $date = getdate(); + $this->setValue('jlog_start_year', $date['year']); + $this->setValue('jlog_max_blog_orginal', 1); + $this->setValue('jlog_max_blog_big', 4); + $this->setValue('jlog_max_blog_small', 15); + $this->setValue('jlog_sub_current', 6); + $this->setValue('jlog_date', $this->l['date_format']); + $this->setValue('jlog_date_comment', $this->l['date_format_comment']); + $this->setValue('jlog_date_subcurrent', $this->l['date_format_subcurrent']); + $this->setValue('jlog_info_by_comment', true); + $this->setValue('jlog_db_url', 'localhost'); + $this->setValue('jlog_db_prefix', 'jlog_'); + $this->setValue('jlog_blogservices', 'http://rpc.pingomatic.com/'); + $this->setValue('jlog_language', (defined('JLOG_LANGUAGE') ? JLOG_LANGUAGE : 'de')); + } + + + /** + * getSuggestPath() - generate a suggestion for JLOG_PATH + * + * @access private + * @return string + */ + function getSuggestPath() { + $host = empty($_SERVER['HTTP_HOST']) + ? (empty($_SERVER['SERVER_NAME']) + ? $_SERVER['SERVER_ADDR'] + : $_SERVER['SERVER_NAME']) + : $_SERVER['HTTP_HOST']; + $proto = (empty($_SERVER['HTTPS']) OR $_SERVER['HTTPS'] == 'off') + ? 'http' + : 'https'; + $port = $_SERVER['SERVER_PORT']; + + $uri = $proto . '://' . $host; + if ((('http' == $proto) and (80 != $port)) + or (('https' == $proto) and (443 != $port))) + { + $uri .= ':' . $port; + } + $uri .= dirname($_SERVER['SCRIPT_NAME']); + + return $uri; + } + + /** + * defaultValue() - gets a value of an array + * + * Look for index $key in the array $array and return + * the corresponding value if it exists or the default + * value $default if it doesn't. + * + * @access public + * @param array $array + * @param mixed $key + * @param mixed $default + * @return mixed + */ + function defaultValue($array, $key, $default = '') { + if(isset($array[$key])) { + return $array[$key]; + } + else { + return $default; + } + } + + /** + * form_output() - generates HTML output for formular + * + * @access public + * @return string + */ + function form_output() { + # returns the filled form + + $data = array_htmlspecialchars($this->d); + + if(isset($data['jlog_clean_url']) AND ($data['jlog_clean_url'] === 'true' OR $data['jlog_clean_url'] === '1')) + $d['clean_url_yes'] = " checked='checked'"; + else $d['clean_url_no'] = " checked='checked'"; + + if(isset($data['jlog_info_by_comment'])) $d['info_by_comment'] = " checked='checked'"; + else $d['info_by_comment'] = ""; + + if(isset($data['jlog_bs_weblogs_com']) AND ($data['jlog_bs_weblogs_com'] === 'true' OR $data['jlog_bs_weblogs_com'] === '1')) + $d['bs_weblogs_com'] = " checked='checked' "; + + if(defined("JLOG_ADMIN") AND JLOG_ADMIN === true) $admincenter_password = " ".$this->l['admin']['m_admin_password_admin']; + else $admincenter_password = ''; + + // get available languages + $dir = opendir(dirname(__FILE__).DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'lang'); + $languages = array(); + while(($file = readdir($dir)) !== false) { + if($file == '.' OR $file == '..') continue; + if(!preg_match('/lang\.([a-zA-z0-9]+)\.inc\.php/', $file, $matches)) continue; + $languages[] = $matches[1]; + } + + // do the form + $form = " +
    +
    ".$this->l['admin']['m_metadata']." +


    "; + + if(defined("JLOG_ADMIN") AND JLOG_ADMIN === true) $form .= add_session_id_input_tag(); + + $form .= "

    +


    +

    +


    +

    +


    +

    +


    +

    +


    +

    +
    + +
    ".$this->l['admin']['m_behavior']." +


    + +

    +


    +

    +


    +

    +


    +

    +


    +

    +

    +

    +

    +

    +

    +

    +

    +
    + "; + + if(defined('JLOG_SETUP') AND JLOG_SETUP === true) { + $form .= + " +
    ".$this->l['admin']['m_database']." +


    +

    +


    +

    +


    +

    +


    +

    +


    + +

    + + +
    + "; + } + + $form .= " +

    +
    + "; + + return $form; + } + + /** + * validate() - validates the current configuration + * + * If the current configuration is valid, an empty array is returned. + * Otherwise the returned array containes all errors, described in the + * current language. + * + * @access public + * @return array + */ + function validate() { + # if everything validate then return true + # otherwise return the $errors array + + $errors = array(); + + // paths + if(empty($this->d['jlog_path']) OR (check_url($this->d['jlog_path'], array ('http')) === false)) $errors[] = $this->l['admin']['e_path']; + if(empty($this->d['jlog_basepath']) OR !is_dir($this->d['jlog_basepath'])) $errors[] = $this->l['admin']['e_basepath']; + if($this->d['jlog_clean_url'] != 'true') $this->d['jlog_clean_url'] = 'false'; + // metadata + if(empty($this->d['jlog_website'])) $errors[] = $this->l['admin']['e_website']; + if(empty($this->d['jlog_publisher'])) $errors[] = $this->l['admin']['e_publisher']; + if(defined('JLOG_SETUP') AND JLOG_SETUP) { + if($this->d['jlog_admin_password'] == md5("")) + $errors[] = $this->l['admin']['e_admin_password']; + elseif($this->d['jlog_admin_password'] !== $this->d['jlog_admin_password_again']) + $errors[] = $this->l['admin']['e_admin_password_again']; + } + elseif(!empty($this->d['jlog_admin_password']) AND $this->d['jlog_admin_password'] !== $this->d['jlog_admin_password_again']) { + $errors[] = $this->l['admin']['e_admin_password_again']; + } + // Fix of bug #148 + if(isset($this->d['jlog_admin_password_again'])) + unset($this->d['jlog_admin_password_again']); + + if(empty($this->d['jlog_email']) OR !strpos($this->d['jlog_email'], '@')) $errors[] = $this->l['admin']['e_email']; + if(empty($this->d['jlog_description'])) $errors[] = $this->l['admin']['e_description']; + // behavour + if(!is_numeric($this->d['jlog_max_blog_orginal']) OR intval($this->d['jlog_max_blog_orginal']) < 0) $errors[] = $this->l['admin']['e_max_blog_orginal']; + if(!is_numeric($this->d['jlog_max_blog_big']) OR intval($this->d['jlog_max_blog_big']) < 0) $errors[] = $this->l['admin']['e_max_blog_big']; + if(!is_numeric($this->d['jlog_max_blog_small']) OR intval($this->d['jlog_max_blog_small']) < 0) $errors[] = $this->l['admin']['e_max_blog_small']; + if(!is_numeric($this->d['jlog_sub_current']) OR intval($this->d['jlog_sub_current']) < 0) $errors[] = $this->l['admin']['e_sub_current']; + if(!is_numeric($this->d['jlog_start_year'])) $errors[] = $this->l['admin']['e_start_year']; + if($this->d['jlog_info_by_comment'] != 'true') $this->d['jlog_info_by_comment'] = 'false'; + // database + if(empty($this->d['jlog_db'])) $errors[] = $this->l['admin']['e_db']; + if(empty($this->d['jlog_db_url'])) $errors[] = $this->l['admin']['e_db_url']; + // Fix of bug #196, prefix should only contain alphanumeric values, can be empty! + if(!preg_match('/^[a-zA-Z0-9_]*$/', $this->d['jlog_db_prefix'])) $errors[] = $this->l['admin']['e_db_prefix']; + + return $errors; + } + + /** + * do_settings() - save configuration + * + * Saves the current configuration to the settings.inc.php file + * in the personal folder. Return an empty array if configuration + * was saved successfully, or an array containing descriptions of + * the errors that occured otherwise. + * + * @access public + * @return array + */ + function do_settings() { + # if it's all done return true + # otherwise return the $errors array + + $errors = array(); + + // if there is no new password set the old + if(JLOG_ADMIN AND empty($this->d['jlog_admin_password'])) $this->d['jlog_admin_password'] = JLOG_ADMIN_PASSWORD; + + // remove slashes at the end of JLOG_PATH if present + $this->d['jlog_path'] = rtrim($this->d['jlog_path'], '/'); + // make shure JLOG_BASEPATH ends with a slash!! + $this->d['jlog_basepath'] = rtrim($this->d['jlog_basepath'], '/\\') . DIRECTORY_SEPARATOR; + + // no quotes for bolean and numbers + $no_quotes = array ( + 'jlog_clean_url' => 'bool', + 'jlog_max_blog_orginal' => 'int', + 'jlog_max_blog_big' => 'int', + 'jlog_max_blog_small' => 'int', + 'jlog_sub_current' => 'int', + 'jlog_start_year' => 'int', + 'jlog_info_by_comment' => 'bool' + ); + + // serialize data to file format + $file_content = 'd as $key => $value) { + $output = ''; + if(isset($no_quotes[$key])) { + // boolean values + if($no_quotes[$key] == 'bool') { + if($value == 'true' OR $value === true) $output = 'true'; + else $output = 'false'; + } + // numeric values + else { + $output = (int) $value; + } + } + // string values + else { + $output = '\'' . $this->escapeForPhp($value) . '\''; + } + $key = '\'' . $this->escapeForPhp(strtoupper($key)) . '\''; + $file_content .= 'define(' . $key . ', ' . $output . ');' . PHP_EOL; + } + + $file_content .= '// eof'; + + // write to settings.inc.php + if(!$handle = fopen(JLOG_BASEPATH."personal".DIRECTORY_SEPARATOR."settings.inc.php", "w")) $errors[] = $this->l['admin']['can_not_open']." /personal/settings.inc.php"; + if(!fwrite($handle, $file_content)) $errors[] = $this->l['admin']['can_not_write']." /personal/settings.inc.php"; + fclose($handle); + + return $errors; + } + + /** + * escapeForPhp() + * + * escapes $value so that it can be used between single quotes in a + * PHP script, single quotes are better than double qoutes, as therein no + * further substituions are performed + * + * @access public + * @param string $value + * @return string + */ + function escapeForPhp($value) { + $value = str_replace('\\', '\\\\', $value); + $value = str_replace("'", "\'", $value); + $value = str_replace("\0", '', $value); + $value = str_replace("\r\n", "'.chr(13).chr(10).'", $value); + $value = str_replace("\r", "'.chr(13).'", $value); + $value = str_replace("\n", "'.chr(10).'", $value); + return $value; + } +} + +// eof \ No newline at end of file diff --git a/scripts/stringparser.class.php b/scripts/stringparser.class.php new file mode 100644 index 0000000..3f48ffa --- /dev/null +++ b/scripts/stringparser.class.php @@ -0,0 +1,1544 @@ + + * @copyright Christian Seiler 2004-2008 + * @package stringparser + * + * The MIT License + * + * Copyright (c) 2004-2009 Christian Seiler + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * String parser mode: Search for the next character + * @see StringParser::_parserMode + */ +define ('STRINGPARSER_MODE_SEARCH', 1); +/** + * String parser mode: Look at each character of the string + * @see StringParser::_parserMode + */ +define ('STRINGPARSER_MODE_LOOP', 2); +/** + * Filter type: Prefilter + * @see StringParser::addFilter, StringParser::_prefilters + */ +define ('STRINGPARSER_FILTER_PRE', 1); +/** + * Filter type: Postfilter + * @see StringParser::addFilter, StringParser::_postfilters + */ +define ('STRINGPARSER_FILTER_POST', 2); + +/** + * Generic string parser class + * + * This is an abstract class for any type of string parser. + * + * @package stringparser + */ +class StringParser { + /** + * String parser mode + * + * There are two possible modes: searchmode and loop mode. In loop mode + * every single character is looked at in a loop and it is then decided + * what action to take. This is the most straight-forward approach to + * string parsing but due to the nature of PHP as a scripting language, + * it can also cost performance. In search mode the class posseses a + * list of relevant characters for parsing and uses the + * {@link PHP_MANUAL#strpos strpos} function to search for the next + * relevant character. The search mode will be faster than the loop mode + * in most circumstances but it is also more difficult to implement. + * The subclass that does the string parsing itself will define which + * mode it will implement. + * + * @access protected + * @var int + * @see STRINGPARSER_MODE_SEARCH, STRINGPARSER_MODE_LOOP + */ + var $_parserMode = STRINGPARSER_MODE_SEARCH; + + /** + * Raw text + * @access protected + * @var string + */ + var $_text = ''; + + /** + * Parse stack + * @access protected + * @var array + */ + var $_stack = array (); + + /** + * Current position in raw text + * @access protected + * @var integer + */ + var $_cpos = -1; + + /** + * Root node + * @access protected + * @var mixed + */ + var $_root = null; + + /** + * Length of the text + * @access protected + * @var integer + */ + var $_length = -1; + + /** + * Flag if this object is already parsing a text + * + * This flag is to prevent recursive calls to the parse() function that + * would cause very nasty things. + * + * @access protected + * @var boolean + */ + var $_parsing = false; + + /** + * Strict mode + * + * Whether to stop parsing if a parse error occurs. + * + * @access public + * @var boolean + */ + var $strict = false; + + /** + * Characters or strings to look for + * @access protected + * @var array + */ + var $_charactersSearch = array (); + + /** + * Characters currently allowed + * + * Note that this will only be evaluated in loop mode; in search mode + * this would ruin every performance increase. Note that only single + * characters are permitted here, no strings. Please also note that in + * loop mode, {@link StringParser::_charactersSearch _charactersSearch} + * is evaluated before this variable. + * + * If in strict mode, parsing is stopped if a character that is not + * allowed is encountered. If not in strict mode, the character is + * simply ignored. + * + * @access protected + * @var array + */ + var $_charactersAllowed = array (); + + /** + * Current parser status + * @access protected + * @var int + */ + var $_status = 0; + + /** + * Prefilters + * @access protected + * @var array + */ + var $_prefilters = array (); + + /** + * Postfilters + * @access protected + * @var array + */ + var $_postfilters = array (); + + /** + * Recently reparsed? + * @access protected + * @var bool + */ + var $_recentlyReparsed = false; + + /** + * Constructor + * + * @access public + */ + function StringParser () { + } + + /** + * Add a filter + * + * @access public + * @param int $type The type of the filter + * @param mixed $callback The callback to call + * @return bool + * @see STRINGPARSER_FILTER_PRE, STRINGPARSER_FILTER_POST + */ + function addFilter ($type, $callback) { + // make sure the function is callable + if (!is_callable ($callback)) { + return false; + } + + switch ($type) { + case STRINGPARSER_FILTER_PRE: + $this->_prefilters[] = $callback; + break; + case STRINGPARSER_FILTER_POST: + $this->_postfilters[] = $callback; + break; + default: + return false; + } + + return true; + } + + /** + * Remove all filters + * + * @access public + * @param int $type The type of the filter or 0 for all + * @return bool + * @see STRINGPARSER_FILTER_PRE, STRINGPARSER_FILTER_POST + */ + function clearFilters ($type = 0) { + switch ($type) { + case 0: + $this->_prefilters = array (); + $this->_postfilters = array (); + break; + case STRINGPARSER_FILTER_PRE: + $this->_prefilters = array (); + break; + case STRINGPARSER_FILTER_POST: + $this->_postfilters = array (); + break; + default: + return false; + } + return true; + } + + /** + * This function parses the text + * + * @access public + * @param string $text The text to parse + * @return mixed Either the root object of the tree if no output method + * is defined, the tree reoutput to e.g. a string or false + * if an internal error occured, such as a parse error if + * in strict mode or the object is already parsing a text. + */ + function parse ($text) { + if ($this->_parsing) { + return false; + } + $this->_parsing = true; + $this->_text = $this->_applyPrefilters ($text); + $this->_output = null; + $this->_length = strlen ($this->_text); + $this->_cpos = 0; + unset ($this->_stack); + $this->_stack = array (); + if (is_object ($this->_root)) { + StringParser_Node::destroyNode ($this->_root); + } + unset ($this->_root); + $this->_root =& new StringParser_Node_Root (); + $this->_stack[0] =& $this->_root; + + $this->_parserInit (); + + $finished = false; + + while (!$finished) { + switch ($this->_parserMode) { + case STRINGPARSER_MODE_SEARCH: + $res = $this->_searchLoop (); + if (!$res) { + $this->_parsing = false; + return false; + } + break; + case STRINGPARSER_MODE_LOOP: + $res = $this->_loop (); + if (!$res) { + $this->_parsing = false; + return false; + } + break; + default: + $this->_parsing = false; + return false; + } + + $res = $this->_closeRemainingBlocks (); + if (!$res) { + if ($this->strict) { + $this->_parsing = false; + return false; + } else { + $res = $this->_reparseAfterCurrentBlock (); + if (!$res) { + $this->_parsing = false; + return false; + } + continue; + } + } + $finished = true; + } + + $res = $this->_modifyTree (); + + if (!$res) { + $this->_parsing = false; + return false; + } + + $res = $this->_outputTree (); + + if (!$res) { + $this->_parsing = false; + return false; + } + + if (is_null ($this->_output)) { + $root =& $this->_root; + unset ($this->_root); + $this->_root = null; + while (count ($this->_stack)) { + unset ($this->_stack[count($this->_stack)-1]); + } + $this->_stack = array (); + $this->_parsing = false; + return $root; + } + + $res = StringParser_Node::destroyNode ($this->_root); + if (!$res) { + $this->_parsing = false; + return false; + } + unset ($this->_root); + $this->_root = null; + while (count ($this->_stack)) { + unset ($this->_stack[count($this->_stack)-1]); + } + $this->_stack = array (); + + $this->_parsing = false; + return $this->_output; + } + + /** + * Apply prefilters + * + * It is possible to specify prefilters for the parser to do some + * manipulating of the string beforehand. + */ + function _applyPrefilters ($text) { + foreach ($this->_prefilters as $filter) { + if (is_callable ($filter)) { + $ntext = call_user_func ($filter, $text); + if (is_string ($ntext)) { + $text = $ntext; + } + } + } + return $text; + } + + /** + * Apply postfilters + * + * It is possible to specify postfilters for the parser to do some + * manipulating of the string afterwards. + */ + function _applyPostfilters ($text) { + foreach ($this->_postfilters as $filter) { + if (is_callable ($filter)) { + $ntext = call_user_func ($filter, $text); + if (is_string ($ntext)) { + $text = $ntext; + } + } + } + return $text; + } + + /** + * Abstract method: Manipulate the tree + * @access protected + * @return bool + */ + function _modifyTree () { + return true; + } + + /** + * Abstract method: Output tree + * @access protected + * @return bool + */ + function _outputTree () { + // this could e.g. call _applyPostfilters + return true; + } + + /** + * Restart parsing after current block + * + * To achieve this the current top stack object is removed from the + * tree. Then the current item + * + * @access protected + * @return bool + */ + function _reparseAfterCurrentBlock () { + // this should definitely not happen! + if (($stack_count = count ($this->_stack)) < 2) { + return false; + } + $topelem =& $this->_stack[$stack_count-1]; + + $node_parent =& $topelem->_parent; + // remove the child from the tree + $res = $node_parent->removeChild ($topelem, false); + if (!$res) { + return false; + } + $res = $this->_popNode (); + if (!$res) { + return false; + } + + // now try to get the position of the object + if ($topelem->occurredAt < 0) { + return false; + } + // HACK: could it be necessary to set a different status + // if yes, how should this be achieved? Another member of + // StringParser_Node? + $this->_setStatus (0); + $res = $this->_appendText ($this->_text{$topelem->occurredAt}); + if (!$res) { + return false; + } + + $this->_cpos = $topelem->occurredAt + 1; + $this->_recentlyReparsed = true; + + return true; + } + + /** + * Abstract method: Close remaining blocks + * @access protected + */ + function _closeRemainingBlocks () { + // everything closed + if (count ($this->_stack) == 1) { + return true; + } + // not everything closed + if ($this->strict) { + return false; + } + while (count ($this->_stack) > 1) { + $res = $this->_popNode (); + if (!$res) { + return false; + } + } + return true; + } + + /** + * Abstract method: Initialize the parser + * @access protected + */ + function _parserInit () { + $this->_setStatus (0); + } + + /** + * Abstract method: Set a specific status + * @access protected + */ + function _setStatus ($status) { + if ($status != 0) { + return false; + } + $this->_charactersSearch = array (); + $this->_charactersAllowed = array (); + $this->_status = $status; + return true; + } + + /** + * Abstract method: Handle status + * @access protected + * @param int $status The current status + * @param string $needle The needle that was found + * @return bool + */ + function _handleStatus ($status, $needle) { + $this->_appendText ($needle); + $this->_cpos += strlen ($needle); + return true; + } + + /** + * Search mode loop + * @access protected + * @return bool + */ + function _searchLoop () { + $i = 0; + while (1) { + // make sure this is false! + $this->_recentlyReparsed = false; + + list ($needle, $offset) = $this->_strpos ($this->_charactersSearch, $this->_cpos); + // parser ends here + if ($needle === false) { + // original status 0 => no problem + if (!$this->_status) { + break; + } + // not in original status? strict mode? + if ($this->strict) { + return false; + } + // break up parsing operation of current node + $res = $this->_reparseAfterCurrentBlock (); + if (!$res) { + return false; + } + continue; + } + // get subtext + $subtext = substr ($this->_text, $this->_cpos, $offset - $this->_cpos); + $res = $this->_appendText ($subtext); + if (!$res) { + return false; + } + $this->_cpos = $offset; + $res = $this->_handleStatus ($this->_status, $needle); + if (!$res && $this->strict) { + return false; + } + if (!$res) { + $res = $this->_appendText ($this->_text{$this->_cpos}); + if (!$res) { + return false; + } + $this->_cpos++; + continue; + } + if ($this->_recentlyReparsed) { + $this->_recentlyReparsed = false; + continue; + } + $this->_cpos += strlen ($needle); + } + + // get subtext + if ($this->_cpos < strlen ($this->_text)) { + $subtext = substr ($this->_text, $this->_cpos); + $res = $this->_appendText ($subtext); + if (!$res) { + return false; + } + } + + return true; + } + + /** + * Loop mode loop + * + * @access protected + * @return bool + */ + function _loop () { + // HACK: This method ist not yet implemented correctly, the code below + // DOES NOT WORK! Do not use! + + return false; + /* + while ($this->_cpos < $this->_length) { + $needle = $this->_strDetect ($this->_charactersSearch, $this->_cpos); + + if ($needle === false) { + // not found => see if character is allowed + if (!in_array ($this->_text{$this->_cpos}, $this->_charactersAllowed)) { + if ($strict) { + return false; + } + // ignore + continue; + } + // lot's of FIXMES + $res = $this->_appendText ($this->_text{$this->_cpos}); + if (!$res) { + return false; + } + } + + // get subtext + $subtext = substr ($this->_text, $offset, $offset - $this->_cpos); + $res = $this->_appendText ($subtext); + if (!$res) { + return false; + } + $this->_cpos = $subtext; + $res = $this->_handleStatus ($this->_status, $needle); + if (!$res && $strict) { + return false; + } + } + // original status 0 => no problem + if (!$this->_status) { + return true; + } + // not in original status? strict mode? + if ($this->strict) { + return false; + } + // break up parsing operation of current node + $res = $this->_reparseAfterCurrentBlock (); + if (!$res) { + return false; + } + // this will not cause an infinite loop because + // _reparseAfterCurrentBlock will increase _cpos by one! + return $this->_loop (); + */ + } + + /** + * Abstract method Append text depending on current status + * @access protected + * @param string $text The text to append + * @return bool On success, the function returns true, else false + */ + function _appendText ($text) { + if (!strlen ($text)) { + return true; + } + // default: call _appendToLastTextChild + return $this->_appendToLastTextChild ($text); + } + + /** + * Append text to last text child of current top parser stack node + * @access protected + * @param string $text The text to append + * @return bool On success, the function returns true, else false + */ + function _appendToLastTextChild ($text) { + $scount = count ($this->_stack); + if ($scount == 0) { + return false; + } + return $this->_stack[$scount-1]->appendToLastTextChild ($text); + } + + /** + * Searches {@link StringParser::_text _text} for every needle that is + * specified by using the {@link PHP_MANUAL#strpos strpos} function. It + * returns an associative array with the key 'needle' + * pointing at the string that was found first and the key + * 'offset' pointing at the offset at which the string was + * found first. If no needle was found, the 'needle' + * element is false and the 'offset' element + * is -1. + * + * @access protected + * @param array $needles + * @param int $offset + * @return array + * @see StringParser::_text + */ + function _strpos ($needles, $offset) { + $cur_needle = false; + $cur_offset = -1; + + if ($offset < strlen ($this->_text)) { + foreach ($needles as $needle) { + $n_offset = strpos ($this->_text, $needle, $offset); + if ($n_offset !== false && ($n_offset < $cur_offset || $cur_offset < 0)) { + $cur_needle = $needle; + $cur_offset = $n_offset; + } + } + } + + return array ($cur_needle, $cur_offset, 'needle' => $cur_needle, 'offset' => $cur_offset); + } + + /** + * Detects a string at the current position + * + * @access protected + * @param array $needles The strings that are to be detected + * @param int $offset The current offset + * @return mixed The string that was detected or the needle + */ + function _strDetect ($needles, $offset) { + foreach ($needles as $needle) { + $l = strlen ($needle); + if (substr ($this->_text, $offset, $l) == $needle) { + return $needle; + } + } + return false; + } + + + /** + * Adds a node to the current parse stack + * + * @access protected + * @param object $node The node that is to be added + * @return bool True on success, else false. + * @see StringParser_Node, StringParser::_stack + */ + function _pushNode (&$node) { + $stack_count = count ($this->_stack); + $max_node =& $this->_stack[$stack_count-1]; + if (!$max_node->appendChild ($node)) { + return false; + } + $this->_stack[$stack_count] =& $node; + return true; + } + + /** + * Removes a node from the current parse stack + * + * @access protected + * @return bool True on success, else false. + * @see StringParser_Node, StringParser::_stack + */ + function _popNode () { + $stack_count = count ($this->_stack); + unset ($this->_stack[$stack_count-1]); + return true; + } + + /** + * Execute a method on the top element + * + * @access protected + * @return mixed + */ + function _topNode () { + $args = func_get_args (); + if (!count ($args)) { + return; // oops? + } + $method = array_shift ($args); + $stack_count = count ($this->_stack); + $method = array (&$this->_stack[$stack_count-1], $method); + if (!is_callable ($method)) { + return; // oops? + } + return call_user_func_array ($method, $args); + } + + /** + * Get a variable of the top element + * + * @access protected + * @return mixed + */ + function _topNodeVar ($var) { + $stack_count = count ($this->_stack); + return $this->_stack[$stack_count-1]->$var; + } +} + +/** + * Node type: Unknown node + * @see StringParser_Node::_type + */ +define ('STRINGPARSER_NODE_UNKNOWN', 0); + +/** + * Node type: Root node + * @see StringParser_Node::_type + */ +define ('STRINGPARSER_NODE_ROOT', 1); + +/** + * Node type: Text node + * @see StringParser_Node::_type + */ +define ('STRINGPARSER_NODE_TEXT', 2); + +/** + * Global value that is a counter of string parser node ids. Compare it to a + * sequence in databases. + * @var int + */ +$GLOBALS['__STRINGPARSER_NODE_ID'] = 0; + +/** + * Generic string parser node class + * + * This is an abstract class for any type of node that is used within the + * string parser. General warning: This class contains code regarding references + * that is very tricky. Please do not touch this code unless you exactly know + * what you are doing. Incorrect handling of references may cause PHP to crash + * with a segmentation fault! You have been warned. + * + * @package stringparser + */ +class StringParser_Node { + /** + * The type of this node. + * + * There are three standard node types: root node, text node and unknown + * node. All node types are integer constants. Any node type of a + * subclass must be at least 32 to allow future developements. + * + * @access protected + * @var int + * @see STRINGPARSER_NODE_ROOT, STRINGPARSER_NODE_TEXT + * @see STRINGPARSER_NODE_UNKNOWN + */ + var $_type = STRINGPARSER_NODE_UNKNOWN; + + /** + * The node ID + * + * This ID uniquely identifies this node. This is needed when searching + * for a specific node in the children array. Please note that this is + * only an internal variable and should never be used - not even in + * subclasses and especially not in external data structures. This ID + * has nothing to do with any type of ID in HTML oder XML. + * + * @access protected + * @var int + * @see StringParser_Node::_children + */ + var $_id = -1; + + /** + * The parent of this node. + * + * It is either null (root node) or a reference to the parent object. + * + * @access protected + * @var mixed + * @see StringParser_Node::_children + */ + var $_parent = null; + + /** + * The children of this node. + * + * It contains an array of references to all the children nodes of this + * node. + * + * @access protected + * @var array + * @see StringParser_Node::_parent + */ + var $_children = array (); + + /** + * Occured at + * + * This defines the position in the parsed text where this node occurred + * at. If -1, this value was not possible to be determined. + * + * @access public + * @var int + */ + var $occurredAt = -1; + + /** + * Constructor + * + * Currently, the constructor only allocates a new ID for the node and + * assigns it. + * + * @access public + * @param int $occurredAt The position in the text where this node + * occurred at. If not determinable, it is -1. + * @global __STRINGPARSER_NODE_ID + */ + function StringParser_Node ($occurredAt = -1) { + $this->_id = $GLOBALS['__STRINGPARSER_NODE_ID']++; + $this->occurredAt = $occurredAt; + } + + /** + * Type of the node + * + * This function returns the type of the node + * + * @access public + * @return int + */ + function type () { + return $this->_type; + } + + /** + * Prepend a node + * + * @access public + * @param object $node The node to be prepended. + * @return bool On success, the function returns true, else false. + */ + function prependChild (&$node) { + if (!is_object ($node)) { + return false; + } + + // root nodes may not be children of other nodes! + if ($node->_type == STRINGPARSER_NODE_ROOT) { + return false; + } + + // if node already has a parent + if ($node->_parent !== false) { + // remove node from there + $parent =& $node->_parent; + if (!$parent->removeChild ($node, false)) { + return false; + } + unset ($parent); + } + + $index = count ($this->_children) - 1; + // move all nodes to a new index + while ($index >= 0) { + // save object + $object =& $this->_children[$index]; + // we have to unset it because else it will be + // overridden in in the loop + unset ($this->_children[$index]); + // put object to new position + $this->_children[$index+1] =& $object; + $index--; + } + $this->_children[0] =& $node; + return true; + } + + /** + * Append text to last text child + * @access public + * @param string $text The text to append + * @return bool On success, the function returns true, else false + */ + function appendToLastTextChild ($text) { + $ccount = count ($this->_children); + if ($ccount == 0 || $this->_children[$ccount-1]->_type != STRINGPARSER_NODE_TEXT) { + $ntextnode =& new StringParser_Node_Text ($text); + return $this->appendChild ($ntextnode); + } else { + $this->_children[$ccount-1]->appendText ($text); + return true; + } + } + + /** + * Append a node to the children + * + * This function appends a node to the children array(). It + * automatically sets the {@link StrinParser_Node::_parent _parent} + * property of the node that is to be appended. + * + * @access public + * @param object $node The node that is to be appended. + * @return bool On success, the function returns true, else false. + */ + function appendChild (&$node) { + if (!is_object ($node)) { + return false; + } + + // root nodes may not be children of other nodes! + if ($node->_type == STRINGPARSER_NODE_ROOT) { + return false; + } + + // if node already has a parent + if ($node->_parent !== null) { + // remove node from there + $parent =& $node->_parent; + if (!$parent->removeChild ($node, false)) { + return false; + } + unset ($parent); + } + + // append it to current node + $new_index = count ($this->_children); + $this->_children[$new_index] =& $node; + $node->_parent =& $this; + return true; + } + + /** + * Insert a node before another node + * + * @access public + * @param object $node The node to be inserted. + * @param object $reference The reference node where the new node is + * to be inserted before. + * @return bool On success, the function returns true, else false. + */ + function insertChildBefore (&$node, &$reference) { + if (!is_object ($node)) { + return false; + } + + // root nodes may not be children of other nodes! + if ($node->_type == STRINGPARSER_NODE_ROOT) { + return false; + } + + // is the reference node a child? + $child = $this->_findChild ($reference); + + if ($child === false) { + return false; + } + + // if node already has a parent + if ($node->_parent !== null) { + // remove node from there + $parent =& $node->_parent; + if (!$parent->removeChild ($node, false)) { + return false; + } + unset ($parent); + } + + $index = count ($this->_children) - 1; + // move all nodes to a new index + while ($index >= $child) { + // save object + $object =& $this->_children[$index]; + // we have to unset it because else it will be + // overridden in in the loop + unset ($this->_children[$index]); + // put object to new position + $this->_children[$index+1] =& $object; + $index--; + } + $this->_children[$child] =& $node; + return true; + } + + /** + * Insert a node after another node + * + * @access public + * @param object $node The node to be inserted. + * @param object $reference The reference node where the new node is + * to be inserted after. + * @return bool On success, the function returns true, else false. + */ + function insertChildAfter (&$node, &$reference) { + if (!is_object ($node)) { + return false; + } + + // root nodes may not be children of other nodes! + if ($node->_type == STRINGPARSER_NODE_ROOT) { + return false; + } + + // is the reference node a child? + $child = $this->_findChild ($reference); + + if ($child === false) { + return false; + } + + // if node already has a parent + if ($node->_parent !== false) { + // remove node from there + $parent =& $node->_parent; + if (!$parent->removeChild ($node, false)) { + return false; + } + unset ($parent); + } + + $index = count ($this->_children) - 1; + // move all nodes to a new index + while ($index >= $child + 1) { + // save object + $object =& $this->_children[$index]; + // we have to unset it because else it will be + // overridden in in the loop + unset ($this->_children[$index]); + // put object to new position + $this->_children[$index+1] =& $object; + $index--; + } + $this->_children[$child + 1] =& $node; + return true; + } + + /** + * Remove a child node + * + * This function removes a child from the children array. A parameter + * tells the function whether to destroy the child afterwards or not. + * If the specified node is not a child of this node, the function will + * return false. + * + * @access public + * @param mixed $child The child to destroy; either an integer + * specifying the index of the child or a reference + * to the child itself. + * @param bool $destroy Destroy the child afterwards. + * @return bool On success, the function returns true, else false. + */ + function removeChild (&$child, $destroy = false) { + if (is_object ($child)) { + // if object: get index + $object =& $child; + unset ($child); + $child = $this->_findChild ($object); + if ($child === false) { + return false; + } + } else { + // remove reference on $child + $save = $child; + unset($child); + $child = $save; + + // else: get object + if (!isset($this->_children[$child])) { + return false; + } + $object =& $this->_children[$child]; + } + + // store count for later use + $ccount = count ($this->_children); + + // index out of bounds + if (!is_int ($child) || $child < 0 || $child >= $ccount) { + return false; + } + + // inkonsistency + if ($this->_children[$child]->_parent === null || + $this->_children[$child]->_parent->_id != $this->_id) { + return false; + } + + // $object->_parent = null would equal to $this = null + // as $object->_parent is a reference to $this! + // because of this, we have to unset the variable to remove + // the reference and then redeclare the variable + unset ($object->_parent); $object->_parent = null; + + // we have to unset it because else it will be overridden in + // in the loop + unset ($this->_children[$child]); + + // move all remaining objects one index higher + while ($child < $ccount - 1) { + // save object + $obj =& $this->_children[$child+1]; + // we have to unset it because else it will be + // overridden in in the loop + unset ($this->_children[$child+1]); + // put object to new position + $this->_children[$child] =& $obj; + // UNSET THE OBJECT! + unset ($obj); + $child++; + } + + if ($destroy) { + return StringParser_Node::destroyNode ($object); + unset ($object); + } + return true; + } + + /** + * Get the first child of this node + * + * @access public + * @return mixed + */ + function &firstChild () { + $ret = null; + if (!count ($this->_children)) { + return $ret; + } + return $this->_children[0]; + } + + /** + * Get the last child of this node + * + * @access public + * @return mixed + */ + function &lastChild () { + $ret = null; + $c = count ($this->_children); + if (!$c) { + return $ret; + } + return $this->_children[$c-1]; + } + + /** + * Destroy a node + * + * @access public + * @static + * @param object $node The node to destroy + * @return bool True on success, else false. + */ + function destroyNode (&$node) { + if ($node === null) { + return false; + } + // if parent exists: remove node from tree! + if ($node->_parent !== null) { + $parent =& $node->_parent; + // directly return that result because the removeChild + // method will call destroyNode again + return $parent->removeChild ($node, true); + } + + // node has children + while (count ($node->_children)) { + $child = 0; + // remove first child until no more children remain + if (!$node->removeChild ($child, true)) { + return false; + } + unset($child); + } + + // now call the nodes destructor + if (!$node->_destroy ()) { + return false; + } + + // now just unset it and prey that there are no more references + // to this node + unset ($node); + + return true; + } + + /** + * Destroy this node + * + * + * @access protected + * @return bool True on success, else false. + */ + function _destroy () { + return true; + } + + /** + * Find a child node + * + * This function searches for a node in the own children and returns + * the index of the node or false if the node is not a child of this + * node. + * + * @access protected + * @param mixed $child The node to look for. + * @return mixed The index of the child node on success, else false. + */ + function _findChild (&$child) { + if (!is_object ($child)) { + return false; + } + + $ccount = count ($this->_children); + for ($i = 0; $i < $ccount; $i++) { + if ($this->_children[$i]->_id == $child->_id) { + return $i; + } + } + + return false; + } + + /** + * Checks equality of this node and another node + * + * @access public + * @param mixed $node The node to be compared with + * @return bool True if the other node equals to this node, else false. + */ + function equals (&$node) { + return ($this->_id == $node->_id); + } + + /** + * Determines whether a criterium matches this node + * + * @access public + * @param string $criterium The criterium that is to be checked + * @param mixed $value The value that is to be compared + * @return bool True if this node matches that criterium + */ + function matchesCriterium ($criterium, $value) { + return false; + } + + /** + * Search for nodes with a certain criterium + * + * This may be used to implement getElementsByTagName etc. + * + * @access public + * @param string $criterium The criterium that is to be checked + * @param mixed $value The value that is to be compared + * @return array All subnodes that match this criterium + */ + function &getNodesByCriterium ($criterium, $value) { + $nodes = array (); + $node_ctr = 0; + for ($i = 0; $i < count ($this->_children); $i++) { + if ($this->_children[$i]->matchesCriterium ($criterium, $value)) { + $nodes[$node_ctr++] =& $this->_children[$i]; + } + $subnodes = $this->_children[$i]->getNodesByCriterium ($criterium, $value); + if (count ($subnodes)) { + $subnodes_count = count ($subnodes); + for ($j = 0; $j < $subnodes_count; $j++) { + $nodes[$node_ctr++] =& $subnodes[$j]; + unset ($subnodes[$j]); + } + } + unset ($subnodes); + } + return $nodes; + } + + /** + * Search for nodes with a certain criterium and return the count + * + * Similar to getNodesByCriterium + * + * @access public + * @param string $criterium The criterium that is to be checked + * @param mixed $value The value that is to be compared + * @return int The number of subnodes that match this criterium + */ + function getNodeCountByCriterium ($criterium, $value) { + $node_ctr = 0; + for ($i = 0; $i < count ($this->_children); $i++) { + if ($this->_children[$i]->matchesCriterium ($criterium, $value)) { + $node_ctr++; + } + $subnodes = $this->_children[$i]->getNodeCountByCriterium ($criterium, $value); + $node_ctr += $subnodes; + } + return $node_ctr; + } + + /** + * Dump nodes + * + * This dumps a tree of nodes + * + * @access public + * @param string $prefix The prefix that is to be used for indentation + * @param string $linesep The line separator + * @param int $level The initial level of indentation + * @return string + */ + function dump ($prefix = " ", $linesep = "\n", $level = 0) { + $str = str_repeat ($prefix, $level) . $this->_id . ": " . $this->_dumpToString () . $linesep; + for ($i = 0; $i < count ($this->_children); $i++) { + $str .= $this->_children[$i]->dump ($prefix, $linesep, $level + 1); + } + return $str; + } + + /** + * Dump this node to a string + * + * @access protected + * @return string + */ + function _dumpToString () { + if ($this->_type == STRINGPARSER_NODE_ROOT) { + return "root"; + } + return (string)$this->_type; + } +} + +/** + * String parser root node class + * + * @package stringparser + */ +class StringParser_Node_Root extends StringParser_Node { + /** + * The type of this node. + * + * This node is a root node. + * + * @access protected + * @var int + * @see STRINGPARSER_NODE_ROOT + */ + var $_type = STRINGPARSER_NODE_ROOT; +} + +/** + * String parser text node class + * + * @package stringparser + */ +class StringParser_Node_Text extends StringParser_Node { + /** + * The type of this node. + * + * This node is a text node. + * + * @access protected + * @var int + * @see STRINGPARSER_NODE_TEXT + */ + var $_type = STRINGPARSER_NODE_TEXT; + + /** + * Node flags + * + * @access protected + * @var array + */ + var $_flags = array (); + + /** + * The content of this node + * @access public + * @var string + */ + var $content = ''; + + /** + * Constructor + * + * @access public + * @param string $content The initial content of this element + * @param int $occurredAt The position in the text where this node + * occurred at. If not determinable, it is -1. + * @see StringParser_Node_Text::content + */ + function StringParser_Node_Text ($content, $occurredAt = -1) { + parent::StringParser_Node ($occurredAt); + $this->content = $content; + } + + /** + * Append text to content + * + * @access public + * @param string $text The text to append + * @see StringParser_Node_Text::content + */ + function appendText ($text) { + $this->content .= $text; + } + + /** + * Set a flag + * + * @access public + * @param string $name The name of the flag + * @param mixed $value The value of the flag + */ + function setFlag ($name, $value) { + $this->_flags[$name] = $value; + return true; + } + + /** + * Get Flag + * + * @access public + * @param string $flag The requested flag + * @param string $type The requested type of the return value + * @param mixed $default The default return value + */ + function getFlag ($flag, $type = 'mixed', $default = null) { + if (!isset ($this->_flags[$flag])) { + return $default; + } + $return = $this->_flags[$flag]; + if ($type != 'mixed') { + settype ($return, $type); + } + return $return; + } + + /** + * Dump this node to a string + */ + function _dumpToString () { + return "text \"".substr (preg_replace ('/\s+/', ' ', $this->content), 0, 40)."\" [f:".preg_replace ('/\s+/', ' ', join(':', array_keys ($this->_flags)))."]"; + } +} + +?> \ No newline at end of file diff --git a/scripts/stringparser_bbcode.class.php b/scripts/stringparser_bbcode.class.php new file mode 100644 index 0000000..9142609 --- /dev/null +++ b/scripts/stringparser_bbcode.class.php @@ -0,0 +1,1979 @@ + + * @copyright Christian Seiler 2004-2008 + * @package stringparser + * + * The MIT License + * + * Copyright (c) 2004-2008 Christian Seiler + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +require_once dirname(__FILE__).'/stringparser.class.php'; + +define ('BBCODE_CLOSETAG_FORBIDDEN', -1); +define ('BBCODE_CLOSETAG_OPTIONAL', 0); +define ('BBCODE_CLOSETAG_IMPLICIT', 1); +define ('BBCODE_CLOSETAG_IMPLICIT_ON_CLOSE_ONLY', 2); +define ('BBCODE_CLOSETAG_MUSTEXIST', 3); + +define ('BBCODE_NEWLINE_PARSE', 0); +define ('BBCODE_NEWLINE_IGNORE', 1); +define ('BBCODE_NEWLINE_DROP', 2); + +define ('BBCODE_PARAGRAPH_ALLOW_BREAKUP', 0); +define ('BBCODE_PARAGRAPH_ALLOW_INSIDE', 1); +define ('BBCODE_PARAGRAPH_BLOCK_ELEMENT', 2); + +/** + * BB code string parser class + * + * @package stringparser + */ +class StringParser_BBCode extends StringParser { + /** + * String parser mode + * + * The BBCode string parser works in search mode + * + * @access protected + * @var int + * @see STRINGPARSER_MODE_SEARCH, STRINGPARSER_MODE_LOOP + */ + var $_parserMode = STRINGPARSER_MODE_SEARCH; + + /** + * Defined BB Codes + * + * The registered BB codes + * + * @access protected + * @var array + */ + var $_codes = array (); + + /** + * Registered parsers + * + * @access protected + * @var array + */ + var $_parsers = array (); + + /** + * Defined maximum occurrences + * + * @access protected + * @var array + */ + var $_maxOccurrences = array (); + + /** + * Root content type + * + * @access protected + * @var string + */ + var $_rootContentType = 'block'; + + /** + * Do not output but return the tree + * + * @access protected + * @var bool + */ + var $_noOutput = false; + + /** + * Global setting: case sensitive + * + * @access protected + * @var bool + */ + var $_caseSensitive = true; + + /** + * Root paragraph handling enabled + * + * @access protected + * @var bool + */ + var $_rootParagraphHandling = false; + + /** + * Paragraph handling parameters + * @access protected + * @var array + */ + var $_paragraphHandling = array ( + 'detect_string' => "\n\n", + 'start_tag' => '

    ', + 'end_tag' => "

    \n" + ); + + /** + * Allow mixed attribute types (e.g. [code=bla attr=blub]) + * @access private + * @var bool + */ + var $_mixedAttributeTypes = false; + + /** + * Whether to call validation function again (with $action == 'validate_auto') when closetag comes + * @access protected + * @var bool + */ + var $_validateAgain = false; + + /** + * Add a code + * + * @access public + * @param string $name The name of the code + * @param string $callback_type See documentation + * @param string $callback_func The callback function to call + * @param array $callback_params The callback parameters + * @param string $content_type See documentation + * @param array $allowed_within See documentation + * @param array $not_allowed_within See documentation + * @return bool + */ + function addCode ($name, $callback_type, $callback_func, $callback_params, $content_type, $allowed_within, $not_allowed_within) { + if (isset ($this->_codes[$name])) { + return false; // already exists + } + if (!preg_match ('/^[a-zA-Z0-9*_!+-]+$/', $name)) { + return false; // invalid + } + $this->_codes[$name] = array ( + 'name' => $name, + 'callback_type' => $callback_type, + 'callback_func' => $callback_func, + 'callback_params' => $callback_params, + 'content_type' => $content_type, + 'allowed_within' => $allowed_within, + 'not_allowed_within' => $not_allowed_within, + 'flags' => array () + ); + return true; + } + + /** + * Remove a code + * + * @access public + * @param $name The code to remove + * @return bool + */ + function removeCode ($name) { + if (isset ($this->_codes[$name])) { + unset ($this->_codes[$name]); + return true; + } + return false; + } + + /** + * Remove all codes + * + * @access public + */ + function removeAllCodes () { + $this->_codes = array (); + } + + /** + * Set a code flag + * + * @access public + * @param string $name The name of the code + * @param string $flag The name of the flag to set + * @param mixed $value The value of the flag to set + * @return bool + */ + function setCodeFlag ($name, $flag, $value) { + if (!isset ($this->_codes[$name])) { + return false; + } + $this->_codes[$name]['flags'][$flag] = $value; + return true; + } + + /** + * Set occurrence type + * + * Example: + * $bbcode->setOccurrenceType ('url', 'link'); + * $bbcode->setMaxOccurrences ('link', 4); + * Would create the situation where a link may only occur four + * times in the hole text. + * + * @access public + * @param string $code The name of the code + * @param string $type The name of the occurrence type to set + * @return bool + */ + function setOccurrenceType ($code, $type) { + return $this->setCodeFlag ($code, 'occurrence_type', $type); + } + + /** + * Set maximum number of occurrences + * + * @access public + * @param string $type The name of the occurrence type + * @param int $count The maximum number of occurrences + * @return bool + */ + function setMaxOccurrences ($type, $count) { + settype ($count, 'integer'); + if ($count < 0) { // sorry, does not make any sense + return false; + } + $this->_maxOccurrences[$type] = $count; + return true; + } + + /** + * Add a parser + * + * @access public + * @param string $type The content type for which the parser is to add + * @param mixed $parser The function to call + * @return bool + */ + function addParser ($type, $parser) { + if (is_array ($type)) { + foreach ($type as $t) { + $this->addParser ($t, $parser); + } + return true; + } + if (!isset ($this->_parsers[$type])) { + $this->_parsers[$type] = array (); + } + $this->_parsers[$type][] = $parser; + return true; + } + + /** + * Set root content type + * + * @access public + * @param string $content_type The new root content type + */ + function setRootContentType ($content_type) { + $this->_rootContentType = $content_type; + } + + /** + * Set paragraph handling on root element + * + * @access public + * @param bool $enabled The new status of paragraph handling on root element + */ + function setRootParagraphHandling ($enabled) { + $this->_rootParagraphHandling = (bool)$enabled; + } + + /** + * Set paragraph handling parameters + * + * @access public + * @param string $detect_string The string to detect + * @param string $start_tag The replacement for the start tag (e.g.

    ) + * @param string $end_tag The replacement for the start tag (e.g.

    ) + */ + function setParagraphHandlingParameters ($detect_string, $start_tag, $end_tag) { + $this->_paragraphHandling = array ( + 'detect_string' => $detect_string, + 'start_tag' => $start_tag, + 'end_tag' => $end_tag + ); + } + + /** + * Set global case sensitive flag + * + * If this is set to true, the class normally is case sensitive, but + * the case_sensitive code flag may override this for a single code. + * + * If this is set to false, all codes are case insensitive. + * + * @access public + * @param bool $caseSensitive + */ + function setGlobalCaseSensitive ($caseSensitive) { + $this->_caseSensitive = (bool)$caseSensitive; + } + + /** + * Get global case sensitive flag + * + * @access public + * @return bool + */ + function globalCaseSensitive () { + return $this->_caseSensitive; + } + + /** + * Set mixed attribute types flag + * + * If set, [code=val1 attr=val2] will cause 2 attributes to be parsed: + * 'default' will have value 'val1', 'attr' will have value 'val2'. + * If not set, only one attribute 'default' will have the value + * 'val1 attr=val2' (the default and original behaviour) + * + * @access public + * @param bool $mixedAttributeTypes + */ + function setMixedAttributeTypes ($mixedAttributeTypes) { + $this->_mixedAttributeTypes = (bool)$mixedAttributeTypes; + } + + /** + * Get mixed attribute types flag + * + * @access public + * @return bool + */ + function mixedAttributeTypes () { + return $this->_mixedAttributeTypes; + } + + /** + * Set validate again flag + * + * If this is set to true, the class calls the validation function + * again with $action == 'validate_again' when closetag comes. + * + * @access public + * @param bool $validateAgain + */ + function setValidateAgain ($validateAgain) { + $this->_validateAgain = (bool)$validateAgain; + } + + /** + * Get validate again flag + * + * @access public + * @return bool + */ + function validateAgain () { + return $this->_validateAgain; + } + + /** + * Get a code flag + * + * @access public + * @param string $name The name of the code + * @param string $flag The name of the flag to get + * @param string $type The type of the return value + * @param mixed $default The default return value + * @return bool + */ + function getCodeFlag ($name, $flag, $type = 'mixed', $default = null) { + if (!isset ($this->_codes[$name])) { + return $default; + } + if (!array_key_exists ($flag, $this->_codes[$name]['flags'])) { + return $default; + } + $return = $this->_codes[$name]['flags'][$flag]; + if ($type != 'mixed') { + settype ($return, $type); + } + return $return; + } + + /** + * Set a specific status + * @access protected + */ + function _setStatus ($status) { + switch ($status) { + case 0: + $this->_charactersSearch = array ('[/', '['); + $this->_status = $status; + break; + case 1: + $this->_charactersSearch = array (']', ' = "', '="', ' = \'', '=\'', ' = ', '=', ': ', ':', ' '); + $this->_status = $status; + break; + case 2: + $this->_charactersSearch = array (']'); + $this->_status = $status; + $this->_savedName = ''; + break; + case 3: + if ($this->_quoting !== null) { + if ($this->_mixedAttributeTypes) { + $this->_charactersSearch = array ('\\\\', '\\'.$this->_quoting, $this->_quoting.' ', $this->_quoting.']', $this->_quoting); + } else { + $this->_charactersSearch = array ('\\\\', '\\'.$this->_quoting, $this->_quoting.']', $this->_quoting); + } + $this->_status = $status; + break; + } + if ($this->_mixedAttributeTypes) { + $this->_charactersSearch = array (' ', ']'); + } else { + $this->_charactersSearch = array (']'); + } + $this->_status = $status; + break; + case 4: + $this->_charactersSearch = array (' ', ']', '="', '=\'', '='); + $this->_status = $status; + $this->_savedName = ''; + $this->_savedValue = ''; + break; + case 5: + if ($this->_quoting !== null) { + $this->_charactersSearch = array ('\\\\', '\\'.$this->_quoting, $this->_quoting.' ', $this->_quoting.']', $this->_quoting); + } else { + $this->_charactersSearch = array (' ', ']'); + } + $this->_status = $status; + $this->_savedValue = ''; + break; + case 7: + $this->_charactersSearch = array ('[/'.$this->_topNode ('name').']'); + if (!$this->_topNode ('getFlag', 'case_sensitive', 'boolean', true) || !$this->_caseSensitive) { + $this->_charactersSearch[] = '[/'; + } + $this->_status = $status; + break; + default: + return false; + } + return true; + } + + /** + * Abstract method Append text depending on current status + * @access protected + * @param string $text The text to append + * @return bool On success, the function returns true, else false + */ + function _appendText ($text) { + if (!strlen ($text)) { + return true; + } + switch ($this->_status) { + case 0: + case 7: + return $this->_appendToLastTextChild ($text); + case 1: + return $this->_topNode ('appendToName', $text); + case 2: + case 4: + $this->_savedName .= $text; + return true; + case 3: + return $this->_topNode ('appendToAttribute', 'default', $text); + case 5: + $this->_savedValue .= $text; + return true; + default: + return false; + } + } + + /** + * Restart parsing after current block + * + * To achieve this the current top stack object is removed from the + * tree. Then the current item + * + * @access protected + * @return bool + */ + function _reparseAfterCurrentBlock () { + if ($this->_status == 2) { + // this status will *never* call _reparseAfterCurrentBlock itself + // so this is called if the loop ends + // therefore, just add the [/ to the text + + // _savedName should be empty but just in case + $this->_cpos -= strlen ($this->_savedName); + $this->_savedName = ''; + $this->_status = 0; + $this->_appendText ('[/'); + return true; + } else { + return parent::_reparseAfterCurrentBlock (); + } + } + + /** + * Apply parsers + */ + function _applyParsers ($type, $text) { + if (!isset ($this->_parsers[$type])) { + return $text; + } + foreach ($this->_parsers[$type] as $parser) { + if (is_callable ($parser)) { + $ntext = call_user_func ($parser, $text); + if (is_string ($ntext)) { + $text = $ntext; + } + } + } + return $text; + } + + /** + * Handle status + * @access protected + * @param int $status The current status + * @param string $needle The needle that was found + * @return bool + */ + function _handleStatus ($status, $needle) { + switch ($status) { + case 0: // NORMAL TEXT + if ($needle != '[' && $needle != '[/') { + $this->_appendText ($needle); + return true; + } + if ($needle == '[') { + $node =& new StringParser_BBCode_Node_Element ($this->_cpos); + $res = $this->_pushNode ($node); + if (!$res) { + return false; + } + $this->_setStatus (1); + } else if ($needle == '[/') { + if (count ($this->_stack) <= 1) { + $this->_appendText ($needle); + return true; + } + $this->_setStatus (2); + } + break; + case 1: // OPEN TAG + if ($needle == ']') { + return $this->_openElement (0); + } else if (trim ($needle) == ':' || trim ($needle) == '=') { + $this->_quoting = null; + $this->_setStatus (3); // default value parser + break; + } else if (trim ($needle) == '="' || trim ($needle) == '= "' || trim ($needle) == '=\'' || trim ($needle) == '= \'') { + $this->_quoting = substr (trim ($needle), -1); + $this->_setStatus (3); // default value parser with quotation + break; + } else if ($needle == ' ') { + $this->_setStatus (4); // attribute parser + break; + } else { + $this->_appendText ($needle); + return true; + } + // break not necessary because every if clause contains return + case 2: // CLOSE TAG + if ($needle != ']') { + $this->_appendText ($needle); + return true; + } + $closecount = 0; + if (!$this->_isCloseable ($this->_savedName, $closecount)) { + $this->_setStatus (0); + $this->_appendText ('[/'.$this->_savedName.$needle); + return true; + } + // this validates the code(s) to be closed after the content tree of + // that code(s) are built - if the second validation fails, we will have + // to reparse. note that as _reparseAfterCurrentBlock will not work correctly + // if we're in $status == 2, we will have to set our status to 0 manually + if (!$this->_validateCloseTags ($closecount)) { + $this->_setStatus (0); + return $this->_reparseAfterCurrentBlock (); + } + $this->_setStatus (0); + for ($i = 0; $i < $closecount; $i++) { + if ($i == $closecount - 1) { + $this->_topNode ('setHadCloseTag'); + } + if (!$this->_popNode ()) { + return false; + } + } + break; + case 3: // DEFAULT ATTRIBUTE + if ($this->_quoting !== null) { + if ($needle == '\\\\') { + $this->_appendText ('\\'); + return true; + } else if ($needle == '\\'.$this->_quoting) { + $this->_appendText ($this->_quoting); + return true; + } else if ($needle == $this->_quoting.' ') { + $this->_setStatus (4); + return true; + } else if ($needle == $this->_quoting.']') { + return $this->_openElement (2); + } else if ($needle == $this->_quoting) { + // can't be, only ']' and ' ' allowed after quoting char + return $this->_reparseAfterCurrentBlock (); + } else { + $this->_appendText ($needle); + return true; + } + } else { + if ($needle == ' ') { + $this->_setStatus (4); + return true; + } else if ($needle == ']') { + return $this->_openElement (2); + } else { + $this->_appendText ($needle); + return true; + } + } + // break not needed because every if clause contains return! + case 4: // ATTRIBUTE NAME + if ($needle == ' ') { + if (strlen ($this->_savedName)) { + $this->_topNode ('setAttribute', $this->_savedName, true); + } + // just ignore and continue in same mode + $this->_setStatus (4); // reset parameters + return true; + } else if ($needle == ']') { + if (strlen ($this->_savedName)) { + $this->_topNode ('setAttribute', $this->_savedName, true); + } + return $this->_openElement (2); + } else if ($needle == '=') { + $this->_quoting = null; + $this->_setStatus (5); + return true; + } else if ($needle == '="') { + $this->_quoting = '"'; + $this->_setStatus (5); + return true; + } else if ($needle == '=\'') { + $this->_quoting = '\''; + $this->_setStatus (5); + return true; + } else { + $this->_appendText ($needle); + return true; + } + // break not needed because every if clause contains return! + case 5: // ATTRIBUTE VALUE + if ($this->_quoting !== null) { + if ($needle == '\\\\') { + $this->_appendText ('\\'); + return true; + } else if ($needle == '\\'.$this->_quoting) { + $this->_appendText ($this->_quoting); + return true; + } else if ($needle == $this->_quoting.' ') { + $this->_topNode ('setAttribute', $this->_savedName, $this->_savedValue); + $this->_setStatus (4); + return true; + } else if ($needle == $this->_quoting.']') { + $this->_topNode ('setAttribute', $this->_savedName, $this->_savedValue); + return $this->_openElement (2); + } else if ($needle == $this->_quoting) { + // can't be, only ']' and ' ' allowed after quoting char + return $this->_reparseAfterCurrentBlock (); + } else { + $this->_appendText ($needle); + return true; + } + } else { + if ($needle == ' ') { + $this->_topNode ('setAttribute', $this->_savedName, $this->_savedValue); + $this->_setStatus (4); + return true; + } else if ($needle == ']') { + $this->_topNode ('setAttribute', $this->_savedName, $this->_savedValue); + return $this->_openElement (2); + } else { + $this->_appendText ($needle); + return true; + } + } + // break not needed because every if clause contains return! + case 7: + if ($needle == '[/') { + // this was case insensitive match + if (strtolower (substr ($this->_text, $this->_cpos + strlen ($needle), strlen ($this->_topNode ('name')) + 1)) == strtolower ($this->_topNode ('name').']')) { + // this matched + $this->_cpos += strlen ($this->_topNode ('name')) + 1; + } else { + // it didn't match + $this->_appendText ($needle); + return true; + } + } + $closecount = $this->_savedCloseCount; + if (!$this->_topNode ('validate')) { + return $this->_reparseAfterCurrentBlock (); + } + // do we have to close subnodes? + if ($closecount) { + // get top node + $mynode =& $this->_stack[count ($this->_stack)-1]; + // close necessary nodes + for ($i = 0; $i <= $closecount; $i++) { + if (!$this->_popNode ()) { + return false; + } + } + if (!$this->_pushNode ($mynode)) { + return false; + } + } + $this->_setStatus (0); + $this->_popNode (); + return true; + default: + return false; + } + return true; + } + + /** + * Open the next element + * + * @access protected + * @return bool + */ + function _openElement ($type = 0) { + $name = $this->_getCanonicalName ($this->_topNode ('name')); + if ($name === false) { + return $this->_reparseAfterCurrentBlock (); + } + $occ_type = $this->getCodeFlag ($name, 'occurrence_type', 'string'); + if ($occ_type !== null && isset ($this->_maxOccurrences[$occ_type])) { + $max_occs = $this->_maxOccurrences[$occ_type]; + $occs = $this->_root->getNodeCountByCriterium ('flag:occurrence_type', $occ_type); + if ($occs >= $max_occs) { + return $this->_reparseAfterCurrentBlock (); + } + } + $closecount = 0; + $this->_topNode ('setCodeInfo', $this->_codes[$name]); + if (!$this->_isOpenable ($name, $closecount)) { + return $this->_reparseAfterCurrentBlock (); + } + $this->_setStatus (0); + switch ($type) { + case 0: + $cond = $this->_isUseContent ($this->_stack[count($this->_stack)-1], false); + break; + case 1: + $cond = $this->_isUseContent ($this->_stack[count($this->_stack)-1], true); + break; + case 2: + $cond = $this->_isUseContent ($this->_stack[count($this->_stack)-1], true); + break; + default: + $cond = false; + break; + } + if ($cond) { + $this->_savedCloseCount = $closecount; + $this->_setStatus (7); + return true; + } + if (!$this->_topNode ('validate')) { + return $this->_reparseAfterCurrentBlock (); + } + // do we have to close subnodes? + if ($closecount) { + // get top node + $mynode =& $this->_stack[count ($this->_stack)-1]; + // close necessary nodes + for ($i = 0; $i <= $closecount; $i++) { + if (!$this->_popNode ()) { + return false; + } + } + if (!$this->_pushNode ($mynode)) { + return false; + } + } + + if ($this->_codes[$name]['callback_type'] == 'simple_replace_single' || $this->_codes[$name]['callback_type'] == 'callback_replace_single') { + if (!$this->_popNode ()) { + return false; + } + } + + return true; + } + + /** + * Is a node closeable? + * + * @access protected + * @return bool + */ + function _isCloseable ($name, &$closecount) { + $node =& $this->_findNamedNode ($name, false); + if ($node === false) { + return false; + } + $scount = count ($this->_stack); + for ($i = $scount - 1; $i > 0; $i--) { + $closecount++; + if ($this->_stack[$i]->equals ($node)) { + return true; + } + if ($this->_stack[$i]->getFlag ('closetag', 'integer', BBCODE_CLOSETAG_IMPLICIT) == BBCODE_CLOSETAG_MUSTEXIST) { + return false; + } + } + return false; + } + + /** + * Revalidate codes when close tags appear + * + * @access protected + * @return bool + */ + function _validateCloseTags ($closecount) { + $scount = count ($this->_stack); + for ($i = $scount - 1; $i >= $scount - $closecount; $i--) { + if ($this->_validateAgain) { + if (!$this->_stack[$i]->validate ('validate_again')) { + return false; + } + } + } + return true; + } + + /** + * Is a node openable? + * + * @access protected + * @return bool + */ + function _isOpenable ($name, &$closecount) { + if (!isset ($this->_codes[$name])) { + return false; + } + + $closecount = 0; + + $allowed_within = $this->_codes[$name]['allowed_within']; + $not_allowed_within = $this->_codes[$name]['not_allowed_within']; + + $scount = count ($this->_stack); + if ($scount == 2) { // top level element + if (!in_array ($this->_rootContentType, $allowed_within)) { + return false; + } + } else { + if (!in_array ($this->_stack[$scount-2]->_codeInfo['content_type'], $allowed_within)) { + return $this->_isOpenableWithClose ($name, $closecount); + } + } + + for ($i = 1; $i < $scount - 1; $i++) { + if (in_array ($this->_stack[$i]->_codeInfo['content_type'], $not_allowed_within)) { + return $this->_isOpenableWithClose ($name, $closecount); + } + } + + return true; + } + + /** + * Is a node openable by closing other nodes? + * + * @access protected + * @return bool + */ + function _isOpenableWithClose ($name, &$closecount) { + $tnname = $this->_getCanonicalName ($this->_topNode ('name')); + if (!in_array ($this->getCodeFlag ($tnname, 'closetag', 'integer', BBCODE_CLOSETAG_IMPLICIT), array (BBCODE_CLOSETAG_FORBIDDEN, BBCODE_CLOSETAG_OPTIONAL))) { + return false; + } + $node =& $this->_findNamedNode ($name, true); + if ($node === false) { + return false; + } + $scount = count ($this->_stack); + if ($scount < 3) { + return false; + } + for ($i = $scount - 2; $i > 0; $i--) { + $closecount++; + if ($this->_stack[$i]->equals ($node)) { + return true; + } + if (in_array ($this->_stack[$i]->getFlag ('closetag', 'integer', BBCODE_CLOSETAG_IMPLICIT), array (BBCODE_CLOSETAG_IMPLICIT_ON_CLOSE_ONLY, BBCODE_CLOSETAG_MUSTEXIST))) { + return false; + } + if ($this->_validateAgain) { + if (!$this->_stack[$i]->validate ('validate_again')) { + return false; + } + } + } + + return false; + } + + /** + * Abstract method: Close remaining blocks + * @access protected + */ + function _closeRemainingBlocks () { + // everything closed + if (count ($this->_stack) == 1) { + return true; + } + // not everything close + if ($this->strict) { + return false; + } + while (count ($this->_stack) > 1) { + if ($this->_topNode ('getFlag', 'closetag', 'integer', BBCODE_CLOSETAG_IMPLICIT) == BBCODE_CLOSETAG_MUSTEXIST) { + return false; // sorry + } + $res = $this->_popNode (); + if (!$res) { + return false; + } + } + return true; + } + + /** + * Find a node with a specific name in stack + * + * @access protected + * @return mixed + */ + function &_findNamedNode ($name, $searchdeeper = false) { + $lname = $this->_getCanonicalName ($name); + $case_sensitive = $this->_caseSensitive && $this->getCodeFlag ($lname, 'case_sensitive', 'boolean', true); + if ($case_sensitive) { + $name = strtolower ($name); + } + $scount = count ($this->_stack); + if ($searchdeeper) { + $scount--; + } + for ($i = $scount - 1; $i > 0; $i--) { + if (!$case_sensitive) { + $cmp_name = strtolower ($this->_stack[$i]->name ()); + } else { + $cmp_name = $this->_stack[$i]->name (); + } + if ($cmp_name == $lname) { + return $this->_stack[$i]; + } + } + $result = false; + return $result; + } + + /** + * Abstract method: Output tree + * @access protected + * @return bool + */ + function _outputTree () { + if ($this->_noOutput) { + return true; + } + $output = $this->_outputNode ($this->_root); + if (is_string ($output)) { + $this->_output = $this->_applyPostfilters ($output); + unset ($output); + return true; + } + + return false; + } + + /** + * Output a node + * @access protected + * @return bool + */ + function _outputNode (&$node) { + $output = ''; + if ($node->_type == STRINGPARSER_BBCODE_NODE_PARAGRAPH || $node->_type == STRINGPARSER_BBCODE_NODE_ELEMENT || $node->_type == STRINGPARSER_NODE_ROOT) { + $ccount = count ($node->_children); + for ($i = 0; $i < $ccount; $i++) { + $suboutput = $this->_outputNode ($node->_children[$i]); + if (!is_string ($suboutput)) { + return false; + } + $output .= $suboutput; + } + if ($node->_type == STRINGPARSER_BBCODE_NODE_PARAGRAPH) { + return $this->_paragraphHandling['start_tag'].$output.$this->_paragraphHandling['end_tag']; + } + if ($node->_type == STRINGPARSER_BBCODE_NODE_ELEMENT) { + return $node->getReplacement ($output); + } + return $output; + } else if ($node->_type == STRINGPARSER_NODE_TEXT) { + $output = $node->content; + $before = ''; + $after = ''; + $ol = strlen ($output); + switch ($node->getFlag ('newlinemode.begin', 'integer', BBCODE_NEWLINE_PARSE)) { + case BBCODE_NEWLINE_IGNORE: + if ($ol && $output{0} == "\n") { + $before = "\n"; + } + // don't break! + case BBCODE_NEWLINE_DROP: + if ($ol && $output{0} == "\n") { + $output = substr ($output, 1); + $ol--; + } + break; + } + switch ($node->getFlag ('newlinemode.end', 'integer', BBCODE_NEWLINE_PARSE)) { + case BBCODE_NEWLINE_IGNORE: + if ($ol && $output{$ol-1} == "\n") { + $after = "\n"; + } + // don't break! + case BBCODE_NEWLINE_DROP: + if ($ol && $output{$ol-1} == "\n") { + $output = substr ($output, 0, -1); + $ol--; + } + break; + } + // can't do anything + if ($node->_parent === null) { + return $before.$output.$after; + } + if ($node->_parent->_type == STRINGPARSER_BBCODE_NODE_PARAGRAPH) { + $parent =& $node->_parent; + unset ($node); + $node =& $parent; + unset ($parent); + // if no parent for this paragraph + if ($node->_parent === null) { + return $before.$output.$after; + } + } + if ($node->_parent->_type == STRINGPARSER_NODE_ROOT) { + return $before.$this->_applyParsers ($this->_rootContentType, $output).$after; + } + if ($node->_parent->_type == STRINGPARSER_BBCODE_NODE_ELEMENT) { + return $before.$this->_applyParsers ($node->_parent->_codeInfo['content_type'], $output).$after; + } + return $before.$output.$after; + } + } + + /** + * Abstract method: Manipulate the tree + * @access protected + * @return bool + */ + function _modifyTree () { + // first pass: try to do newline handling + $nodes =& $this->_root->getNodesByCriterium ('needsTextNodeModification', true); + $nodes_count = count ($nodes); + for ($i = 0; $i < $nodes_count; $i++) { + $v = $nodes[$i]->getFlag ('opentag.before.newline', 'integer', BBCODE_NEWLINE_PARSE); + if ($v != BBCODE_NEWLINE_PARSE) { + $n =& $nodes[$i]->findPrevAdjentTextNode (); + if (!is_null ($n)) { + $n->setFlag ('newlinemode.end', $v); + } + unset ($n); + } + $v = $nodes[$i]->getFlag ('opentag.after.newline', 'integer', BBCODE_NEWLINE_PARSE); + if ($v != BBCODE_NEWLINE_PARSE) { + $n =& $nodes[$i]->firstChildIfText (); + if (!is_null ($n)) { + $n->setFlag ('newlinemode.begin', $v); + } + unset ($n); + } + $v = $nodes[$i]->getFlag ('closetag.before.newline', 'integer', BBCODE_NEWLINE_PARSE); + if ($v != BBCODE_NEWLINE_PARSE) { + $n =& $nodes[$i]->lastChildIfText (); + if (!is_null ($n)) { + $n->setFlag ('newlinemode.end', $v); + } + unset ($n); + } + $v = $nodes[$i]->getFlag ('closetag.after.newline', 'integer', BBCODE_NEWLINE_PARSE); + if ($v != BBCODE_NEWLINE_PARSE) { + $n =& $nodes[$i]->findNextAdjentTextNode (); + if (!is_null ($n)) { + $n->setFlag ('newlinemode.begin', $v); + } + unset ($n); + } + } + + // second pass a: do paragraph handling on root element + if ($this->_rootParagraphHandling) { + $res = $this->_handleParagraphs ($this->_root); + if (!$res) { + return false; + } + } + + // second pass b: do paragraph handling on other elements + unset ($nodes); + $nodes =& $this->_root->getNodesByCriterium ('flag:paragraphs', true); + $nodes_count = count ($nodes); + for ($i = 0; $i < $nodes_count; $i++) { + $res = $this->_handleParagraphs ($nodes[$i]); + if (!$res) { + return false; + } + } + + // second pass c: search for empty paragraph nodes and remove them + unset ($nodes); + $nodes =& $this->_root->getNodesByCriterium ('empty', true); + $nodes_count = count ($nodes); + if (isset ($parent)) { + unset ($parent); $parent = null; + } + for ($i = 0; $i < $nodes_count; $i++) { + if ($nodes[$i]->_type != STRINGPARSER_BBCODE_NODE_PARAGRAPH) { + continue; + } + unset ($parent); + $parent =& $nodes[$i]->_parent; + $parent->removeChild ($nodes[$i], true); + } + + return true; + } + + /** + * Handle paragraphs + * @access protected + * @param object $node The node to handle + * @return bool + */ + function _handleParagraphs (&$node) { + // if this node is already a subnode of a paragraph node, do NOT + // do paragraph handling on this node! + if ($this->_hasParagraphAncestor ($node)) { + return true; + } + $dest_nodes = array (); + $last_node_was_paragraph = false; + $prevtype = STRINGPARSER_NODE_TEXT; + $paragraph = null; + while (count ($node->_children)) { + $mynode =& $node->_children[0]; + $node->removeChild ($mynode); + $subprevtype = $prevtype; + $sub_nodes =& $this->_breakupNodeByParagraphs ($mynode); + for ($i = 0; $i < count ($sub_nodes); $i++) { + if (!$last_node_was_paragraph || ($prevtype == $sub_nodes[$i]->_type && ($i != 0 || $prevtype != STRINGPARSER_BBCODE_NODE_ELEMENT))) { + unset ($paragraph); + $paragraph =& new StringParser_BBCode_Node_Paragraph (); + } + $prevtype = $sub_nodes[$i]->_type; + if ($sub_nodes[$i]->_type != STRINGPARSER_BBCODE_NODE_ELEMENT || $sub_nodes[$i]->getFlag ('paragraph_type', 'integer', BBCODE_PARAGRAPH_ALLOW_BREAKUP) != BBCODE_PARAGRAPH_BLOCK_ELEMENT) { + $paragraph->appendChild ($sub_nodes[$i]); + $dest_nodes[] =& $paragraph; + $last_node_was_paragraph = true; + } else { + $dest_nodes[] =& $sub_nodes[$i]; + $last_onde_was_paragraph = false; + unset ($paragraph); + $paragraph =& new StringParser_BBCode_Node_Paragraph (); + } + } + } + $count = count ($dest_nodes); + for ($i = 0; $i < $count; $i++) { + $node->appendChild ($dest_nodes[$i]); + } + unset ($dest_nodes); + unset ($paragraph); + return true; + } + + /** + * Search for a paragraph node in tree in upward direction + * @access protected + * @param object $node The node to analyze + * @return bool + */ + function _hasParagraphAncestor (&$node) { + if ($node->_parent === null) { + return false; + } + $parent =& $node->_parent; + if ($parent->_type == STRINGPARSER_BBCODE_NODE_PARAGRAPH) { + return true; + } + return $this->_hasParagraphAncestor ($parent); + } + + /** + * Break up nodes + * @access protected + * @param object $node The node to break up + * @return array + */ + function &_breakupNodeByParagraphs (&$node) { + $detect_string = $this->_paragraphHandling['detect_string']; + $dest_nodes = array (); + // text node => no problem + if ($node->_type == STRINGPARSER_NODE_TEXT) { + $cpos = 0; + while (($npos = strpos ($node->content, $detect_string, $cpos)) !== false) { + $subnode =& new StringParser_Node_Text (substr ($node->content, $cpos, $npos - $cpos), $node->occurredAt + $cpos); + // copy flags + foreach ($node->_flags as $flag => $value) { + if ($flag == 'newlinemode.begin') { + if ($cpos == 0) { + $subnode->setFlag ($flag, $value); + } + } else if ($flag == 'newlinemode.end') { + // do nothing + } else { + $subnode->setFlag ($flag, $value); + } + } + $dest_nodes[] =& $subnode; + unset ($subnode); + $cpos = $npos + strlen ($detect_string); + } + $subnode =& new StringParser_Node_Text (substr ($node->content, $cpos), $node->occurredAt + $cpos); + if ($cpos == 0) { + $value = $node->getFlag ('newlinemode.begin', 'integer', null); + if ($value !== null) { + $subnode->setFlag ('newlinemode.begin', $value); + } + } + $value = $node->getFlag ('newlinemode.end', 'integer', null); + if ($value !== null) { + $subnode->setFlag ('newlinemode.end', $value); + } + $dest_nodes[] =& $subnode; + unset ($subnode); + return $dest_nodes; + } + // not a text node or an element node => no way + if ($node->_type != STRINGPARSER_BBCODE_NODE_ELEMENT) { + $dest_nodes[] =& $node; + return $dest_nodes; + } + if ($node->getFlag ('paragraph_type', 'integer', BBCODE_PARAGRAPH_ALLOW_BREAKUP) != BBCODE_PARAGRAPH_ALLOW_BREAKUP || !count ($node->_children)) { + $dest_nodes[] =& $node; + return $dest_nodes; + } + $dest_node =& $node->duplicate (); + $nodecount = count ($node->_children); + // now this node allows breakup - do it + for ($i = 0; $i < $nodecount; $i++) { + $firstnode =& $node->_children[0]; + $node->removeChild ($firstnode); + $sub_nodes =& $this->_breakupNodeByParagraphs ($firstnode); + for ($j = 0; $j < count ($sub_nodes); $j++) { + if ($j != 0) { + $dest_nodes[] =& $dest_node; + unset ($dest_node); + $dest_node =& $node->duplicate (); + } + $dest_node->appendChild ($sub_nodes[$j]); + } + unset ($sub_nodes); + } + $dest_nodes[] =& $dest_node; + return $dest_nodes; + } + + /** + * Is this node a usecontent node + * @access protected + * @param object $node The node to check + * @param bool $check_attrs Also check whether 'usecontent?'-attributes exist + * @return bool + */ + function _isUseContent (&$node, $check_attrs = false) { + $name = $this->_getCanonicalName ($node->name ()); + // this should NOT happen + if ($name === false) { + return false; + } + if ($this->_codes[$name]['callback_type'] == 'usecontent') { + return true; + } + $result = false; + if ($this->_codes[$name]['callback_type'] == 'callback_replace?') { + $result = true; + } else if ($this->_codes[$name]['callback_type'] != 'usecontent?') { + return false; + } + if ($check_attrs === false) { + return !$result; + } + $attributes = array_keys ($this->_topNodeVar ('_attributes')); + $p = @$this->_codes[$name]['callback_params']['usecontent_param']; + if (is_array ($p)) { + foreach ($p as $param) { + if (in_array ($param, $attributes)) { + return $result; + } + } + } else { + if (in_array ($p, $attributes)) { + return $result; + } + } + return !$result; + } + + /** + * Get canonical name of a code + * + * @access protected + * @param string $name + * @return string + */ + function _getCanonicalName ($name) { + if (isset ($this->_codes[$name])) { + return $name; + } + $found = false; + // try to find the code in the code list + foreach (array_keys ($this->_codes) as $rname) { + // match + if (strtolower ($rname) == strtolower ($name)) { + $found = $rname; + break; + } + } + if ($found === false || ($this->_caseSensitive && $this->getCodeFlag ($found, 'case_sensitive', 'boolean', true))) { + return false; + } + return $rname; + } +} + +/** + * Node type: BBCode Element node + * @see StringParser_BBCode_Node_Element::_type + */ +define ('STRINGPARSER_BBCODE_NODE_ELEMENT', 32); + +/** + * Node type: BBCode Paragraph node + * @see StringParser_BBCode_Node_Paragraph::_type + */ +define ('STRINGPARSER_BBCODE_NODE_PARAGRAPH', 33); + + +/** + * BBCode String parser paragraph node class + * + * @package stringparser + */ +class StringParser_BBCode_Node_Paragraph extends StringParser_Node { + /** + * The type of this node. + * + * This node is a bbcode paragraph node. + * + * @access protected + * @var int + * @see STRINGPARSER_BBCODE_NODE_PARAGRAPH + */ + var $_type = STRINGPARSER_BBCODE_NODE_PARAGRAPH; + + /** + * Determines whether a criterium matches this node + * + * @access public + * @param string $criterium The criterium that is to be checked + * @param mixed $value The value that is to be compared + * @return bool True if this node matches that criterium + */ + function matchesCriterium ($criterium, $value) { + if ($criterium == 'empty') { + if (!count ($this->_children)) { + return true; + } + if (count ($this->_children) > 1) { + return false; + } + if ($this->_children[0]->_type != STRINGPARSER_NODE_TEXT) { + return false; + } + if (!strlen ($this->_children[0]->content)) { + return true; + } + if (strlen ($this->_children[0]->content) > 2) { + return false; + } + $f_begin = $this->_children[0]->getFlag ('newlinemode.begin', 'integer', BBCODE_NEWLINE_PARSE); + $f_end = $this->_children[0]->getFlag ('newlinemode.end', 'integer', BBCODE_NEWLINE_PARSE); + $content = $this->_children[0]->content; + if ($f_begin != BBCODE_NEWLINE_PARSE && $content{0} == "\n") { + $content = substr ($content, 1); + } + if ($f_end != BBCODE_NEWLINE_PARSE && $content{strlen($content)-1} == "\n") { + $content = substr ($content, 0, -1); + } + if (!strlen ($content)) { + return true; + } + return false; + } + } +} + +/** + * BBCode String parser element node class + * + * @package stringparser + */ +class StringParser_BBCode_Node_Element extends StringParser_Node { + /** + * The type of this node. + * + * This node is a bbcode element node. + * + * @access protected + * @var int + * @see STRINGPARSER_BBCODE_NODE_ELEMENT + */ + var $_type = STRINGPARSER_BBCODE_NODE_ELEMENT; + + /** + * Element name + * + * @access protected + * @var string + * @see StringParser_BBCode_Node_Element::name + * @see StringParser_BBCode_Node_Element::setName + * @see StringParser_BBCode_Node_Element::appendToName + */ + var $_name = ''; + + /** + * Element flags + * + * @access protected + * @var array + */ + var $_flags = array (); + + /** + * Element attributes + * + * @access protected + * @var array + */ + var $_attributes = array (); + + /** + * Had a close tag + * + * @access protected + * @var bool + */ + var $_hadCloseTag = false; + + /** + * Was processed by paragraph handling + * + * @access protected + * @var bool + */ + var $_paragraphHandled = false; + + ////////////////////////////////////////////////// + + /** + * Duplicate this node (but without children / parents) + * + * @access public + * @return object + */ + function &duplicate () { + $newnode =& new StringParser_BBCode_Node_Element ($this->occurredAt); + $newnode->_name = $this->_name; + $newnode->_flags = $this->_flags; + $newnode->_attributes = $this->_attributes; + $newnode->_hadCloseTag = $this->_hadCloseTag; + $newnode->_paragraphHandled = $this->_paragraphHandled; + $newnode->_codeInfo = $this->_codeInfo; + return $newnode; + } + + /** + * Retreive name of this element + * + * @access public + * @return string + */ + function name () { + return $this->_name; + } + + /** + * Set name of this element + * + * @access public + * @param string $name The new name of the element + */ + function setName ($name) { + $this->_name = $name; + return true; + } + + /** + * Append to name of this element + * + * @access public + * @param string $chars The chars to append to the name of the element + */ + function appendToName ($chars) { + $this->_name .= $chars; + return true; + } + + /** + * Append to attribute of this element + * + * @access public + * @param string $name The name of the attribute + * @param string $chars The chars to append to the attribute of the element + */ + function appendToAttribute ($name, $chars) { + if (!isset ($this->_attributes[$name])) { + $this->_attributes[$name] = $chars; + return true; + } + $this->_attributes[$name] .= $chars; + return true; + } + + /** + * Set attribute + * + * @access public + * @param string $name The name of the attribute + * @param string $value The new value of the attribute + */ + function setAttribute ($name, $value) { + $this->_attributes[$name] = $value; + return true; + } + + /** + * Set code info + * + * @access public + * @param array $info The code info array + */ + function setCodeInfo ($info) { + $this->_codeInfo = $info; + $this->_flags = $info['flags']; + return true; + } + + /** + * Get attribute value + * + * @access public + * @param string $name The name of the attribute + */ + function attribute ($name) { + if (!isset ($this->_attributes[$name])) { + return null; + } + return $this->_attributes[$name]; + } + + /** + * Set flag that this element had a close tag + * + * @access public + */ + function setHadCloseTag () { + $this->_hadCloseTag = true; + } + + /** + * Set flag that this element was already processed by paragraph handling + * + * @access public + */ + function setParagraphHandled () { + $this->_paragraphHandled = true; + } + + /** + * Get flag if this element was already processed by paragraph handling + * + * @access public + * @return bool + */ + function paragraphHandled () { + return $this->_paragraphHandled; + } + + /** + * Get flag if this element had a close tag + * + * @access public + * @return bool + */ + function hadCloseTag () { + return $this->_hadCloseTag; + } + + /** + * Determines whether a criterium matches this node + * + * @access public + * @param string $criterium The criterium that is to be checked + * @param mixed $value The value that is to be compared + * @return bool True if this node matches that criterium + */ + function matchesCriterium ($criterium, $value) { + if ($criterium == 'tagName') { + return ($value == $this->_name); + } + if ($criterium == 'needsTextNodeModification') { + return (($this->getFlag ('opentag.before.newline', 'integer', BBCODE_NEWLINE_PARSE) != BBCODE_NEWLINE_PARSE || $this->getFlag ('opentag.after.newline', 'integer', BBCODE_NEWLINE_PARSE) != BBCODE_NEWLINE_PARSE || ($this->_hadCloseTag && ($this->getFlag ('closetag.before.newline', 'integer', BBCODE_NEWLINE_PARSE) != BBCODE_NEWLINE_PARSE || $this->getFlag ('closetag.after.newline', 'integer', BBCODE_NEWLINE_PARSE) != BBCODE_NEWLINE_PARSE))) == (bool)$value); + } + if (substr ($criterium, 0, 5) == 'flag:') { + $criterium = substr ($criterium, 5); + return ($this->getFlag ($criterium) == $value); + } + if (substr ($criterium, 0, 6) == '!flag:') { + $criterium = substr ($criterium, 6); + return ($this->getFlag ($criterium) != $value); + } + if (substr ($criterium, 0, 6) == 'flag=:') { + $criterium = substr ($criterium, 6); + return ($this->getFlag ($criterium) === $value); + } + if (substr ($criterium, 0, 7) == '!flag=:') { + $criterium = substr ($criterium, 7); + return ($this->getFlag ($criterium) !== $value); + } + return parent::matchesCriterium ($criterium, $value); + } + + /** + * Get first child if it is a text node + * + * @access public + * @return mixed + */ + function &firstChildIfText () { + $ret =& $this->firstChild (); + if (is_null ($ret)) { + return $ret; + } + if ($ret->_type != STRINGPARSER_NODE_TEXT) { + // DON'T DO $ret = null WITHOUT unset BEFORE! + // ELSE WE WILL ERASE THE NODE ITSELF! EVIL! + unset ($ret); + $ret = null; + } + return $ret; + } + + /** + * Get last child if it is a text node AND if this element had a close tag + * + * @access public + * @return mixed + */ + function &lastChildIfText () { + $ret =& $this->lastChild (); + if (is_null ($ret)) { + return $ret; + } + if ($ret->_type != STRINGPARSER_NODE_TEXT || !$this->_hadCloseTag) { + // DON'T DO $ret = null WITHOUT unset BEFORE! + // ELSE WE WILL ERASE THE NODE ITSELF! EVIL! + if ($ret->_type != STRINGPARSER_NODE_TEXT && !$ret->hadCloseTag ()) { + $ret2 =& $ret->_findPrevAdjentTextNodeHelper (); + unset ($ret); + $ret =& $ret2; + unset ($ret2); + } else { + unset ($ret); + $ret = null; + } + } + return $ret; + } + + /** + * Find next adjent text node after close tag + * + * returns the node or null if none exists + * + * @access public + * @return mixed + */ + function &findNextAdjentTextNode () { + $ret = null; + if (is_null ($this->_parent)) { + return $ret; + } + if (!$this->_hadCloseTag) { + return $ret; + } + $ccount = count ($this->_parent->_children); + $found = false; + for ($i = 0; $i < $ccount; $i++) { + if ($this->_parent->_children[$i]->equals ($this)) { + $found = $i; + break; + } + } + if ($found === false) { + return $ret; + } + if ($found < $ccount - 1) { + if ($this->_parent->_children[$found+1]->_type == STRINGPARSER_NODE_TEXT) { + return $this->_parent->_children[$found+1]; + } + return $ret; + } + if ($this->_parent->_type == STRINGPARSER_BBCODE_NODE_ELEMENT && !$this->_parent->hadCloseTag ()) { + $ret =& $this->_parent->findNextAdjentTextNode (); + return $ret; + } + return $ret; + } + + /** + * Find previous adjent text node before open tag + * + * returns the node or null if none exists + * + * @access public + * @return mixed + */ + function &findPrevAdjentTextNode () { + $ret = null; + if (is_null ($this->_parent)) { + return $ret; + } + $ccount = count ($this->_parent->_children); + $found = false; + for ($i = 0; $i < $ccount; $i++) { + if ($this->_parent->_children[$i]->equals ($this)) { + $found = $i; + break; + } + } + if ($found === false) { + return $ret; + } + if ($found > 0) { + if ($this->_parent->_children[$found-1]->_type == STRINGPARSER_NODE_TEXT) { + return $this->_parent->_children[$found-1]; + } + if (!$this->_parent->_children[$found-1]->hadCloseTag ()) { + $ret =& $this->_parent->_children[$found-1]->_findPrevAdjentTextNodeHelper (); + } + return $ret; + } + return $ret; + } + + /** + * Helper function for findPrevAdjentTextNode + * + * Looks at the last child node; if it's a text node, it returns it, + * if the element node did not have an open tag, it calls itself + * recursively. + */ + function &_findPrevAdjentTextNodeHelper () { + $lastnode =& $this->lastChild (); + if ($lastnode === null || $lastnode->_type == STRINGPARSER_NODE_TEXT) { + return $lastnode; + } + if (!$lastnode->hadCloseTag ()) { + $ret =& $lastnode->_findPrevAdjentTextNodeHelper (); + } else { + $ret = null; + } + return $ret; + } + + /** + * Get Flag + * + * @access public + * @param string $flag The requested flag + * @param string $type The requested type of the return value + * @param mixed $default The default return value + * @return mixed + */ + function getFlag ($flag, $type = 'mixed', $default = null) { + if (!isset ($this->_flags[$flag])) { + return $default; + } + $return = $this->_flags[$flag]; + if ($type != 'mixed') { + settype ($return, $type); + } + return $return; + } + + /** + * Set a flag + * + * @access public + * @param string $name The name of the flag + * @param mixed $value The value of the flag + */ + function setFlag ($name, $value) { + $this->_flags[$name] = $value; + return true; + } + + /** + * Validate code + * + * @access public + * @param string $action The action which is to be called ('validate' + * for first validation, 'validate_again' for + * second validation (optional)) + * @return bool + */ + function validate ($action = 'validate') { + if ($action != 'validate' && $action != 'validate_again') { + return false; + } + if ($this->_codeInfo['callback_type'] != 'simple_replace' && $this->_codeInfo['callback_type'] != 'simple_replace_single') { + if (!is_callable ($this->_codeInfo['callback_func'])) { + return false; + } + + if (($this->_codeInfo['callback_type'] == 'usecontent' || $this->_codeInfo['callback_type'] == 'usecontent?' || $this->_codeInfo['callback_type'] == 'callback_replace?') && count ($this->_children) == 1 && $this->_children[0]->_type == STRINGPARSER_NODE_TEXT) { + // we have to make sure the object gets passed on as a reference + // if we do call_user_func(..., &$this) this will clash with PHP5 + $callArray = array ($action, $this->_attributes, $this->_children[0]->content, $this->_codeInfo['callback_params']); + $callArray[] =& $this; + $res = call_user_func_array ($this->_codeInfo['callback_func'], $callArray); + if ($res) { + // ok, now, if we've got a usecontent type, set a flag that + // this may not be broken up by paragraph handling! + // but PLEASE do NOT change if already set to any other setting + // than BBCODE_PARAGRAPH_ALLOW_BREAKUP because we could + // override e.g. BBCODE_PARAGRAPH_BLOCK_ELEMENT! + $val = $this->getFlag ('paragraph_type', 'integer', BBCODE_PARAGRAPH_ALLOW_BREAKUP); + if ($val == BBCODE_PARAGRAPH_ALLOW_BREAKUP) { + $this->_flags['paragraph_type'] = BBCODE_PARAGRAPH_ALLOW_INSIDE; + } + } + return $res; + } + + // we have to make sure the object gets passed on as a reference + // if we do call_user_func(..., &$this) this will clash with PHP5 + $callArray = array ($action, $this->_attributes, null, $this->_codeInfo['callback_params']); + $callArray[] =& $this; + return call_user_func_array ($this->_codeInfo['callback_func'], $callArray); + } + return (bool)(!count ($this->_attributes)); + } + + /** + * Get replacement for this code + * + * @access public + * @param string $subcontent The content of all sub-nodes + * @return string + */ + function getReplacement ($subcontent) { + if ($this->_codeInfo['callback_type'] == 'simple_replace' || $this->_codeInfo['callback_type'] == 'simple_replace_single') { + if ($this->_codeInfo['callback_type'] == 'simple_replace_single') { + if (strlen ($subcontent)) { // can't be! + return false; + } + return $this->_codeInfo['callback_params']['start_tag']; + } + return $this->_codeInfo['callback_params']['start_tag'].$subcontent.$this->_codeInfo['callback_params']['end_tag']; + } + // else usecontent, usecontent? or callback_replace or callback_replace_single + // => call function (the function is callable, determined in validate()!) + + // we have to make sure the object gets passed on as a reference + // if we do call_user_func(..., &$this) this will clash with PHP5 + $callArray = array ('output', $this->_attributes, $subcontent, $this->_codeInfo['callback_params']); + $callArray[] =& $this; + return call_user_func_array ($this->_codeInfo['callback_func'], $callArray); + } + + /** + * Dump this node to a string + * + * @access protected + * @return string + */ + function _dumpToString () { + $str = "bbcode \"".substr (preg_replace ('/\s+/', ' ', $this->_name), 0, 40)."\""; + if (count ($this->_attributes)) { + $attribs = array_keys ($this->_attributes); + sort ($attribs); + $str .= ' ('; + $i = 0; + foreach ($attribs as $attrib) { + if ($i != 0) { + $str .= ', '; + } + $str .= $attrib.'="'; + $str .= substr (preg_replace ('/\s+/', ' ', $this->_attributes[$attrib]), 0, 10); + $str .= '"'; + $i++; + } + $str .= ')'; + } + return $str; + } +} + +?> \ No newline at end of file diff --git a/scripts/update.php b/scripts/update.php new file mode 100644 index 0000000..3b86e05 --- /dev/null +++ b/scripts/update.php @@ -0,0 +1,135 @@ +error()) { + echo "
    \n";
    +        echo $rss_sub->getError();
    +        echo "
    \n"; + die(); + } +if(defined('JLOG_ADMIN') AND !defined('JLOG_COMMENTS')) { + $data['rss'] = " + + + ".htmlspecialchars(JLOG_WEBSITE)." + ".htmlspecialchars(JLOG_PATH)." + ".htmlspecialchars(JLOG_DESCRIPTION)." + ".$l['language']." + ".date('r')." + http://blogs.law.harvard.edu/tech/rss + <a href="".JLOG_SOFTWARE_URL."">Jlog v".JLOG_SOFTWARE_VERSION."</a> + ".htmlspecialchars(JLOG_PUBLISHER)." ".htmlspecialchars(JLOG_EMAIL)." + &copy;".$now_date['year']." by ".htmlspecialchars(JLOG_PUBLISHER)."\n\n"; + + $data['rss_full'] = $data['rss']; +} +$data['sub'] = "
      \n"; + + if(!isset($cc)) $cc = count_comments(); + +$sub = 0; +while ($row = $rss_sub->fetch()) { +++$sub; + + if($sub <= JLOG_SUB_CURRENT) { + $tmp_comments = ""; + if(isset($cc[$row['id']]) AND $cc[$row['id']] != 0) $tmp_comments = " (".$cc[$row['id']].")"; + $data['sub'] .= "
    • ".strftime(JLOG_DATE_SUBCURRENT, $row['date'])." ".htmlspecialchars($row['topic'], ENT_QUOTES)."".$tmp_comments."
    • \n"; + } + + if($sub <= 15 AND defined('JLOG_ADMIN')) { + +# Kopfdaten + $data['rss'] .= " \n ".htmlspecialchars($row['topic'], ENT_QUOTES)."\n"; + $data['rss_full'] .= " \n ".htmlspecialchars($row['topic'], ENT_QUOTES)."\n"; + + $data['rss'] .= " ".blog($row['date'], $row['url'])."\n"; + $data['rss_full'] .= " ".blog($row['date'], $row['url'])."\n"; + + $data['rss'] .= " ".date('r', $row['date'])."\n"; + $data['rss_full'] .= " ".date('r', $row['date'])."\n"; + + $data['rss'] .= " ".blog($row['date'], $row['url'])."\n"; + $data['rss_full'] .= " ".blog($row['date'], $row['url'])."\n"; + + $data['rss'] .= " ".blog($row['date'], $row['url'])."#comments\n"; + $data['rss_full'] .= " ".blog($row['date'], $row['url'])."#comments\n"; + + $data['rss'] .= $categories->output_rss($row['id']); + $data['rss_full'] .= $categories->output_rss($row['id']); + + +# Inhaltsdaten + $data['rss'] .= " \n".htmlspecialchars($bbcode->parse($row['teaser']))."\n \n"; + $data['rss_full'] .= " \n"; + + if($row['teaserpiconblog'] == 1) $data['rss_full'] .= htmlspecialchars(""); + $data['rss_full'] .= htmlspecialchars($bbcode->parse($row['content']))."\n \n"; + + $data['rss'] .= " \n\n"; + $data['rss_full'] .= " \n\n"; + } +} +if(defined('JLOG_ADMIN') AND !defined('JLOG_COMMENTS')) { + $data['rss'] .= "\n"; + $data['rss_full'] .= "\n"; +} +$data['sub'] .= "
    "; + +if(defined('JLOG_ADMIN') AND !defined('JLOG_COMMENTS')) { + $file['rss'] = JLOG_BASEPATH.'personal'.DIRECTORY_SEPARATOR.'rss.xml'; + $file['rss_full'] = JLOG_BASEPATH.'personal'.DIRECTORY_SEPARATOR.'rss-full.xml'; +} + +$file['sub'] = JLOG_BASEPATH.'personal'.DIRECTORY_SEPARATOR.'subcurrent.inc'; + + ### Plugin Hook + if (isset($plugins) and is_object($plugins)) { + $data = $plugins->callHook('onUpdate', $data); + } + +$i = 0; + + foreach($file AS $d => $filename) { + if (is_writable($filename)) { + if (!$handle = fopen($filename, 'w')) { + $errors[] .= $l['admin']['can_not_open']." ($filename)"; + exit; + } + if (!fwrite($handle, $data[$d])) { + $errors[] .= $l['admin']['can_not_write']." ($filename)"; + exit; + } + ++$i; + fclose($handle); + } else { + $errors[] .= $l['admin']['no_wrtitenable']." ($filename)"; + } + } + + +if(count($errors) > 0) { + $c['main'] .= error_output($errors); +} + +if($i == 4 AND defined('JLOG_ADMIN') AND !defined('JLOG_COMMENTS')) $c['main'] .= "

    ".$l['admin']['rss_ok']."

    "; +unset($i); +unset($sub); + +?> diff --git a/scripts/update/102To110.php b/scripts/update/102To110.php new file mode 100644 index 0000000..0166c4e --- /dev/null +++ b/scripts/update/102To110.php @@ -0,0 +1,66 @@ +languages[] = $matches[1]; + } + } + + function getForm($l) + { + $html = "


    + +

    +

    Die Zeichenkodierung ihrer Template-Datei personal/template.tpl muss nach UTF-8 umgewandelt werden. Wenn diese Datei + beschreibbar ist (z.B.: chmod 777), wird dies vom Updatescript automatisch für sie erledigt. + Andernfalls müssen Sie die Konvertierung nachträglich manuell vornehmen.

    + "; + return $html; + } + + function performUpdate($l, $settings) + { + // convert all settings to utf8 + foreach($settings->d as $key => $value) { + $settings->d[$key] = utf8_encode($value); + } + + // reset hash of the administrator password + $settings->d['jlog_admin_password'] = md5($_POST['password']); + + // store chosen language + $lang = in_array($_POST['j110_language'], $this->languages) ? $_POST['j110_language'] : 'de'; + $settings->d['jlog_language'] = $lang; + + $update_errors = array(); + + /** + * On a correct Jlog 1.0.2 installation, the template is saved with an ISO + * encoding, so we're going to try to convert this to UTF-8 + */ + $template = JLOG_BASEPATH."personal".DIRECTORY_SEPARATOR."template.tpl"; + if(@file_put_contents($template, utf8_encode(@file_get_contents($template))) == false) { + $update_errors[] = 'Die Datei personal/template.tpl konnte nicht in UTF-8 Kodierung konvertiert werden.'; + } + + + if(empty($update_errors)) { + return true; + } + else { + return $update_errors; + } + } +} \ No newline at end of file diff --git a/scripts/update/110To111.php b/scripts/update/110To111.php new file mode 100644 index 0000000..62af685 --- /dev/null +++ b/scripts/update/110To111.php @@ -0,0 +1,14 @@ +Keine Einstellungen notwendig.

    '; + } + + function performUpdate($l, $settings) + { + return true; + } +} \ No newline at end of file diff --git a/scripts/update/111To112.php b/scripts/update/111To112.php new file mode 100644 index 0000000..b95394c --- /dev/null +++ b/scripts/update/111To112.php @@ -0,0 +1,28 @@ +Dieses Script behebt ein paar fehlerhafte Einstellungen.' + .' Es ist keine Konfiguration notwendig.

    '; + } + + function performUpdate($l, $settings) + { + // in jlog versions prior to jlog 1.1.2 we had escaping problems that caused + // a lot of backslashes in front of a double quote + // so we have to replace \" or \\" or \\\" and so on by ". + $data = array( + 'jlog_description' => $settings->getValue('jlog_description'), + 'jlog_website' => $settings->getValue('jlog_website'), + 'jlog_publisher' => $settings->getValue('jlog_publisher') + ); + foreach ($data as $key => $value) { + $value = preg_replace('=\\\\+"=', '"', $value); + $settings->setValue($key, $value); + } + + return true; + } +} \ No newline at end of file diff --git a/scripts/update/112To113.php b/scripts/update/112To113.php new file mode 100644 index 0000000..35f6045 --- /dev/null +++ b/scripts/update/112To113.php @@ -0,0 +1,15 @@ +Bitte beachten Sie, dass nach Durchführung dieses Updates eventuell einzelne Plugins nicht mehr funktionieren.
    ' + . 'Kontaktieren Sie in einem solchen Fall den Plugin-Autor bzzgl. eines Updates für das Plugin.

    '; + } + + function performUpdate($l, $settings) + { + return true; + } +} \ No newline at end of file diff --git a/scripts/update/Example.php b/scripts/update/Example.php new file mode 100644 index 0000000..d8faec7 --- /dev/null +++ b/scripts/update/Example.php @@ -0,0 +1,42 @@ +Do not need anything to configure for this update.

    '; + } + + /** + * This function has to perform the update + * + * Must return true, if everything went well, of an array of error + * messages, if something went wrong. + * The first parameter again in the language array. + */ + function performUpdate($l) + { + return true; + } +} \ No newline at end of file diff --git a/scripts/url_syntax.php b/scripts/url_syntax.php new file mode 100644 index 0000000..7657c12 --- /dev/null +++ b/scripts/url_syntax.php @@ -0,0 +1,248 @@ +#%"]'; +$reserved = '[;/?:@&=]'; +$uchar = "(?:${alphanum}|${safe}|${extra}|${escape})"; +$xchar = "(?:${alphanum}|${safe}|${extra}|${reserved}|${escape})"; +$uchar = str_replace (']|[', '', $uchar); // Make string smaller, and speed up regex. +$uchar = str_replace (']|[', '', $xchar); // Make string smaller, and speed up regex. + +# URL schemeparts for ip based protocols: +$user = "(?:(?:${uchar}|[;?&=])*)"; +$password = "(?:(?:${uchar}|[;?&=])*)"; +$hostnumber = "(?:${digits}(?:${dot}${digits}){3})"; +$toplabel = "(?:${alpha}(?:(?:${alphanum}|-)*${alphanum})?)"; +$domainlabel = "(?:${alphanum}(?:(?:${alphanum}|-)*${alphanum})?)"; +$hostname = "(?:(?:${domainlabel}${dot})*${toplabel})"; +$host = "(?:${hostname}|${hostnumber})"; +$hostport = "(?:${host}(?::${digits})?)"; +$login = "(?:(?:${user}(?::${password})?\@)?${hostport})"; + +# The predefined schemes: + +# FTP (see also RFC959) +$fsegment = "(?:(?:${uchar}|[?:\@&=])*)"; +$fpath = "(?:${fsegment}(?:/${fsegment})*)"; +$ftpurl = "(?:ftp://${login}(?:/${fpath}(?:;type=[AIDaid])?)?)"; + +# FILE +$fileurl = "(?:file://(?:${host}|localhost)?/${fpath})"; + +# HTTP +$hsegment = "(?:(?:${uchar}|[~;:\@&=])*)"; +$search = "(?:(?:${uchar}|[;:\@&=])*)"; +$hpath = "(?:${hsegment}(?:/${hsegment})*)"; +$httpurl = "(?:https?://${hostport}(?:/${hpath}(?:${qm}${search})?)?)"; + +# GOPHER (see also RFC1436) +$gopher_plus = "(?:${xchar}*)"; +$selector = "(?:${xchar}*)"; +$gtype = $xchar; // Omitted parens! +$gopherurl = "(?:gopher://${hostport}(?:/${gtype}(?:${selector}" . + "(?:%09${search}(?:%09${gopher_plus})?)?)?)?)"; + +# MAILTO (see also RFC822) +$encoded822addr = "(?:$xchar+)"; +$mailtourl = "(?:mailto:$encoded822addr)"; +$mailtonpurl = $encoded822addr; + +# NEWS (see also RFC1036) +$article = "(?:(?:${uchar}|[;/?:&=])+\@${host})"; +$group = "(?:${alpha}(?:${alphanum}|[_.+-])*)"; +$grouppart = "(?:${article}|${group}|${ast})"; +$newsurl = "(?:news:${grouppart})"; + +# NNTP (see also RFC977) +$nntpurl = "(?:nntp://${hostport}/${group}(?:/${digits})?)"; + +# TELNET +$telneturl = "(?:telnet://${login}/?)"; + +# WAIS (see also RFC1625) +$wpath = "(?:${uchar}*)"; +$wtype = "(?:${uchar}*)"; +$database = "(?:${uchar}*)"; +$waisdoc = "(?:wais://${hostport}/${database}/${wtype}/${wpath})"; +$waisindex = "(?:wais://${hostport}/${database}${qm}${search})"; +$waisdatabase = "(?:wais://${hostport}/${database})"; +# $waisurl = "(?:${waisdatabase}|${waisindex}|${waisdoc})"; +# Speed up: the 3 types share a common prefix. +$waisurl = "(?:wais://${hostport}/${database}" . + "(?:(?:/${wtype}/${wpath})|${qm}${search})?)"; + +# PROSPERO +$fieldvalue = "(?:(?:${uchar}|[?:\@&])*)"; +$fieldname = "(?:(?:${uchar}|[?:\@&])*)"; +$fieldspec = "(?:;${fieldname}=${fieldvalue})"; +$psegment = "(?:(?:${uchar}|[?:\@&=])*)"; +$ppath = "(?:${psegment}(?:/${psegment})*)"; +$prosperourl = "(?:prospero://${hostport}/${ppath}(?:${fieldspec})*)"; + +# LDAP (see also RFC1959) +# First. import stuff from RFC 1779 (Distinguished Names). +# We've modified things a bit. +$dn_separator = "(?:[;,])"; +$dn_optional_space = "(?:${nl}?${space}*)"; +$dn_spaced_separator = "(?:${dn_optional_space}${dn_separator}" . + "${dn_optional_space})"; +$dn_oid = "(?:${digits}(?:${dot}${digits})*)"; +$dn_keychar = "(?:${xalphanum}|${space})"; +$dn_key = "(?:${dn_keychar}+|(?:OID|oid)${dot}${dn_oid})"; +$dn_string = "(?:${uchar}*)"; +$dn_attribute = "(?:(?:${dn_key}${dn_optional_space}=" . + "${dn_optional_space})?${dn_string})"; +$dn_name_component = "(?:${dn_attribute}(?:${dn_optional_space}" . + "${plus}${dn_optional_space}${dn_attribute})*)"; +$dn_name = "(?:${dn_name_component}" . + "(?:${dn_spaced_separator}${dn_name_component})*" . + "${dn_spaced_separator}?)"; + +# RFC 1558 defines the filter syntax, but that requires a PDA to recognize. +# Since that's too powerful for Perl's REs, we allow any char between the +# parenthesis (which have to be there.) +$ldap_filter = "(?:\(${xchar}+\))"; + +# This is from RFC 1777. It defines an attributetype as an 'OCTET STRING', +# whatever that is. +$ldap_attr_type = "(?:${uchar}+)"; # I'm just guessing here. + # The RFCs aren't clear. + +# Now we are at the grammar of RFC 1959. +$ldap_attr_list = "(?:${ldap_attr_type}(?:,${ldap_attr_type})*)"; +$ldap_attrs = "(?:${ldap_attr_list}?)"; + +$ldap_scope = "(?:base|one|sub)"; +$ldapurl = "(?:ldap://(?:${hostport})?/${dn_name}" . + "(?:${qm}${ldap_attrs}" . + "(?:${qm}${ldap_scope}(?:${qm}${ldap_filter})?)?)?)"; + + +# RFC 2056 defines the format of URLs for the Z39.50 protocol. +$z_database = "(?:${uchar}+)"; +$z_docid = "(?:${uchar}+)"; +$z_elementset = "(?:${uchar}+)"; +$z_recordsyntax = "(?:${uchar}+)"; +$z_scheme = "(?:z39${dot}50[rs])"; +$z39_50url = "(?:${z_scheme}://${hostport}" . + "(?:/(?:${z_database}(?:${plus}${z_database})*" . + "(?:${qm}${z_docid})?)?" . + "(?:;esn=${z_elementset})?" . + "(?:;rs=${z_recordsyntax}" . + "(?:${plus}${z_recordsyntax})*)?))"; + + +# RFC 2111 defines the format for cid/mid URLs. +$url_addr_spec = "(?:(?:${uchar}|[;?:@&=])*)"; +$message_id = $url_addr_spec; +$content_id = $url_addr_spec; +$cidurl = "(?:cid:${content_id})"; +$midurl = "(?:mid:${message_id}(?:/${content_id})?)"; + + +# RFC 2122 defines the Vemmi URLs. +$vemmi_attr = "(?:(?:${uchar}|[/?:@&])*)"; +$vemmi_value = "(?:(?:${uchar}|[/?:@&])*)"; +$vemmi_service = "(?:(?:${uchar}|[/?:@&=])*)"; +$vemmi_param = "(?:;${vemmi_attr}=${vemmi_value})"; +$vemmiurl = "(?:vemmi://${hostport}" . + "(?:/${vemmi_service}(?:${vemmi_param}*))?)"; + +# RFC 2192 for IMAP URLs. +# Import from RFC 2060. +# $imap4_astring = ""; +# $imap4_search_key = ""; +# $imap4_section_text = ""; +$imap4_nz_number = $nz_digits; +$achar = "(?:${uchar}|[&=~])"; +$bchar = "(?:${uchar}|[&=~:\@/])"; +$enc_auth_type = "(?:${achar}+)"; +$enc_list_mbox = "(?:${bchar}+)"; +$enc_mailbox = "(?:${bchar}+)"; +$enc_search = "(?:${bchar}+)"; +$enc_section = "(?:${bchar}+)"; +$enc_user = "(?:${achar}+)"; +$i_auth = "(?:;[Aa][Uu][Tt][Hh]=(?:${ast}|${enc_auth_type}))"; +$i_list_type = "(?:[Ll](?:[Ii][Ss][Tt]|[Ss][Uu][Bb]))"; +$i_mailboxlist = "(?:${enc_list_mbox}?;[Tt][Yy][Pp][Ee]=${i_list_type})"; +$i_uidvalidity = "(?:;[Uu][Ii][Dd][Vv][Aa][Ll][Ii][Dd][Ii][Tt][Yy]=" . + "${imap4_nz_number})"; +$i_messagelist = "(?:${enc_mailbox}(?:${qm}${enc_search})?" . + "(?:${i_uidvalidity})?)"; +$i_section = "(?:/;[Ss][Ee][Cc][Tt][Ii][Oo][Nn]=${enc_section})"; +$i_uid = "(?:/;[Uu][Ii][Dd]=${imap4_nz_number})"; +$i_messagepart = "(?:${enc_mailbox}(?:${i_uidvalidity})?${i_uid}" . + "(?:${i_section})?)"; +$i_command = "(?:${i_mailboxlist}|${i_messagelist}|${i_messagepart})"; +$i_userauth = "(?:(?:${enc_user}(?:${i_auth})?)|" . + "(?:${i_auth}(?:${enc_user})?))"; +$i_server = "(?:(?:${i_userauth}\@)?${hostport})"; +$imapurl = "(?:imap://${i_server}/(?:$i_command)?)"; + +# RFC 2224 for NFS. +$nfs_mark = '[\$\-_.\!~*\'(),]'; +$nfs_unreserved = "(?:${alphanum}|${nfs_mark})"; +$nfs_unreserved = str_replace (']|[', '', $nfs_unreserved); // Make string smaller, and speed up regex. +$nfs_pchar = "(?:${nfs_unreserved}|${escape}|[:\@&=+])"; +$nfs_segment = "(?:${nfs_pchar}*)"; +$nfs_path_segs = "(?:${nfs_segment}(?:/${nfs_segment})*)"; +$nfs_url_path = "(?:/?${nfs_path_segs})"; +$nfs_rel_path = "(?:${nfs_path_segs}?)"; +$nfs_abs_path = "(?:/${nfs_rel_path})"; +$nfs_net_path = "(?://${hostport}(?:${nfs_abs_path})?)"; +$nfs_rel_url = "(?:${nfs_net_path}|${nfs_abs_path}|${nfs_rel_path})"; +$nfsurl = "(?:nfs:${nfs_rel_url})"; + +$valid_types = array ( + 'http', 'ftp', 'news', 'nntp', 'telnet', 'gopher', 'wais', 'mailto', + 'mailtonp', 'file', 'prospero', 'ldap', 'z39_50', 'cid', 'mid', 'vemmi', + 'imap', 'nfs' +); + +# Combining all the different URL formats into a single regex. + +$valid = false; + +if (!is_array ($types)) { + $types = array ($types); +} + +foreach ($types as $type) { + if (!in_array ($type, $valid_types)) { + continue; + } + $re = $type.'url'; + if (preg_match ('!^'.$$re.'$!i', $url2check)) { + $valid = $type; + break; + } +} + +return $valid; + +} + +?> diff --git a/scripts/version.inc.php b/scripts/version.inc.php new file mode 100644 index 0000000..23677aa --- /dev/null +++ b/scripts/version.inc.php @@ -0,0 +1,31 @@ +".$l['content_search_header'].""; + + $searchstring = strip($_GET['q']); + + $c['main'] .= '
    +

    +

    +
    + +'; + +if(!empty($searchstring)) { + + $sql_searchstring = escape_for_mysql($searchstring); + + $sql = " + SELECT + id, + url, + UNIX_TIMESTAMP(date) AS date_url, + 0 AS comment_id, + topic, + UNIX_TIMESTAMP(date) AS date, + keywords, + teaser, + section, + comments, + MATCH ( topic, keywords, teaser, content ) AGAINST ('".$sql_searchstring."') AS scoring + FROM ".JLOG_DB_CONTENT." + WHERE + MATCH ( topic, keywords, teaser, content ) AGAINST ( '".$sql_searchstring."' ) + + UNION + SELECT + ".JLOG_DB_COMMENTS.".reference AS id, + ".JLOG_DB_CONTENT.".url AS url, + UNIX_TIMESTAMP(".JLOG_DB_CONTENT.".date) AS date_url, + ".JLOG_DB_COMMENTS.".id AS comment_id, + name AS topic, + UNIX_TIMESTAMP(".JLOG_DB_COMMENTS.".date) AS date, + 'comment_keywords' AS keywords, + ".JLOG_DB_COMMENTS.".content AS teaser, + 'comment', + 2, + MATCH(name, city, email, homepage, ".JLOG_DB_COMMENTS.".content) AGAINST ('".$sql_searchstring."') AS scoring + FROM ".JLOG_DB_COMMENTS.", ".JLOG_DB_CONTENT." + WHERE + MATCH ( name, city, email, homepage, ".JLOG_DB_COMMENTS.".content ) AGAINST ( '".$sql_searchstring."' ) + AND ".JLOG_DB_COMMENTS.".reference = ".JLOG_DB_CONTENT.".id + AND ".JLOG_DB_COMMENTS.".type = '' + + ORDER BY scoring desc + LIMIT 40;"; + + + $search = new Query($sql); + if($search->error()) { + echo "
    \n";
    +        echo $search->getError();
    +        echo "
    \n"; + die(); + } + + if($search->numRows() < 1) { + $c['main'] .= "

    ".$l['content_nothing_found']."

    "; + } + else { + $cc = count_comments(); + $c['main'] .= "\n"; + } +} +require(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'do_template.php'); +echo $body; +?> diff --git a/setup.php b/setup.php new file mode 100644 index 0000000..4aedf19 --- /dev/null +++ b/setup.php @@ -0,0 +1,315 @@ +importDataByArray(strip($_POST)); + + // validate user entry + if(count($errors = $setup->validate()) == 0) { + define("JLOG_BASEPATH", $setup->getValue('jlog_basepath')); + if(is_writable(JLOG_BASEPATH.'personal'.DIRECTORY_SEPARATOR)) { + $c .= "
      \n"; + + // build some MySQL tables + if(count($errors = create_mysql_tables($setup->getValue(false))) == 0) { + $c .= "
    • ".$l['admin']['s_tables_ok']."
    • \n"; + + // create and chmod on some directories and files + if(count($errors = do_personal()) == 0) { + $c .= "
    • ".$l['admin']['s_personal_ok']."
    • \n"; + + // build settings.inc.php + if(count($errors = $setup->do_settings()) == 0) $c .= "
    • ".$l['admin']['master_ok']."
    • \n"; + } + $c .= "
    "; + } + } + else { + $errors[] = $l['admin']['s_personal_not_wrtbl']; + } + } + if(count($errors) > 0) { + $c .= error_output($errors); + $c .= $setup->form_output(); + } + else $c .= "

    ".$l['admin']['s_ready_head']."

    "."

    ".$l['admin']['s_ready']."

    "; + } + else { + // validate PHP and MySQL versions + if(!version_compare(phpversion(), JLOG_PHPV, ">=") == 1) $errors[] = $l['admin']['s_phpv_tolow']; + if(!is_writable($basepath.'personal'.DIRECTORY_SEPARATOR)) $errors[] = $l['admin']['s_personal_not_wrtbl']; + if(!is_writable($basepath.'img'.DIRECTORY_SEPARATOR)) $errors[] = $l['admin']['s_img_not_wrtbl']; + + if(empty($errors)) { + // output form + $setup->importSuggestedData(); + $c .= $setup->form_output(); + } + else $c .= error_output($errors); + } + + echo do_htmlpage($c); + + + + + +#### some needed functions for the setup #### + + function create_mysql_tables($data) { + # returns false if all tables were created, if not returns the $errors array + + $sql['content'] = ' + CREATE TABLE `'.$data['jlog_db_prefix'].'content` ( + id int(11) auto_increment, + url varchar(200), + topic varchar(255), + date datetime, + teaser mediumtext, + teaserpic varchar(10), + teaserpiconblog tinyint(1), + keywords varchar(255), + content longtext, + comments tinyint(1) default \'1\', + allowpingback tinyint(1) default \'1\', + section varchar(10) default \'weblog\', + UNIQUE KEY id (id), + FULLTEXT KEY content_index (content, topic, teaser, keywords) + ) TYPE=MyISAM CHARACTER SET utf8;'; + + $sql['comments'] = ' + CREATE TABLE `'.$data["jlog_db_prefix"].'comments` ( + id int(11) auto_increment, + sid varchar(35), + name varchar(255), + city varchar(255), + email varchar(255), + homepage varchar(255), + content mediumtext, + date datetime, + reference int(11), + mail_by_comment tinyint(1), + type varchar(30) default \'\', + PRIMARY KEY (id), + UNIQUE KEY sid (sid), + FULLTEXT KEY comments_index ( name, city, email, homepage, content ) + ) TYPE=MyISAM CHARACTER SET utf8;'; + + $sql['categories'] = ' + CREATE TABLE `'.$data["jlog_db_prefix"].'categories` ( + id tinyint(4) auto_increment, + name tinytext, + url varchar(100), + description text, + UNIQUE KEY id (id), + UNIQUE KEY url (url) + ) TYPE=MyISAM CHARACTER SET utf8;'; + + $sql['catassign'] = ' + CREATE TABLE `'.$data["jlog_db_prefix"].'catassign` ( + content_id int(11), + cat_id tinyint(4) + ) TYPE=MyISAM CHARACTER SET utf8;'; + + $sql['attributes'] = ' + CREATE TABLE `'.$data["jlog_db_prefix"].'attributes` ( + id int(10) unsigned NOT NULL auto_increment, + entry_id int(10) unsigned NOT NULL default \'0\', + name varchar(120) NOT NULL default \'\', + value varchar(250) NOT NULL default \'\', + PRIMARY KEY (id), + KEY entry_id (entry_id) + ) TYPE=MyISAM CHARACTER SET utf8;'; + + global $l; + + if(!@mysql_connect($data['jlog_db_url'], $data['jlog_db_user'], $data['jlog_db_pwd'])) $errors[] = "Falsche Zugangsdaten | ".mysql_error(); + elseif(!@mysql_select_db($data['jlog_db'])) $errors[] = "Datenbank ".$data['jlog_db']." extistiert nicht".mysql_error(); + elseif(!version_compare(mysql_get_server_info(), JLOG_MYSQLV, ">=") == 1) $errors[] = $l['admin']['s_mysqlv_tolow']; + else { + new Query("SET NAMES utf8"); + $create['content'] = new Query($sql['content']); + if($create['content']->error()) $errors[] = "MySQL
    ".$create['content']->getError()."
    "; + $create['comments'] = new Query($sql['comments']); + if($create['comments']->error()) $errors[] = "MySQL
    ".$create['comments']->getError()."
    "; + $create['categories'] = new Query($sql['categories']); + if($create['categories']->error()) $errors[] = "MySQL
    ".$create['categories']->getError()."
    "; + $create['catassign'] = new Query($sql['catassign']); + if($create['catassign']->error()) $errors[] = "MySQL
    ".$create['catassign']->getError()."
    "; + $create['attributes'] = new Query($sql['attributes']); + if($create['attributes']->error()) $errors[] = "MySQL
    ".$create['attributes']->getError()."
    "; + } + + return $errors; + } + + function do_personal() { + # returns true if all files and dirs could be generated + # if not returns the $errors array + + global $l; + + // make some dirs + $oldmask = umask(0); + + // make some files + if(!fopen(JLOG_BASEPATH."personal".DIRECTORY_SEPARATOR."settings.inc.php", "w")) $errors[] = $l['admin']['s_problem_fwrite']." /personal/settings.inc.php"; + if(!fopen(JLOG_BASEPATH."personal".DIRECTORY_SEPARATOR."rss.xml", "w")) $errors[] = $l['admin']['s_problem_fwrite']." /personal/rss.xml"; + if(!fopen(JLOG_BASEPATH."personal".DIRECTORY_SEPARATOR."rss-full.xml", "w")) $errors[] = $l['admin']['s_problem_fwrite']." /personal/rss-full.xml"; + if(!fopen(JLOG_BASEPATH."personal".DIRECTORY_SEPARATOR."subcurrent.inc", "w")) $errors[] = $l['admin']['s_problem_fwrite']." /personal/subcurrent.inc"; + + // chmod 666 so that the user have the ability to delete/write to this files + if(!chmod(JLOG_BASEPATH."personal".DIRECTORY_SEPARATOR."settings.inc.php", 0666)) $errors[] = $l['admin']['s_problem_chmod']." /personal/settings.inc.php"; + if(!chmod(JLOG_BASEPATH."personal".DIRECTORY_SEPARATOR."rss.xml", 0666)) $errors[] = $l['admin']['s_problem_chmod']." /personal/rss.xml"; + if(!chmod(JLOG_BASEPATH."personal".DIRECTORY_SEPARATOR."rss-full.xml", 0666)) $errors[] = $l['admin']['s_problem_chmod']." /personal/rss-full.xml"; + if(!chmod(JLOG_BASEPATH."personal".DIRECTORY_SEPARATOR."subcurrent.inc", 0666)) $errors[] = $l['admin']['s_problem_chmod']." /personal/subcurrent.inc"; + + umask($oldmask); + + return $errors; + } + + function do_htmlpage($content) { + + return ' + + SETUP Jlog ' . JLOG_NEW_VERSION . ' + + + + + +
    +

    SETUP

    + '.$content.' +
    + +'; + } + + function getlang ($allowed, $default) { + $string = $_SERVER['HTTP_ACCEPT_LANGUAGE']; + if (empty($string)) { + return $default; + } + + $accepted_languages = preg_split('/,\s*/', $string); + + $cur_l = $default; + $cur_q = 0; + + foreach ($accepted_languages as $accepted_language) { + $res = preg_match ('/^([a-z]{1,8}(?:-[a-z]{1,8})*)'. + '(?:;\s*q=(0(?:\.[0-9]{1,3})?|1(?:\.0{1,3})?))?$/i', $accepted_language, $matches); + + if (!$res) { + continue; + } + + $lang_code = explode ('-', $matches[1]); + + if (isset($matches[2])) { + $lang_quality = (float)$matches[2]; + } else { + $lang_quality = 1.0; + } + + while (count ($lang_code)) { + if (in_array (strtolower (join ('-', $lang_code)), $allowed)) { + if ($lang_quality > $cur_q) { + $cur_l = strtolower (join ('-', $lang_code)); + $cur_q = $lang_quality; + break; + } + } + array_pop ($lang_code); + } + } + + return $cur_l; + } diff --git a/stop.php b/stop.php new file mode 100644 index 0000000..f0bba47 --- /dev/null +++ b/stop.php @@ -0,0 +1,27 @@ +error()) { + echo "
    \n";
    +        echo $stop->getError();
    +        echo "
    \n"; + die(); + } + + $c['main'] = "

    ".$l['comments_stop_successful']."

    "; + +require(JLOG_BASEPATH.'scripts'.DIRECTORY_SEPARATOR.'do_template.php'); +echo $body; +?> diff --git a/xmlrpc.php b/xmlrpc.php new file mode 100644 index 0000000..d960502 --- /dev/null +++ b/xmlrpc.php @@ -0,0 +1,244 @@ +get_ping($args); + if($pingback->validate()) { + $pingback->write_to_db(); + return "Thanks for your ping."; + } + } + $server = new IXR_Server(array('pingback.ping' => 'ping')); + } + +class Jlog_GetPingback { + + var $errors = array(); // array + var $method = ""; // string + var $sourceURI = ""; // string + var $targetURI = array(); // array incl: orginal, parsed [array from parse_url()], y, m, url + var $title = ""; // string + var $sid = ""; // string + + function Jlog_GetPingback($db_content, $db_comments, $path, $sid = NULL) { + $this->db_content = $db_content; + $this->db_comments = $db_comments; + $this->path = $path; + if($sid != NULL) $this->sid = $sid; + } + + function get_ping($uris) { + + $ymurls = array(); + $tmp_host_got = ""; + $tmp_host_path_parsed = array(); + $tmp_host_path = ""; + + $this->sourceURI = trim($uris[0]); + $this->targetURI['orginal'] = trim(str_replace(array('"','<', '>', '&'), array('"', '<', '>', '&'), $uris[1])); + $this->targetURI['parsed'] = parse_url($this->targetURI['orginal']); + $tmp_host_got = str_replace('www.', '', $this->targetURI['parsed']['host']).$this->targetURI['parsed']['path']; + $tmp_host_path_parsed = parse_url($this->path); + $tmp_host_path = str_replace('www.', '', $tmp_host_path_parsed['host']).'/log.php'; + + if(!empty($this->targetURI['parsed']['query']) AND ($tmp_host_got == $tmp_host_path)) { + + $ymurls = explode('&', $this->targetURI['parsed']['query']); + $this->_counter = count($ymurls); + + foreach($ymurls AS $ymurl) { + if(substr($ymurl, 0, 2) == 'y=') $this->targetURI['y'] = substr($ymurl, 2); + elseif(substr($ymurl, 0, 2) == 'm=') $this->targetURI['m'] = substr($ymurl, 2); + elseif(substr($ymurl, 0, 4) == 'url=') $this->targetURI['url'] = substr($ymurl, 4); + } + } + else { + ### Plugin Hook + global $plugins; + $tmp_URI = $plugins->callHook('xmlrpcPermalink', $this->targetURI['orginal']); + + $regex = "#^".$this->path."/([0-9]{4})/?([0-9]{2})/?([a-z0-9_\-]+)$#"; + preg_match($regex, $tmp_URI, $matches); + $this->targetURI['y'] = $matches[1]; + $this->targetURI['m'] = $matches[2]; + $this->targetURI['url'] = $matches[3]; + } + + } + + function validate() { + + + if(!strpos($this->targetURI['orginal'], str_replace(array('http://', 'https://'), '', str_replace('www.', '', $this->path)))) + $this->send_error(0, 'Target URI ('.$this->targetURI['orginal'].') is not this page: '.$this->path); + + + // is there such a post? + $sql = "SELECT id, allowpingback FROM ".$this->db_content." WHERE + YEAR(date) = '".escape_for_mysql($this->targetURI['y'])."' AND + MONTH(date) = '".escape_for_mysql($this->targetURI['m'])."' AND + url = '".escape_for_mysql($this->targetURI['url'])."' AND + section = 'weblog' + LIMIT 1"; + $blog = new Query($sql); + if($blog->error()) $this->send_error(0, 'Could not read my database.'); + $blogrow = $blog->fetch(); + + if($blog->numRows() != 1) $this->send_error(32, 'The specified target URI does not exist.'.$this->targetURI['orginal']); + if($blogrow['allowpingback'] === 0) $this->send_error(33, 'The specified target URI cannot be used as a target. It it is not a pingback-enabled resource.'); + else $this->reference = $blogrow['id']; + + $s =& new HTTP_Request($this->sourceURI); + if(PEAR::isError($s->sendRequest())) $this->send_error(16, 'The source URI does not exist.'); + else { + $source = $s->getResponseBody(); + $source = strip_tags(str_replace(''); + + if (!$this->isLinkInHTML($this->targetURI['orginal'], $source)) + $this->send_error(17, 'The source URI does not contain a link to the target URI, and so cannot be used as a source.'); + + preg_match('|([^<]*?)|is', $source, $title); + + if(! $utf8 = preg_match ('/charset\s*=\s*utf-8/i', $s->getResponseHeader("Content-Type"))) + $utf8 = 'application/xhtml+xml' == strtolower(trim($s->getResponseHeader("Content-Type"))); + + // since text in database is utf8 encoded, we need to *en*code the title to utf8 if it isn't already, not *de*code it + $this->title = empty($title[1]) ? $this->sourceURI : html_entity_decode($utf8 ? $title[1] : utf8_encode($title[1])); + } + + $sql = "SELECT COUNT(*) AS ping FROM ".$this->db_comments." WHERE + reference = '".escape_for_mysql($blogrow['id'])."' AND + homepage = '".escape_for_mysql($this->sourceURI)."' AND + name = '".escape_for_mysql($this->title)."' AND + type = 'pingback' + LIMIT 1"; + $p = new Query($sql); + if($p->error()) $this->send_error(0, 'Could not read my database.'); + $f = $p->fetch(); + + if($f['ping'] > 0) $this->send_error(48, 'The pingback has already been registered.'); + + if(count($this->errors) > 0) return false; + else return true; + } + + function write_to_db() { + $sql = "INSERT INTO ".$this->db_comments." ( + sid, + name, + homepage, + reference, + date, + type + ) + VALUES ( + '".escape_for_mysql($this->sid)."', + '".escape_for_mysql($this->title)."', + '".escape_for_mysql($this->sourceURI)."', + '".escape_for_mysql($this->reference)."', + NOW(), + 'pingback' + )"; + $ping = new Query($sql); + + if($ping->error()) $this->send_error(0, 'Could not write to database.'); + + } + + function send_error($nr, $string) { + $this->errors[] = $nr." ".$string; + $error = new IXR_Error($nr, $string); + $this->send_xml($error->getXml()); + } + + function get_errors() { + return $this->errors; + } + + function send_xml($xml) { + header('Connection: close'); + header('Content-Length: '.strlen($xml)); + header('Content-Type: text/xml'); + header('Date: '.date('r')); + echo $xml; + exit; + } + + function isLinkInHTML($search, $html) { + preg_match_all('#]+href\s*=\s*("([^"]+)"|\'([^\']+)\')[^>]*>(.+)#Ui', $html, $matches); + $links = array_unique(array_merge($matches[2], $matches[3])); + + foreach($links as $link) { + if($search === str_replace('&', '&', $link)) return true; + } + return false; + } + +} + +class Jlog_SendPingback { + + var $pageslinkedto = array(); + var $useragent = ""; + + function Jlog_SendPingback($html, $pagelinkedfrom, $useragent) { + // neet to prevent & in url + $this->pagelinkedfrom = htmlspecialchars_decode($pagelinkedfrom); + $this->useragent = $useragent; + + preg_match_all('#]+href\s*=\s*("([^"]+)"|\'([^\']+)\')[^>]*>(.+)#Ui', $html, $matches); + $pageslinkedto = array(); + $pageslinkedto = array_unique(array_merge($matches[2], $matches[3])); + $count = count($pageslinkedto); + for($i = 0; $count > $i; $i++) { + if(substr($pageslinkedto[$i], 0, 4) !== "http") unset($pageslinkedto[$i]); + // htmlspecialchars_decode is easier than str_replace + else $pageslinkedto[$i] = htmlspecialchars_decode($pageslinkedto[$i]); + } + $this->pageslinkedto = $pageslinkedto; + } + + function doPingbacks() { + foreach($this->pageslinkedto as $pagelinkedto) { + $feedback[] = $this->send($pagelinkedto); + } + return $feedback; + } + + function send($pagelinkedto) { + + $s =& new HTTP_Request($pagelinkedto); + if(PEAR::isError($s->sendRequest())) return $pagelinkedto." — Error: The source URI does not exist."; + else { + $xmlrpcserver = $s->getResponseHeader("X-Pingback"); + if(!empty($xmlrpcserver)); + else { + if(preg_match('', $s->getResponseBody(), $matches)) { + $xmlrpcserver = $matches[1]; + } + else return $pagelinkedto." — This is not a pingback-enabled resource."; + } + + $client = new IXR_Client($xmlrpcserver); + $client->timeout = 3; + $client->useragent = $this->useragent; + + // when set to true, this outputs debug messages by itself + $client->debug = false; + + if (! $client->query('pingback.ping', $this->pagelinkedfrom, $pagelinkedto ) ) + return $pagelinkedto." — Error: ".$client->getErrorMessage(); + + else return $pagelinkedto." — ".$client->getResponse(); + } + } + +} +?>