root / phpframework / trunk / fusebox5.php

Revision 412, 14.6 kB (checked in by starkraving2002, 2 years ago)

Fixed bug that would cause full app datafile to be swapped in, in production mode.

  • Property svn:executable set to *
Line 
1<?php
2/*
3Fusebox Software License
4Version 1.0
5
6Copyright (c) 2003, 2004, 2005, 2006 The Fusebox Corporation. All rights reserved.
7
8Redistribution and use in source and binary forms, with or without modification, are permitted
9provided that the following conditions are met:
10
111. Redistributions of source code must retain the above copyright notice, this list of conditions
12   and the following disclaimer.
13
142. Redistributions in binary form or otherwise encrypted form must reproduce the above copyright
15   notice, this list of conditions and the following disclaimer in the documentation and/or other
16   materials provided with the distribution.
17
183. The end-user documentation included with the redistribution, if any, must include the following
19   acknowledgment:
20
21   "This product includes software developed by the Fusebox Corporation (http://www.fusebox.org/)."
22
23   Alternately, this acknowledgment may appear in the software itself, if and wherever such
24   third-party acknowledgments normally appear.
25
264. The names "Fusebox" and "Fusebox Corporation" must not be used to endorse or promote products
27   derived from this software without prior written (non-electronic) permission. For written
28   permission, please contact fusebox@fusebox.org.
29
305. Products derived from this software may not be called "Fusebox", nor may "Fusebox" appear in
31   their name, without prior written (non-electronic) permission of the Fusebox Corporation. For
32   written permission, please contact fusebox@fusebox.org.
33
34If one or more of the above conditions are violated, then this license is immediately revoked and
35can be re-instated only upon prior written authorization of the Fusebox Corporation.
36
37THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
38LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39DISCLAIMED. IN NO EVENT SHALL THE FUSEBOX CORPORATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY
40DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
42BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
43STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
44OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45
46-------------------------------------------------------------------------------
47
48This software consists of voluntary contributions made by many individuals on behalf of the
49Fusebox Corporation. For more information on Fusebox, please see <http://www.fusebox.org/>.
50
51*/
52function __cfthrow($_cfcatch){
53    global $cfcatch;
54    $_cfcatch["detail"] = htmlspecialchars($_cfcatch["detail"]);
55    $cfcatch = $_cfcatch;
56    if ( isset($GLOBALS['_fba']->debug) && $GLOBALS['_fba']->debug && isset($GLOBALS['myFusebox']) ) {
57        $GLOBALS['myFusebox']->trace("Fusebox","Caught Fusebox exception '{$cfcatch['type']}'");
58    }
59    die( (!@include($GLOBALS["FUSEBOX_APPLICATION_PATH"]."errortemplates/".$_cfcatch["type"].".php") ) ? $_cfcatch["detail"] : null );
60}
61
62function Location($URL, $addToken = 1) {
63    $questionORamp = (strstr($URL, "?"))?"&":"?";
64    $location = ( $addToken && substr($URL, 0, 7) != "http://" && defined('SID') ) ? $URL.$questionORamp.SID : $URL; //append the sessionID ($SID) by default
65    //ob_end_clean(); //clear buffer, end collection of content
66    if(headers_sent()) {
67        print('<script type="text/javascript">( document.location.replace ) ? document.location.replace("'.$location.'") : document.location.href = "'.$location.'";</script>'."\n".'<noscript><meta http-equiv="Refresh" content="0;URL='.$location.'" /></noscript>');
68    } else {
69        header('Location: '.$location); //forward to another page
70        exit; //end the PHP processing
71    }
72}
73function isPHP5() {
74    $thisversion = phpversion();
75    return ( $thisversion{0} >= 5 );
76}
77// FB5: allow "" default - FB41 required this variable:
78if ( !isset($FUSEBOX_APPLICATION_PATH) ) $FUSEBOX_APPLICATION_PATH = "";
79if ( strlen($FUSEBOX_APPLICATION_PATH) > 0 && substr($FUSEBOX_APPLICATION_PATH, -1) != "/" ) {
80    $FUSEBOX_APPLICATION_PATH .= '/';
81}
82// FB5: application key - FB41 always uses 'fusebox':
83if ( !isset($FUSEBOX_APPLICATION_KEY) ) $FUSEBOX_APPLICATION_KEY = "fusebox";
84
85// FB5: application name - same as FB41 - FB4 always uses 'cacheddata':
86if ( !isset($FUSEBOX_APPLICATION_NAME) ) $FUSEBOX_APPLICATION_NAME = "cacheddata";
87
88if( !isset($attributes) || !is_array($attributes) ) {
89    $attributes = array();
90    $attributes = array_merge($_GET,$_POST);
91}
92
93if ( isset( $_SERVER['QUERY_STRING']) and strlen($_SERVER['QUERY_STRING']) > 0 ) {
94  // loop through query string to "fix" url variable names with dots in them
95  $qs_array = split("[\&;]",$_SERVER['QUERY_STRING']);
96  for ( $i = 0 ; $i < count( $qs_array ) ; $i++ ) {
97    @list($thisname,$thisvalue) = explode("=",$qs_array[$i]);
98    if ( !isset($attributes[$thisname]) ) $attributes[$thisname] = $thisvalue;
99  }
100}
101
102require_once("myFusebox.php");
103if ( !isPHP5() ) { eval('$myFusebox =& new MyFusebox($FUSEBOX_APPLICATION_KEY,$attributes);'); } else { $myFusebox = new MyFusebox($FUSEBOX_APPLICATION_KEY,$attributes); }
104
105if ( isset($FUSEBOX_APPLICATION_STARTUPTIME) ) $myFusebox->trace('Fusebox','Deserialized app_ datafile',$FUSEBOX_APPLICATION_STARTUPTIME);
106// FB5: indicates whether application was started on this request
107$myFusebox->applicationStart = false;
108// FB5: uses request.__fusebox for internal tracking of compiler / runtime operations:
109$_REQUEST['__fusebox'] = array();
110/*
111    complex condition allows FB5 to drop into a running FB41 site and force re-init because
112    FB41 application.fusebox will not have compileRequest() method - this should make upgrades
113    to FB5 easier!
114*/
115if ( !isset($application[$FUSEBOX_APPLICATION_KEY]) || $myFusebox->parameters['load'] ) {
116    $fa = @fopen($FUSEBOX_APPLICATION_PATH."parsed/_app_".$FUSEBOX_APPLICATION_NAME.".php","r") or
117        $fa = fopen($FUSEBOX_APPLICATION_PATH."parsed/_app_".$FUSEBOX_APPLICATION_NAME.".php","w");
118    if(!flock($fa,LOCK_EX)){
119        $myFusebox->trace("FuseboxError","Could not get exclusive lock to application data file");
120    }
121   
122    if ( !isset($application[$FUSEBOX_APPLICATION_KEY]) || $myFusebox->parameters['load'] ) {
123        // if it doesn't exisit or the user explicitly requested a load it
124        if ( !isset($application[$FUSEBOX_APPLICATION_KEY]) || $myFusebox->parameters['userProvidedLoadParameter'] ) {
125            // can't be conditional: we don't know the state of the debug flag yet
126            $myFusebox->trace("Fusebox","Creating Fusebox application object");
127            require_once("fuseboxApplication.php");
128            if ( !isPHP5() ) { eval('$_fba =& new FuseboxApplication();'); } else { $_fba = new FuseboxApplication(); }
129            $application[$FUSEBOX_APPLICATION_KEY] = $_fba->init($FUSEBOX_APPLICATION_KEY,$FUSEBOX_APPLICATION_PATH,$FUSEBOX_APPLICATION_NAME,$myFusebox);
130        //echo "fusebox5 still running...";
131        } else {
132            // can't be conditional: we don't know the state of the debug flag yet
133            $myFusebox->trace("Fusebox","Reloading Fusebox application object");
134            @include($FUSEBOX_APPLICATION_PATH."parsed/_app_".$FUSEBOX_APPLICATION_NAME.".php");
135            $_fba =& $application[$FUSEBOX_APPLICATION_KEY];
136            // it exists and the load is implicit, not explicit (via user) so just reload XML
137            $_fba->reload($FUSEBOX_APPLICATION_KEY,$FUSEBOX_APPLICATION_PATH,$myFusebox);
138        }
139        // fix attributes precedence
140        if ( $_fba->precedenceFormOrURL == "URL" ) {
141            $attributes = array_merge($_POST,$_GET);
142        }
143        // set the default fuseaction if necessary
144        if ( !array_key_exists($_fba->fuseactionVariable,$attributes) || $attributes[$_fba->fuseactionVariable] == "" ) {
145            $attributes[$_fba->fuseactionVariable] = $_fba->defaultFuseaction;
146        }
147        // set this up for fusebox.appinit.php
148        $attributes['fuseaction'] = $attributes[$_fba->fuseactionVariable];
149        // flag this as the first request for the application
150        $myFusebox->applicationStart = true;
151        // force parse after reload for consistency
152        if ( $_fba->mode != "production" || $myFusebox->parameters['userProvidedLoadParameter'] ) {
153            $myFusebox->parameters['parse'] = true;
154        }
155       
156        // need all of the above set before we attempt any compiles!
157        if ( $myFusebox->parameters['parseall'] ) {
158            $_fba->compileAll($myFusebox);
159        }
160        // FB5: new appinit include file
161        if ( $_fba->debug ) {
162            $myFusebox->trace("Fusebox","Including fusebox.appinit.php");
163        }
164        if ( file_exists($_fba->getWebRootPathToappRoot()."fusebox.appinit.php") ) {
165            include($_fba->getWebRootPathToappRoot()."fusebox.appinit.php");
166        }
167    } else {
168        $_fba =& $application[$FUSEBOX_APPLICATION_KEY];
169        // fix attributes precedence
170        if ( $_fba->precedenceFormOrURL == "URL" ) {
171            $attributes = array_merge($_POST,$_GET);
172        }
173        // set the default fuseaction if necessary
174        if ( !array_key_exists($_fba->fuseactionVariable,$attributes) || $attributes[$_fba->fuseactionVariable] == "" ) {
175            $attributes[$_fba->fuseactionVariable] = $_fba->defaultFuseaction;
176        }
177        $attributes['fuseaction'] = $attributes[$_fba->fuseactionVariable];
178    }
179    @flock($fa,LOCK_UN);
180    fclose($fa);
181} else {
182    $_fba =& $application[$FUSEBOX_APPLICATION_KEY];
183    // fix attributes precedence
184    if ( $_fba->precedenceFormOrURL == "URL" ) {
185        $attributes = array_merge($_POST,$_GET);
186    }
187    // set the default fuseaction if necessary
188    if ( !array_key_exists($_fba->fuseactionVariable,$attributes) || $attributes[$_fba->fuseactionVariable] == "" ) {
189        $attributes[$_fba->fuseactionVariable] = $_fba->defaultFuseaction;
190    }
191    $attributes['fuseaction'] = $attributes[$_fba->fuseactionVariable];
192}
193
194
195
196/*
197    Fusebox 4.1 did not set attributes.fuseaction or default the fuseaction variable until
198    *after* fusebox.init.php had run. This made it hard for fusebox.init.php to do URL
199    rewriting. For Fusebox 5, we default the fuseaction variable and set attributes.fuseaction
200    before fusebox.init.php so it can rely on attributes.fuseaction and rewrite that. However,
201    in order to maintain backward compatibility, we need to allow fusebox.init.php to set
202    attributes[$_fba->fuseactionVariable] and still have that reflected in attributes.fuseaction
203    and for that to actually be the request that gets processed.
204*/
205if ( $_fba->debug ) {
206    $myFusebox->trace("Fusebox","Including fusebox.init.php");
207}
208if ( file_exists($_fba->getWebRootPathToappRoot()."fusebox.init.php") ) {
209    $_fba_attr_fav = $attributes[$_fba->fuseactionVariable];
210    $_fba_attr_fa = $attributes['fuseaction'];
211    include($_fba->getWebRootPathToappRoot()."fusebox.init.php");
212    if ( $attributes['fuseaction'] != $_fba_attr_fa ) {
213        if ( $attributes['fuseaction'] != $attributes[$_fba->fuseactionVariable] ) {
214            if ( $attributes[$_fba->fuseactionVariable] != $_fba_attr_fav ) {
215                // inconsistent modification of both variables?!?
216                __cfthrow(array( 'type'=>"fusebox.inconsistentFuseaction",
217                    'message'=>"Inconsistent fuseaction variables",
218                    'detail'=>"Both attributes.fuseaction and attributes[{fusebox}.fuseactionVariable] changed in fusebox.init.php so Fusebox doesn't know what to do with the values!"
219                ));
220            } else {
221                // ok, only attributes.fuseaction changed
222                $attributes[$_fba->fuseactionVariable] = $attributes['fuseaction'];
223            }
224        } else {
225            // ok, they were both changed and they match
226        }
227    } else {
228        // attributes.fuseaction did not change
229        if ( $attributes[$_fba->fuseactionVariable] != $_fba_attr_fav ) {
230            // make attributes.fuseaction match the other changed variable
231            $attributes['fuseaction'] = $attributes[$_fba->fuseactionVariable];
232        } else {
233            // ok, neither variable changed
234        }
235    }
236}
237/*
238    by default, the _fba file included by index.php is the "slim" version of the object, to
239    keep the unserializing overhead to a minimum. If there is a parse request however, we
240    definitely need the full object, so we need to include it now, if it exists. It's not
241    necessary to include if there is a load request.
242*/
243if ( !$myFusebox->parameters['load'] && ( $myFusebox->parameters['parse'] || !file_exists($_fba->approotdirectory."parsed/".strtolower($attributes['fuseaction']).".php" ) ) ) {
244    if ( $_fba->debug ) $myFusebox->trace("Fusebox","Replacing slim AFB object with full copy");
245    include($FUSEBOX_APPLICATION_PATH."parsed/_app_".$FUSEBOX_APPLICATION_NAME.".php");
246    unset($_fba);
247    $_fba =& $application[$FUSEBOX_APPLICATION_KEY];
248}
249
250/*
251    must special case development-circuit-load mode since it causes circuits to reload during
252    the compile (post-load) phase and therefore must be exclusive
253*/
254if ( $_fba->debug ) {
255    $myFusebox->trace("Fusebox","Compiling requested fuseaction '{$attributes['fuseaction']}'");
256}
257if ( $_fba->mode == "development-circuit-load" ) {
258    $fa = fopen($FUSEBOX_APPLICATION_PATH."parsed/_app_".$FUSEBOX_APPLICATION_NAME.".php","r");
259    if(!flock($fa,LOCK_EX)){
260        $myFusebox->trace("FuseboxError","Could not get exclusive lock to application data file");
261    }
262    $_parsedFileData = $_fba->compileRequest($attributes['fuseaction'],$myFusebox);
263    @flock($fa,LOCK_UN);
264    fclose($fa);
265} else {
266    $fa = fopen($FUSEBOX_APPLICATION_PATH."parsed/_app_".$FUSEBOX_APPLICATION_NAME.".php","r");
267    if ( !flock($fa,LOCK_SH) ) {
268        $myFusebox->trace("FuseboxError","Could not get exclusive lock to application data file");
269    }
270    $_parsedFileData = $_fba->compileRequest($attributes['fuseaction'],$myFusebox);
271    @flock($fa,LOCK_UN);
272    fclose($fa);
273
274}
275/*
276    readonly lock protects against including the parsed file while
277    another threading is writing it...
278*/
279if ( $myFusebox->parameters['execute'] ) {
280    if ( $_fba->debug ) {
281        $myFusebox->trace("Fusebox","Including parsed file for '{$attributes['fuseaction']}'");
282    }
283    if ( file_exists($_parsedFileData['lockName']) ) {
284        $fp = fopen($_parsedFileData['lockName'],'r');
285        if ( !flock($fp,LOCK_SH) ) {
286            $myFusebox->trace("FuseboxError","Could not get exclusive lock to parsed fuseaction file");
287        }
288        include($_parsedFileData['parsedFile']);
289        @flock($fp,LOCK_UN);
290        fclose($fp);
291    } else {
292        __cfthrow(array( 'type'=>"fusebox.missingParsedFile",
293            'message'=>"Parsed File or Directory not found.",
294            'detail'=>"fusebox5.php line 269: Attempting to execute the parsed file '{$_parsedFileData['parsedName']}' threw an error. This can occur if the parsed file does not exist in the parsed directory or if the parsed directory itself is missing."
295        ));
296    }
297}
298
299
300if ( $myFusebox->parameters['load'] ) {
301    if ( $_fba->debug ) $myFusebox->trace("Fusebox","Saving app data file...");
302    $_fba->writeFullObjectToDisk();
303    $_fba->writeSlimObjectToDisk();
304}
305
306$myFusebox->trace("Fusebox","Request completed");
307if ( isset($_fba->debug) && $_fba->debug == "true" && isset($myFusebox) ) {
308    echo $myFusebox->renderTrace();
309}
310?>
Note: See TracBrowser for help on using the browser.