MediaWiki API result

This is the HTML representation of the JSON format. HTML is good for debugging, but is unsuitable for application use.

Specify the format parameter to change the output format. To see the non-HTML representation of the JSON format, set format=json.

See the complete documentation, or the API help for more information.

{
    "batchcomplete": "",
    "continue": {
        "gapcontinue": "Remote_Authentication",
        "continue": "gapcontinue||"
    },
    "query": {
        "pages": {
            "1948": {
                "pageid": 1948,
                "ns": 0,
                "title": "Re-Authentication for expired Tokens",
                "revisions": [
                    {
                        "contentformat": "text/x-wiki",
                        "contentmodel": "wikitext",
                        "*": "== Background ==\n\nThe introduction of [[CSRF Protection]] migitates the risk of Cross Site Request Forgery (CSRF) attacks on Geeklog sites. At the same time, however, it inconveniences Admin users, since an expired token will invalidate a request and may lead to data loss.\n\nRe-authentication (as of Geeklog 1.7.0) attempts to address this problem.\n\n[[Image:Reauthentication.png|center|Request for re-authentication]]\n\n== How it works ==\n\nFollowing the [[CSRF Protection#Considerations|recommendations]] for the use of security tokens, a call to <tt>SEC_checkToken()</tt> will check the token for validity. Previously, that function simply returned <tt>false</tt> when the token was not valid.\n\nFrom now on, when <tt>SEC_checkToken()</tt> detects an invalid token, it will instead display a re-authentication form. This form explains what just happened and asks the user to enter their username and password. If the user provides the correct information, the previous request is recreated and sent again automatically. As a result, the last changes are ''not'' lost and the request is processed as if a valid token had been found.\n\n=== Recreating Requests ===\n\nThe re-authentication form contains the information from the last request (GET or POST) in hidden fields, i.e. the entire <tt>$_GET</tt> and <tt>$_POST</tt> arrays, as well as the information from <tt>$_FILES</tt>, if files were uploaded with the failed request (the uploaded files themselves are temporarily stored in the site's 'data' directory).\n\nOn proper authentication, the GET or POST request is recreated from this information. A new security token is added and the request is sent to the original URL again. So from the target script's point of view, it looks like a regular request with a valid token came through.\n\nIn other words: '''The re-authentication and recreation of the request is entirely transparent. For scripts that already use CSRF protection, no code changes are required.'''\n\n=== Uploaded Files ===\n\nFiles uploaded through the original request (the one with the expired token) are rescued and moved to the site's 'data' directory. This is necessary, as the files would automatically be deleted by PHP otherwise. As a result, the rescued files can no longer be moved with <tt>move_uploaded_file()</tt> since that function only works on files that were uploaded with the last POST request.\n\nIf you are using Geeklog's upload class (<tt>upload.class.php</tt>), this is handled automatically for you.\n\nIf you are using your own upload handling, then check the <tt>$_FILES</tt> array for an <tt>'_gl_data_dir'</tt> entry, e.g. <tt>$_FILES['file1']['_gl_data_dir']</tt>. If such an entry is present and not <tt>false</tt>, then use <tt>rename()</tt> instead of <tt>move_uploaded_file()</tt> to move the uploaded file to its destination. The <tt>'tmp_name'</tt> entry will already contain the correct path (for the 'data' directory), so you don't need to (and shouldn't) bother with its actual location.\n\n\n== Using SEC_checkToken ==\n\nIt is important that you only call <tt>SEC_checkToken()</tt> when you expect a token. In other words, do '''NOT''' do this:\n\n<pre>$token_valid = SEC_checkToken(); // don't do this!\n\nswitch ($_POST['mode']) {\ncase 'delete':\n    if ($token_valid) ...\n    break;\n\ncase 'save':\n    if ($token_valid) ...\n    break;\n\ncase 'edit':\n    // token not checked here\n    display_editor();\n    break;\n}</pre>\n\nIn the above example, a token check is required for the 'delete' and 'save' cases, but not for 'edit'. However, <tt>SEC_checkToken()</tt> is also being called in the 'edit' case. In Geeklog versions 1.5.0 - 1.6.1, this would only cause <tt>SEC_checkToken()</tt> to return <tt>false</tt> for this case - but since the return value isn't checked, this would do no harm. From now on, however, this case would trigger the re-authentication form to be displayed!\n\nSo the proper use of <tt>SEC_checkToken()</tt> would be:\n\n<pre>switch ($_POST['mode']) {\ncase 'delete':\n    if (SEC_checkToken()) ...\n    break;\n\ncase 'save':\n    if (SEC_checkToken()) ...\n    break;\n\ncase 'edit':\n    // token not checked here\n    display_editor();\n    break;\n}</pre>\n\n\n== Known Issues ==\n\n* Re-authentication does not work for users that authenticate against OpenID (it does, however, work with other remote authentication modules like LDAP and LiveJournal).\n* When using a server running as localhost on Mac OS X, the recreated request may fail due to the current IP address being ::1 in the session but 127.0.0.1 in the recreated request.<br>'''Solution:''' Use the machine's Bonjour name (''xxx''.local) instead of localhost.\n\nAlso see: [[Troubleshooting Authentication Problems]]\n\n\n[[Category:Development]]"
                    }
                ]
            },
            "1727": {
                "pageid": 1727,
                "ns": 0,
                "title": "Register globals",
                "revisions": [
                    {
                        "contentformat": "text/x-wiki",
                        "contentmodel": "wikitext",
                        "*": "Starting with version 1.4.0, Geeklog no longer requires to have PHP's register_globals option set to \"on\".\n\nDespite the common conception that register_globals is \"evil\", it is not a security issue ''per se'', as long as you follow a few simple rules (see below). In all the years that Geeklog required register_globals to be \"on\", there was only '''one''' security issue that was a result of that setting.\n\nOn a side note, the register_globals setting will be removed from PHP 6, i.e. it will always be \"off\" and there will be no way to switch it back \"on\". So now would be a good time to review your code for dependency on the register_globals setting ...\n\n\n== Initialising variables ==\n\nThe main rule to avoid problems with the register_globals setting is pretty simple:\n\n:''Initialise your variables!''\n\nThe [http://www.php.net/release_4_1_0.php PHP 4.1.0 release notes] had the following example to illustrate what's bad about register_globals=on:\n\n<pre><?php\nif (authenticate_user()) {\n  $authenticated = true;\n}\n...\n?></pre>\n\nWith register_globals=on, it's simple to override the authentication check by adding \"authenticated=true\" to the URL of this script, e.g.\n\n:http://www.example.com/authenticate.php?authenticated=true\n\nHowever, that problem is easily fixed:\n\n<pre><?php\n$authenticated = false;\nif (authenticate_user()) {\n  $authenticated = true;\n}\n...\n?></pre>\n\nThere. You can pass whatever you want in the URL now - initialising the $authenticated variable fixed the problem.\n\nThis is actually a better programming style anyway, not only from a security point of view. You should adapt this style in your own interest.\n\n=== Switch on error reporting ===\n\nOn your ''development system'' ('''never''' do that on a production site), it's recommended that you switch on error reporting to be made aware of issues with uninitialised variables.\n\nIn your php.ini file, set\n\n<pre>error_reporting   = E_ALL\ndisplay_errors         = On\ndisplay_startup_errors = On</pre>\n\n... and don't forget to restart your webserver after you've made those changes.\n\nThen, in Geeklog's lib-common.php, find the line\n\n<pre>error_reporting( E_ERROR | E_WARNING | E_PARSE | E_COMPILE_ERROR );</pre>\n\nand comment it out or remove it.\n\n'''Note:''' Removing the error_reporting line from lib-common.php will throw up quite a few notices about uninitialised variables in the language files. Those are historic issues that can't be fixed easily but are not a security hazard. Just make sure not to repeat these design issues in your own code ...\n\nThe notices caused by the language files will prevent you from logging in to your site, so you may want to comment out the error_reporting line only during the debugging phase of your development cycle.\n\n\n== Use typesafe comparison operations ==\nThe content of the superglobal arrays ($_GET, $_POST, $_REQUEST etc) are all strings, as are any variables created by register_globals. As this is the case, you can secure your code further by using typesafe comparisons:\n\n<pre>\nif ($authorized === TRUE)\n{\n  // Only matches if $authorized contains an actual boolean true value.\n}\n</pre>\n\n== Hidden problems with register_globals ==\nRegister globals allows you to inject values into arrays in a non-detectable fashion:\n\n<pre>\n$sids[] = \"123\";\nforeach ($sids as $sid)\n{\n   // Delete article by sid\n}\n</pre>\n\nWith the above code, a url such as:\n<pre>somepage.php?sids[]=1&sids[]=2</pre>\nwill inject additional values into the arrays.\n\n\n\n== Use $_GET, $_POST, and $_REQUEST ==\n\nThe above explained how to avoid security issues when register_globals is set to \"on\". Of course, initialising your variables won't make your code work with register_globals=off.\n\nValues passed from user interaction, i.e. when the user clicks on a URL or submits a form, are always passed in the global $_GET and $_POST arrays. The variables you're looking for exist as named array elements in those arrays, e.g.\n\n* $_GET['page'] from a URL like /index.php?page=2\n* $_POST['title'] from a form that contains a comment with a \"title\" field\n\nNote that a form usually has a method=\"POST\" attribute which means that the form is sent as a HTTP POST request. Consequentially, the $_GET array will be empty in such a case and all the form's values will only exist in the $_POST array.\n\nThe $_REQUEST array contains both the contents of the $_GET and the $_POST array. This comes in handy sometimes when a certain portion of your code will have to handle something that could come in via either a GET or a POST request.\n\nHowever, the $_REQUEST should be used sparingly and with caution, as it may make it easier for an attacker to submit manipulated requests. For example, when your form handling code only looks at the $_REQUEST array, it's also possible to submit all the form's parameter through one GET request which, in some situations, is easier to send than a POST request.\n\nThe security implications of the $_REQUEST array are only mild, though. It's recommended, however, that you write your code such that you always know whether the incoming data is in the $_GET or $_POST array, which automatically helps to improve the clarity of your code.\n\n\n=== Switching off register_globals ===\n\nOn your development system, you should switch off register_globals in your php.ini file:\n\n<pre>register_globals = Off</pre>\n\n\n== register_long_arrays ==\n\nA somewhat related setting has been introduced with PHP 5: register_long_arrays, when set to \"on\", re-introduces the long names of the $_GET and $_POST arrays, i.e. $HTTP_GET_VARS and $HTTP_POST_VARS. These long-named arrays are disabled by default as of PHP 5 and any code relying on them will therefore fail.\n\nThe replacement for those, as mentioned above, are the $_GET and $_POST arrays and only those should be used. They were introduced in PHP 4.1.0, which has also been the minimum requirement for Geeklog for a while now.\n\n\n[[Category:Development]]"
                    }
                ]
            }
        }
    }
}