Просмотр исходного кода

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 10 лет назад
Родитель
Сommit
7ec94e0db5
5 измененных файлов с 339 добавлено и 118 удалено
  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();