Explorar o código

implementing request refactoring, beginning JS changes for JSON API, but
discovered that DELETE and PUT are not available on all webservers by
default

El RIDO %!s(int64=11) %!d(string=hai) anos
pai
achega
7ec94e0db5
Modificáronse 5 ficheiros con 339 adicións e 118 borrados
  1. 90 59
      js/zerobin.js
  2. 160 0
      lib/request.php
  3. 44 56
      lib/zerobin.php
  4. 3 1
      tst/request.php
  5. 42 2
      tst/zerobin.php

+ 90 - 59
js/zerobin.js

@@ -482,6 +482,11 @@ $(function() {
     };
 
     var zerobin = {
+        /**
+         * headers to send in AJAX requests
+         */
+        headers: {'X-Requested-With': 'JSONHttpRequest'},
+
         /**
          * Get the current script location (without search or hash part of the URL).
          * eg. http://server.com/zero/?aaaa#bbbb --> http://server.com/zero/
@@ -666,7 +671,12 @@ $(function() {
             }
             if (comments[0].meta.burnafterreading)
             {
-                $.get(this.scriptLocation() + '?pasteid=' + this.pasteID() + '&deletetoken=burnafterreading', 'json')
+                $.ajax({
+                    // type: 'DELETE', // unfortunately many web servers will not support DELETE and PUT by default
+                    url: this.scriptLocation() + '?pasteid=' + this.pasteID() + '&deletetoken=burnafterreading',
+                    dataType: 'json',
+                    headers: this.headers
+                })
                 .fail(function() {
                     zerobin.showError(i18n._('Could not delete the paste, it was not stored in burn after reading mode.'));
                 });
@@ -805,39 +815,52 @@ $(function() {
                 nickname: ciphernickname
             };
 
-            $.post(this.scriptLocation(), data_to_send, function(data)
-            {
-                if (data.status == 0)
+            $.ajax({
+                type: 'POST',
+                url: this.scriptLocation(),
+                data: data_to_send,
+                dataType: 'json',
+                headers: this.headers,
+                success: function(data)
                 {
-                    zerobin.showStatus(i18n._('Comment posted.'), false);
-                    $.get(zerobin.scriptLocation() + '?' + zerobin.pasteID() + '&json', function(data)
+                    if (data.status == 0)
                     {
-                        if (data.status == 0)
-                        {
-                            zerobin.displayMessages(zerobin.pageKey(), data.messages);
-                        }
-                        else if (data.status == 1)
-                        {
-                            zerobin.showError(i18n._('Could not refresh display: %s', data.message));
-                        }
-                        else
-                        {
-                            zerobin.showError(i18n._('Could not refresh display: %s', i18n._('unknown status')));
-                        }
-                    }, 'json')
-                    .fail(function() {
-                        zerobin.showError(i18n._('Could not refresh display: %s', i18n._('server error or not responding')));
-                    });
-                }
-                else if (data.status == 1)
-                {
-                    zerobin.showError(i18n._('Could not post comment: %s', data.message));
-                }
-                else
-                {
-                    zerobin.showError(i18n._('Could not post comment: %s', i18n._('unknown status')));
+                        zerobin.showStatus(i18n._('Comment posted.'), false);
+                        $.ajax({
+                            type: 'GET',
+                            url: zerobin.scriptLocation() + '?' + zerobin.pasteID(),
+                            dataType: 'json',
+                            headers: zerobin.headers,
+                            success: function(data)
+                            {
+                                if (data.status == 0)
+                                {
+                                    zerobin.displayMessages(zerobin.pageKey(), data.messages);
+                                }
+                                else if (data.status == 1)
+                                {
+                                    zerobin.showError(i18n._('Could not refresh display: %s', data.message));
+                                }
+                                else
+                                {
+                                    zerobin.showError(i18n._('Could not refresh display: %s', i18n._('unknown status')));
+                                }
+                            }
+                        })
+                        .fail(function() {
+                            zerobin.showError(i18n._('Could not refresh display: %s', i18n._('server error or not responding')));
+                        });
+                    }
+                    else if (data.status == 1)
+                    {
+                        zerobin.showError(i18n._('Could not post comment: %s', data.message));
+                    }
+                    else
+                    {
+                        zerobin.showError(i18n._('Could not post comment: %s', i18n._('unknown status')));
+                    }
                 }
-            }, 'json')
+            })
             .fail(function() {
                 zerobin.showError(i18n._('Could not post comment: %s', i18n._('server error or not responding')));
             });
@@ -932,36 +955,44 @@ $(function() {
                     data_to_send.attachmentname = cipherdata_attachment_name;
                 }
             }
-            $.post(this.scriptLocation(), data_to_send, function(data)
-            {
-                if (data.status == 0) {
-                    zerobin.stateExistingPaste();
-                    var url = zerobin.scriptLocation() + '?' + data.id + '#' + randomkey;
-                    var deleteUrl = zerobin.scriptLocation() + '?pasteid=' + data.id + '&deletetoken=' + data.deletetoken;
-                    zerobin.showStatus('', false);
-                    zerobin.errorMessage.addClass('hidden');
-
-                    $('#pastelink').html(i18n._('Your paste is <a id="pasteurl" href="%s">%s</a> <span id="copyhint">(Hit [Ctrl]+[c] to copy)</span>', url, url));
-                    $('#deletelink').html('<a href="' + deleteUrl + '">' + i18n._('Delete data') + '</a>');
-                    zerobin.pasteResult.removeClass('hidden');
-                    // We pre-select the link so that the user only has to [Ctrl]+[c] the link.
-                    helper.selectText('pasteurl');
-                    zerobin.showStatus('', false);
-
-                    helper.setElementText(zerobin.clearText, zerobin.message.val());
-                    helper.setElementText(zerobin.prettyPrint, zerobin.message.val());
-                    zerobin.formatPaste(data_to_send.formatter);
-                }
-                else if (data.status==1)
-                {
-                    zerobin.showError(i18n._('Could not create paste: %s', data.message));
-                }
-                else
+            $.ajax({
+                type: 'POST',
+                url: this.scriptLocation(),
+                data: data_to_send,
+                dataType: 'json',
+                headers: this.headers,
+                success: function(data)
                 {
-                    zerobin.showError(i18n._('Could not create paste: %s', i18n._('unknown status')));
+                    if (data.status == 0) {
+                        zerobin.stateExistingPaste();
+                        var url = zerobin.scriptLocation() + '?' + data.id + '#' + randomkey;
+                        var deleteUrl = zerobin.scriptLocation() + '?pasteid=' + data.id + '&deletetoken=' + data.deletetoken;
+                        zerobin.showStatus('', false);
+                        zerobin.errorMessage.addClass('hidden');
+
+                        $('#pastelink').html(i18n._('Your paste is <a id="pasteurl" href="%s">%s</a> <span id="copyhint">(Hit [Ctrl]+[c] to copy)</span>', url, url));
+                        $('#deletelink').html('<a href="' + deleteUrl + '">' + i18n._('Delete data') + '</a>');
+                        zerobin.pasteResult.removeClass('hidden');
+                        // We pre-select the link so that the user only has to [Ctrl]+[c] the link.
+                        helper.selectText('pasteurl');
+                        zerobin.showStatus('', false);
+
+                        helper.setElementText(zerobin.clearText, zerobin.message.val());
+                        helper.setElementText(zerobin.prettyPrint, zerobin.message.val());
+                        zerobin.formatPaste(data_to_send.formatter);
+                    }
+                    else if (data.status==1)
+                    {
+                        zerobin.showError(i18n._('Could not create paste: %s', data.message));
+                    }
+                    else
+                    {
+                        zerobin.showError(i18n._('Could not create paste: %s', i18n._('unknown status')));
+                    }
                 }
-            }, 'json')
-            .fail(function() {
+            })
+            .fail(function()
+            {
                 zerobin.showError(i18n._('Could not create paste: %s', i18n._('server error or not responding')));
             });
         },

+ 160 - 0
lib/request.php

@@ -0,0 +1,160 @@
+<?php
+/**
+ * ZeroBin
+ *
+ * a zero-knowledge paste bin
+ *
+ * @link      http://sebsauvage.net/wiki/doku.php?id=php:zerobin
+ * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
+ * @license   http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
+ * @version   0.21.1
+ */
+
+/**
+ * request
+ *
+ * parses request parameters and provides helper functions for routing
+*/
+class request
+{
+    /**
+     * Input stream to use for PUT parameter parsing.
+     *
+     * @access private
+     * @var string
+     */
+    private $_inputStream = 'php://input';
+
+    /**
+     * Operation to perform.
+     *
+     * @access private
+     * @var string
+     */
+    private $_operation = 'view';
+
+    /**
+     * Request parameters.
+     *
+     * @access private
+     * @var array
+     */
+    private $_params = array();
+
+    /**
+     * If we are in a JSON API context.
+     *
+     * @access private
+     * @var bool
+     */
+    private $_isJsonApi = false;
+
+    /**
+     * Constructor.
+     *
+     * @access public
+     * @return void
+     */
+    public function __construct()
+    {
+        // in case stupid admin has left magic_quotes enabled in php.ini (for PHP < 5.4)
+        if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc())
+        {
+            $_POST   = array_map('filter::stripslashes_deep', $_POST);
+            $_GET    = array_map('filter::stripslashes_deep', $_GET);
+            $_COOKIE = array_map('filter::stripslashes_deep', $_COOKIE);
+        }
+
+        // decide if we are in JSON API or HTML context
+        if (
+            (array_key_exists('HTTP_X_REQUESTED_WITH', $_SERVER) &&
+            $_SERVER['HTTP_X_REQUESTED_WITH'] == 'JSONHttpRequest') ||
+            (array_key_exists('HTTP_ACCEPT', $_SERVER) &&
+            strpos($_SERVER['HTTP_ACCEPT'], 'application/json') !== false)
+        )
+        {
+            $this->_isJsonApi = true;
+        }
+
+        // parse parameters, depending on request type
+        switch (array_key_exists('REQUEST_METHOD', $_SERVER) ? $_SERVER['REQUEST_METHOD'] : 'GET')
+        {
+            case 'PUT':
+                parse_str(file_get_contents($this->_inputStream), $this->_params);
+                break;
+            case 'POST':
+                $this->_params = $_POST;
+                break;
+            default:
+                $this->_params = $_GET;
+        }
+
+        // prepare paremeters, depending on current operation
+        if (
+            (array_key_exists('data', $this->_params) && !empty($this->_params['data'])) ||
+            (array_key_exists('attachment', $this->_params) && !empty($this->_params['attachment']))
+        )
+        {
+            $this->_operation = 'create';
+        }
+        elseif (
+            array_key_exists('pasteid', $this->_params) && !empty($this->_params['pasteid']) &&
+            array_key_exists('deletetoken', $this->_params) && !empty($this->_params['deletetoken'])
+        )
+        {
+            $this->_operation = 'delete';
+        }
+        // display an existing paste
+        elseif (array_key_exists('QUERY_STRING', $_SERVER) && !empty($_SERVER['QUERY_STRING']))
+        {
+            $this->_operation = 'read';
+            $this->_params['pasteid'] = $_SERVER['QUERY_STRING'];
+        }
+    }
+
+    /**
+     * Get current operation.
+     *
+     * @access public
+     * @return string
+     */
+    public function getOperation()
+    {
+        return $this->_operation;
+    }
+
+    /**
+     * Get a request parameter.
+     *
+     * @access public
+     * @param  string $param
+     * @param  string $default
+     * @return string
+     */
+    public function getParam($param, $default = '')
+    {
+        return array_key_exists($param, $this->_params) ? $this->_params[$param] : $default;
+    }
+
+    /**
+     * If we are in a JSON API context.
+     *
+     * @access public
+     * @return bool
+     */
+    public function isJsonApiCall()
+    {
+        return $this->_isJsonApi;
+    }
+
+    /**
+     * Override the default input stream source
+     *
+     * @param unknown $input
+     */
+    public function setInputStream($input)
+    {
+        $this->_inputStream = $input;
+        $this->__construct();
+    }
+}

+ 44 - 56
lib/zerobin.php

@@ -87,6 +87,14 @@ class zerobin
      */
     private $_model;
 
+    /**
+     * request
+     *
+     * @access private
+     * @var    request
+     */
+    private $_request;
+
     /**
      * constructor
      *
@@ -102,38 +110,27 @@ class zerobin
             throw new Exception(i18n::_('ZeroBin requires php 5.2.6 or above to work. Sorry.'), 1);
         }
 
-        // in case stupid admin has left magic_quotes enabled in php.ini
-        if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc())
-        {
-            $_POST   = array_map('filter::stripslashes_deep', $_POST);
-            $_GET    = array_map('filter::stripslashes_deep', $_GET);
-            $_COOKIE = array_map('filter::stripslashes_deep', $_COOKIE);
-        }
-
         // load config from ini file
         $this->_init();
 
-        // create new paste or comment
-        if (
-            (array_key_exists('data', $_POST) && !empty($_POST['data'])) ||
-            (array_key_exists('attachment', $_POST) && !empty($_POST['attachment']))
-        )
+        switch ($this->_request->getOperation())
         {
-            $this->_create();
-        }
-        // delete an existing paste
-        elseif (!empty($_GET['deletetoken']) && !empty($_GET['pasteid']))
-        {
-            $this->_delete($_GET['pasteid'], $_GET['deletetoken']);
-        }
-        // display an existing paste
-        elseif (!empty($_SERVER['QUERY_STRING']))
-        {
-            $this->_read($_SERVER['QUERY_STRING']);
+            case 'create':
+                $this->_create();
+                break;
+            case 'delete':
+                $this->_delete(
+                    $this->_request->getParam('pasteid'),
+                    $this->_request->getParam('deletetoken')
+                );
+                break;
+            case 'read':
+                $this->_read($this->_request->getParam('pasteid'));
+                break;
         }
 
         // output JSON or HTML
-        if (strlen($this->_json))
+        if ($this->_request->isJsonApiCall())
         {
             header('Content-type: application/json');
             echo $this->_json;
@@ -164,6 +161,7 @@ class zerobin
 
         $this->_conf = new configuration;
         $this->_model = new model($this->_conf);
+        $this->_request = new request;
     }
 
     /**
@@ -199,11 +197,9 @@ class zerobin
             )
         );
 
-        $has_attachment = array_key_exists('attachment', $_POST);
-        $has_attachmentname = $has_attachment && array_key_exists('attachmentname', $_POST) && !empty($_POST['attachmentname']);
-        $data = array_key_exists('data', $_POST) ? $_POST['data'] : '';
-        $attachment = $has_attachment ? $_POST['attachment'] : '';
-        $attachmentname = $has_attachmentname ? $_POST['attachmentname'] : '';
+        $data = $this->_request->getParam('data');
+        $attachment = $this->_request->getParam('attachment');
+        $attachmentname = $this->_request->getParam('attachmentname');
 
         // Ensure content is not too big.
         $sizelimit = $this->_conf->getKey('sizelimit');
@@ -218,18 +214,17 @@ class zerobin
         );
 
         // The user posts a comment.
-        if (
-            array_key_exists('parentid', $_POST) && !empty($_POST['parentid']) &&
-            array_key_exists('pasteid',  $_POST) && !empty($_POST['pasteid'])
-        )
+        $pasteid = $this->_request->getParam('pasteid');
+        $parentid = $this->_request->getParam('parentid');
+        if (!empty($pasteid) && !empty($parentid))
         {
-            $paste = $this->_model->getPaste($_POST['pasteid']);
+            $paste = $this->_model->getPaste($pasteid);
             if ($paste->exists()) {
                 try {
-                    $comment = $paste->getComment($_POST['parentid']);
+                    $comment = $paste->getComment($parentid);
 
-                    if (array_key_exists('nickname', $_POST) && !empty($_POST['nickname'])
-                    ) $comment->setNickname($_POST['nickname']);
+                    $nickname = $this->_request->getParam('nickname');
+                    if (!empty($nickname)) $comment->setNickname($nickname);
 
                     $comment->setData($data);
                     $comment->store();
@@ -248,24 +243,24 @@ class zerobin
         {
             $paste = $this->_model->getPaste();
             try {
-                if ($has_attachment)
+                if (!empty($attachment))
                 {
                     $paste->setAttachment($attachment);
-                    if ($has_attachmentname)
+                    if (!empty($attachmentname))
                         $paste->setAttachmentName($attachmentname);
                 }
 
-                if (array_key_exists('expire', $_POST) && !empty($_POST['expire'])
-                ) $paste->setExpiration($_POST['expire']);
+                $expire = $this->_request->getParam('expire');
+                if (!empty($expire)) $paste->setExpiration($expire);
 
-                if (array_key_exists('burnafterreading', $_POST) && !empty($_POST['burnafterreading'])
-                ) $paste->setBurnafterreading($_POST['burnafterreading']);
+                $burnafterreading = $this->_request->getParam('burnafterreading');
+                if (!empty($burnafterreading)) $paste->setBurnafterreading($burnafterreading);
 
-                if (array_key_exists('opendiscussion', $_POST) && !empty($_POST['opendiscussion'])
-                ) $paste->setOpendiscussion($_POST['opendiscussion']);
+                $opendiscussion = $this->_request->getParam('opendiscussion');
+                if (!empty($opendiscussion)) $paste->setOpendiscussion($opendiscussion);
 
-                if (array_key_exists('formatter', $_POST) && !empty($_POST['formatter'])
-                ) $paste->setFormatter($_POST['formatter']);
+                $formatter = $this->_request->getParam('formatter');
+                if (!empty($formatter)) $paste->setFormatter($formatter);
 
                 $paste->setData($data);
                 $paste->store();
@@ -339,12 +334,6 @@ class zerobin
      */
     private function _read($dataid)
     {
-        $isJson = false;
-        if (($pos = strpos($dataid, '&json')) !== false) {
-            $isJson = true;
-            $dataid = substr($dataid, 0, $pos);
-        }
-
         try {
             $paste = $this->_model->getPaste($dataid);
             if ($paste->exists())
@@ -362,10 +351,9 @@ class zerobin
             }
         } catch (Exception $e) {
             $this->_error = $e->getMessage();
-            return;
         }
 
-        if ($isJson)
+        if ($this->_request->isJsonApiCall())
         {
             if (strlen($this->_error))
             {

+ 3 - 1
tst/request.php

@@ -58,8 +58,10 @@ class requestTest extends PHPUnit_Framework_TestCase
         $this->reset();
         $_SERVER['REQUEST_METHOD'] = 'PUT';
         $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
-        $_POST['data'] = 'foo';
+        $file = tempnam(sys_get_temp_dir(), 'FOO');
+        file_put_contents($file, 'data=foo');
         $request = new request;
+        $request->setInputStream($file);
         $this->assertTrue($request->isJsonApiCall(), 'is JSON Api call');
         $this->assertEquals('create', $request->getOperation());
         $this->assertEquals('foo', $request->getParam('data'));

+ 42 - 2
tst/zerobin.php

@@ -113,6 +113,8 @@ class zerobinTest extends PHPUnit_Framework_TestCase
     {
         $this->reset();
         $_POST = helper::getPaste();
+        $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
+        $_SERVER['REQUEST_METHOD'] = 'POST';
         $_SERVER['REMOTE_ADDR'] = '::1';
         ob_start();
         new zerobin;
@@ -134,6 +136,8 @@ class zerobinTest extends PHPUnit_Framework_TestCase
     {
         $this->reset();
         $_POST = helper::getPaste();
+        $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
+        $_SERVER['REQUEST_METHOD'] = 'POST';
         $_SERVER['REMOTE_ADDR'] = '::1';
         ob_start();
         new zerobin;
@@ -155,6 +159,8 @@ class zerobinTest extends PHPUnit_Framework_TestCase
         helper::confBackup();
         helper::createIniFile(CONF, $options);
         $_POST = helper::getPaste();
+        $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
+        $_SERVER['REQUEST_METHOD'] = 'POST';
         $_SERVER['REMOTE_ADDR'] = '::1';
         ob_start();
         new zerobin;
@@ -176,6 +182,8 @@ class zerobinTest extends PHPUnit_Framework_TestCase
         helper::createIniFile(CONF, $options);
         $_POST = helper::getPaste();
         $_SERVER['HTTP_X_FORWARDED_FOR'] = '::1';
+        $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
+        $_SERVER['REQUEST_METHOD'] = 'POST';
         ob_start();
         new zerobin;
         $content = ob_get_contents();
@@ -196,6 +204,8 @@ class zerobinTest extends PHPUnit_Framework_TestCase
         helper::createIniFile(CONF, $options);
         $this->_model->create(helper::getPasteId(), helper::getPaste());
         $_POST = helper::getPaste();
+        $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
+        $_SERVER['REQUEST_METHOD'] = 'POST';
         $_SERVER['REMOTE_ADDR'] = '::1';
         ob_start();
         new zerobin;
@@ -218,6 +228,8 @@ class zerobinTest extends PHPUnit_Framework_TestCase
         $_POST = helper::getPaste();
         $_POST['expire'] = '5min';
         $_POST['formatter'] = 'foo';
+        $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
+        $_SERVER['REQUEST_METHOD'] = 'POST';
         $_SERVER['REMOTE_ADDR'] = '::1';
         ob_start();
         new zerobin;
@@ -244,6 +256,8 @@ class zerobinTest extends PHPUnit_Framework_TestCase
         helper::createIniFile(CONF, $options);
         $_POST = helper::getPaste();
         $_POST['expire'] = 'foo';
+        $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
+        $_SERVER['REQUEST_METHOD'] = 'POST';
         $_SERVER['REMOTE_ADDR'] = '::1';
         ob_start();
         new zerobin;
@@ -270,6 +284,8 @@ class zerobinTest extends PHPUnit_Framework_TestCase
         helper::createIniFile(CONF, $options);
         $_POST = helper::getPaste();
         $_POST['burnafterreading'] = 'neither 1 nor 0';
+        $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
+        $_SERVER['REQUEST_METHOD'] = 'POST';
         $_SERVER['REMOTE_ADDR'] = '::1';
         ob_start();
         new zerobin;
@@ -291,6 +307,8 @@ class zerobinTest extends PHPUnit_Framework_TestCase
         helper::createIniFile(CONF, $options);
         $_POST = helper::getPaste();
         $_POST['opendiscussion'] = 'neither 1 nor 0';
+        $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
+        $_SERVER['REQUEST_METHOD'] = 'POST';
         $_SERVER['REMOTE_ADDR'] = '::1';
         ob_start();
         new zerobin;
@@ -312,6 +330,8 @@ class zerobinTest extends PHPUnit_Framework_TestCase
         helper::confBackup();
         helper::createIniFile(CONF, $options);
         $_POST = helper::getPasteWithAttachment();
+        $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
+        $_SERVER['REQUEST_METHOD'] = 'POST';
         $_SERVER['REMOTE_ADDR'] = '::1';
         $this->assertFalse($this->_model->exists(helper::getPasteId()), 'paste does not exists before posting data');
         ob_start();
@@ -344,6 +364,8 @@ class zerobinTest extends PHPUnit_Framework_TestCase
         helper::createIniFile(CONF, $options);
         $_POST = helper::getPaste();
         $_POST['nickname'] = helper::getComment()['meta']['nickname'];
+        $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
+        $_SERVER['REQUEST_METHOD'] = 'POST';
         $_SERVER['REMOTE_ADDR'] = '::1';
         ob_start();
         new zerobin;
@@ -372,6 +394,8 @@ class zerobinTest extends PHPUnit_Framework_TestCase
         $_POST['pasteid'] = helper::getPasteId();
         $_POST['parentid'] = helper::getPasteId();
         $_POST['nickname'] = 'foo';
+        $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
+        $_SERVER['REQUEST_METHOD'] = 'POST';
         $_SERVER['REMOTE_ADDR'] = '::1';
         $this->_model->create(helper::getPasteId(), helper::getPaste());
         ob_start();
@@ -395,6 +419,8 @@ class zerobinTest extends PHPUnit_Framework_TestCase
         $_POST = helper::getComment();
         $_POST['pasteid'] = helper::getPasteId();
         $_POST['parentid'] = helper::getPasteId();
+        $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
+        $_SERVER['REQUEST_METHOD'] = 'POST';
         $_SERVER['REMOTE_ADDR'] = '::1';
         $this->_model->create(helper::getPasteId(), helper::getPaste());
         ob_start();
@@ -418,6 +444,8 @@ class zerobinTest extends PHPUnit_Framework_TestCase
         $_POST = helper::getComment();
         $_POST['pasteid'] = helper::getPasteId();
         $_POST['parentid'] = 'foo';
+        $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
+        $_SERVER['REQUEST_METHOD'] = 'POST';
         $_SERVER['REMOTE_ADDR'] = '::1';
         $this->_model->create(helper::getPasteId(), helper::getPaste());
         ob_start();
@@ -441,6 +469,8 @@ class zerobinTest extends PHPUnit_Framework_TestCase
         $_POST = helper::getComment();
         $_POST['pasteid'] = helper::getPasteId();
         $_POST['parentid'] = helper::getPasteId();
+        $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
+        $_SERVER['REQUEST_METHOD'] = 'POST';
         $_SERVER['REMOTE_ADDR'] = '::1';
         $paste = helper::getPaste(array('opendiscussion' => false));
         $this->_model->create(helper::getPasteId(), $paste);
@@ -465,6 +495,8 @@ class zerobinTest extends PHPUnit_Framework_TestCase
         $_POST = helper::getComment();
         $_POST['pasteid'] = helper::getPasteId();
         $_POST['parentid'] = helper::getPasteId();
+        $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
+        $_SERVER['REQUEST_METHOD'] = 'POST';
         $_SERVER['REMOTE_ADDR'] = '::1';
         ob_start();
         new zerobin;
@@ -490,6 +522,8 @@ class zerobinTest extends PHPUnit_Framework_TestCase
         $_POST = helper::getComment();
         $_POST['pasteid'] = helper::getPasteId();
         $_POST['parentid'] = helper::getPasteId();
+        $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
+        $_SERVER['REQUEST_METHOD'] = 'POST';
         $_SERVER['REMOTE_ADDR'] = '::1';
         ob_start();
         new zerobin;
@@ -611,7 +645,8 @@ class zerobinTest extends PHPUnit_Framework_TestCase
     {
         $this->reset();
         $this->_model->create(helper::getPasteId(), helper::getPaste());
-        $_SERVER['QUERY_STRING'] = helper::getPasteId() . '&json';
+        $_SERVER['QUERY_STRING'] = helper::getPasteId();
+        $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
         ob_start();
         new zerobin;
         $content = ob_get_contents();
@@ -626,7 +661,8 @@ class zerobinTest extends PHPUnit_Framework_TestCase
     public function testReadInvalidJson()
     {
         $this->reset();
-        $_SERVER['QUERY_STRING'] = helper::getPasteId() . '&json';
+        $_SERVER['QUERY_STRING'] = helper::getPasteId();
+        $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
         ob_start();
         new zerobin;
         $content = ob_get_contents();
@@ -784,6 +820,8 @@ class zerobinTest extends PHPUnit_Framework_TestCase
         $this->assertTrue($this->_model->exists(helper::getPasteId()), 'paste exists before deleting data');
         $_GET['pasteid'] = helper::getPasteId();
         $_GET['deletetoken'] = 'burnafterreading';
+        $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
+        $_SERVER['REQUEST_METHOD'] = 'DELETE';
         ob_start();
         new zerobin;
         $content = ob_get_contents();
@@ -802,6 +840,8 @@ class zerobinTest extends PHPUnit_Framework_TestCase
         $this->assertTrue($this->_model->exists(helper::getPasteId()), 'paste exists before deleting data');
         $_GET['pasteid'] = helper::getPasteId();
         $_GET['deletetoken'] = 'burnafterreading';
+        $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
+        $_SERVER['REQUEST_METHOD'] = 'DELETE';
         ob_start();
         new zerobin;
         $content = ob_get_contents();