diff --git a/CHANGELOG b/CHANGELOG deleted file mode 100644 index 45c2540..0000000 --- a/CHANGELOG +++ /dev/null @@ -1,173 +0,0 @@ -FlatPress 0.803 Vivace -====================== -GENERAL -------- -+ Rewritten bootstrap, index centralized -+ New database backend (soon to be rewroked ;)) -+ New draft system -+ New secure hashing algorhytms for passwords -+ New widget system -+ Post view count moved to plugin PostViews -+ Rewritten main config file -+ Allowing custom appearance for date/time -+ New URLs (still compatible) -+ Allow static pages as home -+ mysite.com/flatpress/?random post goodie :) - - -PLUGINS -------- -+ New PostViews plugin -+ New favicon plugin -+ New prettyurls plugin, supporting pathinfo! (check plugin for help) -+ Added GUI to BlockParser -+ Added GUI to Akismet -F Fixed accessible antispam -F BBCode now allows inline HTML (check plugin for help): this - allows WYSIWYG lovers to install their favourite editor (e.g. - TinyMCE, see the forum for more) -F Modified and cleaned interactions of BBCode with thumbs and - lightbox plugins -F Lightbox shouldn't crash IE7 anymore -F Akismet shouldn't timeout anymore -U jsUtils is mootools 1.1 full (complete download) - -ADMIN PANEL ------------ -+ New GUI -+ Allowing plugins to add panels -+ Validating now without sessions -+ New Widget GUI -+ New Plugin GUI -+ New Theme/Styles GUI -+ New Options (formerly config) GUI - - -0.703.6.2 (2007-11-26) -====================== - -FIXED: removed /test.php -FIXED: version number - - -0.703.6.1 (2007-10-23) -====================== - -FIXED: typo in admin.entry.delete.php - - -0.703.6 (2007-10-19) -==================== - -FIXED: XSS vulnerabilities in comments.tpl and contact.tpl -FIXED: Backported from Crescendo+1 fix for XSS in $_GET fields -FIXED: bug in static handling (THEME_LEGACY_MODE not checked) -FIXED: Moved html escaping from default-filters to bbcode plugin -FIXED: Added option to bbcode plugin to allow inline html! (no more ugly [html] tags! :) - - -0.703.5 (2007-09-22) -==================== - -FIXED: severe bug with -FIXED: smaller one with commslock - - -0.703.4 (2007-09-19) -==================== - -FIXED: several XSS vulnerabilities - - -0.703.3 (2007-09-18) -==================== - -FIXED: XSS in search.php - - -0.703.2 (2007-07-13) -==================== - -FIXED: input validation problems - - -0703.1 Crescendo (July 10, 2007) -=============================== - -Small bug fixes -FIXED: bbcode: [u] tag missing -FIXED: bbcode/syntaxhighlighter: [code=MY_SYNTAX] works again -FIXED: fixed error handling with missing categories - - -0.703 Crescendo Final (June 27, 2007) -===================================== - -UPDATED: jsUtils : Mootools 1.11 -FIXED: URL issues with BBCODE -FIXED: small issues with thumb plugin - - -Crescendo RC2 (June 3, 2007) -============================ - -FIXED: spaces in file names are escaped as dashes "-" when uploaded -FIXED: various bbcode issues -FIXED: scale/width bbcode/thumb issues -MDFD: now thumb creates a .thumb dir for each subdir of images/ -FIXED: leggero CSS -FIXED: double entity encoding -ADDED: (since RC1): when loggedin trying to open a non-existent - static page will bring you to the "add new static" panel - - -Crescendo RC1 (May 29, 2007) -============================ - -FIXED: plugin/bbcode: broken non-local urls -FIXED: core/FPDB archive function: /?y=nn didn't work if a month wasn't specified -FIXED: core/entry/cache : buggy workarounded function (see previous) is now fixed -FIXED: core/users : session was not kept if user IP changed -FIXED: core/rss : template now works, fixed core accordingly -ADDED: core/rss : full content support -UPDATED: plugin/jsUtils, upgraded to mootools 1.1 -UPDATED: plugin/lightbox updated accordingly to slimbox 1.4 -RMVD: temporarily removed prettyurls plugin - (todo: remove from default config); - I'm working to a newer cooler version, but - it will require probably some changes in core, so no-go for this - release - -ADDED: Lang/it-it: added some strings I forgot - -Crescendo beta1 (May 17, 2007) -============================ - -added: some entry/cache hooks -added: many plugin translations thanx to cimangi (http://luielei.altervista.org/) -added: panel notifications for plugins -added: new theme, new icons (updated old admin css) -fixed: lightbox updated and fixed -fixed: removed quote escaping in entries (removed and added fix for old versions) -fixed: directory deletion under php5 (thx cimangi) -fixed: entry_delete did not remove visit counter (cimangi) -fixed: session retaining in control panel under certain conditions (smartyvalidate) -changed: some behaviours in cache; need some rework as introduced a little bug... d'oh! - - -Crescendo alpha -=============== - -fixed: utils_mail() -fixed: bbcode url trim -fixed: bbcode remote image timeouts -changed: WHOLE new POST behaviour (no longer "POSTDATA" messages) -changed: new theme tags (almost finished). support for old themes; soon deprecated -changed: graphics for the old theme (almost finished) -changed: a whole bunch of graphic thingies -changed: plugin organization -added: [video] tag support http://flatpress.nowhereland.it/index.php?entry=entry070210-211548 -added: update checker (experimental) -added: error/success notification system with fancy graphics :P - -NOTE: italian language is still there until the wiki is ready diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..5ee8e63 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,199 @@ +# 2019-xx-xx: FlatPress 1.1 +First release after Edoardo handed over the project ownership to Arvid. +- Runs under PHP7 +- HTTPS support +- Plugins added: Last comments admin, Media manager + +# 2015-06-12: FlatPress 1.0.3 +- This release fixes an XSS (CVE-2014-100036). +- Bonus: a new style for Leggero theme by @MarcThibeault and other UI enhancements by @MarcThibeault and @liquibyte + +# 2013-12-11: FlatPress 1.0.2 +Another bugfix release. +- Fixes errors in the rushed patched vulnerability in v1.0.1. +- Clears some issues with strict standards. +- Timezone now defaults to UTC. You can set your own time offset in the configuration panel of the admin area + +# 2013-11-21: FlatPress 1.0.1 +Bugfix release. +- Addresses Issue #3 http://www.exploit-db.com/exploits/29515/ + +# 2012-01-11: FlatPress 1.0 "Solenne" +- ...still to be documented... + +# 2010-11-07: 0.10xxx +# 2009-10-10: 0.9xx Arioso +# 2008-12-24: 0.8xx Fortissimo + +2008-05-07: FlatPress 0.803 Vivace +====================== +GENERAL +------- ++ Rewritten bootstrap, index centralized ++ New database backend (soon to be rewroked ;)) ++ New draft system ++ New secure hashing algorhytms for passwords ++ New widget system ++ Post view count moved to plugin PostViews ++ Rewritten main config file ++ Allowing custom appearance for date/time ++ New URLs (still compatible) ++ Allow static pages as home ++ mysite.com/flatpress/?random post goodie :) + + +PLUGINS +------- ++ New PostViews plugin ++ New favicon plugin ++ New prettyurls plugin, supporting pathinfo! (check plugin for help) ++ Added GUI to BlockParser ++ Added GUI to Akismet +F Fixed accessible antispam +F BBCode now allows inline HTML (check plugin for help): this + allows WYSIWYG lovers to install their favourite editor (e.g. + TinyMCE, see the forum for more) +F Modified and cleaned interactions of BBCode with thumbs and + lightbox plugins +F Lightbox shouldn't crash IE7 anymore +F Akismet shouldn't timeout anymore +U jsUtils is mootools 1.1 full (complete download) + +ADMIN PANEL +----------- ++ New GUI ++ Allowing plugins to add panels ++ Validating now without sessions ++ New Widget GUI ++ New Plugin GUI ++ New Theme/Styles GUI ++ New Options (formerly config) GUI + + +0.703.6.2 (2007-11-26) +====================== + +- FIXED: removed /test.php +- FIXED: version number + + +0.703.6.1 (2007-10-23) +====================== + +FIXED: typo in admin.entry.delete.php + + +0.703.6 (2007-10-19) +==================== + +- FIXED: XSS vulnerabilities in comments.tpl and contact.tpl +- FIXED: Backported from Crescendo+1 fix for XSS in $_GET fields +- FIXED: bug in static handling (THEME_LEGACY_MODE not checked) +- FIXED: Moved html escaping from default-filters to bbcode plugin +- FIXED: Added option to bbcode plugin to allow inline html! (no more ugly [html] tags! :) + + +0.703.5 (2007-09-22) +==================== + +- FIXED: severe bug with +- FIXED: smaller one with commslock + + +0.703.4 (2007-09-19) +==================== + +FIXED: several XSS vulnerabilities + + +0.703.3 (2007-09-18) +==================== + +FIXED: XSS in search.php + + +0.703.2 (2007-07-13) +==================== + +FIXED: input validation problems + + +0703.1 Crescendo (July 10, 2007) +=============================== + +Small bug fixes +- FIXED: bbcode: [u] tag missing +- FIXED: bbcode/syntaxhighlighter: [code=MY_SYNTAX] works again +- FIXED: fixed error handling with missing categories + + +0.703 Crescendo Final (June 27, 2007) +===================================== + +- UPDATED: jsUtils : Mootools 1.11 +- FIXED: URL issues with BBCODE +- FIXED: small issues with thumb plugin + + +Crescendo RC2 (June 3, 2007) +============================ + +- FIXED: spaces in file names are escaped as dashes "-" when uploaded +- FIXED: various bbcode issues +- FIXED: scale/width bbcode/thumb issues +- MDFD: now thumb creates a .thumb dir for each subdir of images/ +- FIXED: leggero CSS +- FIXED: double entity encoding +- ADDED: (since RC1): when loggedin trying to open a non-existent + static page will bring you to the "add new static" panel + + +Crescendo RC1 (May 29, 2007) +============================ + +- FIXED: plugin/bbcode: broken non-local urls +- FIXED: core/FPDB archive function: /?y=nn didn't work if a month wasn't specified +- FIXED: core/entry/cache : buggy workarounded function (see previous) is now fixed +- FIXED: core/users : session was not kept if user IP changed +- FIXED: core/rss : template now works, fixed core accordingly +- ADDED: core/rss : full content support +- UPDATED: plugin/jsUtils, upgraded to mootools 1.1 +- UPDATED: plugin/lightbox updated accordingly to slimbox 1.4 +- RMVD: temporarily removed prettyurls plugin + (todo: remove from default config); + I'm working to a newer cooler version, but + it will require probably some changes in core, so no-go for this + release +- ADDED: Lang/it-it: added some strings I forgot + +Crescendo beta1 (May 17, 2007) +============================ + +- added: some entry/cache hooks +- added: many plugin translations thanx to cimangi (http://luielei.altervista.org/) +- added: panel notifications for plugins +- added: new theme, new icons (updated old admin css) +- fixed: lightbox updated and fixed +- fixed: removed quote escaping in entries (removed and added fix for old versions) +- fixed: directory deletion under php5 (thx cimangi) +- fixed: entry_delete did not remove visit counter (cimangi) +- fixed: session retaining in control panel under certain conditions (smartyvalidate) +- changed: some behaviours in cache; need some rework as introduced a little bug... d'oh! + + +Crescendo alpha +=============== + +- fixed: utils_mail() +- fixed: bbcode url trim +- fixed: bbcode remote image timeouts +- changed: WHOLE new POST behaviour (no longer "POSTDATA" messages) +- changed: new theme tags (almost finished). support for old themes; soon deprecated +- changed: graphics for the old theme (almost finished) +- changed: a whole bunch of graphic thingies +- changed: plugin organization +- added: [video] tag support http://flatpress.nowhereland.it/index.php?entry=entry070210-211548 +- added: update checker (experimental) +- added: error/success notification system with fancy graphics :P + +NOTE: italian language is still there until the wiki is ready diff --git a/COPYING b/COPYING deleted file mode 100755 index 1a7a09e..0000000 --- a/COPYING +++ /dev/null @@ -1,300 +0,0 @@ - - FlatPress, flat-file based blog platform - Copyright (C) 2006 Edoardo Vacchi (NoWhereMan) - - 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - - - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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 diff --git a/LICENSE b/LICENSE.md similarity index 100% rename from LICENSE rename to LICENSE.md diff --git a/README b/README deleted file mode 100755 index 8b97df2..0000000 --- a/README +++ /dev/null @@ -1,132 +0,0 @@ - - -FLATPRESS README (or "the file that nobody reads except who writes") (draft 1) -============================================================================== - - - -## 1. WHAT THE FLATPRESS? - -First of all, let me thank you for choosing my FlatPress. I hope you'll -enjoy using it as I (almost) enjoyed writing it :) - -FlatPress is a brand new blogging platform under heavy development. - -Now, you may be like: «Another blog?? Who the heck would need that?». - - - -## 2. WHO THE HECK NEED THAT? - -Oh-kay, FP is flat-file based. This means *it doesn't require databases*. -Actually all the content in stored in text files, so you don't need -MySQL if you can't afford an hosting service which can provide that to you. - - - -## 3. COOL. I STILL DON'T SEE WHY I SHOULD USE IT - -«...as I could use SimplePHPBlog, Pivot, etc...». -Good question. FlatPress was born as an extension to SPB. -But let's clear the things out - -1. This is not a _fork_: we didn't take the SPB code and edited it; -2. This is not a rewrite: we didn't take SPB concept and reinvented its wheel - -This is a *new* project, which inherits from SPB just its *storing system*. -This means you can take your content/, images/ dirs from your SPB installation, -put them in FP's fp-content/ dir as they are, and, once installed, it should -almost work out-of-the-box. This is the aim. - -Note that we don't want every single SPB user to switch to FP, it's just -that, as a SPB user myself, I wanted an easy way to switch from that to my project -and by the way its storing system is not bad at all :) - - - -## 4. IF IT'S NOT THAT BAD, WHY THIS REWRITE? - -As I said, this *IS NOT* a rewrite. This is a new blog. -At the time we (I) started this project SPB lacked some features, it -wasn't W3C standard-compliant and, above all, it was obviously a pain -to upgrade if you had made many changes to the code. - -So the most important lacks were a plugin system and a little more -flexible theming engine. - -FlatPress uses the same plugin system of WordPress. -Beware: this doesn't mean you will be able to use any of the WordPress -plugins without any effort. Only a few of the plugin "hooks" have been -implemented (search the sources for apply_filters and do_action to know which ones). - -Also FlatPress uses the famous Smarty template engine for the themes (the -same of PhpBB). - -Of course, this now will sound great (and quite conceited), then remember -1. This is my first complete work in PHP -2. It's unfinished :) - - - -## 5. ANYWAY, IT SOUNDS PRETTY DECENT, HOW DO I GET IT TO WORK? - -OK, let's see what it will take you to run the fruit of my sweat -(sounds juicy, doesn't it? Yech!). - -A basic Apache+PHP system as a server should work. It has been small tested on IIS, -too. If you experience any problem, just let me know (be detailed describing the problem). -As I said, no need for databases. Anyway I must ask for a -version of PHP >= 4.3.0. I can't tell if it will work on older versions -so if it something is going wrong, first check this :) - -Unpack the .tar.bz2 you downloaded from the main site (probably -http://flatpress.nowhereland.it/) and http://flatpress.nowhereland.it/downloads/) -and then upload it on your webserver (or test it locally). - -Point your browser to http://yoursite.com/flatpress/ and just follow -*carefully* the istructions :p - - - -## 6. FINAL WARNING AND GOODBYE - -This you're using (or you're about to use) is intended as a TEST version; -it should be very stable, but it if it ever blew your PC up, just -remember you'd been told. - -Kidding. - -People tell me I'm quite unprofessional presenting this project. -You'll see why when you'll install FlatPress for the first time... -If that won't make your day, I just hope to make you smile :) - -Once you're ready tell us what you think on the main site; any -feedback is appreciated! - - - -## CREDITS - -I want to thank here some people that helped (and are helping) me with -this project. - -Hydra, betatester, small-coder, and official cheerleader :D -drudo, theme designer, supporter, space and time provider - -Other thanks to giulio and alcor for their precious advice. - -As an additional note, I'd like to thank also Tychondriax -another friend of mine who occasionally helps me with betasting -and bug-discovering :) - -Thank you all, guys, without you I would have already given up. - - - -Edoardo Vacchi (NoWhereMan), August, 2 2006 - -email: real_nowhereman at users dot sf dot net -www: http://www.nowhereland.it -flatpress home: http://flatpress.nowhereland.it - - diff --git a/README.md b/README.md index fae5799..cf4a193 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,22 @@ -flatpress -========= +# Welcome to FlatPress! +FlatPress is a lightweight, easy-to-set-up blogging engine. Plain and simple, just PHP. No database needed! +
+Official FlatPress site: http://flatpress.org/
+Official FlatPress GitHub project: https://github.com/flatpressblog/flatpress -FlatPress official repository +## Requirements +FlatPress runs on any web server (e.g. Apache or IIS) with PHP 5.6 or higher. Since all data is stored in files, no database is needed. + +## Installation +Installing FlatPress is really easy! +- Unzip FlatPress package +- Upload to your web server +- Browse to your web server, FlatPress installer appears +- Enter your desired user name, password etc. +- Enjoy blogging with FlatPress! + +## Credits +FlatPress was initially developed by Edoardo Vacchi (NoWhereMan): http://www.nowhereland.it
+Edoardo was supported by Hydra, drudo, giulio, alcor, and Tychondriax.
+
+Since 2018, FlatPress is taken care of by Arvid Zimmermann: https://arvidzimmermann.de diff --git a/TESTING b/TESTING deleted file mode 100755 index 701a938..0000000 --- a/TESTING +++ /dev/null @@ -1 +0,0 @@ -This is a test version and it's not intended for production. diff --git a/admin/includes/panels.prototypes.php b/admin/includes/panels.prototypes.php index ff915ab..5e4466b 100644 --- a/admin/includes/panels.prototypes.php +++ b/admin/includes/panels.prototypes.php @@ -22,7 +22,7 @@ var $actionpanel = null; - function AdminPanel(&$smarty) { + function __construct(&$smarty) { $this->smarty =& $smarty; if (!$this->panelname) trigger_error("Variable \$panelname is not defined!", E_USER_ERROR); @@ -100,7 +100,7 @@ var $langres = ''; - function AdminPanelAction(&$smarty) { + function __construct(&$smarty) { $this->smarty =& $smarty; $the_action_panel = get_class($this); $this->smarty->assign('admin_panel_id', $the_action_panel); diff --git a/admin/panels/maintain/admin.maintain.php b/admin/panels/maintain/admin.maintain.php index be7abcc..04180c4 100755 --- a/admin/panels/maintain/admin.maintain.php +++ b/admin/panels/maintain/admin.maintain.php @@ -16,12 +16,12 @@ /* utility class */ class tpl_deleter extends fs_filelister { - function tpl_deleter() { + function __construct() { //$this->smarty = $GLOBALS['_FP_SMARTY']; $this->_directory = CACHE_DIR; - parent::fs_filelister(); + parent::__construct(); } function _checkFile($directory, $file) { @@ -40,9 +40,9 @@ var $_directory = CONTENT_DIR; - function s_entry_crawler() { + function __construct() { $this->index = entry_init(); - parent::fs_filelister(); + parent::__construct(); } function _checkFile($directory, $file) { diff --git a/admin/panels/themes/admin.themes.php b/admin/panels/themes/admin.themes.php index ec5ef82..9ef7dc4 100644 --- a/admin/panels/themes/admin.themes.php +++ b/admin/panels/themes/admin.themes.php @@ -4,13 +4,13 @@ var $panelname = 'themes'; var $actions = array('default' => true); - function admin_themes(&$smarty) { + function __construct(&$smarty) { global $theme; if ($theme['version'] > 0.703) $this->actions['style'] = true; - parent::AdminPanel($smarty); + parent::__construct($smarty); } diff --git a/admin/panels/themes/admin.themes.style.php b/admin/panels/themes/admin.themes.style.php index a74d6bb..36c4ed6 100644 --- a/admin/panels/themes/admin.themes.style.php +++ b/admin/panels/themes/admin.themes.style.php @@ -2,9 +2,9 @@ class admin_themes_obj_style_idx extends fs_filelister { - function admin_themes_obj_style_idx() { + function __construct() { $this->_directory = THEMES_DIR . THE_THEME; - parent::fs_filelister(); + parent::__construct(); } function _checkFile($d, $f) { diff --git a/admin/panels/uploader/admin.uploader.browse.php b/admin/panels/uploader/admin.uploader.browse.php index 661d3ef..6daad8d 100644 --- a/admin/panels/uploader/admin.uploader.browse.php +++ b/admin/panels/uploader/admin.uploader.browse.php @@ -26,7 +26,7 @@ $this->thumburl = BLOG_BASEURL . 'admin.php?p=uploader&action=thumb&f='; - return parent::fs_filelister($d); + return parent::__construct($d); } function _checkFile($d, $f) { diff --git a/defaults.php b/defaults.php index 04dc4e0..6d0fff4 100755 --- a/defaults.php +++ b/defaults.php @@ -103,16 +103,69 @@ set_include_path(ABS_PATH); - + + // + // original Flatpress 1.0.3 coding disabled + // // compatibility with ISS + // if (!isset($_SERVER['REQUEST_URI'])) + // $_SERVER['REQUEST_URI'] = 'http://localhost/flatpress/'; + + // #define('BLOG_ROOT', dirname($_SERVER['PHP_SELF']) . '/'); + // define('BLOG_ROOT', ('/'==($v=dirname($_SERVER['SCRIPT_NAME']))? $v : $v.'/') ); + + // define('BLOG_BASEURL', 'http://'.$_SERVER['HTTP_HOST']. BLOG_ROOT); + + // + // Adding security and HTTPS support + // + + ini_set('session.cookie_httponly', 1); + ini_set('session.use_only_cookies', 1); + + if (isset($_SERVER['HTTPS'])) { + $_SERVER['HTTPS'] = htmlspecialchars($_SERVER['HTTPS'], ENT_QUOTES, "UTF-8"); + } + $serverport = "false"; + // Unterstützung für Apache und IIS + if (isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == '1' || strtolower($_SERVER['HTTPS'])=='on')) { + $serverport = "https://"; + // Uses a secure connection (HTTPS) if possible + ini_set('session.cookie_secure', 1); + } else { + $serverport = "http://"; + } + + // compatibility with ISS + $_SERVER["REQUEST_URI"] = htmlspecialchars($_SERVER["REQUEST_URI"], ENT_QUOTES, "UTF-8"); if (!isset($_SERVER['REQUEST_URI'])) - $_SERVER['REQUEST_URI'] = 'http://localhost/flatpress/'; + $_SERVER['REQUEST_URI'] = $serverport . 'localhost/flatpress/'; #define('BLOG_ROOT', dirname($_SERVER['PHP_SELF']) . '/'); define('BLOG_ROOT', ('/'==($v=dirname($_SERVER['SCRIPT_NAME']))? $v : $v.'/') ); - define('BLOG_BASEURL', 'http://'.$_SERVER['HTTP_HOST']. BLOG_ROOT); + define('BLOG_BASEURL', $serverport . $_SERVER['HTTP_HOST'] . BLOG_ROOT); + + // + // OWASP - Browser Cache - How can the browser cache be used in attacks? + // https://www.owasp.org/index.php/OWASP_Application_Security_FAQ#How_can_the_browser_cache_be_used_in_attacks.3F + // + // http://stackoverflow.com/questions/13640109/how-to-prevent-browser-cache-for-php-site + // + header('Expires: Sun, 01 Jan 2015 00:00:00 GMT'); + header('Cache-Control: no-store, no-cache, must-revalidate'); + header('Cache-Control: post-check=0, pre-check=0', FALSE); + header('Pragma: no-cache'); + // + // http://de.wikipedia.org/wiki/Liste_der_HTTP-Headerfelder + // + header('X-Frame-Options: SAMEORIGIN'); + header('X-XSS-Protection: 1; mode=block'); + header('X-Content-Type-Options: nosniff'); + // + // End of send header + // #function _dummy() {} #set_error_handler('_dummy'); diff --git a/fp-includes/core/core.bplustree.class.php b/fp-includes/core/core.bplustree.class.php index 937f9f4..c8c2b67 100755 --- a/fp-includes/core/core.bplustree.class.php +++ b/fp-includes/core/core.bplustree.class.php @@ -8,16 +8,16 @@ * (c)2008 E.Vacchi * Based on the original work by Aaron Watters (bplustree.py) * - * Classes: + * Classes: * * - BPlustTree - * Mapping keys, integers + * Mapping keys, integers * * - caching_BPT - * Subclass of BPlusTree, caching - * key,value pairs - * read-only: create using BPlusTree, read - * using caching_BPT + * Subclass of BPlusTree, caching + * key,value pairs + * read-only: create using BPlusTree, read + * using caching_BPT * * * Usage @@ -37,7 +37,7 @@ * # read-only * $f = open('myfile', 'r'); * $o = caching_BPT($f); - * + * * $o->open(); * echo $o->getitem('my-key'); * @@ -54,12 +54,12 @@ * ================= * * $walker = $tree->walker( - * string $key_lower, bool $include_lower, - * string $key_upper, bool $include_upper); + * string $key_lower, bool $include_lower, + * string $key_upper, bool $include_upper); * while ($walker->valid) { - * echo $walker->current_key(), - * $walker->current_value(); - * $walker->next(); + * echo $walker->current_key(), + * $walker->current_value(); + * $walker->next(); * } * $walker->first(); #resets internal pointer * @@ -67,7 +67,7 @@ * Internal FIFO * ============= * - * $tree->enable_fifo(); + * $tree->enable_fifo(); * do_some_processing(); * $tree->disable_fifo(); * @@ -75,7 +75,7 @@ * when key accesses are localized. Don't use it in walking * (no need for it) or for single write operations. * - * enable_fifo() takes an optional parameter $length + * enable_fifo() takes an optional parameter $length * (defaults to 33) remember that larger fifos will consume * more memory. * @@ -93,125 +93,139 @@ * * In this case, you just have to define somewhere in your code * - * define('BPT_SORT', SORT_DESC); + * define('BPT_SORT', SORT_DESC); * * and the include the library. - * + * * This somehow weird approach should however make the computation * slightly faster: the setting is evaluated only once, - * when including the library; the compare routine is then defined + * when including the library; the compare routine is then defined * accordingly, and never checked again; otherwise the compare * routine would have to check the setting each time it's called. * - */ - - + */ function d($s) { - return; // disable debug output - if (is_array($s)) { $s = '{ '.implode(", ", $s) . ' }'; } - + return; // disable debug output + if (is_array($s)) { + $s = '{ ' . implode(", ", $s) . ' }'; + } + $x = debug_backtrace(); - $f = @$x[1]['function']; - $l = $x[0]['line']; - + $f = @$x [1] ['function']; + $l = $x [0] ['line']; + echo "[{$f}:{$l}]\t", $s, "\n"; - #echo "---[{$x[2]['function']}:{$x[2]['line']}]\n"; + // echo "---[{$x[2]['function']}:{$x[2]['line']}]\n"; } error_reporting(E_ALL); - if (!defined('BPT_SORT')) { -/** - * @const int type of sorting, defaults to SORT_ASC (ascending); - * SORT_DESC (descending) is also possibile - */ -define('BPT_SORT', SORT_ASC); + /** + * + * @const int type of sorting, defaults to SORT_ASC (ascending); + * SORT_DESC (descending) is also possibile + */ + define('BPT_SORT', SORT_ASC); } - /** + * * @const int no room error */ define('NOROOMERROR', -100); /** + * * @const int null node */ define('BPT_NULL', 0); /** + * * @const int null seek position */ define('BPT_NULLSEEK', 0); /** + * * @const string magic string for bplustree */ define('BPT_VERSION_MAGIC', 'BPT01'); - -#define('BPT_INT_SIZE', 4); - +// define('BPT_INT_SIZE', 4); /** + * * @const int root bit flag */ define('BPT_FLAG_ROOT_BIT', 1); /** - * @const int interior node flag + * + * @const int interior node flag */ define('BPT_FLAG_INTERIOR', 2); /** + * * @const int root flag, shorthand for BPT_FLAG_ROOT_BIT | BPT_FLAG_INTERIOR */ define('BPT_FLAG_ROOT', BPT_FLAG_ROOT_BIT | BPT_FLAG_INTERIOR); /** + * * @const int free node flag */ define('BPT_FLAG_FREE', 4); /** + * * @const int leaf flag */ define('BPT_FLAG_LEAF', 8); /** + * * @const int leaf+root flag, shorthand for BPT_FLAG_ROOT_BIT | BPT_FLAG_LEAF */ -define('BPT_FLAG_LEAFANDROOT', BPT_FLAG_ROOT_BIT | BPT_FLAG_LEAF); +define('BPT_FLAG_LEAFANDROOT', BPT_FLAG_ROOT_BIT | BPT_FLAG_LEAF); /** - * Abstraction for array of pairs + * Abstraction for array of pairs * (meaning with "pair" an array containing two elements) * works only read-only - * */ class pairs { + /** + * * @var array of the first elements of each pair (private) - * + * */ - var $a; + var $a; + /** + * * @var array of the second elements of each pair (private) - * + * */ - var $b; + var $b; + /** - * @var integer current size of the array of pairs * + * @var integer current size of the array of pairs + * */ var $count; - + /* * Constructor * @param array $a array of the first elements of each pair * @parma array $b array of the second elements of each pair * */ - function pairs($a, $b) { - if (($v=count($a))!=count($b)) + function __construct($a, $b) { + if (($v = count($a)) != count($b)) trigger_error("Size of params must match", E_USER_ERROR); - $this->a=$a; $this->b=$b; + $this->a = $a; + $this->b = $b; $this->count = $v; } + /* * returns a slice of the current Couplets object as a new Couplets object * (works like array_slice()) @@ -221,184 +235,214 @@ class pairs { * @returns pairs object * */ - function &slice($offset, $count=null) { - if (is_null($count)) $count = $this->count; - - $a = new pairs( - array_slice($this->a, $offset, $count), - array_slice($this->b, $offset, $count) - ); - + function &slice($offset, $count = null) { + if (is_null($count)) + $count = $this->count; + + $a = new pairs(array_slice($this->a, $offset, $count), array_slice($this->b, $offset, $count)); + return $a; } + /** * inserts a pair ($a, $b) at the offset $offset eventually * pushing other elements to the right - * @param int $offset offset at which insert - * @param mixed $a first element in the pair - * @param mixed $b second element in the pair + * + * @param int $offset + * offset at which insert + * @param mixed $a + * first element in the pair + * @param mixed $b + * second element in the pair */ function insert($offset, $a, $b) { array_splice($this->a, $offset, 0, $a); array_splice($this->b, $offset, 0, $b); $this->count++; } + /** * inserts a pair ($a, $b) in the sub-array of pairs * between $lo and $hi, assuming the array is ordered, - * comparing only the first elements of each pair + * comparing only the first elements of each pair * (assumes there aren't duplicates) * uses {@link BPT_keycmp} for comparing * - * @param mixed $a first element of the pair - * @param mixed $b second element of the pair - * @param int $lo starting offset of the sub-array - * @param int|nul $hi ending offset of the sub-array + * @param mixed $a + * first element of the pair + * @param mixed $b + * second element of the pair + * @param int $lo + * starting offset of the sub-array + * @param int|nul $hi + * ending offset of the sub-array */ - function insort($a, $b, $lo=0, $hi=null) { - if (is_null($hi)) $hi=$this->count; + function insort($a, $b, $lo = 0, $hi = null) { + if (is_null($hi)) + $hi = $this->count; $A = $this->a; $X = $a; - while($lo<$hi) { - $mid = (int)(($lo+$hi)/2); - if (BPT_keycmp($X,$A[$mid])<0) $hi=$mid; - else $lo=$mid+1; + while ($lo < $hi) { + $mid = (int) (($lo + $hi) / 2); + if (BPT_keycmp($X, $A [$mid]) < 0) + $hi = $mid; + else + $lo = $mid + 1; } $this->insert($lo, $a, $b); } + /** * removes the pair at the offset $offset - * @param int $offset offset of the pair targeted for deletion - */ - + * + * @param int $offset + * offset of the pair targeted for deletion + */ function remove($offset) { array_splice($this->a, $offset, 1); array_splice($this->b, $offset, 1); $this->count--; } + /** * append at the end of the current object the contents * of another pairs object * - * @param pairs $pairs a pair object of which the contents - * will be appended to this + * @param pairs $pairs + * a pair object of which the contents + * will be appended to this */ function append(&$pairs) { array_splice($this->a, $this->count, 0, $pairs->a); array_splice($this->b, $this->count, 0, $pairs->b); - $this->count+=$pairs->count; + $this->count += $pairs->count; } + /** * make the object fields read-only */ - function __set($x,$y) { + function __set($x, $y) { trigger_error("Can't edit pairs directly'", E_USER_ERROR); } - + } - if (BPT_SORT == SORT_ASC) { -/** - * compares key $a and $b using a less-than or greather-than relation - * depending on {@link BPT_SORT} constants - * - * the function is very simple, returns strcmp($a,$b) or -strcmp($a,$b) - * depending on the BPT_SORT constant: to be a little bit faster, no check is done - * by the function itself; instead it is defined at load time, depending - * on the value of the BPT_SORT constant - * - */ -function BPT_keycmp($a,$b) { return strcmp($a,$b); } + + /** + * compares key $a and $b using a less-than or greather-than relation + * depending on {@link BPT_SORT} constants + * + * the function is very simple, returns strcmp($a,$b) or -strcmp($a,$b) + * depending on the BPT_SORT constant: to be a little bit faster, no check is done + * by the function itself; instead it is defined at load time, depending + * on the value of the BPT_SORT constant + */ + function BPT_keycmp($a, $b) { + return strcmp($a, $b); + } } else { -function BPT_keycmp($a,$b) { return -strcmp($a,$b); } + + function BPT_keycmp($a, $b) { + return -strcmp($a, $b); + } } /* -function _BPT_bisect($a, $x, $lo=0, $hi=null) { - if (is_null($hi)) - $hi=count($a); - while($lo<$hi && $a[$lo++]<$x) ; - return $lo; -} + * function _BPT_bisect($a, $x, $lo=0, $hi=null) { + * if (is_null($hi)) + * $hi=count($a); + * while($lo<$hi && $a[$lo++]<$x) ; + * return $lo; + * } */ /** * locate an element $x or the nearest bigger one * in the array $a, starting from offset $lo - * and limiting to offset $hi, assuming that $a is + * and limiting to offset $hi, assuming that $a is * ordered by the relation BPT_keycmp - * - * @param mixed $a source array - * @param mixed $x element to find - * @param int $lo leftmost offset - * @param int|null $hi rightmost offset * + * @param mixed $a + * source array + * @param mixed $x + * element to find + * @param int $lo + * leftmost offset + * @param int|null $hi + * rightmost offset + * * @returns integer * */ - -function BPT_bisect($a, $x, $lo=0, $hi=null) { +function BPT_bisect($a, $x, $lo = 0, $hi = null) { if (is_null($hi)) { $hi = count($a); } while ($lo < $hi) { - $mid = (int)(($lo+$hi)/2); - #if ($x < $a[$mid]) - if (BPT_keycmp($x,$a[$mid])<0) + $mid = (int) (($lo + $hi) / 2); + // if ($x < $a[$mid]) + if (BPT_keycmp($x, $a [$mid]) < 0) $hi = $mid; else - $lo = $mid+1; + $lo = $mid + 1; } return $lo; } /* -function BPT_insort(&$a, $x, $lo=0, $hi=null) { - if (is_null($hi)) - $hi = count($a); - while ($lo<$hi) { - $mid = (int) (($lo+$hi)/2); - if ($x < $a[$mid]) - $hi = $mid; - else - $lo = $mid+1; - } - array_splice($a, $lo, 0, array($x)); -} -*/ + * function BPT_insort(&$a, $x, $lo=0, $hi=null) { + * if (is_null($hi)) + * $hi = count($a); + * while ($lo<$hi) { + * $mid = (int) (($lo+$hi)/2); + * if ($x < $a[$mid]) + * $hi = $mid; + * else + * $lo = $mid+1; + * } + * array_splice($a, $lo, 0, array($x)); + * } + */ /* * fifo of bplustree nodes */ class BPlusTree_Node_Fifo { + /** + * * @var array array of elements */ var $fifo = array(); + /** + * * @var array dictionary (associative array) of elements */ var $fifo_dict = array(); + /** * var int size of the fifo */ var $size; - + /** * constructor - * @param int $size specifies size (defaults to 30) + * + * @param int $size + * specifies size (defaults to 30) */ - function BPlusTree_Node_Fifo($size=30) { - $this->fifosize=$size; + function __construct($size = 30) { + $this->fifosize = $size; } /** * flushes all of the contents of the fifo * to disk */ - function flush_fifo(){ + function flush_fifo() { reset($this->fifo); - while(list(,$node)=each($this->fifo)){ + while ($node = array_shift($this->fifo)) { if ($node->dirty) { $node->store(1); } @@ -406,270 +450,276 @@ class BPlusTree_Node_Fifo { $this->fifo = array(); $this->fifo_dict = array(); } + } /** * defines structure and methods of the node * of a bplustree */ - class BPlusTree_Node { - + /** - * @var integer flags (defined as BPT_* constants) - * specifying the nature of the node (leaf, interior, and combos) * + * @var integer flags (defined as BPT_* constants) + * specifying the nature of the node (leaf, interior, and combos) + * */ var $flag; - /** - * @var integer number of child elements (or values, if a leaf) - * - */ - var $size; + /** - * @var int seek position in the file * + * @var integer number of child elements (or values, if a leaf) + * + */ + var $size; + + /** + * + * @var int seek position in the file + * */ var $position; + /** - * @var resource stream where to output the data - * (typically a file open with fopen()) + * + * @var resource stream where to output the data + * (typically a file open with fopen()) */ - var $infile; + var $infile; + /** + * * @var int maximum lenght of a string key */ - var $keylen; + var $keylen; + /** + * * @var array array of strings, containing keys, of size $size */ var $keys; - /** - * @var array array of longs, of size $size+1 - * if leaf, elements in [0,$size] are the values of each key in $keys: - * at offset $size - ($size+1)-th element - there's the seek - * position of the next leaf (or BPT_NULLSEEK if rightmost leaf) - * - * if interior, - * - * - offset 0 points to the child node where keys are - * are all LESS than those in this node (actually, to $keys[0]), - * - * - offset 1 points to the child node where keys are GREATER or EQUAL to $keys[0] - * but LESS than $keys[1], - * - * - offset 2 points to the child node where keys are >= $keys[1] but < $keys[2], etc... - * - * - * with LESS, GREATER we always mean by the relation {@link BPT_keycmp} - * - * - */ - var $indices; - /** - * @var bool controls deferred writes (using fifo) - * - */ - var $dirty= false; /** + * + * @var array array of longs, of size $size+1 + * if leaf, elements in [0,$size] are the values of each key in $keys: + * at offset $size - ($size+1)-th element - there's the seek + * position of the next leaf (or BPT_NULLSEEK if rightmost leaf) + * + * if interior, + * + * - offset 0 points to the child node where keys are + * are all LESS than those in this node (actually, to $keys[0]), + * + * - offset 1 points to the child node where keys are GREATER or EQUAL to $keys[0] + * but LESS than $keys[1], + * + * - offset 2 points to the child node where keys are >= $keys[1] but < $keys[2], etc... + * + * + * with LESS, GREATER we always mean by the relation {@link BPT_keycmp} + * + * + */ + var $indices; + + /** + * + * @var bool controls deferred writes (using fifo) + * + */ + var $dirty = false; + + /** + * * @var BPlusTree_Node_Fifo object of type {@link BPlusTree_Node_Fifo} */ var $fifo = null; + /** + * * @var int number of valid keys in $keys */ var $validkeys; - /** * constructor - * @param int $flag flag of current node - * @param int $size size of node - * @param int $keylen max key length - * @param long $position seek position in file - * @param resource resource stream (opened file) - * @param BPlusTree_Node object from which cloning properties + * + * @param int $flag + * flag of current node + * @param int $size + * size of node + * @param int $keylen + * max key length + * @param long $position + * seek position in file + * @param + * resource resource stream (opened file) + * @param + * BPlusTree_Node object from which cloning properties */ - function BPlusTree_Node($flag, - $size, - $keylen, - $position, - $infile, - $cloner = null) { - + function __construct($flag, $size, $keylen, $position, $infile, $cloner = null) { $this->flag = $flag; - + if ($size < 0) { trigger_error('size must be positive', E_USER_ERROR); } - + $this->size = $size; - + $this->keylen = $keylen; $this->position = $position; $this->infile = $infile; // last (+1) is successor seek TODO move to its own! - $this->indices = array_fill(0, $size+1, BPT_NULL); + $this->indices = array_fill(0, $size + 1, BPT_NULL); $this->keys = array_fill(0, $size, ''); if (is_null($cloner)) { $this->storage = 2 + /* 2 chars for flag, validkeys */ - $size*4+4 + /* n 4B-long indices + 1 4B-long next pointer*/ - $size*$keylen ; /* n keylen-bytes long keys */ + $size * 4 + 4 + /* n 4B-long indices + 1 4B-long next pointer*/ + $size * $keylen; /* n keylen-bytes long keys */ } else { - $this->storage = $cloner->storage; - $this->fifo = $cloner->fifo; + $this->storage = $cloner->storage; + $this->fifo = $cloner->fifo; } - + if ($flag == BPT_FLAG_INTERIOR || $flag == BPT_FLAG_ROOT) { $this->validkeys = -1; } else { $this->validkeys = 0; } - } - /** - * + /** * reinitialize keys - * */ - function clear() { $size = $this->size; // re-init keys - + $this->keys = array_fill(0, $size, ''); $this->validkeys = 0; if (($this->flag & BPT_FLAG_INTERIOR) == BPT_FLAG_INTERIOR) { // re-init all indices - $this->indices = array_fill(0, $size+1, BPT_NULL); + $this->indices = array_fill(0, $size + 1, BPT_NULL); $this->validkeys = -1; } else { - $fwd = $this->indices[$size]; // forward pointer + $fwd = $this->indices [$size]; // forward pointer $this->indices = array_fill(0, $size, BPT_NULL); $this->keys = array_fill(0, $size, ''); - $this->indices[] = $fwd; + $this->indices [] = $fwd; } } - + /** * returns clone of the obect at position $position - * @param long $position seek position + * + * @param long $position + * seek position */ function &getclone($position) { - if ($this->fifo) { - $dict =& $this->fifo->fifo_dict; - if (isset($dict[$position])) { - return $dict[$position]; + $dict = & $this->fifo->fifo_dict; + if (isset($dict [$position])) { + return $dict [$position]; } } - - $o = new BPlusTree_Node( - $this->flag, - $this->size, - $this->keylen, - $position, - $this->infile, - $this - ); + $o = new BPlusTree_Node($this->flag, $this->size, $this->keylen, $position, $this->infile, $this); return $o; } - - /** + + /** * put first index (seek position for less-than child) * - * @param int $index seek position + * @param int $index + * seek position */ function putfirstindex($index) { - if ($this->validkeys>=0) + if ($this->validkeys >= 0) trigger_error("Can't putfirstindex on full node", E_USER_ERROR); - $this->indices[0] = $index; + $this->indices [0] = $index; $this->validkeys = 0; } - /** - * links node $node to this node as a child, using key $key - * (this node must be interior) - * - * @param string $key key string - * @param object $node node to link - * - */ + /** + * links node $node to this node as a child, using key $key + * (this node must be interior) + * + * @param string $key + * key string + * @param object $node + * node to link + * + */ function putnode($key, &$node) { $position = $node->position; return $this->putposition($key, $position); - # if ($x == NOROOMERROR) {print_r(debug_backtrace());fail();} + // if ($x == NOROOMERROR) {print_r(debug_backtrace());fail();} } - + /* - * + * * links a seek position $position to the key $key - * + * * @param string $key key string * @param int $position seek position (pointer to the new child node) * */ - function putposition($key, $position) { - if (($this->flag & BPT_FLAG_INTERIOR) != BPT_FLAG_INTERIOR) { trigger_error("Can't insert into leaf node", E_USER_ERROR); } - + $validkeys = $this->validkeys; - $last = $this->validkeys+1; - - if ($this->validkeys>=$this->size) { - #trigger_error('No room error', E_USER_WARNING); + $last = $this->validkeys + 1; + + if ($this->validkeys >= $this->size) { + // trigger_error('No room error', E_USER_WARNING); return NOROOMERROR; } - + // store the key - if ($validkeys<0) { // no nodes currently + if ($validkeys < 0) { // no nodes currently d("no keys"); $this->validkeys = 0; - $this->indices[0] = $position; + $this->indices [0] = $position; } else { // there are nodes - $keys =& $this->keys; + $keys = & $this->keys; // is the key there already? if (in_array($key, $keys, true)) { if (array_search($key, $keys, true) < $validkeys) - trigger_error("reinsert of node for existing key ($key)", - E_USER_ERROR); + trigger_error("reinsert of node for existing key ($key)", E_USER_ERROR); } - + $place = BPT_bisect($keys, $key, 0, $validkeys); // insert at position $place array_splice($keys, $place, 0, $key); // delete last element - unset($keys[$last]); - $keys = array_values($keys); # reset array indices - #array_splice($keys, $last, 1); - + unset($keys [$last]); + $keys = array_values($keys); // reset array indices + // array_splice($keys, $last, 1); + // store the index - $indices =& $this->indices; - #echo "inserting $position before ", var_dump($indices,1), "\n"; - array_splice($indices, $place+1, 0, $position); - unset($indices[$last+1]); + $indices = & $this->indices; + // echo "inserting $position before ", var_dump($indices,1), "\n"; + array_splice($indices, $place + 1, 0, $position); + unset($indices [$last + 1]); $indices = array_values($indices); - #array_splice($indices, $last+1, 1); + // array_splice($indices, $last+1, 1); $this->validkeys = $last; } } - /** * deletes from interior nodes * - * @param string $key target key + * @param string $key + * target key */ - function delnode($key) { // {{{ if (($this->flag & BPT_FLAG_INTERIOR) != BPT_FLAG_INTERIOR) { @@ -678,99 +728,79 @@ class BPlusTree_Node { if ($this->validkeys < 0) { trigger_error("No such key (empty)"); } - + $validkeys = $this->validkeys; - $indices =& $this->indices; - $keys =& $this->keys; + $indices = & $this->indices; + $keys = & $this->keys; if (is_null($key)) { $place = 0; $indexplace = 0; } else { $place = array_search($key, $keys, true); - $indexplace = $place+1; + $indexplace = $place + 1; } - #unset($indices[$indexplace]); + // unset($indices[$indexplace]); array_splice($indices, $indexplace, 1); - $indices[] = BPT_NULLSEEK; - #$indices = array_values($indices); - - #unset($keys[$place]); + $indices [] = BPT_NULLSEEK; + // $indices = array_values($indices); + + // unset($keys[$place]); array_splice($keys, $place, 1); - $keys[] = ''; - #$keys = array_values($keys); - + $keys [] = ''; + // $keys = array_values($keys); + $this->validkeys = $validkeys - 1; } - // }}} + // }}} + /** - * slices the $this->keys array to the number of valid keys + * slices the $this->keys array to the number of valid keys * in $this->validkeys * * @returns array array of valid keys */ - function get_keys() { $validkeys = $this->validkeys; - if ($validkeys<=0) { + if ($validkeys <= 0) { return array(); - } + } return array_slice($this->keys, 0, $validkeys); } - - - /* - * mimics python's map(None, a, b) - * returns the list of (a,b) pairs - * where a is in list $a and b is in list $b - * - * - - function _oldpairs($a, $b) { - $c = array(); - reset($a); - reset($b); - while((list(,$v1) = each($a)) && - (list(,$v2) = each($b))) { - $c[] = array($v1, $v2); - } - return $c; - } - */ - /** - * mimic's python's map(None, a, b); + * mimic's python's map(None, a, b); * a, b must be of the same size * - * @param array $a first array - * @param array $b second array - * + * @param array $a + * first array + * @param array $b + * second array + * * @returns object {@link pairs} */ function &_pairs($a, $b) { - $x = new pairs($a,$b); + $x = new pairs($a, $b); return $x; - } - /** - * returns an object containing pairs (key, index) + * returns an object containing pairs (key, index) * for all of the valid keys and indices - * - * @param string $leftmost leftmost key corresponding - * to first index (seek) in interior nodes; ignored in leaves * + * @param string $leftmost + * leftmost key corresponding + * to first index (seek) in interior nodes; ignored in leaves + * * @returns object pairs * */ function keys_indices($leftmost) { $keys = $this->get_keys(); if (($this->flag & BPT_FLAG_INTERIOR) == BPT_FLAG_INTERIOR) { - // interior nodes start with + // interior nodes start with // the pointer to the "less than key[0]" subtree: // we need pairs (key, indices) so we add the leftmost key // on top @@ -780,11 +810,11 @@ class BPlusTree_Node { return $this->_pairs($keys, $indices); } - /** * returns child, searching for $key in an interior node * - * @param string $key target $key + * @param string $key + * target $key * @returns object BPlusTree_Node * */ @@ -794,24 +824,24 @@ class BPlusTree_Node { } if (is_null($key)) $index = 0; - else - $index = array_search($key, $this->keys, true)+1; - - $place = $this->indices[$index]; - if ($place<0) { + else + $index = array_search($key, $this->keys, true) + 1; + + $place = $this->indices [$index]; + if ($place < 0) { debug_print_backtrace(); trigger_error("Invalid position! ($place, $key)", E_USER_ERROR); } - + // fifo - $fifo =& $this->fifo; + $fifo = & $this->fifo; if ($fifo) { - $ff =& $fifo->fifo; - $fd =& $fifo->fifo_dict; - if (isset($fd[$place])) { - $node =& $fd[$place]; - #unset($ff[$place]); + $ff = & $fifo->fifo; + $fd = & $fifo->fifo_dict; + if (isset($fd [$place])) { + $node = & $fd [$place]; + // unset($ff[$place]); $idx = array_search($node, $ff, true); array_splice($ff, $idx, 1); array_unshift($ff, $node); @@ -819,72 +849,73 @@ class BPlusTree_Node { } } - $node =& $this->getclone($place); - $node =& $node->materialize(); + $node = & $this->getclone($place); + $node = & $node->materialize(); return $node; } - /***** leaf mode operations *****/ - + /** + * *** leaf mode operations **** + */ + /** * if leaf returns the next leaf on the right - * */ - function &next() { if (($this->flag & BPT_LEAF_FLAG) != BPT_FLAG_LEAF) { trigger_error("cannot get next for non-leaf", E_USER_ERROR); } - $place = $this->indices[$this->size]; + $place = $this->indices [$this->size]; if ($place == BPT_NULLSEEK) return null; else { - $node =& $this->getclone($place); - $node =& $node->materialize(); + $node = & $this->getclone($place); + $node = & $node->materialize(); return $node; } - } /* - function &prev() { - if (($this->flag & BPT_LEAF_FLAG) != BPT_FLAG_LEAF) { - trigger_error("cannot get next for non-leaf", E_USER_ERROR); - } - $place = $this->prev; - if ($place == BPT_NULLSEEK) - return null; - else { - $node =& $this->getclone($place); - $node =& $node->materialize(); - return $node; - } - - } + * function &prev() { + * if (($this->flag & BPT_LEAF_FLAG) != BPT_FLAG_LEAF) { + * trigger_error("cannot get next for non-leaf", E_USER_ERROR); + * } + * $place = $this->prev; + * if ($place == BPT_NULLSEEK) + * return null; + * else { + * $node =& $this->getclone($place); + * $node =& $node->materialize(); + * return $node; + * } + * + * } */ - + /** * put ($key, $val) in a leaf * - * @param string $key target string - * @param int $val value for $key + * @param string $key + * target string + * @param int $val + * value for $key */ function putvalue($key, $val) { if (!is_string($key)) trigger_error("$key must be string", E_USER_ERROR); - + if (($this->flag & BPT_FLAG_LEAF) != BPT_FLAG_LEAF) { - #print_r($this); + // print_r($this); trigger_error("cannot get next for non-leaf ($key)", E_USER_ERROR); } $validkeys = $this->validkeys; - $indices =& $this->indices; - $keys =& $this->keys; - - if ($validkeys<=0) { // empty - // first entry - $indices[0] = $val; - $keys[0] = $key; + $indices = & $this->indices; + $keys = & $this->keys; + + if ($validkeys <= 0) { // empty + // first entry + $indices [0] = $val; + $keys [0] = $key; $this->validkeys = 1; } else { $place = null; @@ -895,239 +926,243 @@ class BPlusTree_Node { } } if (!is_null($place)) { - $keys[$place] = $key; - $indices[$place] = $val; + $keys [$place] = $key; + $indices [$place] = $val; } else { if ($validkeys >= $this->size) { - #trigger_error("no room", E_USER_WARNING); + // trigger_error("no room", E_USER_WARNING); return NOROOMERROR; } - + $place = BPT_bisect($keys, $key, 0, $validkeys); - $last = $validkeys+1; - - # del keys[validkeys] - # del indices[validkeys] - #array_splice($keys, $validkeys, 1); - unset($keys[$validkeys]); + $last = $validkeys + 1; + + // del keys[validkeys] + // del indices[validkeys] + // array_splice($keys, $validkeys, 1); + unset($keys [$validkeys]); $keys = array_values($keys); - #array_splice($indices, $validkeys, 1); - unset($indices[$validkeys]); + // array_splice($indices, $validkeys, 1); + unset($indices [$validkeys]); $indices = array_values($indices); - + array_splice($keys, $place, 0, $key); array_splice($indices, $place, 0, $val); - #echo implode(', ', $keys), " ::: $place \n"; + // echo implode(', ', $keys), " ::: $place \n"; $this->validkeys = $last; - } } } /** - * for each $key, $index in $keys_indices + * for each $key, $index in $keys_indices * put the correspoding values (assumes this is a leaf) * - * @param object $keys_indices object of type {@link pairs} + * @param object $keys_indices + * object of type {@link pairs} */ function put_all_values($keys_indices) { $this->clear(); - $indices =& $this->indices; - $keys =& $this->keys; - $length = $this->validkeys = $keys_indices->count;#count($keys_indices); + $indices = & $this->indices; + $keys = & $this->keys; + $length = $this->validkeys = $keys_indices->count; // count($keys_indices); if ($length > $this->size) trigger_error("bad length $length", E_USER_ERROR); - - for ($i=0; $i<$length; $i++) { - #list($keys[$i], $indices[$i]) = $keys_indices[$i]; - $keys[$i] = $keys_indices->a[$i]; - $indices[$i] = $keys_indices->b[$i]; + + for($i = 0; $i < $length; $i++) { + // list($keys[$i], $indices[$i]) = $keys_indices[$i]; + $keys [$i] = $keys_indices->a [$i]; + $indices [$i] = $keys_indices->b [$i]; } } - /** - * for each $key, $index in $keys_indices + * for each $key, $index in $keys_indices * put the correspoding seek positions (assumes this is an interior node) * - * @param int $first_position leftmost pointer (to less-than child) - * @param object $keys_indices object of type {@link pairs} - * + * @param int $first_position + * leftmost pointer (to less-than child) + * @param object $keys_indices + * object of type {@link pairs} + * */ - - function put_all_positions($first_position, $keys_positions) { + function put_all_positions($first_position, $keys_positions) { $this->clear(); - $indices =& $this->indices; - $keys =& $this->keys; - $length = $this->validkeys = $keys_positions->count;#count($keys_positions); + $indices = & $this->indices; + $keys = & $this->keys; + $length = $this->validkeys = $keys_positions->count; // count($keys_positions); if ($length > $this->size) { trigger_error("bad length $length", E_USER_ERROR); } - $indices[0] = $first_position; - for ($i=0; $i<$length; $i++) { - #list($keys[$i], $indices[$i+1]) = $keys_positions[$i]; - $keys[$i] = $keys_positions->a[$i]; - $indices[$i+1] = $keys_positions->b[$i]; + $indices [0] = $first_position; + for($i = 0; $i < $length; $i++) { + // list($keys[$i], $indices[$i+1]) = $keys_positions[$i]; + $keys [$i] = $keys_positions->a [$i]; + $indices [$i + 1] = $keys_positions->b [$i]; } - } - + } /** * assuming this is a leaf, returns value for $key - * @param $key string target key + * + * @param $key string + * target key * @returns int|false corresponding integer or false if key is missing * */ - function getvalue(&$key, $loose=false) { - - #d(implode(",",$this->keys)); - #$place = array_search($key, $this->keys); + function getvalue(&$key, $loose = false) { + + // d(implode(",",$this->keys)); + // $place = array_search($key, $this->keys); $place = BPT_bisect($this->keys, $key, 0, $this->validkeys); - if ($this->keys[$place-1] == $key) { - return $this->indices[$place-1]; + if ($this->keys [$place - 1] == $key) { + return $this->indices [$place - 1]; } else { if ($loose) { - if ($place>1) $place--; - $key = $this->keys[$place]; - return $this->indices[$place]; + if ($place > 1) + $place--; + $key = $this->keys [$place]; + return $this->indices [$place]; } trigger_error("key '$key' not found", E_USER_WARNING); return false; } - } /** * if leaf, creates a neighbor for this node: a new leaf * linked to this * - * @param int $position seek position for the new neighborù + * @param int $position + * seek position for the new neighbor� * @returns object BPlusTree_Node * */ function &newneighbour($position) { if (($this->flag & BPT_FLAG_LEAF) != BPT_FLAG_LEAF) trigger_error('cannot make leaf neighbour for non-leaf'); - + // create clone - $neighbour =& $this->getclone($position); + $neighbour = & $this->getclone($position); $size = $this->size; - $indices =& $this->indices; - + $indices = & $this->indices; + // linking siblings - $neighbour->indices[$size] = $indices[$size]; - $indices[$size] = $position; + $neighbour->indices [$size] = $indices [$size]; + $indices [$size] = $position; return $neighbour; } /** * if leaf, returns the leaf next to this + * * @return object BPlusTree_Node */ function &nextneighbour() { - if (($this->flag & BPT_FLAG_LEAF) != BPT_FLAG_LEAF) + if (($this->flag & BPT_FLAG_LEAF) != BPT_FLAG_LEAF) trigger_error('cannot get leaf neighbour for non-leaf'); - + $size = $this->size; - $position = $this->indices[$size]; + $position = $this->indices [$size]; if ($position == BPT_NULLSEEK) { $neighbour = null; } else { $neighbour = $this->getclone($position); $neighbour = $neighbour->materialize(); } - + return $neighbour; - } - + /* - function &prevneighbour() { - if (($this->flag & BPT_FLAG_LEAF) != BPT_FLAG_LEAF) - trigger_error('cannot get leaf neighbour for non-leaf'); - - #$size = $this->size; - $position = $this->prev; # $this->indices[$size]; - if ($position == BPT_NULLSEEK) { - return null; - } else { - $neighbour = $this->getclone($position); - $neighbour = $neighbour->materialize(); - return $neighbour; - } + * function &prevneighbour() { + * if (($this->flag & BPT_FLAG_LEAF) != BPT_FLAG_LEAF) + * trigger_error('cannot get leaf neighbour for non-leaf'); + * + * #$size = $this->size; + * $position = $this->prev; # $this->indices[$size]; + * if ($position == BPT_NULLSEEK) { + * return null; + * } else { + * $neighbour = $this->getclone($position); + * $neighbour = $neighbour->materialize(); + * return $neighbour; + * } + * + * } + */ - }*/ - /** * if leaf, deletes neighbor on the right, and re-link * with the following * - * @param object $next target for deletion - * @param free $free seek position of last free node in free list - * + * @param object $next + * target for deletion + * @param free $free + * seek position of last free node in free list + * * @returns int new free position */ function delnext(&$next, $free) { d("delnext called:"); - #print_r($this); + // print_r($this); $size = $this->size; - if ($this->indices[$size]!=$next->position) { - trigger_error("invalid next pointer ". - "{$this->indices[$size]}!={$next->position})", E_USER_ERROR); + if ($this->indices [$size] != $next->position) { + trigger_error("invalid next pointer " . "{$this->indices[$size]}!={$next->position})", E_USER_ERROR); } - $this->indices[$size] = $next->indices[$size]; + $this->indices [$size] = $next->indices [$size]; return $next->free($free); } /** * if leaf, deletes corresponding value * - * @param string $key target key + * @param string $key + * target key */ - function delvalue($key) { - $keys =& $this->keys; - $indices =& $this->indices; + function delvalue($key) { + $keys = & $this->keys; + $indices = & $this->indices; if (!in_array($key, $keys, true)) { d($keys); - trigger_error ("missing key, can't delete", E_USER_ERROR); + trigger_error("missing key, can't delete", E_USER_ERROR); } $place = array_search($key, $keys, true); $validkeys = $this->validkeys; - $prev = $validkeys-1; - - # delete + $prev = $validkeys - 1; + + // delete array_splice($keys, $place, 1); array_splice($indices, $place, 1); - #unset($keys[$place]); - #$keys[]=''; - #$keys = array_values($keys); - #unset($indices[$place]); - #$indices[] = BPT_NULL; - #$indices = array_values($indices); + // unset($keys[$place]); + // $keys[]=''; + // $keys = array_values($keys); + // unset($indices[$place]); + // $indices[] = BPT_NULL; + // $indices = array_values($indices); - # insert NULLs/empties + // insert NULLs/empties array_splice($keys, $prev, 0, ''); array_splice($indices, $prev, 0, BPT_NULL); - $this->validkeys=$prev;//validkeys-1 - + $this->validkeys = $prev; // validkeys-1 } - + /* - * add self to free list, retunr position as new free position + * add self to free list, retunr position as new free position * * @param int $freenodeposition current last free node * */ function free($freenodeposition) { $this->flag = BPT_FLAG_FREE; - $this->indices[0] = $freenodeposition; + $this->indices [0] = $freenodeposition; $this->store(); return $this->position; } - + /* * assuming self is head of free list, * pop self off freelist, return next free position; @@ -1136,84 +1171,85 @@ class BPlusTree_Node { * @param integer $flag flag for new node * @return object new node * - function unfree($flag) { - $next = $this->indices[0]; - $this->flag = $flag; - $this->validkeys = 0; - $this->indices[0] = BPT_NULLSEEK; - $this->clear(); - return $next; - } + * function unfree($flag) { + * $next = $this->indices[0]; + * $this->flag = $flag; + * $this->validkeys = 0; + * $this->indices[0] = BPT_NULLSEEK; + * $this->clear(); + * return $next; + * } */ - + /** - * get free node of same shape as self from $this->file; + * get free node of same shape as self from $this->file; * make one if none exist; * assume $freeposition is seek position of next free node * - * @param int $freeposition seek position of next freenode - * @param callback $freenode_callback is specified it is a func to call - * with a new free list head, if needed - * + * @param int $freeposition + * seek position of next freenode + * @param callback $freenode_callback + * is specified it is a func to call + * with a new free list head, if needed + * * @returns array(&$node, $newfreeposition) * * - * + * * */ - function getfreenode($freeposition, $freenode_callback=null) { + function getfreenode($freeposition, $freenode_callback = null) { d("GETTING FREE AT $freeposition"); if ($freeposition == BPT_NULLSEEK) { $file = $this->infile; - fseek($file, 0, SEEK_END); + fseek($file, 0, SEEK_END); $position = ftell($file); d("ALLOCATING SPACE..."); - $thenode =& $this->getclone($position); + $thenode = & $this->getclone($position); $thenode->store(); - return array(&$thenode, BPT_NULLSEEK); + return array( + &$thenode, + BPT_NULLSEEK + ); } else { $position = $freeposition; $thenode = $this->getclone($position); // get old node $thenode = $thenode->materialize(); // ptr to next - $next = $thenode->indices[0]; + $next = $thenode->indices [0]; if (!is_null($freenode_callback)) { call_user_func($freenode_callback, $next); } - - $thenode->BplusTree_Node( - $this->flag, - $this->size, - $this->keylen, - $position, - $this->infile - ); - + + $thenode->BplusTree_Node($this->flag, $this->size, $this->keylen, $position, $this->infile); + $thenode->store(); // save reinit'ed node - return array(&$thenode, $next); + return array( + &$thenode, + $next + ); } } - /** * * write this to file * - * @param bool $force forces write back if fifo is enabled, defaults to false - * + * @param bool $force + * forces write back if fifo is enabled, defaults to false + * */ - function store($force = false) { - // {{{ + // {{{ $position = $this->position; if (is_null($position)) - trigger_error("position cannot be null",E_USER_ERROR); + trigger_error("position cannot be null", E_USER_ERROR); - $fifo =& $this->fifo; + $fifo = & $this->fifo; if (!$force && $fifo) { - $fd =& $fifo->fifo_dict; - if (isset($fd[$this->position]) && $fd[$position] === $this) { + $fd = & $fifo->fifo_dict; + if (isset($fd [$this->position]) && $fd [$position] === $this) { $this->dirty = true; return; // defer processing } @@ -1231,9 +1267,9 @@ class BPlusTree_Node { } return $last; - } - //}}} + + // }}} /** * load node from file @@ -1245,122 +1281,119 @@ class BPlusTree_Node { $position = $this->position; if ($this->fifo) { - $fifo =& $this->fifo; - $dict =& $fifo->fifo_dict; - $ff =& $fifo->fifo; - if (isset($dict[$position])) { - $node =& $dict[$position]; - if ($node !== $ff[0]) { + $fifo = & $this->fifo; + $dict = & $fifo->fifo_dict; + $ff = & $fifo->fifo; + if (isset($dict [$position])) { + $node = & $dict [$position]; + if ($node !== $ff [0]) { $nidx = array_search($node, $ff, true); - unset($ff[$nidx]); + unset($ff [$nidx]); array_unshift($ff, $node); } return $node; } } - $f = $this->infile; + $f = $this->infile; fseek($f, $position); $data = fread($f, $this->storage); $this->delinearize($data); - if ($this->fifo) { $this->add_to_fifo(); } - - return $this; } /** + * * @returns string binary string encoding this node */ function linearize() { $params = array( - 'C2L'.($this->size+1), + 'C2L' . ($this->size + 1), $this->flag, $this->validkeys ); - - foreach($this->indices as $i) - $params[] = $i; - - $s = call_user_func_array('pack', $params); - - + + foreach ($this->indices as $i) + $params [] = $i; + + $s = call_user_func_array('pack', $params); + $x = ''; - for($i = 0; $i<$this->validkeys; $i++) { - $k = $this->keys[$i]; - if (strlen($k)>$this->keylen) + for($i = 0; $i < $this->validkeys; $i++) { + $k = $this->keys [$i]; + if (strlen($k) > $this->keylen) trigger_error("Invalid keylen for '$k'", E_USER_ERROR); $x .= str_pad($k, $this->keylen, chr(0)); } - $x = str_pad($x, $this->size*$this->keylen, chr(0)); - - + $x = str_pad($x, $this->size * $this->keylen, chr(0)); + $s .= $x; $l = strlen($s); if (strlen($s) != $this->storage) { trigger_error("bad storage $l != {$this->storage}", E_USER_ERROR); } - + return $s; } /** * get properties of this node from the string $s encoded via {@link BPlusTree_Node::linearize} * - * @param string $s binary string - * + * @param string $s + * binary string + * */ - - function delinearize($s) { - //{{{ - if (strlen($s)!=$this->storage) + function delinearize($s) { + // {{{ + if (strlen($s) != $this->storage) trigger_error("bad storage", E_USER_ERROR); - - + $x = 'Cflag/Cvalidkeys/'; - $n = $this->size+1; - for ($i = 0; $i<$n; $i++) { + $n = $this->size + 1; + for($i = 0; $i < $n; $i++) { $x .= "lindices{$i}/"; } $arr = unpack($x, $s); - - $this->flag = $arr['flag']; - $this->validkeys = $arr['validkeys']; - - for ($i = 0; $i<$n; $i++) { - $this->indices[$i] = $arr["indices{$i}"]; + + $this->flag = $arr ['flag']; + $this->validkeys = $arr ['validkeys']; + + for($i = 0; $i < $n; $i++) { + $this->indices [$i] = $arr ["indices{$i}"]; } - for ($i = 0, $j = ($n*4+2); $i<$this->validkeys; $i++, $j+=$this->keylen) { + for($i = 0, $j = ($n * 4 + 2); $i < $this->validkeys; $i++, $j += $this->keylen) { - $this->keys[$i] = rtrim(substr($s, $j, $this->keylen)); + $this->keys [$i] = rtrim(substr($s, $j, $this->keylen)); } - } - //}}} + // }}} + // foo dump /** * * prints a dump of the tree on scree - * @param string $indent custom indentation * + * @param string $indent + * custom indentation + * */ - function dump($indent='') { - //{{{ + function dump($indent = '') { + // {{{ $flag = $this->flag; if ($flag == BPT_FLAG_FREE) { echo "free->", $this->position, "\n"; - $nextp = $this->indices[0]; - if ($nextp!=BPT_NULLSEEK) { - $next =& $this->getclone($nextp); - $next =& $next->materialize(); + $nextp = $this->indices [0]; + if ($nextp != BPT_NULLSEEK) { + $next = & $this->getclone($nextp); + $next = & $next->materialize(); $next->dump(); } else { echo "!last\n"; @@ -1370,74 +1403,90 @@ class BPlusTree_Node { $nextindent = $indent . " "; echo $indent; switch ($flag) { - case BPT_FLAG_ROOT: echo "root"; break; - case BPT_FLAG_INTERIOR: echo "interior"; break; - case BPT_FLAG_LEAF: echo "leaf"; break; - case BPT_FLAG_LEAFANDROOT: echo "root&leaf"; break; - default : echo "invalid flag??? ", $flag; + case BPT_FLAG_ROOT: + echo "root"; + break; + case BPT_FLAG_INTERIOR: + echo "interior"; + break; + case BPT_FLAG_LEAF: + echo "leaf"; + break; + case BPT_FLAG_LEAFANDROOT: + echo "root&leaf"; + break; + default: + echo "invalid flag??? ", $flag; } - - echo "($flag) "; + + echo "($flag) "; echo " ", $this->position, " valid=", $this->validkeys, "\n"; echo $indent, "keys {", implode(', ', $this->keys), "}\n"; - echo $indent, "seeks {", implode(", ", $this->indices),"}\n"; + echo $indent, "seeks {", implode(", ", $this->indices), "}\n"; if (($flag & BPT_FLAG_INTERIOR) == BPT_FLAG_INTERIOR) { reset($this->indices); - while(list(,$i) = each($this->indices)) { - if ($i!=BPT_NULLSEEK) { + while ($i = array_shift($this->indices)) { + if ($i != BPT_NULLSEEK) { // interior - $n =& $this->getclone($i); - $n =& $n->materialize(); + $n = & $this->getclone($i); + $n = & $n->materialize(); $n->dump($nextindent); } else { - //leaf + // leaf continue; } } } echo $indent, "*****\n"; + } - }//}}}*/ - + // }}}*/ /** * adds this node to fifo */ function add_to_fifo() { - $fifo =& $this->fifo; - $ff =& $fifo->fifo; - $dict =& $fifo->fifo_dict; - + $fifo = & $this->fifo; + $ff = & $fifo->fifo; + $dict = & $fifo->fifo_dict; + $position = $this->position; - if(isset($dict[$position])) { - $old =& $dict[$position]; - unset($dict[$position]); - # ff.remove(old) + if (isset($dict [$position])) { + $old = & $dict [$position]; + unset($dict [$position]); + // ff.remove(old) array_splice($ff, array_search($old, $ff, true), 1); } - $dict[$this->position] =& $this; - array_splice($ff, 0, 0, array(&$this)); - if (count($ff)>$this->fifo->fifosize) { - $lastidx = count($ff)-1; - $last = $ff[$lastidx]; - unset($ff[$lastidx]); - unset($dict[$last->position]); + $dict [$this->position] = & $this; + array_splice($ff, 0, 0, array( + &$this + )); + if (count($ff) > $this->fifo->fifosize) { + $lastidx = count($ff) - 1; + $last = $ff [$lastidx]; + unset($ff [$lastidx]); + unset($dict [$last->position]); if ($last->dirty) { $last->store(true); } } - $is_o=true; - while((list(,$v)=each($ff)) && $is_o=is_object($v)); - if (!$is_o) {trigger_error('ERR', E_USER_ERROR);} + $is_o = true; + // Arvid: The loop doesn't do anything - but contains a deprecated each(). Commented out. + // while ((list (, $v) = each($ff)) && $is_o = is_object($v)) + // ; + if (!$is_o) { + trigger_error('ERR', E_USER_ERROR); + } } /** - * @param int $size defaults to 33 * + * @param int $size + * defaults to 33 + * */ - function enable_fifo($size = 33) { - if ($size<5 || $size>1000000) { + if ($size < 5 || $size > 1000000) { trigger_error("size not valid $size"); } $this->fifo = new BPlusTree_Node_Fifo($size); @@ -1445,9 +1494,7 @@ class BPlusTree_Node { /** * disables fifo (first flushes to disk) - * */ - function disable_fifo() { if ($this->fifo) { $this->fifo->flush_fifo(); @@ -1455,7 +1502,6 @@ class BPlusTree_Node { } } - } /** @@ -1465,98 +1511,113 @@ class BPlusTree_Node { * public methods are only {@link BPlusTree::getitem} * {@link BPlusTree::setitem} {@link BPlusTree::delitem} * {@link BPlusTree::walker} - * - * */ +class BPlusTree { -class BPlusTree { /** + * * @var int number of values */ var $length = null; + /** + * * @var bool used for deferred writes (if fifo is enabled */ var $dirty = false; - # var $headerformat = "%10d %10d %10d %10d %10d\n"; + + // var $headerformat = "%10d %10d %10d %10d %10d\n"; /** + * * @var int seek position of root in file */ var $root_seek = BPT_NULLSEEK; + /** - * @var int seek position of the start of the freelist * + * @var int seek position of the start of the freelist + * */ var $free = BPT_NULLSEEK; + /** + * * @var object BPlusTree_Node root node */ - var $root = null; /* */ + var $root = null; + + /* */ /** + * * @var int length of the file header in bytes */ var $headersize; + /** + * * @var bool true if fifo is enabled */ var $fifo_enabled = false; /** * constructor - * @param resource $infile resource of open file - * @param int $position offset from the beginning of the file (usually 0) - * @param int $nodesize size of the node - * @param int $keylen maximum lenght of a key in bytes (unicode extended chars evaluate to two chars) + * + * @param resource $infile + * resource of open file + * @param int $position + * offset from the beginning of the file (usually 0) + * @param int $nodesize + * size of the node + * @param int $keylen + * maximum lenght of a key in bytes (unicode extended chars evaluate to two chars) */ - - function BPlusTree($infile, $pos=null, $nodesize=null, $keylen=10) { - if (!is_null($keylen) && $keylen<=2) { + function __construct($infile, $pos = null, $nodesize = null, $keylen = 10) { + if (!is_null($keylen) && $keylen <= 2) { trigger_error("$keylen must be greater than 2", E_USER_ERROR); } $this->root_seek = BPT_NULLSEEK; $this->free = BPT_NULLSEEK; $this->root = null; $this->file = $infile; - #if ($nodesize<6) trigger_error("nodesize must be >= 6", E_USER_ERROR); + // if ($nodesize<6) trigger_error("nodesize must be >= 6", E_USER_ERROR); $this->nodesize = $nodesize; $this->keylen = $keylen; if (is_null($pos)) { $pos = 0; } $this->position = $pos; - $this->headersize = 4*4+6; /* 4 4-byte longs, 1 char, 5-byte magic string*/ + $this->headersize = 4 * 4 + 6; /* 4 4-byte longs, 1 char, 5-byte magic string */ } /** * returns an iterator for the tree - * @param string $keylower key lower limit of the iterator - * @param bool|int $includelower if true $keylower is included in the iterator; - * if $includelower > 1 then 'loose' search is assumed: - * the tree will be walked starting from - * the key $k in the tree such as $k <= $keylower - * and such as there are NO other keys $k' - * such as $k < $k' <= $keylower - * @param string $keyupper key upper bound of the iterator - * @param bool $includeupper if true $keyupper is included in the iterator + * + * @param string $keylower + * key lower limit of the iterator + * @param bool|int $includelower + * if true $keylower is included in the iterator; + * if $includelower > 1 then 'loose' search is assumed: + * the tree will be walked starting from + * the key $k in the tree such as $k <= $keylower + * and such as there are NO other keys $k' + * such as $k < $k' <= $keylower + * @param string $keyupper + * key upper bound of the iterator + * @param bool $includeupper + * if true $keyupper is included in the iterator */ - function &walker( - &$keylower, - $includelower =null, - $keyupper =null, - $includeupper =null - ) { - - $o = new BPlusWalker($this, $keylower, $includelower, $keyupper, $includeupper); - return $o; - + function &walker(&$keylower, $includelower = null, $keyupper = null, $includeupper = null) { + $o = new BPlusWalker($this, $keylower, $includelower, $keyupper, $includeupper); + return $o; } - + /** + * * @returns array array of properties of this object */ - function init_params() { + function init_params() { return array( - $this->file, + $this->file, $this->position, $this->nodesize, $this->keylen @@ -1564,18 +1625,21 @@ class BPlusTree { } /** + * * @returns object BPlusTree_Node of the root */ function get_root() { return $this->root; - } + } /** * updates the head of the freelist and writes back to file - * @param int $position seek position of the head of the freelist - */ + * + * @param int $position + * seek position of the head of the freelist + */ function update_freelist($pos) { - if ($this->free!=$pos) { + if ($this->free != $pos) { $this->free = $pos; $this->reset_header(); } @@ -1587,52 +1651,42 @@ class BPlusTree { */ function startup() { if (is_null($this->nodesize) || is_null($this->keylen)) { - trigger_error("cannot initialize without nodesize, keylen specified\n") ; + trigger_error("cannot initialize without nodesize, keylen specified\n"); } $this->length = 0; - $this->root_seek = 22; //pack('a5LCL3',...) + $this->root_seek = 22; // pack('a5LCL3',...) $this->reset_header(); $file = $this->file; fseek($file, 0, SEEK_END); - $this->root = new BplusTree_Node( - BPT_FLAG_LEAFANDROOT, - $this->nodesize, $this->keylen, $this->root_seek, $file - ); + $this->root = new BplusTree_Node(BPT_FLAG_LEAFANDROOT, $this->nodesize, $this->keylen, $this->root_seek, $file); $this->root->store(); } - /** + /** * reload the bplustree from file and setup for use */ - function open() { $file = $this->file; - if ($this->get_parameters()===false) + if ($this->get_parameters() === false) return false; - $this->root = new BplusTree_Node( - BPT_FLAG_LEAFANDROOT, - $this->nodesize, - $this->keylen, - $this->root_seek, - $file - ); - $this->root =& $this->root->materialize(); + $this->root = new BplusTree_Node(BPT_FLAG_LEAFANDROOT, $this->nodesize, $this->keylen, $this->root_seek, $file); + $this->root = & $this->root->materialize(); return true; } /** * enable fifo - * @param int $size defaults to 33 + * + * @param int $size + * defaults to 33 */ - - function enable_fifo($size=33) { + function enable_fifo($size = 33) { $this->fifo_enabled = true; $this->root->enable_fifo($size); } /** * disables fifo (writes back header to file if needed) - * */ function disable_fifo() { $this->fifo_enabled = false; @@ -1647,11 +1701,8 @@ class BPlusTree { * * @returns string header string */ - function _makeheader() { - return pack('a5LCL3', BPT_VERSION_MAGIC, - $this->length, $this->keylen, - $this->nodesize, $this->root_seek, $this->free); + return pack('a5LCL3', BPT_VERSION_MAGIC, $this->length, $this->keylen, $this->nodesize, $this->root_seek, $this->free); } /** @@ -1659,20 +1710,19 @@ class BPlusTree { * fifo is again disabled */ function reset_header() { - if ($this->fifo_enabled) { $this->dirty = true; d("[FIFO]: deferring header reset"); return; } - $file = $this->file; + $file = $this->file; fseek($file, $this->position); - + $s = $this->_makeheader(); - + fwrite($file, $s); } - + /** * reads back properties/parameters of this tree from file; * raises an error if version magic is wrong @@ -1680,246 +1730,250 @@ class BPlusTree { * @returns bool false on failure, true on success */ function get_parameters() { - $file = $this->file; + $file = $this->file; fseek($file, $this->position); $data = fread($file, $this->headersize); $hdr = unpack('a5magic/Llength/Ckeylen/Lnodesize/Lroot_seek/Lfree', $data); - if ($hdr['magic']!=BPT_VERSION_MAGIC) { - trigger_error("Version magic mismatch ({$hdr['magic']}!=" - .BPT_VERSION_MAGIC.')', E_USER_WARNING); + if ($hdr ['magic'] != BPT_VERSION_MAGIC) { + trigger_error("Version magic mismatch ({$hdr['magic']}!=" . BPT_VERSION_MAGIC . ')', E_USER_WARNING); return false; } - $this->length = $hdr['length']; - $this->keylen = $hdr['keylen']; - $this->nodesize = $hdr['nodesize']; - $this->root_seek = $hdr['root_seek']; - $this->free = $hdr['free']; + $this->length = $hdr ['length']; + $this->keylen = $hdr ['keylen']; + $this->nodesize = $hdr ['nodesize']; + $this->root_seek = $hdr ['root_seek']; + $this->free = $hdr ['free']; return true; } /** + * * @returns length of the tree (number of values) */ - function length() { + function length() { if (is_null($this->length)) { - if (false===$this->get_parameters()) return false; + if (false === $this->get_parameters()) + return false; } return $this->length; } /** - * @param string &$key key to find. - * @param bool $loose if true searches the tree for the "nearest" key to $key; - * + * + * @param + * string &$key key to find. + * @param bool $loose + * if true searches the tree for the "nearest" key to $key; + * * @returns int associated value - * + * */ - function getitem(&$key, $loose=false) { + function getitem(&$key, $loose = false) { if (is_null($this->root)) trigger_error("not open!", E_USER_ERROR); return $this->find($key, $this->root, $loose); } - + /** * traverses tree starting from $node, searching for $key - * @param string $key target key - * @param object BPlusTree_Node starting node * + * @param string $key + * target key + * @param + * object BPlusTree_Node starting node + * * @returns int|bool value at the leaf node containing key or false if key is missing * */ - function find(&$key, &$node, $loose=false) { - + function find(&$key, &$node, $loose = false) { while (($node->flag & BPT_FLAG_INTERIOR) == BPT_FLAG_INTERIOR) { - + $thesekeys = $node->keys; $validkeys = $node->validkeys; - - #d(array_slice($thesekeys, 0, $validkeys)); + + // d(array_slice($thesekeys, 0, $validkeys)); $place = BPT_bisect($thesekeys, $key, 0, $validkeys); - if ($place>=$validkeys || BPT_keycmp($thesekeys[$place],$key)>0) { - #$thesekeys[$place]>$key) { + if ($place >= $validkeys || BPT_keycmp($thesekeys [$place], $key) > 0) { + // $thesekeys[$place]>$key) { if ($place == 0) $nodekey = null; else - $nodekey=$thesekeys[$place-1]; + $nodekey = $thesekeys [$place - 1]; } else { $nodekey = $key; } - - - $node =& $node->getnode($nodekey); + + $node = & $node->getnode($nodekey); } - + return $node->getvalue($key, $loose); } /** - * @param $key target key + * + * @param $key target + * key * @returns bool false if key does not exists, true otherwise */ - function has_key(&$key, $loose=false) { - if (@$this->getitem($key, $loose)!==false) { + function has_key(&$key, $loose = false) { + if (@$this->getitem($key, $loose) !== false) { return true; } else { return false; } } - /** * sets an item in the tree with key $key and value $val * * @param string $key - * @param integer $val (internally stored as a 4byte long: keep it in mind!) - * - * + * @param integer $val + * (internally stored as a 4byte long: keep it in mind!) + * + * */ - function setitem($key, $val) { if (!is_numeric($val)) trigger_error("Second parameter must be numeric", E_USER_ERROR); $curr_length = $this->length; - $root =& $this->root; - if (is_null($root)) trigger_error("not open", E_USER_ERROR); - if (!is_string($key)) trigger_error("$key must be string", E_USER_ERROR); - if (strlen($key)>$this->keylen) + $root = & $this->root; + if (is_null($root)) + trigger_error("not open", E_USER_ERROR); + if (!is_string($key)) + trigger_error("$key must be string", E_USER_ERROR); + if (strlen($key) > $this->keylen) trigger_error("$key is too long: MAX is {$this->keylen}", E_USER_ERROR); + d("STARTING FROM ROOT..."); - d( "STARTING FROM ROOT..." ); - $test1 = $this->set($key, $val, $this->root); if (!is_null($test1)) { d("SPLITTING ROOT"); - - // getting new rightmost interior node - list($leftmost, $node) = $test1; - #print_r($test1); - d("LEFTMOST [$leftmost]"); - - // getting new non-leaf root - list($newroot, $this->free) = $root->getfreenode($this->free); - $newroot->flag = BPT_FLAG_ROOT; - - /* - if ($root->flag == BPT_FLAG_LEAFANDROOT) { - $root->flag = BPT_FLAG_LEAF; - } else { - $root->flag = BPT_FLAG_INTERIOR; - }*/ - // zero-ing root flag (makes an interior or leaf node + // getting new rightmost interior node + list ($leftmost, $node) = $test1; + // print_r($test1); + d("LEFTMOST [$leftmost]"); + + // getting new non-leaf root + list ($newroot, $this->free) = $root->getfreenode($this->free); + $newroot->flag = BPT_FLAG_ROOT; + + /* + * if ($root->flag == BPT_FLAG_LEAFANDROOT) { + * $root->flag = BPT_FLAG_LEAF; + * } else { + * $root->flag = BPT_FLAG_INTERIOR; + * } + */ + + // zero-ing root flag (makes an interior or leaf node // respectively from a normal root or a leaf-root) $root->flag &= ~BPT_FLAG_ROOT_BIT; - + $newroot->clear(); $newroot->putfirstindex($root->position); $newroot->putnode($leftmost, $node); - $this->root =& $newroot; + $this->root = & $newroot; $this->root_seek = $newroot->position; $newroot->store(); $root->store(); $this->reset_header(); - d("root split."); + d("root split."); } else { - if ($this->length!=$curr_length) { + if ($this->length != $curr_length) { // length changed: updating header $this->reset_header(); } } } - /** * traverses subtree starting at $node, searching a place for $key * and associates $val; split nodes if needed * - * This function is not meant to be called outside the class, it is a + * This function is not meant to be called outside the class, it is a * support method for {@link BPlusTree::setitem} * * @param string $key - * @param int $val value associated to $key - * @param object BPlusTree_Node starting node - * - * @returns array|null a pair (leftmost, newnode) where "leftmost" is + * @param int $val + * value associated to $key + * @param + * object BPlusTree_Node starting node + * + * @returns array|null a pair (leftmost, newnode) where "leftmost" is * the leftmost key in newnode, and newnode is the split node; * returns null if no split took place */ - - function set($key, $val, &$node) { - //{{{ - $keys =& $node->keys; + function set($key, $val, &$node) { + // {{{ + $keys = & $node->keys; $validkeys = $node->validkeys; - if (($node->flag & BPT_FLAG_INTERIOR) == BPT_FLAG_INTERIOR) { + if (($node->flag & BPT_FLAG_INTERIOR) == BPT_FLAG_INTERIOR) { d("NON LEAF: FIND DESCENDANT"); // non-leaf: find descendant to insert - d($keys); + d($keys); $place = BPT_bisect($keys, $key, 0, $validkeys); - if ($place >= $validkeys || BPT_keycmp($keys[$place],$key)>=0) { - #$keys[$place]>=$key) { + if ($place >= $validkeys || BPT_keycmp($keys [$place], $key) >= 0) { + // $keys[$place]>=$key) { // insert at previous node $index = $place; - } else { - $index = $place +1 ; + } else { + $index = $place + 1; } - + if ($index == 0) $nodekey = null; - else - $nodekey =$keys[$place-1]; - - $nextnode =$node->getnode($nodekey); + else + $nodekey = $keys [$place - 1]; + + $nextnode = $node->getnode($nodekey); $test = $this->set($key, $val, $nextnode); // split ? if (!is_null($test)) { - list($leftmost, $insertnode) = $test; + list ($leftmost, $insertnode) = $test; // TRY $TRY = $node->putnode($leftmost, $insertnode); if ($TRY == NOROOMERROR) { - - d( "$key::SPLIT!" ); + + d("$key::SPLIT!"); // EXCEPT - + $insertindex = $insertnode->position; - - list($newnode, $this->free) = - $node->getfreenode( - $this->free, - array(&$this, 'update_freelist') - ); + + list ($newnode, $this->free) = $node->getfreenode($this->free, array( + &$this, + 'update_freelist' + )); $newnode->flag = BPT_FLAG_INTERIOR; - + $ki = $node->keys_indices("dummy"); - - #list($dummy, $firstindex) = $ki[0]; #each($ki); - $firstindex = $ki->b[0]; - - #$ki = array_slice($ki, 1); + + // list($dummy, $firstindex) = $ki[0]; #each($ki); + $firstindex = $ki->b [0]; + + // $ki = array_slice($ki, 1); $ki->remove(0); - #print_r($ki); + // print_r($ki); // insert new pair - #BPT_insort($ki, array($leftmost, $insertindex)); + // BPT_insort($ki, array($leftmost, $insertindex)); $ki->insort($leftmost, $insertindex); - - $newleftmost = $this->divide_entries( - $firstindex, - $node, - $newnode, - $ki - ); - + + $newleftmost = $this->divide_entries($firstindex, $node, $newnode, $ki); + $node->store(); $newnode->store(); - return array($newleftmost, &$newnode); - - } else { - - d( "$key::NO SPLIT" ); + return array( + $newleftmost, + &$newnode + ); + } else { + + d("$key::NO SPLIT"); d($node->keys); $node->store(); return null; // no split @@ -1929,47 +1983,49 @@ class BPlusTree { // leaf d("FOUND LEAF:"); d($keys); - if (!in_array($key, $keys, true) - || array_search($key, $keys, true) >= $validkeys) { - $newlength = $this->length +1; + if (!in_array($key, $keys, true) || array_search($key, $keys, true) >= $validkeys) { + $newlength = $this->length + 1; } else { $newlength = $this->length; } - + d("[LEAF] TRYING TO PUT $key=>$val"); - if ($node->putvalue($key, $val)==NOROOMERROR) { + if ($node->putvalue($key, $val) == NOROOMERROR) { d("GOT NOROOMERROR"); $ki = $node->keys_indices("dummy"); - #BPT_insort($ki, array($key, $val)); + // BPT_insort($ki, array($key, $val)); $ki->insort($key, $val); - list($newnode, $this->free) = - $node->getfreenode( - $this->free, - array(&$this, 'update_freelist') - ); + list ($newnode, $this->free) = $node->getfreenode($this->free, array( + &$this, + 'update_freelist' + )); d("CREATE NEW NEIGHBOUR"); - $newnode =& $node->newneighbour($newnode->position); + $newnode = & $node->newneighbour($newnode->position); $newnode->flag = BPT_FLAG_LEAF; $newleftmost = $this->divide_entries(0, $node, $newnode, $ki); $node->store(); - #print_r($node); - #print_r($newnode); + // print_r($node); + // print_r($newnode); $newnode->store(); $this->length = $newlength; - return array($newleftmost, &$newnode); + return array( + $newleftmost, + &$newnode + ); } else { - d("STORING NODE [{$node->position}]") ; + d("STORING NODE [{$node->position}]"); d($node->keys); - + $node->store(); $this->length = $newlength; return null; } } } - //}}} + // }}} + /** * * removes key from tree at node $node; @@ -1978,29 +2034,31 @@ class BPlusTree { * not meant to be called outside the class, it is a support method * for {@link BPlusTree::delitem} * - * @param $key target key - * @param $node node from which start - * + * @param $key target + * key + * @param $node node + * from which start + * * @returns array a pair(&$leftmost, $size): if leftmost changes it is a string with the new leftmost * of $node otherwise returns array(null, $size)- caller will restructure node, if needed * size is the new size of $node * */ - function remove($key, &$node, $NESTING=0) { + function remove($key, &$node, $NESTING = 0) { $newnodekey = null; d("NESTING LEVEL $NESTING"); d("($NESTING) current size = {$this->nodesize}"); - - // first of all we check if it is non-leaf + + // first of all we check if it is non-leaf if (($node->flag & BPT_FLAG_INTERIOR) == BPT_FLAG_INTERIOR) { // non-leaf - $keys =& $node->keys; - $validkeys =$node->validkeys; + $keys = & $node->keys; + $validkeys = $node->validkeys; $place = BPT_bisect($keys, $key, 0, $validkeys); - - if ($place>=$validkeys || BPT_keycmp($keys[$place],$key)>=0) { - #$keys[$place]>=$key) { + + if ($place >= $validkeys || BPT_keycmp($keys [$place], $key) >= 0) { + // $keys[$place]>=$key) { // delete occurs before $place // (remember that indices are [i_0,i_1,...,i_n] // where i_0 points to the node where all keys are < K_search @@ -2010,62 +2068,58 @@ class BPlusTree { // delete occurs in $place (k_i <= K_search < k_(i+1) ) $index = $place + 1; } - - if ($index==0) { + + if ($index == 0) { $nodekey = null; } else { - $nodekey = $keys[$place-1]; + $nodekey = $keys [$place - 1]; } - + // get child node - $nextnode =& $node->getnode($nodekey); - + $nextnode = & $node->getnode($nodekey); + // RECURSION! remove from nextnode; - // returns new leftmost if changed, otherwise null, + // returns new leftmost if changed, otherwise null, // and new size of the child node - list($lm, $size) = $this->remove($key, $nextnode, $NESTING+1); - + list ($lm, $size) = $this->remove($key, $nextnode, $NESTING + 1); + // check now for size of nodesize: is it too small? // (less than half) $nodesize = $this->nodesize; - $half = (int)($nodesize/2); - - # if($size==0) trigger_error("SIZE==0", E_USER_WARNING); - + $half = (int) ($nodesize / 2); + + // if($size==0) trigger_error("SIZE==0", E_USER_WARNING); + if ($size < $half) { d("($NESTING) node too small ($size<$nodesize/2), redistribute children"); - + // node is too small, need to redistribute // children - + if (is_null($nodekey) && $validkeys == 0) { - #print_r($node); - trigger_error( - "invalid node, only one child", - E_USER_ERROR - ); + // print_r($node); + trigger_error("invalid node, only one child", E_USER_ERROR); } - if ($place >= $validkeys) { // final node in row, get previous - $rightnode =& $nextnode; - $rightkey = $nodekey; - if ($validkeys<=1) { + $rightnode = & $nextnode; + $rightkey = $nodekey; + if ($validkeys <= 1) { $leftkey = null; } else { - $leftkey = $keys[$place-2]; + $leftkey = $keys [$place - 2]; } - $leftnode =& $node->getnode($leftkey); + $leftnode = & $node->getnode($leftkey); } else { // non-final, get next - $leftnode =& $nextnode; + $leftnode = & $nextnode; $leftkey = $nodekey; - + if ($index == 0) { - $rightkey = $keys[0]; + $rightkey = $keys [0]; } else { - $rightkey = $keys[$place]; + $rightkey = $keys [$place]; } $rightnode = $node->getnode($rightkey); } @@ -2073,45 +2127,36 @@ class BPlusTree { $rightki = $rightnode->keys_indices($rightkey); $leftki = $leftnode->keys_indices($leftkey); - #$ki = array_merge($leftki, $rightki); + // $ki = array_merge($leftki, $rightki); $leftki->append($rightki); - $ki =& $leftki; + $ki = & $leftki; - #array_splice ($leftki, count($leftki), 0, $rightki); - - $lki = $ki->count;#count($ki); - + // array_splice ($leftki, count($leftki), 0, $rightki); + + $lki = $ki->count; // count($ki); + // merging? - if (($lki>$nodesize) || ( - ($leftnode->flag & BPT_FLAG_LEAF)!=BPT_FLAG_LEAF - && - ($lki>=$nodesize) - )) { + if (($lki > $nodesize) || (($leftnode->flag & BPT_FLAG_LEAF) != BPT_FLAG_LEAF && ($lki >= $nodesize))) { // redistribute - #list($newleftkey, $firstindex) = $ki[0]; - $newleftkey = $ki->a[0]; - $firstindex = $ki->b[0]; + // list($newleftkey, $firstindex) = $ki[0]; + $newleftkey = $ki->a [0]; + $firstindex = $ki->b [0]; if (is_null($leftkey)) { $newleftkey = $lm; } - if (($leftnode->flag&BPT_FLAG_LEAF)!=BPT_FLAG_LEAF) { + if (($leftnode->flag & BPT_FLAG_LEAF) != BPT_FLAG_LEAF) { // kill first pair - #$ki = array_slice($ki, 1); + // $ki = array_slice($ki, 1); $ki->remove(0); } - $newrightkey = $this->divide_entries( - $firstindex, - $leftnode, - $rightnode, - $ki - ); - + $newrightkey = $this->divide_entries($firstindex, $leftnode, $rightnode, $ki); + // delete, reinsert right $node->delnode($rightkey); $node->putnode($newrightkey, $rightnode); - + // same for left if first changed - if (!is_null($leftkey) && $leftkey!=$newleftkey) { + if (!is_null($leftkey) && $leftkey != $newleftkey) { $node->delnode($leftkey); $node->putnode($newleftkey, $leftnode); } @@ -2124,28 +2169,23 @@ class BPlusTree { d($leftnode->keys); d($leftnode->indices); d($rightnode->indices); - #list($newleftkey, $firstindex) = $ki[0]; - $newleftkey = $ki->a[0]; - $firstindex = $ki->b[0]; + // list($newleftkey, $firstindex) = $ki[0]; + $newleftkey = $ki->a [0]; + $firstindex = $ki->b [0]; - if (($leftnode->flag&BPT_FLAG_LEAF)!=BPT_FLAG_LEAF) { - $leftnode->put_all_positions( - $firstindex, - $ki->slice(1) - #array_slice($ki, 1) - ); + if (($leftnode->flag & BPT_FLAG_LEAF) != BPT_FLAG_LEAF) { + $leftnode->put_all_positions($firstindex, $ki->slice(1)); + // array_slice($ki, 1) } else { $leftnode->put_all_values($ki); } - - if ($rightnode->flag==BPT_FLAG_LEAF) { - $this->free = $leftnode->delnext( - $rightnode, $this->free - ); + + if ($rightnode->flag == BPT_FLAG_LEAF) { + $this->free = $leftnode->delnext($rightnode, $this->free); } else { $this->free = $rightnode->free($this->free); } - if (!is_null($leftkey) && $newleftkey!=$leftkey) { + if (!is_null($leftkey) && $newleftkey != $leftkey) { d("$newleftkey!=$leftkey"); $node->delnode($leftkey); $node->putnode($newleftkey, $leftnode); @@ -2153,10 +2193,10 @@ class BPlusTree { $node->delnode($rightkey); $node->store(); $leftnode->store(); - d('redist:'); + d('redist:'); d($node->keys); d($leftnode->keys); - + $this->reset_header(); } if (is_null($leftkey)) @@ -2169,7 +2209,7 @@ class BPlusTree { // we return a new leftmost key to update parent // ($lm is null if no update is needed) $newnodekey = $lm; - } elseif(!is_null($lm)) { + } elseif (!is_null($lm)) { // child's leftmost has changed: // delete old reference $node->delnode($nodekey); @@ -2177,134 +2217,133 @@ class BPlusTree { $node->putnode($lm, $nextnode); } } // end restructuring if - } else { - //leaf, base case: just delete. - if ($node->validkeys<1) { + // leaf, base case: just delete. + if ($node->validkeys < 1) { // only for empty root trigger_error("No such key $key", E_USER_ERROR); } - $first=$node->keys[0]; + $first = $node->keys [0]; d($node->keys); $node->delvalue($key); d($node->keys); - $rest = $node->keys[0]; - if ($first!=$rest) { + $rest = $node->keys [0]; + if ($first != $rest) { $newnodekey = $rest; } $node->store(); $this->length--; - + d("NEWNODEKEY: $newnodekey"); d("VALIDKEYS: {$node->validkeys}"); } d($node->keys); - return array($newnodekey, $node->validkeys); + return array( + $newnodekey, + $node->validkeys + ); } - /** * - * equally divides $entries ("array" of pairs (key,index) - + * equally divides $entries ("array" of pairs (key,index) - * implemented with a pair object) between two nodes $node1 and $node2 * - * @param int $firstindex if interior node, leftmost index (pointer to less-than sub-tree) for $node1 - * @param object $node1 BPlusTree_Node first destination node - * @param object $node2 BplusTree_Node second destination node - * @param object $entries {@link pairs} object - * + * @param int $firstindex + * if interior node, leftmost index (pointer to less-than sub-tree) for $node1 + * @param object $node1 + * BPlusTree_Node first destination node + * @param object $node2 + * BplusTree_Node second destination node + * @param object $entries + * {@link pairs} object + * * @returns string leftmost key of $node1 */ - function divide_entries($firstindex, &$node1, &$node2, &$entries) { -//{{{ - #$middle = (int)(count($entries)/2); - $middle = ceil($entries->count/2); + // {{{ + // $middle = (int)(count($entries)/2); + $middle = ceil($entries->count / 2); d("divide entries at $middle"); - - #$left = array_slice($entries, 0, $middle); - #$right = array_slice($entries, $middle); + + // $left = array_slice($entries, 0, $middle); + // $right = array_slice($entries, $middle); $left = $entries->slice(0, $middle); $right = $entries->slice($middle); - - - if (($node1->flag & BPT_FLAG_INTERIOR) == BPT_FLAG_INTERIOR) { - d("DIVIDING INTERIOR\n"); - #list($leftmost, $midindex) = $right[0]; - $leftmost = $right->a[0]; - $midindex = $right->b[0]; - + + if (($node1->flag & BPT_FLAG_INTERIOR) == BPT_FLAG_INTERIOR) { + d("DIVIDING INTERIOR\n"); + // list($leftmost, $midindex) = $right[0]; + $leftmost = $right->a [0]; + $midindex = $right->b [0]; + $node1->put_all_positions($firstindex, $left); - #$node2->put_all_positions($midindex, array_slice($right, 1)); + // $node2->put_all_positions($midindex, array_slice($right, 1)); $node2->put_all_positions($midindex, $right->slice(1)); d($node1->keys); d($node2->keys); - if (in_array( - array_fill(0,$node1->size,''), - array($node1->keys,$node2->keys), true) - ) { + if (in_array(array_fill(0, $node1->size, ''), array( + $node1->keys, + $node2->keys + ), true)) { trigger_error("splitting an empty node!", E_USER_ERROR); } - return $leftmost; + return $leftmost; } else { - d("DIVIDING non-INTERIOR"); + d("DIVIDING non-INTERIOR"); $node1->put_all_values($left); $node2->put_all_values($right); d($node1->keys); d($node2->keys); // returns right leftmost - #return $right[0][0]; - return $right->a[0]; + // return $right[0][0]; + return $right->a [0]; } } -// }}} - + // }}} + /** * delete item $key - * @param string $key the key to delete * + * @param string $key + * the key to delete + * */ - function delitem($key) { $root = $this->root; $currentlength = $this->length; - - $this->remove($key, $root, $NESTING=0); - + + $this->remove($key, $root, $NESTING = 0); + if ($root->flag == BPT_FLAG_ROOT) { $validkeys = $root->validkeys; - - if ($validkeys <1) { + + if ($validkeys < 1) { - - if ($validkeys<0) { - trigger_error( - "invalid empty non-leaf root", - E_USER_ERROR - ); + if ($validkeys < 0) { + trigger_error("invalid empty non-leaf root", E_USER_ERROR); } - - - $this->root =& $root->getnode(null); - $newroot =& $this->root; + + $this->root = & $root->getnode(null); + $newroot = & $this->root; $this->root_seek = $newroot->position; $this->free = $root->free($this->free); $this->reset_header(); /* - if ($newroot->flag == BPT_FLAG_LEAF) { - $newroot->flag = BPT_FLAG_LEAFANDROOT; - } else { - $newroot->flag = BPT_FLAG_ROOT; - } - */ + * if ($newroot->flag == BPT_FLAG_LEAF) { + * $newroot->flag = BPT_FLAG_LEAFANDROOT; + * } else { + * $newroot->flag = BPT_FLAG_ROOT; + * } + */ $newroot->flag |= BPT_FLAG_ROOT_BIT; $newroot->store(); } elseif ($this->length != $currentlength) { $this->reset_header(); } - } elseif($root->flag != BPT_FLAG_LEAFANDROOT) { + } elseif ($root->flag != BPT_FLAG_LEAFANDROOT) { trigger_error("invalid flag for root", E_USER_ERROR); } elseif ($this->length != $currentlength) { $this->reset_header(); @@ -2312,58 +2351,51 @@ class BPlusTree { } function _dump() { - $free =& $this->root->getclone($this->free); - for ($i=$this->headersize; - !feof($this->file); - fseek($this->file, $i), $i+=$free->storage) { - $s = fread($this->file, $free->storage); - $free->delinearize($s); - #print_r($free); - } + $free = & $this->root->getclone($this->free); + for($i = $this->headersize; !feof($this->file); fseek($this->file, $i), $i += $free->storage) { + $s = fread($this->file, $free->storage); + $free->delinearize($s); + // print_r($free); + } } /** * dumps contents of the tree to screen */ - function dump() { - $this->root->dump() ; + $this->root->dump(); if ($this->free != BPT_NULLSEEK) { - $free =& $this->root->getclone($this->free); - $free =& $free->materialize(); + $free = & $this->root->getclone($this->free); + $free = & $free->materialize(); $free->dump(); } } - - + } class BPlusWalker { - + var $tree; + var $keylower; + var $includelower; + var $keyupper; + var $includeupper; - - function BPlusWalker( - &$tree, - &$keylower, - $includelower=null, - $keyupper=null, - $includeupper=null){ - - $this->tree =& $tree; + function __construct(&$tree, &$keylower, $includelower = null, $keyupper = null, $includeupper = null) { + $this->tree = & $tree; $this->keylower = $keylower; $this->includelower = $includelower; $this->keyupper = $keyupper; $this->includeupper = $includeupper; - if ($this->tree->get_root()==null) { + if ($this->tree->get_root() == null) { $this->tree->open(); } $node = $this->tree->get_root(); - while(BPT_FLAG_INTERIOR == ($node->flag & BPT_FLAG_INTERIOR)) { + while (BPT_FLAG_INTERIOR == ($node->flag & BPT_FLAG_INTERIOR)) { if (is_null($keylower)) { $nkey = null; @@ -2371,20 +2403,20 @@ class BPlusWalker { $keys = $node->get_keys(); $n_keys = count($keys); $place = BPT_bisect($keys, $keylower); - if ($place==0) { + if ($place == 0) { $nkey = null; - } elseif ($place>$n_keys) { - $nkey = $keys[$n_keys-1]; + } elseif ($place > $n_keys) { + $nkey = $keys [$n_keys - 1]; } else { - $nkey = $keys[$place-1]; + $nkey = $keys [$place - 1]; } } - - $node =& $node->getnode($nkey); + + $node = & $node->getnode($nkey); } - - $this->startnode =& $node; - $this->node =& $node; + + $this->startnode = & $node; + $this->node = & $node; $this->node_index = null; $this->valid = 0; @@ -2393,51 +2425,50 @@ class BPlusWalker { } function first() { - $this->node =& $this->startnode; - $node =& $this->node; - - $keys =& $node->keys; + $this->node = & $this->startnode; + $node = & $this->node; + + $keys = & $node->keys; $keylower = $this->keylower; $keyupper = $this->keyupper; - $validkeys= $node->validkeys; - $this->valid=0; - if ($keylower==null) { + $validkeys = $node->validkeys; + $this->valid = 0; + if ($keylower == null) { $this->node_index = 0; - $this->valid=1; + $this->valid = 1; } elseif (in_array($keylower, $keys, true) && $this->includelower) { $this->node_index = array_search($keylower, $keys, true); $index = $this->node_index; - if ($index<$validkeys) { + if ($index < $validkeys) { $this->valid = 1; } } if (!$this->valid) { $place = BPT_bisect($keys, $keylower, 0, $validkeys); - if ($place < $validkeys || ($place==$validkeys && $this->includelower>1)) { + if ($place < $validkeys || ($place == $validkeys && $this->includelower > 1)) { if ($place > 0) $index = $place - 1; - else $index = $place; - + else + $index = $place; + $this->node_index = $index; - $testk = $keys[$index]; + $testk = $keys [$index]; /* - if ($testk>$keylower || - ($this->includelower && $testk==$keylower)) { - $this->valid = true; - } else { - $this->valid = false; - } - */ - $this->valid = BPT_keycmp($testk,$keylower)<0||#$testk>$keylower || - ($this->includelower && ($this->includelower>1 || $testk==$keylower) ); - - + * if ($testk>$keylower || + * ($this->includelower && $testk==$keylower)) { + * $this->valid = true; + * } else { + * $this->valid = false; + * } + */ + $this->valid = BPT_keycmp($testk, $keylower) < 0 || // $testk>$keylower || + ($this->includelower && ($this->includelower > 1 || $testk == $keylower)); + $this->keylower = $testk; - } else { - $next =& $node->nextneighbour(); + $next = & $node->nextneighbour(); if (!is_null($next)) { - $this->startnode =& $next; + $this->startnode = & $next; $this->first(); return; } else { @@ -2446,75 +2477,77 @@ class BPlusWalker { } if ($this->valid && !is_null($keyupper)) { $key = $this->current_key(); - $this->valid= ( - BPT_keycmp($key,$keyupper)<0 #$key<$keyupper - ||($this->includeupper && $key==$keyupper)); + $this->valid = (BPT_keycmp($key, $keyupper) < 0 || // $key<$keyupper + ($this->includeupper && $key == $keyupper)); } } } function current_key() { - if ($this->valid) return $this->node->keys[$this->node_index]; - else trigger_error("WALKER: Not a valid index ({$this->node_index})"); + if ($this->valid) + return $this->node->keys [$this->node_index]; + else + trigger_error("WALKER: Not a valid index ({$this->node_index})"); } function current_value() { - if ($this->valid) return $this->node->indices[$this->node_index]; - else trigger_error("WALKER: Not a valid index ({$this->node_index})"); + if ($this->valid) + return $this->node->indices [$this->node_index]; + else + trigger_error("WALKER: Not a valid index ({$this->node_index})"); } function current() { if ($this->valid) { return array( - $this->node->keys[$this->node_index], - $this->node->indices[$this->node_index] + $this->node->keys [$this->node_index], + $this->node->indices [$this->node_index] ); } else { - trigger_error("WALKER: Not a valid index ({$this->node_index})"); + trigger_error("WALKER: Not a valid index ({$this->node_index})"); } } function next() { - $nextp = $this->node_index+1; - $node =& $this->node; - if ($nextp>=$node->validkeys) { - $next =& $node->nextneighbour(); + $nextp = $this->node_index + 1; + $node = & $this->node; + if ($nextp >= $node->validkeys) { + $next = & $node->nextneighbour(); if (is_null($next)) { $this->valid = 0; return; } - $this->node =& $next; - $node =& $next; + $this->node = & $next; + $node = & $next; $nextp = 0; } - if($node->validkeys <= $nextp) { + if ($node->validkeys <= $nextp) { $this->valid = 0; } else { - $testkey = $node->keys[$nextp]; + $testkey = $node->keys [$nextp]; $keyupper = $this->keyupper; - $this->valid =( is_null($keyupper) || - BPT_keycmp($testkey,$keyupper)<0|| - #$testkey < $keyupper || - ($this->includeupper && $testkey == $keyupper) ); - if ($this->valid) $this->node_index = $nextp; + $this->valid = (is_null($keyupper) || BPT_keycmp($testkey, $keyupper) < 0 || + // $testkey < $keyupper || + ($this->includeupper && $testkey == $keyupper)); + if ($this->valid) + $this->node_index = $nextp; } - + return $this->valid; - } - + } class caching_BPT extends BPlusTree { var $cache = array(); - function getitem(&$key, $loose=false) { - if (isset($this->cache[$key])) - return $this->cache[$key]; - else { - $this->cache[$key] = parent::getitem($key, $loose); - return $this->cache[$key]; + function getitem(&$key, $loose = false) { + if (isset($this->cache [$key])) + return $this->cache [$key]; + else { + $this->cache [$key] = parent::getitem($key, $loose); + return $this->cache [$key]; } } @@ -2526,20 +2559,24 @@ class caching_BPT extends BPlusTree { trigger_error("operation not permitted in caching_BPT", E_USER_WARNING); } - function setitem($key, $val) { $this->nope(); } + function setitem($key, $val) { + $this->nope(); + } - function delitem($key) { $this->nope(); } + function delitem($key) { + $this->nope(); + } } class SBPlusTree extends BPlusTree { - - var $maxstring; var $stringfile; - - function SBPlusTree($infile, $stringfile, - $maxstring = 256, - $pos=null, $nodesize=null, $keylen=null) { - parent::BPlusTree($infile, $pos, $nodesize, $keylen); + + var $maxstring; + + var $stringfile; + + function __construct($infile, $stringfile, $maxstring = 256, $pos = null, $nodesize = null, $keylen = null) { + parent::__construct($infile, $pos, $nodesize, $keylen); $this->stringfile = $stringfile; $this->maxstring = $maxstring; } @@ -2564,24 +2601,26 @@ class SBPlusTree extends BPlusTree { fseek($this->stringfile, $seek); } // nul-pad string - if (strlen($s>$this->maxstring)) + if (strlen($s > $this->maxstring)) $x = substr($s, 0, $this->maxstring); $x = str_pad($s, $this->maxstring, chr(0)); fwrite($this->stringfile, $x); return $seek; } - function getitem(&$key, $loose=false) { + function getitem(&$key, $loose = false) { $seek = $this->has_key($key, $loose); - return is_numeric($seek)? $this->getstring($seek) : false; + return is_numeric($seek) ? $this->getstring($seek) : false; } /** - * @param $key target key + * + * @param $key target + * key * @returns int seek point if key exists, 0 otherwise */ - function has_key(&$key, $loose=false) { - return @parent::getitem($key, $loose); + function has_key(&$key, $loose = false) { + return @parent::getitem($key, $loose); } function setitem($key, $val) { @@ -2590,15 +2629,11 @@ class SBPlusTree extends BPlusTree { return $seek; } - function &walker( - &$keylower, - $includelower =null, - $keyupper =null, - $includeupper =null - ) { - $o = new SBPlusWalker($this, $keylower, $includelower, $keyupper, $includeupper); - return $o; - } + function &walker(&$keylower, $includelower = null, $keyupper = null, $includeupper = null) { + $o = new SBPlusWalker($this, $keylower, $includelower, $keyupper, $includeupper); + return $o; + } + } class SBPlusWalker extends BPlusWalker { @@ -2607,28 +2642,23 @@ class SBPlusWalker extends BPlusWalker { $id = parent::current_value(); return $this->tree->getstring($id); } - + } class caching_SBPT extends SBPlusTree { var $cache = array(); - function caching_SBPT($infile, $stringfile, - $maxstring = 256, - $pos=null, $nodesize=null, $keylen=null) { - - parent::SBPlusTree($infile, $stringfile, - $maxstring, - $pos, $nodesize, $keylen); + function __construct($infile, $stringfile, $maxstring = 256, $pos = null, $nodesize = null, $keylen = null) { + parent::__construct($infile, $stringfile, $maxstring, $pos, $nodesize, $keylen); } - function getitem(&$key, $loose=false) { - if (isset($this->cache[$key])) - return $this->cache[$key]; + function getitem(&$key, $loose = false) { + if (isset($this->cache [$key])) + return $this->cache [$key]; else { $item = parent::getitem($key, $loose); - $this->cache[$key] = $item; + $this->cache [$key] = $item; return $item; } } @@ -2641,28 +2671,32 @@ class caching_SBPT extends SBPlusTree { trigger_error("operation not permitted in caching_BPT", E_USER_WARNING); } - function setitem($key, $val) { $this->nope(); } + function setitem($key, $val) { + $this->nope(); + } - function delitem($key) { $this->nope(); } + function delitem($key) { + $this->nope(); + } } class BPlusUtils { - function recopy_bplus($fromfile, $tofile, $class='BPlusTree') { + function recopy_bplus($fromfile, $tofile, $class = 'BPlusTree') { $fromtree = new $class($fromfile); $fromtree->open; - list($f, $p, $n, $k) = $fromtree->init_params(); - $totree = new $class($tofile, $p, $n, $k); + list ($f, $p, $n, $k) = $fromtree->init_params(); + $totree = new $class($tofile, $p, $n, $k); $totree->startup(); - return BPlusUtils::recopy_tree($fromtree,$totree); + return BPlusUtils::recopy_tree($fromtree, $totree); } function recopy_tree($fromtree, $totree) { - list($f, $p, $n, $k) = $totree->init_params(); - // .... + list ($f, $p, $n, $k) = $totree->init_params(); + // .... } - + } diff --git a/fp-includes/core/core.cache.php b/fp-includes/core/core.cache.php index d499f75..a60553a 100755 --- a/fp-includes/core/core.cache.php +++ b/fp-includes/core/core.cache.php @@ -10,7 +10,7 @@ var $_keysize = 12; // sub-classes will fill the above variables on constructing - function cache_filelister() { + function __construct() { if (!$this->_cachefile) trigger_error('CACHE: no cache file specified', E_USER_ERROR); diff --git a/fp-includes/core/core.comment.php b/fp-includes/core/core.comment.php index d68fc5a..33d468d 100755 --- a/fp-includes/core/core.comment.php +++ b/fp-includes/core/core.comment.php @@ -2,10 +2,10 @@ class comment_indexer extends fs_filelister { - function comment_indexer($id) { + function __construct($id) { $f = bdb_idtofile($id,BDB_COMMENT); //todo change $this->_directory = $f; - parent::fs_filelister(); + parent::__construct(); //substr(bdb_idtofile($id), -strlen(EXT)); } diff --git a/fp-includes/core/core.draft.php b/fp-includes/core/core.draft.php index 52eedb1..b6dbe63 100644 --- a/fp-includes/core/core.draft.php +++ b/fp-includes/core/core.draft.php @@ -1,223 +1,204 @@ _cachefile = CACHE_DIR . 'draft_index.php'; - return parent::fs_filelister(); - } - - - function _checkFile($directory, $file) { - - $f = "$directory/$file"; - if ( is_dir($f) && ctype_digit($file)) { - return 1; - } - - if (fnmatch('entry*'.EXT, $file)) { - $id=basename($file,EXT); - $arr=draft_parse($id); - - //$this->add($id, $arr['subject']); - $this->_list[$id] = $arr['subject']; - - return 0; - } - - } - - } - - function &draft_init() { - global $draftdb; - if (!isset($draftdb)) - $draftdb = new draft_indexer; - return $draftdb; - } - - - function draft_getlist() { - - static $list = array(); - - if (!$list) { - $obj =& draft_init(); - $list = $obj->getList(); - krsort($list); - } - - return $list; - - } - - function draft_parse($id) { - - if ($fname=draft_exists($id)) { - - $entry = io_load_file($fname); - - $entry = utils_kexplode($entry); - if (!isset($entry['categories'])) - $entry['categories'] = array(); - else - $entry['categories'] = explode(',', $entry['categories']); - - return $entry; - } - return array(); +class draft_indexer extends fs_filelister { + + var $_varname = 'cache'; + + var $_cachefile = null; + + var $_directory = DRAFT_DIR; + + function __construct() { + $this->_cachefile = CACHE_DIR . 'draft_index.php'; + return parent::__construct(); } - - function draft_save(&$entry, $id=null, $update_index = false, $update_date=false) { - - if (!$id) { - $id = bdb_idfromtime('entry', $entry['date']); + function _checkFile($directory, $file) { + $f = "$directory/$file"; + if (is_dir($f) && ctype_digit($file)) { + return 1; } - - $ed = entry_dir($id); - $dd = draft_dir($id); - if (file_exists($ed.EXT)) { - - // move collateral files - @rename($ed, $dd); + if (fnmatch('entry*' . EXT, $file)) { + $id = basename($file, EXT); + $arr = draft_parse($id); - if ($update_index) { - // delete normal entry - fs_delete($ed.EXT); + // $this->add($id, $arr['subject']); + $this->_list [$id] = $arr ['subject']; - // remove from normal flow - $o =& entry_init(); - $o->delete($id, null); - } - + return 0; } - - $new_entry = entry_prepare($entry); - if ($new_entry['categories']) - $new_entry['categories']=implode(',', $entry['categories']); - else unset($new_entry['categories']); - - $string = utils_kimplode($new_entry); - + } - if (!io_write_file($dd.EXT, $string)) { - return false; - } else return $id; +} + +function &draft_init() { + global $draftdb; + if (!isset($draftdb)) + $draftdb = new draft_indexer(); + return $draftdb; +} + +function draft_getlist() { + static $list = array(); + + if (!$list) { + $obj = & draft_init(); + $list = $obj->getList(); + krsort($list); + } + + return $list; +} + +function draft_parse($id) { + if ($fname = draft_exists($id)) { + $entry = io_load_file($fname); + + $entry = utils_kexplode($entry); + if (!isset($entry ['categories'])) + $entry ['categories'] = array(); + else + $entry ['categories'] = explode(',', $entry ['categories']); + + return $entry; + } + return array(); +} + +function draft_save(&$entry, $id = null, $update_index = false, $update_date = false) { + if (!$id) { + $id = bdb_idfromtime('entry', $entry ['date']); + } + + $ed = entry_dir($id); + $dd = draft_dir($id); + + if (file_exists($ed . EXT)) { + + // move collateral files + @rename($ed, $dd); + + if ($update_index) { + // delete normal entry + fs_delete($ed . EXT); + + // remove from normal flow + $o = & entry_init(); + $o->delete($id, null); + } + } + + $new_entry = entry_prepare($entry); + if ($new_entry ['categories']) + $new_entry ['categories'] = implode(',', $entry ['categories']); + else + unset($new_entry ['categories']); + + $string = utils_kimplode($new_entry); + + if (!io_write_file($dd . EXT, $string)) { return false; - - } + } else + return $id; - function draft_dir($id) { - if (!preg_match('|^entry[0-9]{6}-[0-9]{6}$|', $id)) - return false; - //$date = date_from_id($id); - //$f = CONTENT_DIR . "{$date['y']}/{$date['m']}/$id"; - return DRAFT_DIR . $id; - //return $f; - - - } - - function draft_exists($id) { - - $dir = draft_dir($id); - if (!$dir) - return false; - - $f = $dir .EXT; - if (file_exists($f)) - return $f; - + return false; +} + +function draft_dir($id) { + if (!preg_match('|^entry[0-9]{6}-[0-9]{6}$|', $id)) return false; - } + // $date = date_from_id($id); + // $f = CONTENT_DIR . "{$date['y']}/{$date['m']}/$id"; + return DRAFT_DIR . $id; + // return $f; +} - function draft_delete($id) { - $dir = draft_dir($id); - - $f=$dir.EXT; - if (!file_exists($f)) - return false; - - //$draftdb =& draft_init(); - //$draftdb->delete($id); - fs_delete_recursive($dir); - - return fs_delete($f); - } +function draft_exists($id) { + $dir = draft_dir($id); + if (!$dir) + return false; - /* - function draft_from_entry($entryid) { - $dir = entry_dir($entryid); - //$dir2 = str_replace('entry', 'draft', $dir); - $dir2 = draft_dir($entryid); - @rename($dir, $dir2); - @rename($dir.EXT, $dir2.EXT); - } - */ + $f = $dir . EXT; + if (file_exists($f)) + return $f; - function draft_to_entry($draftid) { - - $dir = draft_dir($draftid); - $dir2 = entry_dir($draftid); - - @rename($dir, $dir2); - draft_delete($draftid); - } - - - function smarty_block_draftlist($params, $content, &$smarty, &$repeat) { - global $fpdb; - - if ($list = draft_getlist()) { - $smarty->assign('draft_list', $list); - return $content; - } - - } - - - function smarty_block_draft($params, $content, &$smarty, &$repeat) { - - static $list = array(); - - $smarty->assign(array( 'subject'=>'', - 'content'=>'', - 'date'=>'', - 'author'=>'', - 'version'=>'', - 'id'=>'' - ) - ); - $arr =& $smarty->get_template_vars('draft_list'); - - $id = $subject = null; - if ($arr) - list($id, $subject)=each($arr); - - if ($id){ - $smarty->assign('subject', $subject); - $smarty->assign('id', $id); - } - - $repeat = (bool) $id; + return false; +} - return $content; +function draft_delete($id) { + $dir = draft_dir($id); + + $f = $dir . EXT; + if (!file_exists($f)) + return false; + + // $draftdb =& draft_init(); + // $draftdb->delete($id); + fs_delete_recursive($dir); + + return fs_delete($f); +} + +/* + * function draft_from_entry($entryid) { + * $dir = entry_dir($entryid); + * //$dir2 = str_replace('entry', 'draft', $dir); + * $dir2 = draft_dir($entryid); + * @rename($dir, $dir2); + * @rename($dir.EXT, $dir2.EXT); + * } + */ +function draft_to_entry($draftid) { + $dir = draft_dir($draftid); + $dir2 = entry_dir($draftid); + + @rename($dir, $dir2); + draft_delete($draftid); +} + +function smarty_block_draftlist($params, $content, &$smarty, &$repeat) { + global $fpdb; + + if ($list = draft_getlist()) { + $smarty->assign('draft_list', $list); + return $content; + } +} + +function smarty_block_draft($params, $content, &$smarty, &$repeat) { + static $list = array(); + + $smarty->assign(array( + 'subject' => '', + 'content' => '', + 'date' => '', + 'author' => '', + 'version' => '', + 'id' => '' + )); + $arr = & $smarty->get_template_vars('draft_list'); + + $id = $subject = null; + if ($arr) { + $firstElement = utils_array_kshift($arr); + $id = array_keys($firstElement) [0]; + $subject = $firstElement [$id]; } + if ($id) { + $smarty->assign('subject', $subject); + $smarty->assign('id', $id); + } + $repeat = (bool) $id; - $smarty->register_block('draft_block', 'smarty_block_draftlist'); - $smarty->register_block('draft', 'smarty_block_draft'); + return $content; +} +$smarty->register_block('draft_block', 'smarty_block_draftlist'); +$smarty->register_block('draft', 'smarty_block_draft'); ?> diff --git a/fp-includes/core/core.entry.php b/fp-includes/core/core.entry.php index 678a85d..64777cf 100755 --- a/fp-includes/core/core.entry.php +++ b/fp-includes/core/core.entry.php @@ -1,872 +1,818 @@ position, - $this->nodesize, - $this->keylen - ); - - $this->open(); - } - - } - - class entry_index { - - var $indices = array(); - var $_offset = 0; - var $_chunksize = 30; - var $_keysize = 12; - - var $_lock_file = null; - - - function entry_index() { - $this->_lock_file = CACHE_DIR.'bpt.lock'; - - $this->catlist = entry_categories_list(); - - // only main index s a SBPlus (string BPlus): - // the other (other categories) are managed - // as if they were simple BPlus trees, so - // values in key,value pairs won't - // be strings but integers - // - // the integer will be the seek position - // in the SBPlus' string file - // - // they'll be loaded back with the string file - // as SBPlus trees: the string-key, string-value pair - // will be returned - - if ($oldfile = file_exists($f=INDEX_DIR.'index-0.dat')) - $mode = 'r+b'; - else - $mode = 'w+b'; - - $this->indices[0] = new SBPlusTree( - fopen($f, $mode), - fopen(INDEX_DIR.'index.strings.dat', $mode), - 256, - $this->_offset, - $this->_chunksize, - $this->_keysize - ); - - if ($oldfile) - $this->indices[0]->open(); - else - $this->indices[0]->startup(); - - - } - - function _lock_acquire($exclusive=true, $cat=0) { - if (file_exists($this->_lock_file)) { - trigger_error("Could not acquire write lock on INDEX. ". - "Didn't I told you FlatPress is not designed for concurrency, already? ;) ". - "Don't worry: your entry has been saved as draft!", E_USER_WARNING); - return false; - } - - // simulates atomic write by writing to a file, then moving in place - $tmp = $this->_lock_file.".tmp"; - if (io_write_file($tmp, 'dummy')) { - if (rename($tmp, $this->_lock_file)) { - return true; - } - } - - return false; - - } - - function _lock_release($cat=0) { - if (file_exists($this->_lock_file)) { - return @unlink($this->_lock_file); - } else { - trigger_error("Lock file did not exist: ignoring (index was already unlocked.)", E_USER_NOTICE); - return 2; - } - - } - - function &get_index($cat=0) { - if (!is_numeric($cat)) - trigger_error("CAT must be an integer ($cat was given)", E_USER_ERROR); - if (!isset($this->indices[$cat])) { - $f = INDEX_DIR.'index-'.$cat.'.dat'; - if ($oldfile = file_exists($f)) - $mode = 'r+b'; - else $mode = 'w+b'; - - $this->indices[$cat] = new BPlusTree( - fopen($f, $mode), - $this->_offset, - $this->_chunksize, - $this->_keysize - ); - if ($oldfile) - $this->indices[$cat]->open(); - else $this->indices[$cat]->startup(); - } - return $this->indices[$cat]; - } - - function add($id, $entry, $del = array(), $update_title = true) { - $key = entry_idtokey($id); - $val = $entry['subject']; - - if (!$this->_lock_acquire()) return false; // we're DOOMED! - - $main =& $this->get_index(); - $seek = null; - - // title must not be updated, let's get the offset value from has_key - if (!$update_title) - $seek = $main->has_key($key, $val); - - // if seek is null, then there is no such key, and we must set it - // in the main index - if (!is_numeric($seek)) - $seek = $main->setitem($key, $val); - - // key has been set, let's set the other indices (if any), and link them - // to the title string using $seek - - if (isset($entry['categories']) && is_array($entry['categories'])) { - - $categories = array(); - - foreach ($entry['categories'] as $cat) { - - // skip non-numeric special categories (such as 'draft') - if (!is_numeric($cat)) continue; - - $categories[] = $cat; - - // traverse the full cat tree (in linearized form) - // to update categories which eventually aren't - // explicitly listed - while ($parent = $this->catlist[ $cat ]) { - $categories[] = $parent; - $cat = $parent; - } - } - - // delete any duplicate - $categories = array_unique($categories); - - foreach ($categories as $cat) { - $this_index =& $this->get_index($cat); - $this_index->setitem($key, $seek); - } - } - - // if the set of indices changed, some might have to be deleted - if ($del) { - foreach($del as $cat) { - // echo 'DEL '. $cat,"\n"; - if (!is_numeric($cat)) continue; - $this_index =& $this->get_index($cat); - $this_index->delitem($key); - } - } - - return $this->_lock_release(); - - } - - function delete($id, $entry) { - $key = entry_idtokey($id); - - if (!$this->_lock_acquire()) return false; // we're DOOMED! - - $main =& $this->get_index(); - $main->delitem($key); - - - if (isset($entry['categories']) && is_array($entry['categories'])) { - foreach ($entry['categories'] as $cat) { - if (!is_numeric($cat)) continue; - $this_index =& $this->get_index($cat); - if ($this_index->has_key($key)) - $this_index->delitem($key); - } - } - - return $this->_lock_release(); - - } - - } - - class entry_archives extends fs_filelister { - - var $_directory = CONTENT_DIR; - var $_y = null; - var $_m = null; - var $_d = null; - - var $_count = 0; - - var $_filter = 'entry*'; - - function entry_archives($y, $m = null, $d = null) { - - $this->_y = $y; - $this->_m = $m; - $this->_d = $d; - - $this->_directory .= "$y/"; - - if ($m){ - - $this->_directory .= "$m/"; - - if ($d) { - $this->_filter = "entry$y$m$d*"; - } - - } - - return parent::fs_filelister(); - } - - function _checkFile($directory, $file) { - $f = "$directory/$file"; - if ( is_dir($f) && ctype_digit($file)) { - return 1; - } - - if (fnmatch($this->_filter.EXT, $file)) { - $id=basename($file,EXT); - $this->_count++; - array_push($this->_list, $id); - return 0; - } - } - - function getList() { - rsort($this->_list); - return parent::getList(); - } - - function getCount() { - return $this->_count; - } - - } - - /* //work in progress - class entry { - - var $_indexer; - var $id; - - function entry($id, $content) { - //$this->_indexer =& $indexer; - } - - function get($field) { - $field = strtolower($field); - if (!isset($this->$field)) { - // if it is not set - // tries to fetch from the database - $arr = entry_parse($id); - while(list($field, $val) = each($arr)) - $this->$field = $val; - - // if still is not set raises an error - if (!isset($this->$field)) - trigger_error("$field is not set", E_USER_NOTICE); - return; - - - } - - return $this->$field; - - } - - function set($field, $val) { - $field = strtolower($field); - $this->$field = $val; - } - - } - */ - /** - * function entry_init - * fills the global array containing the entry object - */ - function &entry_init() { - - #global $fpdb; - #$fpdb->init(); - - static $entry_index = null; - - if (is_null($entry_index)) - $entry_index= new entry_index; - - return $entry_index; - - } - - function &entry_cached_index($id_cat) { - - $F = INDEX_DIR.'index-'.$id_cat.'.dat'; + * opens the index belonging to a given category + * + * @params int $id_cat + */ + function __construct($id_cat = 0) { + $F = INDEX_DIR . 'index-' . $id_cat . '.dat'; if (!file_exists($F)) { - $o = false; - } else { - $o = new entry_cached_index($id_cat); + trigger_error("Can't find index '{$F}'", E_USER_ERROR); } - - return $o; - + + parent::__construct(fopen($F, 'rb'), fopen(INDEX_DIR . 'index.strings.dat', 'rb'), 256, $this->position, $this->nodesize, $this->keylen); + + $this->open(); } - - - /* - function entry_query($params=array()){ - - global $fpdb; - $queryid = $fpdb->query($params); - $fpdb->doquery($queryid); - - - } - - function entry_hasmore() { - global $fpdb; - return $fpdb->hasmore(); - - } - - function entry_get() { - $fpdb->get(); - } - */ - - function entry_keytoid($key) { - $date = substr($key,0,6); - $time = substr($key,6); - return "entry{$date}-{$time}"; - } - - function entry_idtokey($id) { - return substr($id, 5, 6) . substr($id, 12); - } - - function entry_timetokey($time) { - return date('ymdHis', $time); - } - - function entry_keytotime($key) { - $arr[ 'y' ] = substr($key, 0, 2); - $arr[ 'm' ] = substr($key, 2, 2); - $arr[ 'd' ] = substr($key, 4, 2); - - $arr[ 'H' ] = substr($key, 6, 2); - $arr[ 'M' ] = substr($key, 8, 2); - $arr[ 'S' ] = substr($key, 10, 2); - - return mktime($arr['H'], $arr['M'], $arr['S'], - $arr['m'], $arr['d'], $arr['y']); - } - - function entry_idtotime($id) { - $date = date_from_id($id); - return $date['time']; - } - - function entry_list() { - - trigger_error('function deprecated', E_USER_ERROR); - - $obj =& entry_init(); - - $entry_arr = $obj->getList(); - - - if ($entry_arr) { - krsort($entry_arr); - return $entry_arr; - } - } - - function entry_exists($id) { - $f = entry_dir($id).EXT; - return file_exists($f)? $f : false; - } - - function entry_dir($id, $month_only = false) { - if (!preg_match('|^entry[0-9]{6}-[0-9]{6}$|', $id)) - return false; - $date = date_from_id($id); - if ($month_only) - $f = CONTENT_DIR . "{$date['y']}/{$date['m']}/"; - else - $f = CONTENT_DIR . "{$date['y']}/{$date['m']}/$id"; - return $f; - - - } - - function entry_parse($id, $raw=false) { - - $f = entry_exists($id); - if (!$f) - return array(); - - $fc = io_load_file($f); - - if (!$fc) - return array(); - - $arr = utils_kexplode($fc); - - // propagates the error if entry does not exist - - - if (isset($arr['categories']) && // fix to bad old behaviour: - (trim($arr['categories']) != '')) { - - - $cats = (array)explode(',',$arr['categories']); - $arr['categories'] = (array) $cats; - - - - } else $arr['categories'] = array(); - - // if (!is_array($arr['categories'])) die(); - - if (!isset($arr['AUTHOR'])) { - global $fp_config; - $arr['AUTHOR'] = $fp_config['general']['author']; - } - - if ($raw) return $arr; - return $arr; - - } - - - /** - * function entry_get_comments - * - * @param string id entry id - * @param array entry entry content array by ref; 'commentcount' field is added to the array - * - * @return object comment_indexer as reference - * - */ - - function &entry_get_comments($id, &$count) { - $obj = new comment_indexer($id); - - $count = count($obj->getList()); - - return $obj; - - } - - - function entry_categories_encode($cat_file) { - - - //if ($string = io_load_file(CONTENT_DIR . 'categories.txt')) { - $lines = explode("\n", trim($cat_file)); - $idstack = $result = $indentstack=array(); - - while (!empty($lines)) { - - $v = array_pop($lines); - - $vt = trim($v); - - if ($vt) { - - $text=''; - $indent = utils_countdashes($vt, $text); - - $val = explode(':', $text); - - $id = trim($val[1]); - $label = trim($val[0]); - - // IDs must be strictly positive - - if ($label && $id <= 0) return -1; - - - - if (empty($indentstack)) { - array_push($indentstack,$indent); - array_push($idstack, $id); - $indent_old = $indent; - } else { - $indent_old = end($indentstack); - } - - if ($indent < $indent_old) { - array_push($indentstack, $indent); - array_push($idstack, $id); - } elseif ($indent > $indent_old) { - $idstack = array($id); - $indentstack = array($indent); - } else { - array_pop($idstack); - $idstack = array($id); - } - - - - $result['rels'][$id] = $idstack; - $result['defs'][$id] = $label; - } - - } - - ksort($result['rels']); - ksort($result['defs']); - - //print_r($result); - - return io_write_file(CONTENT_DIR . 'categories_encoded.dat', serialize($result)); - - //} - - return false; - - - } - - /* - - function entry_categories_print(&$lines, &$indentstack, &$result, $params) { - } -*/ - function entry_categories_list() { - if (!$string = io_load_file(CONTENT_DIR . 'categories.txt')) +class entry_index { + + var $indices = array(); + + var $_offset = 0; + + var $_chunksize = 30; + + var $_keysize = 12; + + var $_lock_file = null; + + function __construct() { + $this->_lock_file = CACHE_DIR . 'bpt.lock'; + + $this->catlist = entry_categories_list(); + + // only main index s a SBPlus (string BPlus): + // the other (other categories) are managed + // as if they were simple BPlus trees, so + // values in key,value pairs won't + // be strings but integers + // + // the integer will be the seek position + // in the SBPlus' string file + // + // they'll be loaded back with the string file + // as SBPlus trees: the string-key, string-value pair + // will be returned + + if ($oldfile = file_exists($f = INDEX_DIR . 'index-0.dat')) + $mode = 'r+b'; + else + $mode = 'w+b'; + + $this->indices [0] = new SBPlusTree(fopen($f, $mode), fopen(INDEX_DIR . 'index.strings.dat', $mode), 256, $this->_offset, $this->_chunksize, $this->_keysize); + + if ($oldfile) + $this->indices [0]->open(); + else + $this->indices [0]->startup(); + } + + function _lock_acquire($exclusive = true, $cat = 0) { + if (file_exists($this->_lock_file)) { + trigger_error("Could not acquire write lock on INDEX. " . "Didn't I told you FlatPress is not designed for concurrency, already? ;) " . "Don't worry: your entry has been saved as draft!", E_USER_WARNING); return false; - - $lines = explode("\n", trim($string)); - $idstack = array(0); - $indentstack=array(); - - - // $categories = array(0=>null); - $lastindent = 0; - $lastid = 0; - $parent = 0; - - $NEST = 0; - - foreach ($lines as $v) { - - $vt = trim($v); - - if (!$vt) continue; - - $text=''; - $indent = utils_countdashes($vt, $text); - - $val = explode(':', $text); - - $id = trim($val[1]); - $label = trim($val[0]); - - // echo "PARSE: $id:$label\n"; - if ($indent > $lastindent) { - // echo "INDENT ($indent, $id, $lastid)\n"; - $parent = $lastid; - array_push($indentstack, $lastindent); - array_push($idstack, $lastid); - $lastindent = $indent; - $NEST++; - } elseif ($indent < $lastindent) { - // echo "DEDENT ($indent)\n"; - do { - $dedent = array_pop($indentstack); - array_pop($idstack); - $NEST--; - } while ($dedent > $indent); - if ($dedent < $indent) return false; //trigger_error("failed parsing ($dedent<$indent)", E_USER_ERROR); - $parent = end($idstack); - $lastindent = $indent; - $lastid = $id; - } - - $lastid = $id; - // echo "NEST: $NEST\n"; - - - $categories[ $id ] = $parent; - + } + + // simulates atomic write by writing to a file, then moving in place + $tmp = $this->_lock_file . ".tmp"; + if (io_write_file($tmp, 'dummy')) { + if (rename($tmp, $this->_lock_file)) { + return true; } - - return $categories; - + } + + return false; } - function entry_categories_get($what=null) { - - global $fpdb; - - $categories = array(); - - if (!empty($fpdb->_categories)) { - $categories = $fpdb->_categories; - } else { + function _lock_release($cat = 0) { + if (file_exists($this->_lock_file)) { + return @unlink($this->_lock_file); + } else { + trigger_error("Lock file did not exist: ignoring (index was already unlocked.)", E_USER_NOTICE); + return 2; + } + } + + function &get_index($cat = 0) { + if (!is_numeric($cat)) + trigger_error("CAT must be an integer ($cat was given)", E_USER_ERROR); + if (!isset($this->indices [$cat])) { + $f = INDEX_DIR . 'index-' . $cat . '.dat'; + if ($oldfile = file_exists($f)) + $mode = 'r+b'; + else + $mode = 'w+b'; - $f = CONTENT_DIR . 'categories_encoded.dat'; - if (file_exists($f)) { - if ($c = io_load_file($f)) - $categories = unserialize($c); + $this->indices [$cat] = new BPlusTree(fopen($f, $mode), $this->_offset, $this->_chunksize, $this->_keysize); + if ($oldfile) + $this->indices [$cat]->open(); + else + $this->indices [$cat]->startup(); + } + return $this->indices [$cat]; + } + + function add($id, $entry, $del = array(), $update_title = true) { + $key = entry_idtokey($id); + $val = $entry ['subject']; + + if (!$this->_lock_acquire()) + return false; // we're DOOMED! + + $main = & $this->get_index(); + $seek = null; + + // title must not be updated, let's get the offset value from has_key + if (!$update_title) + $seek = $main->has_key($key, $val); + + // if seek is null, then there is no such key, and we must set it + // in the main index + if (!is_numeric($seek)) + $seek = $main->setitem($key, $val); + + // key has been set, let's set the other indices (if any), and link them + // to the title string using $seek + + if (isset($entry ['categories']) && is_array($entry ['categories'])) { + + $categories = array(); + + foreach ($entry ['categories'] as $cat) { + + // skip non-numeric special categories (such as 'draft') + if (!is_numeric($cat)) + continue; + + $categories [] = $cat; + + // traverse the full cat tree (in linearized form) + // to update categories which eventually aren't + // explicitly listed + while ($parent = $this->catlist [$cat]) { + $categories [] = $parent; + $cat = $parent; + } } + // delete any duplicate + $categories = array_unique($categories); + + foreach ($categories as $cat) { + $this_index = & $this->get_index($cat); + $this_index->setitem($key, $seek); + } } - if ($categories) { - - if ($what=='defs' || $what=='rels') - return $categories[$what]; - else - return $categories; + // if the set of indices changed, some might have to be deleted + if ($del) { + foreach ($del as $cat) { + // echo 'DEL '. $cat,"\n"; + if (!is_numeric($cat)) + continue; + $this_index = & $this->get_index($cat); + $this_index->delitem($key); + } } + + return $this->_lock_release(); + } + + function delete($id, $entry) { + $key = entry_idtokey($id); + + if (!$this->_lock_acquire()) + return false; // we're DOOMED! + + $main = & $this->get_index(); + $main->delitem($key); + + if (isset($entry ['categories']) && is_array($entry ['categories'])) { + foreach ($entry ['categories'] as $cat) { + if (!is_numeric($cat)) + continue; + $this_index = & $this->get_index($cat); + if ($this_index->has_key($key)) + $this_index->delitem($key); + } + } + + return $this->_lock_release(); + } + +} + +class entry_archives extends fs_filelister { + + var $_directory = CONTENT_DIR; + + var $_y = null; + + var $_m = null; + + var $_d = null; + + var $_count = 0; + + var $_filter = 'entry*'; + + function __construct($y, $m = null, $d = null) { + $this->_y = $y; + $this->_m = $m; + $this->_d = $d; + + $this->_directory .= "$y/"; + + if ($m) { + + $this->_directory .= "$m/"; + + if ($d) { + $this->_filter = "entry$y$m$d*"; + } + } + + return parent::__construct(); + } + + function _checkFile($directory, $file) { + $f = "$directory/$file"; + if (is_dir($f) && ctype_digit($file)) { + return 1; + } + + if (fnmatch($this->_filter . EXT, $file)) { + $id = basename($file, EXT); + $this->_count++; + array_push($this->_list, $id); + return 0; + } + } + + function getList() { + rsort($this->_list); + return parent::getList(); + } + + function getCount() { + return $this->_count; + } + +} + +// //work in progress +// class entry { + +// var $_indexer; +// var $id; + +// function entry($id, $content) { +// //$this->_indexer =& $indexer; +// } + +// function get($field) { +// $field = strtolower($field); +// if (!isset($this->$field)) { +// // if it is not set +// // tries to fetch from the database +// $arr = entry_parse($id); +// while(list($field, $val) = each($arr)) +// $this->$field = $val; + +// // if still is not set raises an error +// if (!isset($this->$field)) +// trigger_error("$field is not set", E_USER_NOTICE); +// return; + +// } + +// return $this->$field; + +// } + +// function set($field, $val) { +// $field = strtolower($field); +// $this->$field = $val; +// } + +// } + +/** + * function entry_init + * fills the global array containing the entry object + */ +function &entry_init() { + + // global $fpdb; + // $fpdb->init(); + static $entry_index = null; + + if (is_null($entry_index)) + $entry_index = new entry_index(); + + return $entry_index; +} + +function &entry_cached_index($id_cat) { + $F = INDEX_DIR . 'index-' . $id_cat . '.dat'; + + if (!file_exists($F)) { + $o = false; + } else { + $o = new entry_cached_index($id_cat); + } + + return $o; +} + +/* + * function entry_query($params=array()){ + * + * global $fpdb; + * $queryid = $fpdb->query($params); + * $fpdb->doquery($queryid); + * + * + * } + * + * function entry_hasmore() { + * global $fpdb; + * return $fpdb->hasmore(); + * + * } + * + * function entry_get() { + * $fpdb->get(); + * } + */ +function entry_keytoid($key) { + $date = substr($key, 0, 6); + $time = substr($key, 6); + return "entry{$date}-{$time}"; +} + +function entry_idtokey($id) { + return substr($id, 5, 6) . substr($id, 12); +} + +function entry_timetokey($time) { + return date('ymdHis', $time); +} + +function entry_keytotime($key) { + $arr ['y'] = substr($key, 0, 2); + $arr ['m'] = substr($key, 2, 2); + $arr ['d'] = substr($key, 4, 2); + + $arr ['H'] = substr($key, 6, 2); + $arr ['M'] = substr($key, 8, 2); + $arr ['S'] = substr($key, 10, 2); + + return mktime($arr ['H'], $arr ['M'], $arr ['S'], $arr ['m'], $arr ['d'], $arr ['y']); +} + +function entry_idtotime($id) { + $date = date_from_id($id); + return $date ['time']; +} + +function entry_list() { + trigger_error('function deprecated', E_USER_ERROR); + + $obj = & entry_init(); + + $entry_arr = $obj->getList(); + + if ($entry_arr) { + krsort($entry_arr); + return $entry_arr; + } +} + +function entry_exists($id) { + $f = entry_dir($id) . EXT; + return file_exists($f) ? $f : false; +} + +function entry_dir($id, $month_only = false) { + if (!preg_match('|^entry[0-9]{6}-[0-9]{6}$|', $id)) + return false; + $date = date_from_id($id); + if ($month_only) + $f = CONTENT_DIR . "{$date['y']}/{$date['m']}/"; + else + $f = CONTENT_DIR . "{$date['y']}/{$date['m']}/$id"; + return $f; +} + +function entry_parse($id, $raw = false) { + $f = entry_exists($id); + if (!$f) return array(); + + $fc = io_load_file($f); + + if (!$fc) + return array(); + + $arr = utils_kexplode($fc); + + // propagates the error if entry does not exist + + if (isset($arr ['categories']) && // fix to bad old behaviour: + (trim($arr ['categories']) != '')) { + + $cats = (array) explode(',', $arr ['categories']); + $arr ['categories'] = (array) $cats; + } else + $arr ['categories'] = array(); + + // if (!is_array($arr['categories'])) die(); + + if (!isset($arr ['AUTHOR'])) { + global $fp_config; + $arr ['AUTHOR'] = $fp_config ['general'] ['author']; } - /** - - flags are actually special categories - which are usually hidden. - - they can be set when editing your entries - to let flatpress perform special actions - - draft: Draft entry (hidden, awaiting publication) - static: Static entry (allows saving an alias, so you can reach it with - ?page=myentry) - commslock: Comments locked (comments disallowed for this entry) - - - */ + if ($raw) + return $arr; + return $arr; +} + +/** + * function entry_get_comments + * + * @param + * string id entry id + * @param + * array entry entry content array by ref; 'commentcount' field is added to the array + * + * @return object comment_indexer as reference + * + */ +function &entry_get_comments($id, &$count) { + $obj = new comment_indexer($id); - function entry_flags_get() { - - return array( - 'draft', - //'static', - 'commslock' - ); + $count = count($obj->getList()); + + return $obj; +} + +function entry_categories_encode($cat_file) { + + // if ($string = io_load_file(CONTENT_DIR . 'categories.txt')) { + $lines = explode("\n", trim($cat_file)); + $idstack = $result = $indentstack = array(); + + while (!empty($lines)) { + $v = array_pop($lines); - } - - // @TODO : check against schema ? - function entry_prepare(&$entry) { // prepare for serialization - global $post; + $vt = trim($v); - // fill in missing value - if (!isset($entry['date'])) { - $entry['date']=date_time(); - } - - // import into global scope - $post = $entry; - - // apply *_pre filters - $entry['content'] = apply_filters('content_save_pre', $entry['content']); - $entry['subject'] = apply_filters('title_save_pre', $entry['subject']); - - - // prepare for serialization - if (isset($entry['categories'])) { - - if (!is_array($entry['categories'])) { - trigger_error("Expected 'categories' to be an array, found " - . gettype($entry['categories']), E_USER_WARNING); - $entry['categories'] = array(); + if ($vt) { + + $text = ''; + $indent = utils_countdashes($vt, $text); + + $val = explode(':', $text); + + $id = trim($val [1]); + $label = trim($val [0]); + + // IDs must be strictly positive + + if ($label && $id <= 0) + return -1; + + if (empty($indentstack)) { + array_push($indentstack, $indent); + array_push($idstack, $id); + $indent_old = $indent; + } else { + $indent_old = end($indentstack); } - - } else { $entry['categories'] = array(); } - - - - return $entry; + + if ($indent < $indent_old) { + array_push($indentstack, $indent); + array_push($idstack, $id); + } elseif ($indent > $indent_old) { + $idstack = array( + $id + ); + $indentstack = array( + $indent + ); + } else { + array_pop($idstack); + $idstack = array( + $id + ); + } + + $result ['rels'] [$id] = $idstack; + $result ['defs'] [$id] = $label; + } } + + ksort($result ['rels']); + ksort($result ['defs']); + + // print_r($result); + + return io_write_file(CONTENT_DIR . 'categories_encoded.dat', serialize($result)); + + // } + + return false; +} - /** - * - * @param array entry contents - * @param string|null entry id, null if can be deducted from the date field of $entry; - * defaults to null - * - * @param bool updates entry index; defaults to true - * - * - * @return integer -1 failure while storing preliminar draft, abort. Index not touched. - * -2 index updated succesfully, but draft doesn't exist anymore - * (should never happen!) OR - * failure while trying to move draft to entry path, draft does not exist anymore - * index not touched - * -3 error while moving draft still exists, index written succesfully but rolled back - * -4 failure while saving to index, aborted (draft still exists) - * - * +/* + * + * function entry_categories_print(&$lines, &$indentstack, &$result, $params) { + * + * + * } + * + */ +function entry_categories_list() { + if (!$string = io_load_file(CONTENT_DIR . 'categories.txt')) + return false; + + $lines = explode("\n", trim($string)); + $idstack = array( + 0 + ); + $indentstack = array(); + + // $categories = array(0=>null); + $lastindent = 0; + $lastid = 0; + $parent = 0; + + $NEST = 0; + + foreach ($lines as $v) { + + $vt = trim($v); + + if (!$vt) + continue; + + $text = ''; + $indent = utils_countdashes($vt, $text); + + $val = explode(':', $text); + + $id = trim($val [1]); + $label = trim($val [0]); + + // echo "PARSE: $id:$label\n"; + if ($indent > $lastindent) { + // echo "INDENT ($indent, $id, $lastid)\n"; + $parent = $lastid; + array_push($indentstack, $lastindent); + array_push($idstack, $lastid); + $lastindent = $indent; + $NEST++; + } elseif ($indent < $lastindent) { + // echo "DEDENT ($indent)\n"; + do { + $dedent = array_pop($indentstack); + array_pop($idstack); + $NEST--; + } while ($dedent > $indent); + if ($dedent < $indent) + return false; // trigger_error("failed parsing ($dedent<$indent)", E_USER_ERROR); + $parent = end($idstack); + $lastindent = $indent; + $lastid = $id; + } + + $lastid = $id; + // echo "NEST: $NEST\n"; + + $categories [$id] = $parent; + } + + return $categories; +} + +function entry_categories_get($what = null) { + global $fpdb; + + $categories = array(); + + if (!empty($fpdb->_categories)) { + $categories = $fpdb->_categories; + } else { + + $f = CONTENT_DIR . 'categories_encoded.dat'; + if (file_exists($f)) { + if ($c = io_load_file($f)) + $categories = unserialize($c); + } + } + + if ($categories) { + + if ($what == 'defs' || $what == 'rels') + return $categories [$what]; + else + return $categories; + } + return array(); +} + +/** + * flags are actually special categories + * which are usually hidden. + * + * they can be set when editing your entries + * to let flatpress perform special actions + * + * draft: Draft entry (hidden, awaiting publication) + * static: Static entry (allows saving an alias, so you can reach it with + * ?page=myentry) + * commslock: Comments locked (comments disallowed for this entry) + */ +function entry_flags_get() { + return array( + 'draft', + // 'static', + 'commslock' + ); +} + +// @TODO : check against schema ? +function entry_prepare(&$entry) { // prepare for serialization + global $post; + + // fill in missing value + if (!isset($entry ['date'])) { + $entry ['date'] = date_time(); + } + + // import into global scope + $post = $entry; + + // apply *_pre filters + $entry ['content'] = apply_filters('content_save_pre', $entry ['content']); + $entry ['subject'] = apply_filters('title_save_pre', $entry ['subject']); + + // prepare for serialization + if (isset($entry ['categories'])) { + + if (!is_array($entry ['categories'])) { + trigger_error("Expected 'categories' to be an array, found " . gettype($entry ['categories']), E_USER_WARNING); + $entry ['categories'] = array(); + } + } else { + $entry ['categories'] = array(); + } + + return $entry; +} + +/** + * + * @param + * array entry contents + * @param + * string|null entry id, null if can be deducted from the date field of $entry; + * defaults to null + * + * @param + * bool updates entry index; defaults to true + * + * + * @return integer -1 failure while storing preliminar draft, abort. Index not touched. + * -2 index updated succesfully, but draft doesn't exist anymore + * (should never happen!) OR + * failure while trying to move draft to entry path, draft does not exist anymore + * index not touched + * -3 error while moving draft still exists, index written succesfully but rolled back + * -4 failure while saving to index, aborted (draft still exists) + * + * + */ +function entry_save($entry, $id = null, $update_index = true) { + + // PHASE 1 : prepare entry + if (!$id) { + if (!@$entry ['date']) + $entry ['date'] = date_time(); + $id = bdb_idfromtime(BDB_ENTRY, $entry ['date']); + } + + // PHASE 2 : Store + + // secure data as DRAFT + // (entry is also implicitly entry_prepare()'d here) + $ret = draft_save($entry, $id); + do_action('publish_post', $id, $entry); + + if ($ret === false) { + return -1; // FAILURE: ABORT + } + + // PHASE 3 : Update index + $delete_cats = array(); + $all_cats = @$entry ['categories']; + $update_title = true; + if ($old_entry = entry_parse($id)) { + if ($all_cats) { + $delete_cats = array_diff($old_entry ['categories'], $all_cats); + } + $all_cats = $all_cats ? array_merge($all_cats, $old_entry ['categories']) : $old_entry ['categories']; + $update_title = $entry ['subject'] != $old_entry ['subject']; + } + + /* + * echo 'old'; + * print_r($old_entry['categories']); + * echo 'new'; + * print_r($entry['categories']); + * echo 'del'; + * print_r($delete_cats); + * echo 'all'; + * print_r($all_cats); */ + + $INDEX = & entry_init(); + $ok = ($update_index) ? $INDEX->add($id, $entry, $delete_cats, $update_title) : true; + + // PHASE 4 : index updated; let's move back the entry + if ($ok) { - function entry_save($entry, $id=null, $update_index = true) { - - // PHASE 1 : prepare entry - if (!$id) { - if (!@$entry['date']) $entry['date'] = date_time(); - $id = bdb_idfromtime(BDB_ENTRY, $entry['date']); - } - - - // PHASE 2 : Store - - // secure data as DRAFT - // (entry is also implicitly entry_prepare()'d here) - $ret = draft_save($entry, $id); - do_action('publish_post', $id, $entry); - - if ($ret === false) { - return -1; // FAILURE: ABORT - } - - - // PHASE 3 : Update index - $delete_cats = array(); - $all_cats = @$entry['categories']; - $update_title = true; - if ($old_entry = entry_parse($id)) { - if ($all_cats) { - $delete_cats = array_diff($old_entry['categories'], $all_cats); + $entryd = entry_dir($id, true); + $entryf = $entryd . $id . EXT; + $draftf = draft_exists($id); + if ($draftf === false) { // this should never happen! + if ($update_index) { + $INDEX->delete($id, $all_cats); } - $all_cats = $all_cats? array_merge($all_cats, $old_entry['categories']) : $old_entry['categories']; - $update_title = $entry['subject'] != $old_entry['subject']; - } - - /* - echo 'old'; - print_r($old_entry['categories']); - echo 'new'; - print_r($entry['categories']); - echo 'del'; - print_r($delete_cats); - echo 'all'; - print_r($all_cats); - */ - - $INDEX =& entry_init(); - $ok = ($update_index) ? $INDEX->add($id, $entry, $delete_cats, $update_title) : true; - - // PHASE 4 : index updated; let's move back the entry - if ($ok) { - - $entryd = entry_dir($id, true); - $entryf = $entryd.$id.EXT; - $draftf = draft_exists($id); - if ($draftf === false) { // this should never happen! + return -2; + } + + fs_delete($entryf); + fs_mkdir($entryd); + $ret = rename($draftf, $entryf); + + if (!$ret) { + if (draft_exists($id)) { + // rollback changes in the index + // (keep the draft file) if ($update_index) { - $INDEX->delete($id, $all_cats); + $INDEX->delete($id, $all_cats); } + return -3; + } else { return -2; } - - fs_delete($entryf); - fs_mkdir($entryd); - $ret = rename($draftf, $entryf); + } else { + // SUCCESS : delete draft, move comments along + draft_to_entry($id); + return $id; + } + } + return -4; +} - if (!$ret) { - if (draft_exists($id)) { - // rollback changes in the index - // (keep the draft file) - if ($update_index) { - $INDEX->delete($id, $all_cats); - } - return -3; - } else { - return -2; - } - } else { - // SUCCESS : delete draft, move comments along - draft_to_entry($id); - return $id; - } - - } - return -4; - - } +function entry_delete($id) { + if (!$f = entry_exists($id)) + return; + + /* + * $d = bdb_idtofile($id,BDB_COMMENT); + * fs_delete_recursive("$d"); + * + * // thanks to cimangi for noticing this + * $f = dirname($d) . '/view_counter' .EXT; + * fs_delete($f); + * + * + * $f = bdb_idtofile($id); + */ + + $d = entry_dir($id); + fs_delete_recursive($d); + + $obj = & entry_init(); + $obj->delete($id, entry_parse($id)); + + do_action('delete_post', $id); + + return fs_delete($f); +} - - function entry_delete($id) { - - if ( ! $f = entry_exists($id) ) - return; - - - /* - $d = bdb_idtofile($id,BDB_COMMENT); - fs_delete_recursive("$d"); - - // thanks to cimangi for noticing this - $f = dirname($d) . '/view_counter' .EXT; - fs_delete($f); - - - $f = bdb_idtofile($id); - */ - - $d = entry_dir($id); - fs_delete_recursive($d); - - $obj =& entry_init(); - $obj->delete($id, entry_parse($id)); - - do_action('delete_post', $id); - - return fs_delete($f); - } - - function entry_purge_cache() { - $obj =& entry_init(); - $obj->purge(); - } - //add_action('init', +function entry_purge_cache() { + $obj = & entry_init(); + $obj->purge(); +} +// add_action('init', ?> diff --git a/fp-includes/core/core.filesystem.php b/fp-includes/core/core.filesystem.php index 36b936c..219296d 100755 --- a/fp-includes/core/core.filesystem.php +++ b/fp-includes/core/core.filesystem.php @@ -16,7 +16,7 @@ //constructor - function fs_filelister($directory = null) { + function __construct($directory = null) { if ($directory) $this->_directory = $directory; $this->_listFiles($this->_directory); } @@ -184,11 +184,11 @@ var $_chmod_dir; var $_chmod_file; - function fs_chmodder($directory, $ch_file=FILE_PERMISSIONS, $ch_dir=DIR_PERMISSIONS) { + function __construct($directory, $ch_file=FILE_PERMISSIONS, $ch_dir=DIR_PERMISSIONS) { $this->_directory = $directory; $this->_chmod_file = $ch_file; $this->_chmod_dir = $ch_dir; - parent::fs_filelister(); + parent::__construct(); } function _checkFile($directory, $file) { @@ -221,7 +221,7 @@ function fs_deleter($directory) { $this->_directory = $directory; - parent::fs_filelister(); + parent::__construct(); } function _checkFile($directory, $file) { diff --git a/fp-includes/core/core.fpdb.class.php b/fp-includes/core/core.fpdb.class.php index 37c4641..e455b61 100644 --- a/fp-includes/core/core.fpdb.class.php +++ b/fp-includes/core/core.fpdb.class.php @@ -15,7 +15,7 @@ var $fullparse = false; var $comments = false; - function FPDB_QueryParams($params) { + function __construct($params) { if (is_string($params)) { $this->parse_string($params); @@ -152,7 +152,7 @@ var $secondary_idx = null; var $walker = null; - function FPDB_Query($params, $ID) { + function __construct($params, $ID) { global $current_query; @@ -297,13 +297,13 @@ $filteredkeys = $obj->getList(); $index_count = $obj->getCount(); - if ($filteredkeys) - $this->walker =& $entry_index->walker( - entry_idtokey($filteredkeys[0]), true, - entry_idtokey($filteredkeys[$index_count-1]), true - ); - - + if ($filteredkeys) { + $error302var1 = entry_idtokey($filteredkeys[0]); + + $this->walker = $entry_index->walker( + $error302var1, true, + entry_idtokey($filteredkeys[$index_count-1]), true); + } } if ($qp->count < 0) { @@ -595,7 +595,7 @@ var $current = ''; var $entryid = ''; - function FPDB_CommentList($ID, $array) { + function __construct($ID, $array) { if (is_array($array)) { $this->list = $array; @@ -624,7 +624,7 @@ if (!$this->hasMore()) return false; - list($k,$id) = each($this->list); + $id = array_shift($this->list); $comment = comment_parse($this->entryid, $id); $couplet = array(&$id, &$comment); @@ -641,7 +641,7 @@ var $queries = array(); - function FPDB() { + function __construct() { // constructor } @@ -769,7 +769,7 @@ var $_nodesize = 30; var $_keysize = 12; - function FPDB_transaction($id_cat=0) { + function __construct($id_cat=0) { $this->_index = INDEX_DIR.'index-'.$id_cat; $this->_tree = caching_SBPT( diff --git a/fp-includes/core/core.plugins.php b/fp-includes/core/core.plugins.php index 208ad09..29e452c 100644 --- a/fp-includes/core/core.plugins.php +++ b/fp-includes/core/core.plugins.php @@ -9,9 +9,9 @@ var $_enabledlist = null; var $_directory = PLUGINS_DIR; - function plugin_indexer() { + function __construct() { $this->_enabledlist = CONFIG_DIR . 'plugins.conf.php'; - parent::fs_filelister(); + parent::__construct(); } function _checkFile($directory, $file) { diff --git a/fp-includes/core/core.system.php b/fp-includes/core/core.system.php index 40e367f..ce96ee1 100755 --- a/fp-includes/core/core.system.php +++ b/fp-includes/core/core.system.php @@ -1,234 +1,223 @@ - - * $my_arr); //same as: $save_arr['$my_arr'] = $my_arr); - * system_save($my_file, $my_arr); - * // now the file $my_file will contain the following lines: - * // global $my_arr; - * // $my_arr = array ( - * // '$my_arr' => val1', - * // '$my_arr' => 'val2', - * // '$my_arr' => 'val3' - * // ); - * ?> - * - * - * @param string $file file path where $array contents will be saved - * @array $var_list list of vars to be saved - * @return bool - * - * @see config_save, config_load - * - */ - function system_save($file, $array ) { - - //if ( ( $numargs = func_num_args() ) > 1) { - - $string = " $arg) { - //$vname = utils_vname ($arg); - //var_export($arg); - $s = /*" global {$key};\n*/ "\${$key} = " . - var_export($arg, true) . ";\n"; - $string .= $s; - } - - $string .= "\n?>"; - - return io_write_file($file, $string); - - //} else die('Wrong number of parameters!'); - +/** + * function system_save + * + * This function saves a list of variables provided after $file + * encapsulated in an array where KEY is the var name + * in a php file. + * + * Example usage: + * + * $my_arr); //same as: $save_arr['$my_arr'] = $my_arr); + * system_save($my_file, $my_arr); + * // now the file $my_file will contain the following lines: + * // global $my_arr; + * // $my_arr = array ( + * // '$my_arr' => val1', + * // '$my_arr' => 'val2', + * // '$my_arr' => 'val3' + * // ); + * ?> + * + * + * @param string $file + * file path where $array contents will be saved + * @array $var_list list of vars to be saved + * @return bool + * + * @see config_save, config_load + * + */ +function system_save($file, $array) { + + // if ( ( $numargs = func_num_args() ) > 1) { + $string = " $arg) { + // $vname = utils_vname ($arg); + // var_export($arg); + $s = /*" global {$key};\n*/ "\${$key} = " . var_export($arg, true) . ";\n"; + $string .= $s; } - - function system_hashsalt_save($force=false) { - global $fp_config; - if ($force || !file_exists(HASHSALT_FILE)) - return system_save(HASHSALT_FILE, array('fp_hashsalt'=>$fp_config['general']['blogid'] . ABS_PATH . BLOG_BASEURL .mt_rand())); - return true; - } - - - define('SYSTEM_VER', '1.0.3'); - function system_ver() { - return 'fp-' . SYSTEM_VER; - } + $string .= "\n?>"; + + return io_write_file($file, $string); + + // } else die('Wrong number of parameters!'); +} - function system_ver_compare($newver, $oldver) { - $nv_arr = explode('.', $newver); - $ov_arr = explode('.', $oldver); - $cn = count($nv_arr); - $co = count($ov_arr); - $max = min($cn, $co); +function system_hashsalt_save($force = false) { + global $fp_config; + if ($force || !file_exists(HASHSALT_FILE)) + return system_save(HASHSALT_FILE, array( + 'fp_hashsalt' => $fp_config ['general'] ['blogid'] . ABS_PATH . BLOG_BASEURL . mt_rand() + )); + return true; +} - // let's compare if one of the first version numbers differs - // from new version, being greater - for ($i=0; $i<$max; $i++) { - if ( $nv_arr[ $i ] > $ov_arr[ $i ] ) { return 1; } - if ( $nv_arr[ $i ] < $ov_arr[ $i ] ) { return 0; } +define('SYSTEM_VER', '1.1'); + +function system_ver() { + return 'fp-' . SYSTEM_VER; +} + +function system_ver_compare($newver, $oldver) { + $nv_arr = explode('.', $newver); + $ov_arr = explode('.', $oldver); + $cn = count($nv_arr); + $co = count($ov_arr); + $max = min($cn, $co); + + // let's compare if one of the first version numbers differs + // from new version, being greater + for($i = 0; $i < $max; $i++) { + if ($nv_arr [$i] > $ov_arr [$i]) { + return 1; } - - // if they equals, but still new version has more digits - // then old-version is still outdated - if ($cn > $co) return 1; - - - } - - function system_generate_id($string) { - return 'fp-'.dechex(crc32($string) ^ mt_rand()); - } - - function system_guessblogroot() { - return substr($_SERVER['REQUEST_URI'], 0,strrpos($_SERVER['REQUEST_URI'],'/')+1); - } - - function system_guessbaseurl() { - return 'http://'.$_SERVER['HTTP_HOST']. BLOG_ROOT; - } - - function system_getindex() { - if (MOD_BLOG != INDEX) - return MOD_BLOG; - else - return 'index.php'; - } - - function system_unregister_globals() { - $v = @ini_get('register_globals'); - - // on error we unregister anyway - if ($v || is_null($v)) { - foreach ($_REQUEST as $var => $val) { - unset($GLOBALS[$var]); - } - } - - } - - function system_sanitizequery() { - $err = false; - foreach ($_GET as $k => $v) { - if (preg_match('![<>]|://!', $v)) { - $err = true; - break; - } - } - if ($err) { - // @todo add log handler - utils_redirect(); + if ($nv_arr [$i] < $ov_arr [$i]) { + return 0; } } - - function system_prepare_iis() { - if (!@$_SERVER['REQUEST_URI']) { - $_SERVER['REQUEST_URI'] = substr($_SERVER['PHP_SELF'],1 ); - if (isset($_SERVER['QUERY_STRING'])) { - $_SERVER['REQUEST_URI'].='?'.$_SERVER['QUERY_STRING']; - } - } - } + // if they equals, but still new version has more digits + // then old-version is still outdated + if ($cn > $co) + return 1; +} - function system_init_action_params() { - - global $fp_params; - - $fp_params = array(); - - if ($x = @$_GET['x']) - $fp_params = utils_kexplode($x, ':;', false); - - $fp_params = array_merge($_GET, $fp_params); - - } +function system_generate_id($string) { + return 'fp-' . dechex(crc32($string) ^ mt_rand()); +} +function system_guessblogroot() { + return substr($_SERVER ['REQUEST_URI'], 0, strrpos($_SERVER ['REQUEST_URI'], '/') + 1); +} +function system_guessbaseurl() { + return 'http://' . $_SERVER ['HTTP_HOST'] . BLOG_ROOT; +} + +function system_getindex() { + if (MOD_BLOG != INDEX) + return MOD_BLOG; + else + return 'index.php'; +} + +function system_unregister_globals() { + $v = @ini_get('register_globals'); - function system_init() { - - system_sanitizequery(); - system_unregister_globals(); - system_prepare_iis(); - - $GLOBALS['fpdb'] = new FPDB; - - $GLOBALS['fp_widgets'] = new widget_indexer; - - $GLOBALS['smarty'] =& $GLOBALS['_FP_SMARTY']; - $smarty =& $GLOBALS['smarty']; - - $GLOBALS['fp_config'] = config_load(); - - cookie_setup(); - sess_setup(); - user_loggedin(); - - ob_start(); - - $GLOBALS['theme'] = theme_loadsettings(); - - $GLOBALS['lang'] = lang_load(); - + // on error we unregister anyway + if ($v || is_null($v)) { + foreach ($_REQUEST as $var => $val) { + unset($GLOBALS [$var]); + } + } +} - plugin_loadall(); - - // init smarty - $smarty->compile_dir = CACHE_DIR; - $smarty->cache_dir = SMARTY_DIR . 'cache/'; - $smarty->caching = 0; - - do_action('init'); - ob_end_clean(); - +function system_sanitizequery() { + $err = false; + foreach ($_GET as $k => $v) { + if (preg_match('![<>]|://!', $v)) { + $err = true; + break; + } } + if ($err) { + // @todo add log handler + utils_redirect(); + } +} - function system_seterr($module, $val) { - if ($module) - $elem = 'success_'.$module; - else - $elem = 'success'; - sess_add($elem, $val); +function system_prepare_iis() { + if (!@$_SERVER ['REQUEST_URI']) { + $_SERVER ['REQUEST_URI'] = substr($_SERVER ['PHP_SELF'], 1); + if (isset($_SERVER ['QUERY_STRING'])) { + $_SERVER ['REQUEST_URI'] .= '?' . $_SERVER ['QUERY_STRING']; + } } +} - function system_geterr($module='') { - if ($module) - $elem = 'success_'.$module; - else - $elem = 'success'; - return sess_remove($elem); - } +function system_init_action_params() { + global $fp_params; - /* delayed print */ - function system_dpr($action, $content) { - $p = print_r($content,1); - $f = create_function('', "echo '
$p
';"); - add_action($action, $f); - } + $fp_params = array(); + if ($x = @$_GET ['x']) + $fp_params = utils_kexplode($x, ':;', false); + + $fp_params = array_merge($_GET, $fp_params); +} + +function system_init() { + system_sanitizequery(); + system_unregister_globals(); + system_prepare_iis(); + + $GLOBALS ['fpdb'] = new FPDB(); + + $GLOBALS ['fp_widgets'] = new widget_indexer(); + + $GLOBALS ['smarty'] = & $GLOBALS ['_FP_SMARTY']; + $smarty = & $GLOBALS ['smarty']; + + $GLOBALS ['fp_config'] = config_load(); + + cookie_setup(); + sess_setup(); + user_loggedin(); + + ob_start(); + + $GLOBALS ['theme'] = theme_loadsettings(); + + $GLOBALS ['lang'] = lang_load(); + + plugin_loadall(); + + // init smarty + $smarty->compile_dir = CACHE_DIR; + $smarty->cache_dir = SMARTY_DIR . 'cache/'; + $smarty->caching = 0; + + do_action('init'); + ob_end_clean(); +} + +function system_seterr($module, $val) { + if ($module) + $elem = 'success_' . $module; + else + $elem = 'success'; + sess_add($elem, $val); +} + +function system_geterr($module = '') { + if ($module) + $elem = 'success_' . $module; + else + $elem = 'success'; + return sess_remove($elem); +} + +/* delayed print */ +function system_dpr($action, $content) { + $p = print_r($content, 1); + $f = create_function('', "echo '
$p
';"); + add_action($action, $f); +} ?> diff --git a/fp-includes/core/core.theme.php b/fp-includes/core/core.theme.php index 3aa74b4..299730a 100644 --- a/fp-includes/core/core.theme.php +++ b/fp-includes/core/core.theme.php @@ -167,7 +167,8 @@ echo "\n\n"; - echo '$string - keys were supposed to be UPPERCASE but \"$k\" was found; file may be corrupted - or in an expected format.
- Some SimplePHPBlog files may raise this error: set DUMB_MODE_ENABLED - to true in your defaults.php to force parsing of the offending keys.", - E_USER_WARNING); - */ - continue; - } - - $arr[strtolower($k)] = strtok($delim); + $k = strtolower(strtok($string, $delim)); + $arr [$k] = strtok($delim); + while (($k = strtok($delim)) !== false) { + if ($keyupper && !preg_match('/[A-Z-_]/', $k)) { + /* + * trigger_error("Failed parsing
$string
+ * keys were supposed to be UPPERCASE but \"$k\" was found; file may be corrupted + * or in an expected format.
+ * Some SimplePHPBlog files may raise this error: set DUMB_MODE_ENABLED + * to true in your defaults.php to force parsing of the offending keys.", + * E_USER_WARNING); + */ + continue; } - return $arr; + $arr [strtolower($k)] = strtok($delim); } + return $arr; +} - /* - function utils_newkexplode($string, $delim='|') { - - $arr = array(); - - $lastoffset = $offset = 0; - $len = strlen($string); - - while ($lastoffset<$len) { - $offset = strpos($string, $delim, $lastoffset); - $key = substr($string, $lastoffset, $offset-$lastoffset); - //echo 'parsing key: ', $key, $offset, chr(10); - - $lastoffset = $offset + 1; - - if (!ctype_upper($key)) - trigger_error("Failed parsing \"$string\" - keys were supposed to be UPPERCASE", E_USER_ERROR); - - $offset = strpos($string, $delim, $lastoffset); +/* + * function utils_newkexplode($string, $delim='|') { + * + * $arr = array(); + * + * $lastoffset = $offset = 0; + * $len = strlen($string); + * + * while ($lastoffset<$len) { + * $offset = strpos($string, $delim, $lastoffset); + * $key = substr($string, $lastoffset, $offset-$lastoffset); + * //echo 'parsing key: ', $key, $offset, chr(10); + * + * $lastoffset = $offset + 1; + * + * if (!ctype_upper($key)) + * trigger_error("Failed parsing \"$string\" + * keys were supposed to be UPPERCASE", E_USER_ERROR); + * + * $offset = strpos($string, $delim, $lastoffset); + * + * if ($offset===false) + * $offset = $len; + * + * $val = substr($string, $lastoffset, $offset-$lastoffset); + * + * //echo 'parsing value ', $val, $offset, chr(10); + * + * $lastoffset = $offset + 1; + * + * $arr[$key] = $val; + * + * } + * return $arr; + * + * } + */ - if ($offset===false) - $offset = $len; +// function prototype: +// array utils_kimplode(string $string, string $delim='|') - $val = substr($string, $lastoffset, $offset-$lastoffset); - - //echo 'parsing value ', $val, $offset, chr(10); - - $lastoffset = $offset + 1; - - $arr[$key] = $val; - - } - return $arr; - - }*/ - - - // function prototype: - // array utils_kimplode(string $string, string $delim='|') - - // explodes a string into an array by the given delimiter; - // delimiter defaults to pipe ('|'). - // the string must be formatted as in: - // key1|value1|key2|value2 , etc. - // the array will look like - // $arr['key1'] = 'value1'; $arr['key2'] = 'value2'; etc. - - function utils_kimplode($arr, $delim='|') { - - $string = ""; - foreach ($arr as $k => $val) { - if ($val) - $string .= strtoupper($k) . $delim . ($val) . $delim; - } - return $string; +// explodes a string into an array by the given delimiter; +// delimiter defaults to pipe ('|'). +// the string must be formatted as in: +// key1|value1|key2|value2 , etc. +// the array will look like +// $arr['key1'] = 'value1'; $arr['key2'] = 'value2'; etc. +function utils_kimplode($arr, $delim = '|') { + $string = ""; + foreach ($arr as $k => $val) { + if ($val) + $string .= strtoupper($k) . $delim . ($val) . $delim; } + return $string; +} + +/** + * + * @todo send mail to admin + */ +function &utils_explode_recursive($array, &$string, $rdelim, $ldelim = '', $outerldelim = '', $outerrdelim = '') { + $string .= $outerldelim; - /** - * @todo send mail to admin - */ - - - function &utils_explode_recursive($array, &$string, $rdelim, $ldelim='', $outerldelim='', $outerrdelim='') { - - $string .= $outerldelim; - - while (list(,$val) = each($array)) { - - $string .= $rdelim; - if (is_array($val)) { - $string .= utils_explode_recursive($val, $string, $rdelim, $ldelim, $outerldelim, $outerrdelim); - } else { - $string .= $val; - } - - $string .= $ldelim; - - } - - $string .= $outerrdelim; - - } - - - - - - function utils_validateinput($str) { + while ($val = array_shift($array)) { - if (preg_match('/[^a-z0-9\-_]/i',$str)){ - trigger_error("String \"$str\" is not a valid input", E_USER_ERROR); - //return false; - } else - return true; - } - - function utils_cut_string($str,$maxc) { - $car = strlen($str); - if($car > $maxc) { - return substr($str, 0, $maxc)."..."; + $string .= $rdelim; + if (is_array($val)) { + $string .= utils_explode_recursive($val, $string, $rdelim, $ldelim, $outerldelim, $outerrdelim); } else { - return $str; - } - } - - - function utils_status_header($status) { - - switch ($status) { - case 301: - header("HTTP/1.1 301 Moved Permanently"); - break; - case 403: - header("HTTP/1.1 403 Forbidden"); - break; - case 404: - header("HTTP/1.1 404 Not Found"); - break; - - } - - } - - // code from php.net ;) - // defaults to index.php ;) - function utils_redirect($location="", $absolute_path=false, $red_type=null) { - - if (!$absolute_path) - $location = BLOG_BASEURL . $location; - - if ( function_exists('wp_redirect') ) { - wp_redirect($location); - } else { - header("Location: $location"); + $string .= $val; } - exit(); - + $string .= $ldelim; } + $string .= $outerrdelim; +} + +function utils_validateinput($str) { + if (preg_match('/[^a-z0-9\-_]/i', $str)) { + trigger_error("String \"$str\" is not a valid input", E_USER_ERROR); + // return false; + } else + return true; +} + +function utils_cut_string($str, $maxc) { + $car = strlen($str); + if ($car > $maxc) { + return substr($str, 0, $maxc) . "..."; + } else { + return $str; + } +} + +function utils_status_header($status) { + switch ($status) { + case 301: + header("HTTP/1.1 301 Moved Permanently"); + break; + case 403: + header("HTTP/1.1 403 Forbidden"); + break; + case 404: + header("HTTP/1.1 404 Not Found"); + break; + } +} + +// code from php.net ;) +// defaults to index.php ;) +function utils_redirect($location = "", $absolute_path = false, $red_type = null) { + if (!$absolute_path) + $location = BLOG_BASEURL . $location; - /* - * utils_geturlstring() - * - * @return string complete url string as displayed in the browser - * - */ - - function utils_geturlstring() { - $str = BLOG_BASEURL . $_SERVER['PHP_SELF']; - if ($_SERVER['QUERY_STRING']) - $str .='?'.$_SERVER['QUERY_STRING']; - return $str; + if (function_exists('wp_redirect')) { + wp_redirect($location); + } else { + header("Location: $location"); } - // custom array_merge: - // pads the second array to match the length of the first - // this can be improved, anyway for now I'd just - // do a quick & dirty solution :) - function utils_array_merge($arr1, $arr2) { - - $len=count($arr1[0]); - - foreach($arr2 as $k=>$v) - $arr2[$k]=array_pad((Array) $v, $len, null); - - return array_merge($arr1, $arr2); + exit(); +} + +/* + * utils_geturlstring() + * + * @return string complete url string as displayed in the browser + * + */ +function utils_geturlstring() { + $str = BLOG_BASEURL . $_SERVER ['PHP_SELF']; + if ($_SERVER ['QUERY_STRING']) + $str .= '?' . $_SERVER ['QUERY_STRING']; + return $str; +} + +// custom array_merge: +// pads the second array to match the length of the first +// this can be improved, anyway for now I'd just +// do a quick & dirty solution :) +function utils_array_merge($arr1, $arr2) { + $len = count($arr1 [0]); + + foreach ($arr2 as $k => $v) + $arr2 [$k] = array_pad((array) $v, $len, null); + + return array_merge($arr1, $arr2); +} + +/* + * Simple function to replicate PHP 5 behaviour + */ +function utils_microtime() { + list ($usec, $sec) = explode(" ", microtime()); + return ((float) $usec + (float) $sec); +} + +function utils_countdashes($string, &$rest) { + trim($string); + $i = 0; + while ($string {$i} == '-') { + $i++; } + if ($i) + $rest = substr($string, $i); + else + $rest = $string; + + return $i; +} - - /* - * Simple function to replicate PHP 5 behaviour - */ - function utils_microtime() - { - list($usec, $sec) = explode(" ", microtime()); - return ((float)$usec + (float)$sec); - } - - function utils_countdashes($string, &$rest) { - trim($string); - $i = 0; - while ($string{$i} == '-') { - $i++; - } - if ($i) - $rest = substr($string, $i); - else $rest = $string; - - return $i; - - - } - - function utils_mail($from, $subject, $message, $headers = '') { - global $fp_config; - if( $headers == '' ) { - $headers = "MIME-Version: 1.0\n" . - "From: " . $from . "\n" . - "Content-Type: text/plain; charset=\"" . $fp_config['general']['charset'] . "\"\n"; - } - - return mail($fp_config['general']['email'], $subject, $message, $headers); +function utils_mail($from, $subject, $message, $headers = '') { + global $fp_config; + if ($headers == '') { + $headers = "MIME-Version: 1.0\n" . "From: " . $from . "\n" . "Content-Type: text/plain; charset=\"" . $fp_config ['general'] ['charset'] . "\"\n"; } + return mail($fp_config ['general'] ['email'], $subject, $message, $headers); +} + /* * props: http://crisp.tweakblogs.net/blog/2031 */ - function utils_validateIPv4($IP) { - return $IP == long2ip(ip2long($IP)); - } - - function utils_validateIPv6($IP) { - // fast exit for localhost - if (strlen($IP) < 3) - return $IP == '::'; - - // Check if part is in IPv4 format - if (strpos($IP, '.')) - { - $lastcolon = strrpos($IP, ':'); - if (!($lastcolon && validateIPv4(substr($IP, $lastcolon + 1)))) - return false; - - // replace IPv4 part with dummy - $IP = substr($IP, 0, $lastcolon) . ':0:0'; - } - - // check uncompressed - if (strpos($IP, '::') === false) - { - return preg_match('/^(?:[a-f0-9]{1,4}:){7}[a-f0-9]{1,4}$/i', $IP); - } - - // check colon-count for compressed format - if (substr_count($IP, ':') < 8) - { - return preg_match('/^(?::|(?:[a-f0-9]{1,4}:)+):(?:(?:[a-f0-9]{1,4}:)*[a-f0-9]{1,4})?$/i', $IP); - } - - return false; - } +function utils_validateIPv4($IP) { + return $IP == long2ip(ip2long($IP)); +} - // get client IP - function utils_ipget() { +function utils_validateIPv6($IP) { + // fast exit for localhost + if (strlen($IP) < 3) + return $IP == '::'; + + // Check if part is in IPv4 format + if (strpos($IP, '.')) { + $lastcolon = strrpos($IP, ':'); + if (!($lastcolon && validateIPv4(substr($IP, $lastcolon + 1)))) + return false; - $ip = ''; - - if ( !empty ( $_SERVER[ 'HTTP_CLIENT_IP' ] ) ) { - $ip = $_SERVER[ 'HTTP_CLIENT_IP' ]; - } - elseif ( !empty ( $_SERVER[ 'HTTP_X_FORWARDED_FOR' ] ) ) { - $ip = $_SERVER[ 'HTTP_X_FORWARDED_FOR' ]; - } - elseif ( !empty ( $_SERVER[ 'REMOTE_ADDR' ] ) ) { - $ip = $_SERVER[ 'REMOTE_ADDR' ]; - } - elseif ( getenv( "HTTP_CLIENT_IP" ) ) { - $ip = getenv( "HTTP_CLIENT_IP" ); - } - elseif ( getenv( "HTTP_X_FORWARDED_FOR" ) ) { - $ip = getenv( "HTTP_X_FORWARDED_FOR" ); - } - elseif ( getenv( "REMOTE_ADDR") ) { - $ip = getenv( "REMOTE_ADDR" ); - } - - if (utils_validateIPv4($ip) || utils_validateIPv6($ip)) { - return $ip; - } else { - return ''; - } - - + // replace IPv4 part with dummy + $IP = substr($IP, 0, $lastcolon) . ':0:0'; } - - function utils_nocache_headers() { - @ header('Expires: Wed, 11 Jan 1984 05:00:00 GMT'); - @ header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); - @ header('Cache-Control: no-cache, must-revalidate, max-age=0'); - @ header('Pragma: no-cache'); + + // check uncompressed + if (strpos($IP, '::') === false) { + return preg_match('/^(?:[a-f0-9]{1,4}:){7}[a-f0-9]{1,4}$/i', $IP); } + + // check colon-count for compressed format + if (substr_count($IP, ':') < 8) { + return preg_match('/^(?::|(?:[a-f0-9]{1,4}:)+):(?:(?:[a-f0-9]{1,4}:)*[a-f0-9]{1,4})?$/i', $IP); + } + + return false; +} + +// get client IP +function utils_ipget() { + $ip = ''; + + if (!empty($_SERVER ['HTTP_CLIENT_IP'])) { + $ip = $_SERVER ['HTTP_CLIENT_IP']; + } elseif (!empty($_SERVER ['HTTP_X_FORWARDED_FOR'])) { + $ip = $_SERVER ['HTTP_X_FORWARDED_FOR']; + } elseif (!empty($_SERVER ['REMOTE_ADDR'])) { + $ip = $_SERVER ['REMOTE_ADDR']; + } elseif (getenv("HTTP_CLIENT_IP")) { + $ip = getenv("HTTP_CLIENT_IP"); + } elseif (getenv("HTTP_X_FORWARDED_FOR")) { + $ip = getenv("HTTP_X_FORWARDED_FOR"); + } elseif (getenv("REMOTE_ADDR")) { + $ip = getenv("REMOTE_ADDR"); + } + + if (utils_validateIPv4($ip) || utils_validateIPv6($ip)) { + return $ip; + } else { + return ''; + } +} + +function utils_nocache_headers() { + @ header('Expires: Wed, 11 Jan 1984 05:00:00 GMT'); + @ header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); + @ header('Cache-Control: no-cache, must-revalidate, max-age=0'); + @ header('Pragma: no-cache'); +} // from http://nadeausoftware.com/articles/2007/06/php_tip_how_get_web_page_using_curl // code under OSI BSD /** - * Get a web file (HTML, XHTML, XML, image, etc.) from a URL. Return an + * Get a web file (HTML, XHTML, XML, image, etc.) from a URL. + * Return an * array containing the HTTP server response header fields and content. */ function utils_geturl($url) { /* - if (ini_get('allow_url_fopen')) { - return array('content' => io_load_file($url)); - } - */ + * if (ini_get('allow_url_fopen')) { + * return array('content' => io_load_file($url)); + * } + */ if (!function_exists('curl_init')) { trigger_error('curl extension is not installed'); return array(); } - - $options = array( - CURLOPT_RETURNTRANSFER => true, // return web page - CURLOPT_HEADER => false, // don't return headers - CURLOPT_FOLLOWLOCATION => false, // don't follow redirects - CURLOPT_ENCODING => "", // handle all encodings - CURLOPT_USERAGENT => "spider", // who am i - CURLOPT_AUTOREFERER => true, // set referer on redirect - CURLOPT_CONNECTTIMEOUT => 120, // timeout on connect - CURLOPT_TIMEOUT => 120, // timeout on response - CURLOPT_MAXREDIRS => 10, // stop after 10 redirects - ); - - $ch = curl_init( $url ); - curl_setopt_array( $ch, $options ); - $content = curl_exec( $ch ); - $err = curl_errno( $ch ); - $errmsg = curl_error( $ch ); - $header = curl_getinfo( $ch ); - curl_close( $ch ); - - $header['errno'] = $err; - $header['errmsg'] = $errmsg; - $header['content'] = $content; - return $header; + + $options = array( + CURLOPT_RETURNTRANSFER => true, // return web page + CURLOPT_HEADER => false, // don't return headers + CURLOPT_FOLLOWLOCATION => false, // don't follow redirects + CURLOPT_ENCODING => "", // handle all encodings + CURLOPT_USERAGENT => "spider", // who am i + CURLOPT_AUTOREFERER => true, // set referer on redirect + CURLOPT_CONNECTTIMEOUT => 120, // timeout on connect + CURLOPT_TIMEOUT => 120, // timeout on response + CURLOPT_MAXREDIRS => 10 // stop after 10 redirects + ); + + $ch = curl_init($url); + curl_setopt_array($ch, $options); + $content = curl_exec($ch); + $err = curl_errno($ch); + $errmsg = curl_error($ch); + $header = curl_getinfo($ch); + curl_close($ch); + + $header ['errno'] = $err; + $header ['errmsg'] = $errmsg; + $header ['content'] = $content; + return $header; } - - - function utils_checksmarty() { - - if (!file_exists(SMARTY_DIR . 'Smarty.class.php')) { +function utils_checksmarty() { + if (!file_exists(SMARTY_DIR . 'Smarty.class.php')) { $err = <<http://smarty.php.net; you will probably need SmartyValidate as well; unpack them to fp-includes/core/smarty: please do not overwrite files in fp-includes/core/smarty/plugins/ ERR; trigger_error($err, E_USER_ERROR); - } + } +} +function fplog($str) { + if (!defined('DEBUG_MODE')) + echo "\n[DEBUG] $str \n"; +} + +/** + * Shift an element with its key off the beginning of array. + * Just like array_shift(), but for an associative array. + * + * @param array $arr + * The input array + * @return unknown the shifted value, or NULL if array is empty or is not an array + */ +function utils_array_kshift(&$arr) { + if (!is_array($arr) || count($arr) === 0) { + return null; } - - - function fplog($str) { - if(!defined('DEBUG_MODE')) - echo "\n[DEBUG] $str \n"; - } - + list ($k) = array_keys($arr); + $r = array( + $k => $arr [$k] + ); + unset($arr [$k]); + return $r; +} + ?> diff --git a/fp-includes/core/core.widgets.php b/fp-includes/core/core.widgets.php index c4d5e7c..2363c97 100755 --- a/fp-includes/core/core.widgets.php +++ b/fp-includes/core/core.widgets.php @@ -11,7 +11,7 @@ var $_varname = 'fp_widgets'; var $_enabledlist = null; - function widget_indexer() { + function __construct() { if (!file_exists(CONFIG_DIR. 'widgets.conf.php')) trigger_error('widgets.conf.php not found. Blog may not work as expected, create a widgetlist.conf.php or reinstall completely FlatPress. If you have just installed FlatPress, the package you @@ -45,7 +45,7 @@ do { $content = array(); - list(,$id) = each($this->_list[$hor]); + $id = array_shift($this->_list[$hor]); $newid=$id;# @list($newid, $params) = explode(":", $id); if (@$params) $params = explode(',', $params); else $params = array(); diff --git a/fp-includes/core/function.list_categories.php b/fp-includes/core/function.list_categories.php new file mode 100644 index 0000000..2353e13 --- /dev/null +++ b/fp-includes/core/function.list_categories.php @@ -0,0 +1,157 @@ +'
  • ','ird'=>"
  • \n", + 'old'=>"\n", + 'name' => isset($params['name'])? $params['name'] : '', + 'selected' => array() + ); + + $cat_params = array_merge($cat_params, $params); + + // makese 'selected' an arr + $cat_params['selected'] = (array)$params['selected']; + + //echo "
    " . print_r(entry_categories_get()) . "
    "; + + if (file_exists(CONTENT_DIR . 'categories.txt')) { + $cats = trim(io_load_file(CONTENT_DIR . 'categories.txt')); + $stack=array(0); + $arr=array(); + + $line36error = explode("\n", $cats); + $line35error = ''; + + return $line35error; + } else { + global $lang; + + $content = 'Unfiled'; + if (isset($lang['admin']['entry']['publish']['nocategories'])) + $content = $lang['admin']['entry']['publish']['nocategories']; + return '' ; + } + + //
    + +} + + + + + +function do_print_categories_list(&$lines, &$indentstack, &$result, $params) { + + global $smarty, $fpdb; + + extract($params); + + if (empty($lines)) { + $l = count($indentstack)-1; + if ($l > 0) + $arr = array_fill(0, $l, $ord.$ird); + else + $arr = array(); + + $result = array_merge($result, $arr); + return ''; + } + + + $str = ''; + $v = reset($lines); + $vt = ltrim($v); + + $indent = utils_countdashes($vt, $text); + $indent_old = end($indentstack); + + $val = explode(':', $text); + $vt = $val[0]; + $vid = trim($val[1]); + + $catname = $params['name']; + + if ($indent > $indent_old) { + array_push($indentstack, $indent); + + array_pop($result); + array_push($result, $old); + //array_push($result, $ild); + do_print_categories_list($lines, $indentstack, $result, $params); + }elseif($indent < $indent_old) { + array_pop($indentstack); + + array_push($result, $ord); + array_push($result, $ird); + + do_print_categories_list($lines, $indentstack, $result, $params); + }else{ + array_push($result, $ild); + + + $cat_entry = $params['selected']; + + if (isset($params['type']) && ($params['type']=='form' || $params['type']=='check')) { + $string = ''; + $after = $string; + }elseif(isset($params['type']) && $params['type']=='linked'){ + $after=''; + if (isset($params['count']) && $params['count']) { + $index =& $fpdb->get_index($vid); + $count = ($index)? $index->length() : 0; + $after = " ($count) ". $after; + } + } + + array_push($result, $after); + + array_push($result, $ird); + array_shift($lines); + do_print_categories_list($lines, $indentstack, $result, $params); + } + + return implode($result); + +} diff --git a/fp-includes/smarty/Config_File.class.php b/fp-includes/smarty/Config_File.class.php index 5787ad1..6d8c298 100644 --- a/fp-includes/smarty/Config_File.class.php +++ b/fp-includes/smarty/Config_File.class.php @@ -22,14 +22,14 @@ * smarty-discussion-subscribe@googlegroups.com * * @link http://www.smarty.net/ - * @version 2.6.26 + * @version 2.6.25-dev * @copyright Copyright: 2001-2005 New Digital Group, Inc. * @author Andrei Zmievski * @access public * @package Smarty */ -/* $Id: Config_File.class.php 3149 2009-05-23 20:59:25Z monte.ohrt $ */ +/* $Id$ */ /** * Config file reading class @@ -73,7 +73,7 @@ class Config_File { * * @param string $config_path (optional) path to the config files */ - function Config_File($config_path = NULL) + public function __construct($config_path = NULL) { if (isset($config_path)) $this->set_path($config_path); diff --git a/fp-includes/smarty/Smarty.class.php b/fp-includes/smarty/Smarty.class.php index e7298f2..41d5370 100644 --- a/fp-includes/smarty/Smarty.class.php +++ b/fp-includes/smarty/Smarty.class.php @@ -20,17 +20,17 @@ * * For questions, help, comments, discussion, etc., please join the * Smarty mailing list. Send a blank e-mail to - * smarty-discussion-subscribe@googlegroups.com + * smarty-discussion-subscribe@googlegroups.com * * @link http://www.smarty.net/ * @copyright 2001-2005 New Digital Group, Inc. * @author Monte Ohrt * @author Andrei Zmievski * @package Smarty - * @version 2.6.26 + * @version 2.6.30 */ -/* $Id: Smarty.class.php 3163 2009-06-17 14:39:24Z monte.ohrt $ */ +/* $Id$ */ /** * DIR_SEP isn't used anymore, but third party apps might @@ -465,7 +465,7 @@ class Smarty * * @var string */ - var $_version = '2.6.26'; + var $_version = '2.6.30'; /** * current template inclusion depth @@ -562,11 +562,17 @@ class Smarty */ var $_cache_including = false; + /** + * plugin filepath cache + * + * @var array + */ + var $_filepaths_cache = array(); /**#@-*/ /** * The class constructor. */ - function Smarty() + public function __construct() { $this->assign('SCRIPT_NAME', isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : @$GLOBALS['HTTP_SERVER_VARS']['SCRIPT_NAME']); @@ -1058,7 +1064,7 @@ class Smarty } else { // var non-existant, return valid reference $_tmp = null; - return $_tmp; + return $_tmp; } } @@ -1090,7 +1096,8 @@ class Smarty */ function trigger_error($error_msg, $error_type = E_USER_WARNING) { - trigger_error("Smarty error: $error_msg", $error_type); + $msg = htmlentities($error_msg); + trigger_error("Smarty error: $msg", $error_type); } @@ -1117,7 +1124,7 @@ class Smarty function fetch($resource_name, $cache_id = null, $compile_id = null, $display = false) { static $_cache_info = array(); - + $_smarty_old_error_level = $this->debugging ? error_reporting() : error_reporting(isset($this->error_reporting) ? $this->error_reporting : error_reporting() & ~E_NOTICE); @@ -1933,10 +1940,10 @@ class Smarty { return eval($code); } - + /** * Extracts the filter name from the given callback - * + * * @param callback $function * @return string */ @@ -1951,7 +1958,7 @@ class Smarty return $function; } } - + /**#@-*/ } diff --git a/fp-includes/smarty/SmartyValidate.class.php b/fp-includes/smarty/SmartyValidate.class.php index f7b4575..dccc5e1 100644 --- a/fp-includes/smarty/SmartyValidate.class.php +++ b/fp-includes/smarty/SmartyValidate.class.php @@ -35,16 +35,18 @@ class SmartyValidate { /** * Class Constructor */ - function SmartyValidate() { } - + public function __construct() { } + // public static function SmartyValidate() { } + public function SmartyValidate() { } + /** * initialize the validator * * @param obj $smarty the smarty object * @param string $reset reset the default form? */ - function connect(&$smarty, $reset = false) { + public static function connect(&$smarty, $reset = false) { if(SmartyValidate::is_valid_smarty_object($smarty)) { SmartyValidate::_object_instance('Smarty', $smarty); SmartyValidate::register_form(SMARTY_VALIDATE_DEFAULT_FORM, $reset); @@ -59,7 +61,7 @@ class SmartyValidate { * * @param obj $smarty_obj the smarty object */ - function is_valid_smarty_object(&$smarty_obj) { + public static function is_valid_smarty_object(&$smarty_obj) { return (is_object($smarty_obj) && (strtolower(get_class($smarty_obj)) == 'smarty' || is_subclass_of($smarty_obj, 'smarty'))); } @@ -68,7 +70,7 @@ class SmartyValidate { * clear the entire SmartyValidate session * */ - function disconnect() { + public static function disconnect() { unset($_SESSION['SmartyValidate']); SmartyValidate::_object_instance('-', $_dummy); } @@ -79,7 +81,7 @@ class SmartyValidate { * @param string $form the name of the form being validated * @param string $reset reset an already registered form? */ - function register_form($form, $reset = false) { + public static function register_form($form, $reset = false) { if(SmartyValidate::is_registered_form($form) && !$reset) { return false; } else { @@ -99,7 +101,7 @@ class SmartyValidate { * * @param string $form the name of the form being validated */ - function unregister_form($form) { + public static function unregister_form($form) { unset($_SESSION['SmartyValidate'][$form]); } @@ -108,11 +110,11 @@ class SmartyValidate { * * @param string $form the name of the form being validated */ - function is_registered_form($form = SMARTY_VALIDATE_DEFAULT_FORM) { + public static function is_registered_form($form = SMARTY_VALIDATE_DEFAULT_FORM) { return isset($_SESSION['SmartyValidate'][$form]); } - function _failed_fields(&$formvars, $form = SMARTY_VALIDATE_DEFAULT_FORM, $revalidate = false) + public static function _failed_fields(&$formvars, $form = SMARTY_VALIDATE_DEFAULT_FORM, $revalidate = false) { // keep track of failed fields static $_failed_fields = array(); @@ -254,7 +256,7 @@ class SmartyValidate { * @param string $formvars the array of submitted for variables * @param string $form the name of the form being validated */ - function is_valid(&$formvars, $form = SMARTY_VALIDATE_DEFAULT_FORM) { + public static function is_valid(&$formvars, $form = SMARTY_VALIDATE_DEFAULT_FORM) { static $_is_valid = array(); @@ -297,7 +299,7 @@ class SmartyValidate { * * @param string $func_name the function being registered */ - function register_object($object_name, &$object) { + public static function register_object($object_name, &$object) { if(!is_object($object)) { trigger_error("SmartyValidate: [register_object] not a valid object."); return false; @@ -310,7 +312,7 @@ class SmartyValidate { * * @param string $func_name the function being registered */ - function is_registered_object($object_name) { + public static function is_registered_object($object_name) { $_object =& SmartyValidate::_object_instance($object_name, $_dummy); return is_object($_object); } @@ -320,7 +322,7 @@ class SmartyValidate { * * @param string $func_name the function being registered */ - function register_criteria($name, $func_name, $form = SMARTY_VALIDATE_DEFAULT_FORM) { + public static function register_criteria($name, $func_name, $form = SMARTY_VALIDATE_DEFAULT_FORM) { return SmartyValidate::_register_function('criteria', $name, $func_name, $form); } @@ -329,7 +331,7 @@ class SmartyValidate { * * @param string $func_name the function being registered */ - function register_transform($name, $func_name, $form = SMARTY_VALIDATE_DEFAULT_FORM) { + public static function register_transform($name, $func_name, $form = SMARTY_VALIDATE_DEFAULT_FORM) { return SmartyValidate::_register_function('transform', $name, $func_name, $form); } @@ -338,7 +340,7 @@ class SmartyValidate { * * @param string $var the value being booleanized */ - function is_registered_criteria($name, $form = SMARTY_VALIDATE_DEFAULT_FORM) { + public static function is_registered_criteria($name, $form = SMARTY_VALIDATE_DEFAULT_FORM) { if(!SmartyValidate::is_registered_form($form)) { trigger_error("SmartyValidate: [is_registered_criteria] form '$form' is not registered."); return false; @@ -351,7 +353,7 @@ class SmartyValidate { * * @param string $var the value being booleanized */ - function is_registered_transform($name, $form = SMARTY_VALIDATE_DEFAULT_FORM) { + public static function is_registered_transform($name, $form = SMARTY_VALIDATE_DEFAULT_FORM) { if(!SmartyValidate::is_registered_form($form)) { trigger_error("SmartyValidate: [is_registered_transform] form '$form' is not registered."); return false; @@ -370,7 +372,7 @@ class SmartyValidate { * @param string $transform transform function(s) to apply (optional) * @param string $form name of the form (optional) */ - function register_validator($id, $field, $criteria, $empty = false, $halt = false, $transform = null, $form = SMARTY_VALIDATE_DEFAULT_FORM) { + public static function register_validator($id, $field, $criteria, $empty = false, $halt = false, $transform = null, $form = SMARTY_VALIDATE_DEFAULT_FORM) { if(!SmartyValidate::is_registered_form($form)) { trigger_error("SmartyValidate: [register_validator] form '$form' is not registered."); return false; @@ -408,7 +410,7 @@ class SmartyValidate { * @param string $transform the name of the transform function(s) * @param string $form name of the form (optional) */ - function set_transform($id, $transform, $form = SMARTY_VALIDATE_DEFAULT_FORM) { + public static function set_transform($id, $transform, $form = SMARTY_VALIDATE_DEFAULT_FORM) { if(($_validator_key = SmartyValidate::is_registered_validator($id,$form)) === false) { trigger_error("SmartyValidate: [set_transform] validator '$id' is not registered."); @@ -424,7 +426,7 @@ class SmartyValidate { * * @param string $id the validator to test */ - function is_registered_validator($id, $form = SMARTY_VALIDATE_DEFAULT_FORM) { + public static function is_registered_validator($id, $form = SMARTY_VALIDATE_DEFAULT_FORM) { if(!SmartyValidate::is_registered_form($form)) { trigger_error("SmartyValidate: [is_registered_validator] form '$form' is not registered."); return false; @@ -444,7 +446,7 @@ class SmartyValidate { * * @param string $id the validator to unregister */ - function unregister_validator($id, $form = SMARTY_VALIDATE_DEFAULT_FORM) { + public static function unregister_validator($id, $form = SMARTY_VALIDATE_DEFAULT_FORM) { if(!SmartyValidate::is_registered_form($form)) { return false; } @@ -465,7 +467,7 @@ class SmartyValidate { * @param string $page the name of the page being validated * @param string $form the name of the form being validated */ - function set_page($page, $form = SMARTY_VALIDATE_DEFAULT_FORM) { + public static function set_page($page, $form = SMARTY_VALIDATE_DEFAULT_FORM) { $_SESSION['SmartyValidate'][$form]['page'] = $page; $_SESSION['SmartyValidate'][$form]['is_error'] = false; $_SESSION['SmartyValidate'][$form]['is_init'] = true; @@ -478,7 +480,7 @@ class SmartyValidate { * @param string $name the registered name * @param string $form the form name */ - function _execute_transform($name, $value, $params, &$formvars, $form) { + public static function _execute_transform($name, $value, $params, &$formvars, $form) { if(SmartyValidate::is_registered_transform($name, $form)) { $_func_name = SmartyValidate::_get_registered_func_name('transform', $name, $form); @@ -515,7 +517,7 @@ class SmartyValidate { * * @param string $func_name the function being registered */ - function _register_function($type, $name, $func_name, $form = SMARTY_VALIDATE_DEFAULT_FORM) { + public static function _register_function($type, $name, $func_name, $form = SMARTY_VALIDATE_DEFAULT_FORM) { if(!SmartyValidate::is_registered_form($form)) { trigger_error("SmartyValidate: [register_$type] form '$form' is not registered."); return false; @@ -552,7 +554,7 @@ class SmartyValidate { * @param string $name the registered name * @param string $form the form name */ - function _get_registered_func_name($type,$name,$form) { + public static function _get_registered_func_name($type,$name,$form) { return isset($_SESSION['SmartyValidate'][$form]['registered_funcs'][$type][$name]) ? $_SESSION['SmartyValidate'][$form]['registered_funcs'][$type][$name] : false; @@ -564,7 +566,7 @@ class SmartyValidate { * * @param string $var the value being booleanized */ - function _booleanize($var) { + public static function _booleanize($var) { if(in_array(strtolower($var), array(true, 1, 'true','on','yes','y'),true)) { return true; } @@ -578,7 +580,7 @@ class SmartyValidate { * @param string $value the value being tested * @param string $empty skip empty values or not */ - function _is_valid_criteria($criteria, $value, $empty, &$params, &$formvars, $form) { + public static function _is_valid_criteria($criteria, $value, $empty, &$params, &$formvars, $form) { if(SmartyValidate::is_registered_criteria($criteria,$form)) { $_func_name = SmartyValidate::_get_registered_func_name('criteria',$criteria, $form); } else { @@ -615,7 +617,7 @@ class SmartyValidate { * @param string $name the object name * @param object $object the object being set */ - function &_object_instance($name, &$object) { + public static function &_object_instance($name, &$object) { $return = false; static $_objects = array(); if ($name=='-') { @@ -638,7 +640,7 @@ class SmartyValidate { * * @param string $value the value being tested */ - function _smarty_assign($vars = array()) { + public static function _smarty_assign($vars = array()) { $_smarty_obj =& SmartyValidate::_object_instance('Smarty', $_dummy); diff --git a/fp-includes/smarty/Smarty_Compiler.class.php b/fp-includes/smarty/Smarty_Compiler.class.php index 1178b84..904601d 100644 --- a/fp-includes/smarty/Smarty_Compiler.class.php +++ b/fp-includes/smarty/Smarty_Compiler.class.php @@ -21,12 +21,12 @@ * @link http://smarty.php.net/ * @author Monte Ohrt * @author Andrei Zmievski - * @version 2.6.26 + * @version 2.6.25-dev * @copyright 2001-2005 New Digital Group, Inc. * @package Smarty */ -/* $Id: Smarty_Compiler.class.php 3163 2009-06-17 14:39:24Z monte.ohrt $ */ +/* $Id$ */ /** * Template compiling class @@ -78,7 +78,7 @@ class Smarty_Compiler extends Smarty { /** * The class constructor. */ - function Smarty_Compiler() + public function __construct() { // matches double quoted strings: // "foobar" @@ -259,14 +259,9 @@ class Smarty_Compiler extends Smarty { preg_match_all($search, $source_content, $match, PREG_SET_ORDER); $this->_folded_blocks = $match; - reset($this->_folded_blocks); /* replace special blocks by "{php}" */ - $source_content = preg_replace($search.'e', "'" - . $this->_quote_replace($this->left_delimiter) . 'php' - . "' . str_repeat(\"\n\", substr_count('\\0', \"\n\")) .'" - . $this->_quote_replace($this->right_delimiter) - . "'" + $source_content = preg_replace_callback($search, array($this,'_preg_callback') , $source_content); /* Gather all template tags. */ @@ -556,7 +551,7 @@ class Smarty_Compiler extends Smarty { case 'php': /* handle folded tags replaced by {php} */ - list(, $block) = each($this->_folded_blocks); + $block = array_shift($this->_folded_blocks); $this->_current_line_no += substr_count($block[0], "\n"); /* the number of matched elements in the regexp in _compile_file() determins the type of folded tag that was found */ @@ -754,7 +749,12 @@ class Smarty_Compiler extends Smarty { return true; } - + function _preg_callback ($matches) { + return $this->_quote_replace($this->left_delimiter) + . 'php' + . str_repeat("\n", substr_count($matches[1], "\n")) + . $this->_quote_replace($this->right_delimiter); + } /** * compile custom function tag * @@ -2122,7 +2122,7 @@ class Smarty_Compiler extends Smarty { return null; case 'template': - $compiled_ref = "'$this->_current_file'"; + $compiled_ref = "'" . addslashes($this->_current_file) . "'"; $_max_index = 1; break; diff --git a/fp-includes/smarty/internals/core.assemble_plugin_filepath.php b/fp-includes/smarty/internals/core.assemble_plugin_filepath.php index 690d3dd..22c0248 100644 --- a/fp-includes/smarty/internals/core.assemble_plugin_filepath.php +++ b/fp-includes/smarty/internals/core.assemble_plugin_filepath.php @@ -14,11 +14,9 @@ */ function smarty_core_assemble_plugin_filepath($params, &$smarty) { - static $_filepaths_cache = array(); - $_plugin_filename = $params['type'] . '.' . $params['name'] . '.php'; - if (isset($_filepaths_cache[$_plugin_filename])) { - return $_filepaths_cache[$_plugin_filename]; + if (isset($smarty->_filepaths_cache[$_plugin_filename])) { + return $smarty->_filepaths_cache[$_plugin_filename]; } $_return = false; @@ -58,7 +56,7 @@ function smarty_core_assemble_plugin_filepath($params, &$smarty) } } } - $_filepaths_cache[$_plugin_filename] = $_return; + $smarty->_filepaths_cache[$_plugin_filename] = $_return; return $_return; } diff --git a/fp-includes/smarty/plugins/function.cycle.php b/fp-includes/smarty/plugins/function.cycle.php index fe78bb8..80378b7 100644 --- a/fp-includes/smarty/plugins/function.cycle.php +++ b/fp-includes/smarty/plugins/function.cycle.php @@ -63,7 +63,11 @@ function smarty_function_cycle($params, &$smarty) $cycle_vars[$name]['values'] = $params['values']; } - $cycle_vars[$name]['delimiter'] = (isset($params['delimiter'])) ? $params['delimiter'] : ','; + if (isset($params['delimiter'])) { + $cycle_vars[$name]['delimiter'] = $params['delimiter']; + } elseif (!isset($cycle_vars[$name]['delimiter'])) { + $cycle_vars[$name]['delimiter'] = ','; + } if(is_array($cycle_vars[$name]['values'])) { $cycle_array = $cycle_vars[$name]['values']; diff --git a/fp-includes/smarty/plugins/function.fetch.php b/fp-includes/smarty/plugins/function.fetch.php index 81b1bfc..d72c7b1 100644 --- a/fp-includes/smarty/plugins/function.fetch.php +++ b/fp-includes/smarty/plugins/function.fetch.php @@ -181,12 +181,12 @@ function smarty_function_fetch($params, &$smarty) $content .= fgets($fp,4096); } fclose($fp); - $csplit = split("\r\n\r\n",$content,2); + $csplit = preg_split("!\r\n\r\n!",$content,2); $content = $csplit[1]; if(!empty($params['assign_headers'])) { - $smarty->assign($params['assign_headers'],split("\r\n",$csplit[0])); + $smarty->assign($params['assign_headers'],preg_split("!\r\n!",$csplit[0])); } } } else { diff --git a/fp-includes/smarty/plugins/function.html_select_date.php b/fp-includes/smarty/plugins/function.html_select_date.php index 2a9cb1b..e5eb183 100644 --- a/fp-includes/smarty/plugins/function.html_select_date.php +++ b/fp-includes/smarty/plugins/function.html_select_date.php @@ -42,7 +42,7 @@ function smarty_function_html_select_date($params, &$smarty) require_once $smarty->_get_plugin_filepath('function','html_options'); /* Default values. */ $prefix = "Date_"; - $start_year = date_strformat("%Y"); + $start_year = strftime("%Y"); $end_year = $start_year; $display_days = true; $display_months = true; @@ -142,8 +142,8 @@ function smarty_function_html_select_date($params, &$smarty) $time = $found[1]; } else { // use smarty_make_timestamp to get an unix timestamp and - // date_strformat to make yyyy-mm-dd - $time = date_strformat('%Y-%m-%d', smarty_make_timestamp($time)); + // strftime to make yyyy-mm-dd + $time = strftime('%Y-%m-%d', smarty_make_timestamp($time)); } // Now split this in pieces, which later can be used to set the select $time = explode("-", $time); @@ -151,16 +151,16 @@ function smarty_function_html_select_date($params, &$smarty) // make syntax "+N" or "-N" work with start_year and end_year if (preg_match('!^(\+|\-)\s*(\d+)$!', $end_year, $match)) { if ($match[1] == '+') { - $end_year = date_strformat('%Y') + $match[2]; + $end_year = strftime('%Y') + $match[2]; } else { - $end_year = date_strformat('%Y') - $match[2]; + $end_year = strftime('%Y') - $match[2]; } } if (preg_match('!^(\+|\-)\s*(\d+)$!', $start_year, $match)) { if ($match[1] == '+') { - $start_year = date_strformat('%Y') + $match[2]; + $start_year = strftime('%Y') + $match[2]; } else { - $start_year = date_strformat('%Y') - $match[2]; + $start_year = strftime('%Y') - $match[2]; } } if (strlen($time[0]) > 0) { @@ -188,8 +188,8 @@ function smarty_function_html_select_date($params, &$smarty) $month_values[''] = ''; } for ($i = 1; $i <= 12; $i++) { - $month_names[$i] = date_strformat($month_format, mktime(0, 0, 0, $i, 1, 2000)); - $month_values[$i] = date_strformat($month_value_format, mktime(0, 0, 0, $i, 1, 2000)); + $month_names[$i] = strftime($month_format, mktime(0, 0, 0, $i, 1, 2000)); + $month_values[$i] = strftime($month_value_format, mktime(0, 0, 0, $i, 1, 2000)); } $month_result .= ''; diff --git a/fp-includes/smarty/plugins/function.list_categories.php b/fp-includes/smarty/plugins/function.list_categories.php index 7e77414..2353e13 100755 --- a/fp-includes/smarty/plugins/function.list_categories.php +++ b/fp-includes/smarty/plugins/function.list_categories.php @@ -20,7 +20,6 @@ function smarty_function_list_categories($params) //, &$smarty) 'selected' => array() ); - //list($catId) = each($categories); $cat_params = array_merge($cat_params, $params); // makese 'selected' an arr @@ -32,8 +31,11 @@ function smarty_function_list_categories($params) //, &$smarty) $cats = trim(io_load_file(CONTENT_DIR . 'categories.txt')); $stack=array(0); $arr=array(); - $explode_result=explode("\n", $cats); - return '
      '.do_print_categories_list($explode_result, $stack, $arr, $cat_params).'
    '; + + $line36error = explode("\n", $cats); + $line35error = '
      '.do_print_categories_list($line36error, $stack, $arr, $cat_params).'
    '; + + return $line35error; } else { global $lang; @@ -103,8 +105,6 @@ function do_print_categories_list(&$lines, &$indentstack, &$result, $params) { $cat_entry = $params['selected']; - //list($catId) = each($categories); - if (isset($params['type']) && ($params['type']=='form' || $params['type']=='check')) { $string = '