I've made an img editor which works fine in 99.9% of the situations.
However, in that rare 0.1% something weird happends, my session remember doesn't the proper value.
I have this in the page that inits the class:
$imgScreen = new img4crop();
// And here some settings like $imgScreen->setExtraJs($extraJs);
In this class I have a functions to save the $this data to an array:
private function save(){
$_SESSION['cropper'][$this->uniqid] = serialize($this);
}
In init-page.php I open a fancybox, loading the settings back into the class:
$info = unserialize($_SESSION['cropper'][$_GET['id']]);
// Should now be the same as $imgScreen
The problem
Sometimes $_SESSION['cropper'][$_GET['id']] is set to NULL. I have no clue why. This only happens very rarely. The key is set.
When I debug, and appendecho $_SESSION['cropper'][$this->uniqid]; to the save() function, it gives me the value I want it to have.
So, where does my session value go, only in that rare occation? Why isn't it there in the fancybox screen?
After 1st comment: It is possible for the init-page to start multiple instances, they each get their own value in $_SESSION['cropper']. In the situation above, they all work, just that one doesnt. On reload, I start new instances and the exact same screen doesnt work, even though I now has a new, fresh id
Edit: It gets weirder: If the location where the image has a file with the same name as the class will use, there are no problems. Weird part: The whole class has no code regarding to files, apart from the final step (the screen has 3 steps), where I use ImageMagick.
Important to know: When I installed the page where this occurs, the targetfile didn't exist either, started blank.
When you are serializing objects you have to make sure you load the base class (prototype) before unserializing the object. For PHP native objects you don't have to do anything, it will load the base classes.
Your variable $this is an instance of a class. In order for $this to exist the base class need to exist. Perhaps it's working most of the time because of an autoloader or the particular sequence you are loading items.
Turns out the solution was, as to be expected, a quircky little something unrelated to the actual code:
In my index.php I do $_SESSION['cropper'] = array(); to reset the array, then let the function which shows an editorscreen set new settings to the cropper, this works perfectly fine.
In that html I have an image with an anti cache:
echo '<img src="'.$image_url.'?'.time.'" />';
The problem occured when $image_url is empty/undefined, resulting in a source something like the following: ?1420793438. It starts with a ?, so it's effectively calling index.php?1420793438.
And at the beginning of that index.php we reset, resulting in an empty array.
Related
I am working on a TYPO3 project where I have to dynamically disable caching based on a condition. It is a very specific usecase, that will not happen a lot.
I planned to use a USER_INT function, where I would perform the check and disable the cache if necessary. The USER_INT function works flawlessly, it is being called on every page load.
The thing is, I can not disable the cache, or at least I do not know how.
The code, I have right now:
page = PAGE
page {
typeNum = 0
adminPanelStyles = 0
11 = USER_INT
11.userFunc = [COMPANY_NAMESPACE]\PageHandler->checkCache
And in the function I perform the check:
public function checkCache($content,$conf){
global $TSFE;
$id = $TSFE->id;
if($this->checkIfDisableCache($id)){
//$TSFE->set_no_cache(); // <---- first I tried this one
$TSFE->no_cache=true; // <-----after a while I got despoerate and tried to disable it directly
}
}
I also tried to play with the config, it did not work.
The funny thing is, if I set it directly in typoscript:
config.no_cache = 1
it works, but since the check is rather complex, I want to use PHP to determine, if the cache should be disabled.
I know I am doing something wrong, I just don't know what. Any help would be appretiated :)
I don't think either of the previous answers really explain the situation. You have sort of a catch-22 here, in that your USER_INT is executed after the page cache entry has been generated. The way it works internally is everything that can be cached gets rendered first, and every USER_INT then outputs a marker in the HTML source which gets replaced afterwards. This way the cache can contain the version with markers and those can be rendered without having to render the whole page.
So what you need to do in this case if you want the page cache to be disabled only in some conditions, is to use a custom TypoScript condition that is capable of setting config.no_cache = 1 only under special circumstances. That way you prevent generating a cache entry if the condition is met, but preserve full caching and cached output for every other request.
https://docs.typo3.org/typo3cms/TyposcriptSyntaxReference/TypoScriptParserApi/CustomConditions/Index.html
Note that it is still recommended that you instead create the parts of your page that must not be cached, as USER_INT objects. Having a use case where you in some cases need to disable the entire page cache indicates a possible misunderstanding of how the caching framework and/or USER_INT works. Hopefully the above explains those parts a bit.
if you look at the pibase (AbstractPlugin) code you will see that probably setting $conf['useCacheHash']and $conf['no_cache'] should be done.
https://api.typo3.org/typo3cms/current/html/_abstract_plugin_8php_source.html#l00190
If you create this object as USER_INT, it will be rendered non-cached, outside the main page-rendering.
https://docs.typo3.org/typo3cms/TyposcriptReference/ContentObjects/UserAndUserInt/Index.html
I am working within an existing PHP program that has an established way that it dynamically loads certain PHP files for rendering HTML, by doing something basically this:
try {
$includeFilePath = realpath($mySubPath);
include $includeFilePath;
} catch (Exception $e) {
//imagine code that handles error
}
Assume that both file to be included and the file containing the above method are read-only and it's not permissible to alter these actual files on disk. However the above method may be overridden by extending the class it is part of. Meanwhile the file that's being included cannot be overridden gracefully because it does not contain classes, just a mix of PHP and HTML instructions (old school "phtml").
Now what I want to do instead is:
try {
$includeFilePath = realpath($mySubPath);
$codeToModify = substr(file_get_contents($includeFilePath),5);
$codeToEval = $this->modifyCode($codeToModify);
eval($codeToExecute);
} catch (Exception $e) {
//imagine code that handles error
}
... where the modifyCode($str) method is defined elsewhere, and basically what it would do is (a) check the existing file against a pre-known hash checksum value to ensure it has not been modified, and (b) inject known safe code into it in order to add additional functionality to the application (it's "known safe" because we also would use a similar hash verification system on it and validate it).
Now my question is, assuming that security risks are not a concern here, is there any functional reason why eval would be problematic?
Note: no files we'd be including have closing html tags, only opening ones. I chose to use substr($str,5) to trim the opening tag as opposed to adding opening and closing tags as I've seen done elsewhere; that ought to work, right?
Explanation:
Since I anticipate a lot of you might wonder, "Why would you want to do that?", the reason is fairly complicated, but I'll try to explain it. The alternative to doing the above would be to include an entirely different file: one that already contains the custom code I want to use on top of the code from the base file. However the custom code I want to use is all additional code not present in the original base file, so we would end up with a fair amount of duplicated code instead of a more elegant solution where only the new code is "injected" into the base code prior to execution. Even still, using a new file that contains both the old and new code would technically work fine for now.
The problem is, though, in the future it's entirely possible that when we upgrade the base program, there will be changes to the original file (the one that's been effectively overridden by using my custom version of it). If that happens, our override would continue to rely on the previous version's code for that file, since the part of it that carried over from the original base system would no longer match up with the new version's normal default code for that file.
So, to address that problem, I want to go with the method of injecting the code using my custom modifyCode($str) method. That method can tell if there's been any updates to the original file (whether due to a hacker or due to system update) and it would be able to then warn the admin to check out why this code has changed, and issue an approval before executing the modified version of the code by updating the checksum with the hash of the new version of the file to be overridden. That way we can safely update the system and know it will fall back on the default behavior of the new version of the system rather than continue to run old code (which risks breaking the system) or adding mods intended for old versions of the code to new versions of the code that they haven't yet been tested on.
I hope that makes sense.
No. Call stack would be changed (error messages, magic constant __FILE__). Relative includes in evaled code could be broken. Two new variables $codeToModify, $codeToEval would appear in evaled code scope. Evaled code would not be cached. Parse error inside evaled code does not interrupt whole script. Eval could be disabled with Suhosin.
OK, so I have searched around for long enough to finally post this one here. Sure enough, it has been asked before a zillion time...
What I have, is one file, which includes another. No magic here. The trouble is, the included file then includes another file, which... includes yet another... Yep, a pain. Actually it's all working quite nicely, except that I now wanted to read the URL of the original file in the last of the included files.
So I thought in the original file, file_1.php I just say
$var_foo = dirname(__FILE__);
or
$var_foo = $_SERVER['SCRIPT_NAME'];
and then read that value in the first include, file_2.php, passing it on like
$var_foo_2 = $var_foo;
then in file_3.php
$var_foo_3 = $var_foo_2
etc, until I arrive at the final file, file_4.php, where I'd like to know the exact value of the original file's URL. Passing it on the first level works OK, but then it gets lost somewhere along the way. Tried going GLOBAL in file_1 -- to no avail.
Since file_3 and file_4 must both execute to produce data, setting a breakpoint a la echo / exit to spoof the current value (if any) is no option. I can live without that particular value, but I just would like to have it -- for the fun of it... Any ideas how to accomplish this?
Your examples use filesystem paths, not "URLs";I am assuming the filepath of the parent file is what you actually want.
You don't need to "pass" the variable on each included page. It will automatically be available to the code on the new page.
(If it is not, you may not be in the right scope: e.g., if you're inside a class or function, you'll need to pass it deliberately or use some other method - global, maybe, or even define the filename as a constant instead of a variable.)
main script
$parent_filename = __FILE__;
// alternatively
// define( 'PARENT_FILENAME',__FILE__ );
include "other-file.php";
other-file.php
include "other-dir/somefile.php";
other-dir/somefile.php
print $parent_filename;
// alternatively
// print PARENT_FILENAME;
/* prints something like:
/path/to/main.php
*/
As mentioned before, the issue has been solved like so:
set variable before the first include
add variable to query string
Thanks all for the input, appreciated.
I am currently writing an ajax-application, which gets some of its config-params by sessions.
The session['apps']['appXY'], which is holding these params, is built in the php-script, which provides the js-links, calling the ajax. As i dont want the sessions['apps']['appXY'] consume resources, when the user doesnt use the ajax-app, i have the session['apps'] array deleted each time, the user calls any site by regular/synchron way.
The order of the site-buildup is like this:
session['apps'] is deleted;
app-classes are included
within each app (f.e. appXY), if needed for ajax, the session['apps']['appXY'] is built (Step3)
site is built, loading is complete, user is calling some ajax-functionality, which may depend on the session['apps']['appXY']
The Problem with this now, if at the beginning of the sites building process the session['apps'] is deleted, that the session-array $session['apps']['appXY'] is not available within the ajax-script anymore, even though, it was rebuilt - and is existing and usable - in step3, the regular php-script of appXY.
If i dont delete the session its available by ajax too, but i dont understand, why is the session not available in the ajax-application, as the deleting of it is before the rebuilding? What could cause the fact, that session is available in regular php-script, but not in ajax, after deleting and rebuilding it?
Thanx, Jayden
As suggested by Ninsuo, i try to make the szenario more clearly by a more detailed model, containing some code:
In the main-class, before including any of the modules (apps) all ajax-sessions are deleted:
function get-apps()
{
unset($_SESSION['ajaxconf']);
require_once(appXY.php);
require_once(appABC.php);
}
Then, in class 'appXY.php' the session '$_SESSION['ajaxconf']['appXY']' is (re)filled:
class appXY extends base
{
function main ( $localconf, $lang )
{
foreach ($array as $key => $value)
$_SESSION['ajaxconf']['appXY'][$key] = $value;
return 'click
}
}
Getting the values from '$_SESSION['ajaxconf']['appXY']' works fine in the ajax-script, which is called by the javascript-function 'ajax-app()', as long as the the session is not deleted at the beginnning of the php function 'get-apps()'. If the session is deleted though, its not available in the ajax-file, even though, it has been redefined again in the class 'appXY', which clearly is included after deleting the sessions. to me, this doesnt make much sense, as the session is available in the class 'appXY'.
I'm having a multiplayer server that's using PHPSockets, and thus is written entirely in PHP.
Currently, whenever I'm making any changes to the PHP server-script I have to kill the script and then start it over again. This means that any users online is disconnected (normally not a problem because there aren't so many at the moment).
Now I am rewriting the server-script to use custom PHP classes and sorten things up a little bit (you don't want to know how nasty it looks today). Today I was thinking: "Shouldn't it be possible to make changes to the php source without having to restart the whole script?".
For example, I'm planning on having a main.php file that is including user.php which contains the class MyUser and game.php which contains the class MyGame. Now let's say that I would like to make a change to user.php and "reload" the server so that the changes to user.php goes into effect, without disconnecting any online users?
I tried to find other questions that answered this, the closest I got is this question: Modifying a running script and having it reload without killing it (php) , which however doesn't seem to solve the disconnection of online users.
UPDATE
My own solutions to this were:
At special occations, include the file external.php, which can access a few variables and use them however it'd like. When doing this, I had to make sure that there were no errors in the code as the whole server would crash if I tried accessing a method that did not exist.
Rewrite the whole thing to Java, which gave me the possibility of adding a plugin system using dynamic class reloading. Works like a charm. Bye bye PHP.
Shouldn't it be possible to make changes to the php source without having to restart the whole script?
[...]
I'm planning on having a main.php file that is including user.php
which contains the class MyUser
In your case, you can't. Classes can only be defined once within a running script. You would need to restart the script to have those classes redefined.
I am not too familiar with PHP but I would assume that a process is created to run the script, in doing so it copies the instructions needed to run the program and begins execution on the CPU, during this, if you were to "update" the instructions, you'd need to kill the process ultimate and restart it. Includes are a fancy way of linking your classes and files together but ultimately the processor will have that information separate from where the file of them are stored and it is ultimately different until you restart the process.
I do not know of any system in which you can create code and actively edit it and see the changes while that code is being run. Most active programs require restart to reload new source code.
Runkit will allow you to add, remove, and redefine methods (among other things) at runtime. While you cannot change the defined properties of a class or its existing instances, it would allow you to change the behavior of those objects.
I don't recommend this as a permanent solution, but it might be useful during development. Eventually you'll want to store the game state to files, a database, Memcache, etc.
How about storing your User object into APC cache while your main script loads from the cache and checks every so often for new opcode.
To include a function in the cache, you must include the SuperClosure Class. An example would be:
if (!apc_exists('area')) {
// simple closure
// calculates area given length and width
$area = new SuperClosure(
function($length, $width) {
return $length * $width;
}
);
apc_store('area', $area);
echo 'Added closure to cache.';
} else {
$func = apc_fetch('area');
echo 'Retrieved closure from cache. ';
echo 'The area of a 6x5 polygon is: ' . $func(6,5);
}
See here for a tutorial on APC.
Simple solution use $MyUser instead of MyUser
require MyUserV1.php;
$MyUser = 'MyUserV1';
$oldUser = new $MyUser('your name');
//Some time after
require MyUserV2.php;
$MyUser = 'MyUserV2';
$newUser = new $MyUser('your name');
Every declared class stay in memory but become unused when the last MyUserV1 logout
you can make them inherit from an abstract class MyUser for using is_a
You cannot include again a file with the same class, but you can do so with an array. You can also convert from array to class, if you really need to do so. This only applies to data, though, not to behavior (methods).
I don't know much about these things with the games on PC but you can try to get all the variables from your database for the user and then update the text fields or buttons using those variables
In web is using AJAX (change data without refreshing the page).Isn't one for programming?