PHP FPM Script Name Bug Breaking Owncloud

Submitted by kevin on Mon, 08/08/2016 - 13:22

Recently updated my Raspberry Pi 2 running Arch Linux through pacman -Syu. This pulled in the latest versions of Apache 2.4 and PHP 7, normally staying on the same major version doesn't introduce any breaking changes, however this time all the PHP based applications stopped working.

OwnCloud was one which started a redirect 302 loop on the login page and the Sync Client also stopped working. The actual setup is quite basic, Owncloud installed though pacman -S owncloud

Apache 2.4 installed with a simple virtual host:

sudo vim /etc/httpd/conf/extra/owncloud.conf 

<VirtualHost>

ServerName owncloud.castle 
ServerAdmin support@castle 
DocumentRoot /usr/share/webapps/owncloud/ 

SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 
SetEnv HOME /usr/share/webapps/owncloud 
SetEnv HTTP_HOME /usr/share/webapps/owncloud 

DirectoryIndex index.php 
ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9001/usr/share/webapps/owncloud/$1 

<Directory>
AllowOverride All 
Require all granted 
</Directory>

ErrorLog "/var/log/httpd/owncloud.error.log" 
CustomLog "/var/log/httpd/owncloud.access.log" combined 

</VirtualHost>

PHP 7 through php-fpm service on port 9001

/etc/php/php-fpm.d/owncloud.conf 

[owncloud] 
user = http 
group = http 
listen = 127.0.0.1:9001 
listen.owner = http 
listen.group = http 
listen.allowed_clients = 127.0.0.1 
pm = dynamic 
pm.max_children = 5 
pm.start_servers = 2 
pm.min_spare_servers = 1 
pm.max_spare_servers = 3 

Applying the below patch file to OwnCloud 9.1.0-1 will fix the $_SERVER['SCRIPT_NAME'] bug for now. The bug is FPM/Apache setting SCRIPT_NAME to be the entire URI after the domain instead of just the script/file name being called. E.g /index.php/apps/files instead of the expected /index.php.

Patch file for /usr/share/webapps/owncloud/lib/private/AppFramework/Http/Request.php

diff --git a/lib/private/AppFramework/Http/Request.php b/lib/private/AppFramework/Http/Request.php
index 1508158..994ef60 100644
--- a/lib/private/AppFramework/Http/Request.php
+++ b/lib/private/AppFramework/Http/Request.php
@@ -594,7 +594,7 @@
    public function getRequestUri() {
        $uri = isset($this->server['REQUEST_URI']) ? $this->server['REQUEST_URI'] : '';
        if($this->config->getSystemValue('overwritewebroot') !== '' &amp;&amp; $this->isOverwriteCondition()) {
-           $uri = $this->getScriptName() . substr($uri, strlen($this->server['SCRIPT_NAME']));
+           $uri = $this->getScriptName() . substr($uri, strlen($this->fixPhpFpmScriptName()));
        }
        return $uri;
    }
@@ -618,7 +618,7 @@
            $requestUri = substr($requestUri, 0, $pos);
        }

-       $scriptName = $this->server['SCRIPT_NAME'];
+       $scriptName = $this->fixPhpFpmScriptName();
        $pathInfo = $requestUri;

        // strip off the script name's dir and file name
@@ -674,7 +674,7 @@
     * @return string the script name
     */
    public function getScriptName() {
-       $name = $this->server['SCRIPT_NAME'];
+       $name = $this->fixPhpFpmScriptName();
        $overwriteWebRoot =  $this->config->getSystemValue('overwritewebroot');
        if ($overwriteWebRoot !== '' &amp;&amp; $this->isOverwriteCondition()) {
            // FIXME: This code is untestable due to __DIR__, also that hardcoded path is really dangerous
@@ -770,5 +770,18 @@
        }
        return null;
    }
+    
+    /**
+     * Fixes major bug in Apache 2.4 / PHP 7 FPM where script_name contains full
+     * uri not just script name e.g /index.php/app/files instead of expected /index.php 
+     * @param string $name
+     * @return string
+     */
+    private function fixPhpFpmScriptName() {
+        if (strpos($this->server['SCRIPT_NAME'], '.php') !== false) {
+            $name = DIRECTORY_SEPARATOR . basename($this->server['SCRIPT_FILENAME']);
+        }
+        return $name;
+    }

 }