[OJS3.0.2] Webserver delivers [ORIG_PATH_INFO] instead of [PATH_INFO]


I finally figured out, that the webserver, on which our OJS journal is hosted, delivers [ORIG_PATH_INFO] instead of [PATH_INFO].

PHP manual (http://php.net/manual/en/reserved.variables.server.php) simply says »‘ORIG_PATH_INFO’: Original version of ‘PATH_INFO’ before processed by PHP.«. I can not see, how to change this behavior, so I’m strongly considering to change the core of OJS (but it hurts so much to only think about this …).

I made a search over all OJS files and found many occurrences where $_SERVER[‘PATH_INFO’] is used:
—> if (!isset($_SERVER[‘PATH_INFO’])) return null;
—> $pathInfoParts = explode(’/’, trim($_SERVER[‘PATH_INFO’], ‘/’));
—> $id = isset($_SERVER[‘PATH_INFO’])?$_SERVER[‘PATH_INFO’]:‘index’;
—> $id = isset($_SERVER[‘PATH_INFO’])?$_SERVER[‘PATH_INFO’]:‘index’;
—> if (isset($_SERVER[‘PATH_INFO’])) {
—> $url = $_SERVER[‘PATH_INFO’];
—> $_this->_requestPath .= isset($_SERVER[‘PATH_INFO’]) ? $_SERVER[‘PATH_INFO’] : ‘’;
—> $_this->_requestPath .= isset($_SERVER[‘PATH_INFO’]) ? $_SERVER[‘PATH_INFO’] : ‘’;
—> if (isset($_SERVER[‘PATH_INFO’])) {
—> $url = $_SERVER[‘PATH_INFO’];
—> $_SERVER[‘PATH_INFO’] = null;
—> $_SERVER[‘PATH_INFO’] = ‘/context1/context2/other/path/vars’;
—> $_SERVER[‘PATH_INFO’] = ‘/context’;
—> $_SERVER[‘PATH_INFO’] = ‘/context:?#/’;
—> $_SERVER[‘PATH_INFO’] = ‘/contextPath’;
—> $_SERVER[‘PATH_INFO’] = ‘/’;
—> $_SERVER[‘PATH_INFO’] = $path;
—> $path = (isset($_SERVER[‘PATH_INFO’])) ? $_SERVER[‘PATH_INFO’] : @getenv(‘PATH_INFO’);
—> $path = (isset($_SERVER[‘PATH_INFO’])) ? $_SERVER[‘PATH_INFO’] : @getenv(‘PATH_INFO’);

I do have to change all – right? Or is there another solution to this problem?

Since I don’t think, that this is specifically hurting me: Would’nt it be better, if OJS takes care of both variants [ORIG_PATH_INFO] and [PATH_INFO]?


PS. tinymce takes a lot more alternatives for [PATH_INFO] into consideration either:
TATuP-302/plugins/generic/tinymce/plugins/justboil.me/ci/system/core/URI.php (lines 85 to 147)

Hadn’t noticed such problem, when was playing with the code. How could OJS, in theory, modify $_SERVER variable?

Ahh, the problem is in the web server…


maybe I haven’t pointed it out exactly enough (pardon for that): OJS doesn’t modify the $_SERVER. The apache of our hosting provider delivers $_SERVER with [ORIG_PATH_INFO] instead of [PATH_INFO].


I should add here, that we are on a service hosting provider, so I don’t have any chance to change webserver configuration except for .htaccess or php.ini within the ojs folder.


Hi @twa,

You may be able to fix this via .htaccess – but it’ll depend on your server configuration. Your best bet would be to contact your ISP and see if they’re willing to get that CGI variable working. You could modify OJS, but that wouldn’t be hitting the problem at the root.

Alec Smecher
Public Knowledge Project Team

Hej @asmecher,

I’ll contact the ISP (1und1.de), but I’m not very optimistic about that …

Do you have any idea, which .htaccess command could changes this behaviour? I tried »AcceptPathInfo On«, but it doesn’t change anything.


Hi @twa,

The short answer is that your web server is operating out of spec. See RFC3875 – it includes a description of the PATH_INFO CGI variable but not ORIG_PATH_INFO, which appears to be some kind of hack around various servers’ SAPI configurations and PHP integration. I’m afraid I’d be googling around for solutions, same as you.

Alec Smecher
Public Knowledge Project Team

Thanks for your thoughts. I contacted the ISP and still have to be patient about an answer. If there ever will be one, I’ll post it.

But wouldn’t it be better to extend the PKP support for those systems? I already mentioned tinymce’s image plugin »justboil.me« procedure, which takes a lot more alternatives for [PATH_INFO] into consideration:
justboil.me/URI.php at master · vikdiesel/justboil.me · GitHub (lines 103 to 129)
Even something like

if (empty($path_info)) {
$path_info = str_replace($_SERVER[‘SCRIPT_NAME’],’’,$_SERVER[‘REQUEST_URI’]);


Hi @asmecher,

I found another interesting implementation:

| This item determines which server global should be used to retrieve the
| URI string. The default setting of ‘AUTO’ works for most servers.
| If your links do not seem to work, try one of the other delicious flavors:
| ‘AUTO’ Default - auto detects
$config[‘uri_protocol’] = ‘QUERY_STRING’;

An approach like this instead of PATH_INFO yes/no would bring way more flexibility to fit all the different server settings out there (and BTW solve my problem). Please consider something like this for a future release …


@asmecher, would you mind answering me a question for my try to change the code? I’d like to give it a try.

I searched the whole code for PATH_INFO and changed it to ORIG_PATH_INFO, which is the corresponding variable part on our ISP server configuration. After the upload of the changed code, the connection to the stylesheets are lost. When I look at the HTML, there is a »$$$call$$$« insider the path for the stylesheet. What’s this? And: Is this »normal behaviour«?


@asmecher, you could see a test installation with broken stylesheets online here:

Hi @twa,

I’d be open to a pull request. Either approach (configuring which CGI parameter to use in the config.inc.php configuration file, or automatically falling back on ORIG_PATH_INFO when PATH_INFO isn’t set) would be fine with me.

Strictly speaking, I think this is solving the problem in the wrong place – the web server should be fixed to operate within the CGI spec. However, it’s common enough that OJS users won’t have access to make that fix that a work-around is acceptable.

Alec Smecher
Public Knowledge Project Team

@asmecher, thanks for taking that up.

Meanwhile I got a workaround for the server (mis)configuration on my ISP, which needs to have the possibility to inject local php.ini (or .user.ini):

Add the file on OJS root folder or append a new line into existing

auto_prepend_file = set_path_info.php

Add a new file in OJS root folder

if (getenv('ORIG_PATH_INFO')) {
if ($_ENV['ORIG_PATH_INFO']) {

This automatically rewrites ‘ORIG_PATH_INFO’ into ‘PATH_INFO’ without touching the source code of OJS. My tests with a test.php (<?php print_r($_SERVER); ?>) were successful. But, still, all my stylesheets are broken and the navigation doesn’t work properly after setting disable_path_info = Off in config.inc.php.

Do I miss something? Do I have to change another variable inside config.inc.php to make this work? Or do I have to change something in .htaccess?
Any help would be great!



## activate PATH_INFO ?
AcceptPathInfo On

Header add Access-Control-Allow-Origin "*"
Header add Access-Control-Allow-Headers "origin, x-requested-with, content-type"
Header add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"

##<IfModule mod_rewrite.c>

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !^.*/index.php/.*$
RewriteRule ^(.*)$ /index.php/$1 [QSA,L]



; <?php exit(); // DO NOT DELETE ?>
; Doing so will expose this configuration file through your web site!

; config.TEMPLATE.inc.php
; Copyright (c) 2014-2017 Simon Fraser University
; Copyright (c) 2003-2017 John Willinsky
; Distributed under the GNU GPL v2. For full terms see the file docs/COPYING.
; OJS Configuration settings.
; Rename config.TEMPLATE.inc.php to config.inc.php to use.

; General Settings ;


; Set this to On once the system has been installed
; (This is generally done automatically by the installer)
installed = On

; The canonical URL to the OJS installation (excluding the trailing slash)
base_url = "http://www.tatup.de"

; Session cookie name
session_cookie_name = OJSSID

; Session cookie path; if not specified, defaults to the detected base path
; session_cookie_path = /

; Number of days to save login cookie for if user selects to remember
; (set to 0 to force expiration at end of current session)
session_lifetime = 30

; Enable support for running scheduled tasks
; Set this to On if you have set up the scheduled tasks script to
; execute periodically
scheduled_tasks = Off

; Site time zone
; Please refer to lib/pkp/registry/timeZones.xml for a full list of supported
; time zones.
; I.e.:
; <entry key="Europe/Amsterdam" name="Amsterdam" />
; time_zone="Amsterdam"
time_zone = "Berlin"

; Short and long date formats
date_format_trunc = "%m-%d"
date_format_short = "%d.%m.%Y"
date_format_long = "%B %e, %Y"
datetime_format_short = "%d.%m.%Y - %I:%M %p"
datetime_format_long = "%B %e, %Y - %I:%M %p"
time_format = "%I:%M %p"

; Use URL parameters instead of CGI PATH_INFO. This is useful for
; broken server setups that don't support the PATH_INFO environment
; variable.
disable_path_info = On

; Use fopen(...) for URL-based reads. Modern versions of dspace
; will not accept requests using fopen, as it does not provide a
; User Agent, so this option is disabled by default. If this feature
; is disabled by PHP's configuration, this setting will be ignored.
allow_url_fopen = Off

; Base URL override settings: Entries like the following examples can
; be used to override the base URLs used by OJS. If you want to use a
; proxy to rewrite URLs to OJS, configure your proxy's URL here.
; Syntax: base_url[journal_path] = http://www.myUrl.com
; To override URLs that aren't part of a particular journal, use a
; journal_path of "index".
; Examples:
; base_url[index] = http://www.myUrl.com
; base_url[myJournal] = http://www.myUrl.com/myJournal
; base_url[myOtherJournal] = http://myOtherJournal.myUrl.com

; Generate RESTful URLs using mod_rewrite.  This requires the
; rewrite directive to be enabled in your .htaccess or httpd.conf.
; See FAQ for more details.
restful_urls = On

; Allow the X_FORWARDED_FOR header to override the REMOTE_ADDR as the source IP
; Set this to "On" if you are behind a reverse proxy and you control the X_FORWARDED_FOR
; Warning: This defaults to "On" if unset for backwards compatibility.
trust_x_forwarded_for = Off

; Allow javascript files to be served through a content delivery network (set to off to use local files)
enable_cdn = On

; Set the maximum number of citation checking processes that may run in parallel.
; Too high a value can increase server load and lead to too many parallel outgoing
; requests to citation checking web services. Too low a value can lead to significantly
; slower citation checking performance. A reasonable value is probably between 3
; and 10. The more your connection bandwidth allows the better.
citation_checking_max_processes = 3

; Display a message on the site admin and journal manager user home pages if there is an upgrade available
show_upgrade_warning = On

; Set the following parameter to off if you want to work with the uncompiled (non-minified) JavaScript
; source for debugging or if you are working off a development branch without compiled JavaScript.
enable_minified = On

; Provide a unique site ID and OAI base URL to PKP for statistics and security
; alert purposes only.
enable_beacon = On

; Database Settings ;


; Enable persistent connections
persistent = Off

; Enable database debug output (very verbose!)
debug = Off

; Cache Settings ;


; Choose the type of object data caching to use. Options are:
; - memcache: Use the memcache server configured below
; - xcache: Use the xcache variable store
; - apc: Use the APC variable store
; - none: Use no caching.
object_cache = none

; Enable memcache support
memcache_hostname = localhost
memcache_port = 11211

; For site visitors who are not logged in, many pages are often entirely
; static (e.g. About, the home page, etc). If the option below is enabled,
; these pages will be cached in local flat files for the number of hours
; specified in the web_cache_hours option. This will cut down on server
; overhead for many requests, but should be used with caution because:
; 1) Things like journal metadata changes will not be reflected in cached
;    data until the cache expires or is cleared, and
; However, for situations like hosting high-volume open access journals, it's
; an easy way of decreasing server load.
; When using web_cache, configure a tool to periodically clear out cache files
; such as CRON. For example, configure it to run the following command:
; find .../ojs/cache -maxdepth 1 -name wc-\*.html -mtime +1 -exec rm "{}" ";"
web_cache = Off
web_cache_hours = 1

; Localization Settings ;


; Default locale
locale = en_US

; Client output/input character set
client_charset = utf-8

; Database connection character set
; Must be set to "Off" if not supported by the database server
; If enabled, must be the same character set as "client_charset"
; (although the actual name may differ slightly depending on the server)
connection_charset = Off

; Database storage character set
; Must be set to "Off" if not supported by the database server
database_charset = Off

; Enable character normalization to utf-8 (recommended)
; If disabled, strings will be passed through in their native encoding
; Note that client_charset and database collation must be set
; to "utf-8" for this to work, as characters are stored in utf-8
charset_normalization = Off

; File Settings ;


; Complete path to directory to store uploaded files
; (This directory should not be directly web-accessible)
; Windows users should use forward slashes
files_dir = /...

; Path to the directory to store public uploaded files
; (This directory should be web-accessible and the specified path
; should be relative to the base OJS directory)
; Windows users should use forward slashes
public_files_dir = public

; Permissions mask for created files and directories
umask = 0022

; The minimum percentage similarity between filenames that should be considered
; a possible revision
filename_revision_match = 70

; Fileinfo (MIME) Settings ;

; mime_database_path = /etc/magic.mime

; Security Settings ;


; Force SSL connections site-wide
force_ssl = Off

; Force SSL connections for login only
force_login_ssl = Off

; This check will invalidate a session if the user's IP address changes.
; Enabling this option provides some amount of additional security, but may
; cause problems for users behind a proxy farm (e.g., AOL).
session_check_ip = On

; The encryption (hashing) algorithm to use for encrypting user passwords
; Valid values are: md5, sha1
; NOTE: This hashing method is deprecated, but necessary to permit gradual
; migration of old password hashes.
encryption = sha1

; The unique salt to use for generating password reset hashes
salt = "...."

; The number of seconds before a password reset hash expires (defaults to 7200 / 2 hours)
reset_seconds = 7200

; Allowed HTML tags for fields that permit restricted HTML.
; Use e.g. "img[src,alt],p" to allow "src" and "alt" attributes to the "img"
; tag, and also to permit the "p" paragraph tag. Unspecified attributes will be
; stripped.
allowed_html = "a[href|target|title],em,strong,cite,code,ul,ol,li[class],dl,dt,dd,b,i,u,img[src|alt],sup,sub,br,p"

;Is implicit authentication enabled or not

;implicit_auth = On

;Implicit Auth Header Variables

;implicit_auth_header_first_name = HTTP_GIVENNAME
;implicit_auth_header_last_name = HTTP_SN
;implicit_auth_header_email = HTTP_MAIL
;implicit_auth_header_phone = HTTP_TELEPHONENUMBER
;implicit_auth_header_initials = HTTP_METADATA_INITIALS
;implicit_auth_header_mailing_address = HTTP_METADATA_HOMEPOSTALADDRESS
;implicit_auth_header_uin = HTTP_UID

; A space delimited list of uins to make admin
;implicit_auth_admin_list = "jdoe@email.ca jshmo@email.ca"

; URL of the implicit auth 'Way Finder' page. See pages/login/LoginHandler.inc.php for usage.

;implicit_auth_wayf_url = "/Shibboleth.sso/wayf"

; Email Settings ;


; Use SMTP for sending mail instead of mail()
; smtp = On

; SMTP server settings
; smtp_server = mail.example.com
; smtp_port = 25

; Enable SMTP authentication
; Supported mechanisms: ssl, tls
; smtp_auth = ssl
; smtp_username = username
; smtp_password = password

; Allow envelope sender to be specified
; (may not be possible with some server configurations)
; allow_envelope_sender = Off

; Default envelope sender to use if none is specified elsewhere
; default_envelope_sender = my_address@my_host.com

; Force the default envelope sender (if present)
; This is useful if setting up a site-wide noreply address
; The reply-to field will be set with the reply-to or from address.
; force_default_envelope_sender = Off

; Amount of time required between attempts to send non-editorial emails
; in seconds. This can be used to help prevent email relaying via OJS.
time_between_emails = 3600

; Maximum number of recipients that can be included in a single email
; (either as To:, Cc:, or Bcc: addresses) for a non-priveleged user
max_recipients = 10

; If enabled, email addresses must be validated before login is possible.
require_validation = Off

; Maximum number of days before an unvalidated account expires and is deleted
validation_timeout = 14

; Search Settings ;


; Minimum indexed word length
min_word_length = 3

; The maximum number of search results fetched per keyword. These results
; are fetched and merged to provide results for searches with several keywords.
results_per_keyword = 500

; The number of hours for which keyword search results are cached.
result_cache_hours = 1

; Paths to helper programs for indexing non-text files.
; Programs are assumed to output the converted text to stdout, and "%s" is
; replaced by the file argument.
; Note that using full paths to the binaries is recommended.
; Uncomment applicable lines to enable (at most one per file type).
; Additional "index[MIME_TYPE]" lines can be added for any mime type to be
; indexed.

; index[application/pdf] = "/usr/bin/pstotext -enc UTF-8 -nopgbrk %s - | /usr/bin/tr '[:cntrl:]' ' '"
; index[application/pdf] = "/usr/bin/pdftotext -enc UTF-8 -nopgbrk %s - | /usr/bin/tr '[:cntrl:]' ' '"

; PostScript
; index[application/postscript] = "/usr/bin/pstotext -enc UTF-8 -nopgbrk %s - | /usr/bin/tr '[:cntrl:]' ' '"
; index[application/postscript] = "/usr/bin/ps2ascii %s | /usr/bin/tr '[:cntrl:]' ' '"

; Microsoft Word
; index[application/msword] = "/usr/bin/antiword %s"
; index[application/msword] = "/usr/bin/catdoc %s"

; OAI Settings ;


; Enable OAI front-end to the site
oai = On

; OAI Repository identifier
repository_id = TaTup

; Maximum number of records per request to serve via OAI
oai_max_records = 100

; Interface Settings ;


; Number of items to display per page; overridable on a per-journal basis
items_per_page = 25

; Number of page links to display; overridable on a per-journal basis
page_links = 10

; Captcha Settings ;


; Whether or not to enable ReCaptcha
recaptcha = off

; Public key for reCaptcha (see http://www.google.com/recaptcha)
recaptcha_public_key = your_public_key

; Private key for reCaptcha (see http://www.google.com/recaptcha)
recaptcha_private_key = your_private_key

; Whether or not to use Captcha on user registration
captcha_on_register = on

; External Commands ;


; These are paths to (optional) external binaries used in
; certain plug-ins or advanced program features.

; Using full paths to the binaries is recommended.

; perl (used in paracite citation parser)
perl = /usr/bin/perl

; tar (used in backup plugin, translation packaging)
tar = /bin/tar

; On systems that do not have libxsl/xslt libraries installed, or for those who
; require a specific XSLT processor, you may enter the complete path to the
; XSLT renderer tool, with any required arguments. Use %xsl to substitute the
; location of the XSL stylesheet file, and %xml for the location of the XML
; source file; eg:
; /usr/bin/java -jar ~/java/xalan.jar -HTML -IN %xml -XSL %xsl
xslt_command = ""

; Proxy Settings ;


; Note that allow_url_fopen must be set to Off before these proxy settings
; will take effect.

; The HTTP proxy configuration to use
; http_host = localhost
; http_port = 80
; proxy_username = username
; proxy_password = password

; Debug Settings ;


; Display a stack trace when a fatal error occurs.
; Note that this may expose private information and should be disabled
; for any production system.
show_stacktrace = Off

; Display an error message when something goes wrong.
display_errors = Off

; Display deprecation warnings
deprecation_warnings = Off

; Log web service request information for debugging
log_web_service_info = Off

Hi @twa,

What kinds of paths are showing up in e.g. the CSS requests that are erroneous?

Alec Smecher
Public Knowledge Project Team

Is there a progress on this thread.

In multi journal setup when each journal is given a URL something like example.com/ojs/index.php/jrnl the URL throws a 4040 not found error but works if the URL is appended with index i.e. example.com/ojs/index.php/jrnl/index and many pages end up look like example.com/ojs/index.php/index/index for the list of all journals.

I thought the tread would help me resolve this issue as well. Waiting…

Solution IONOS and OJS 3.3.X

change $_SERVER[‘PATH_INFO’] by $_SERVER[‘ORIG_PATH_INFO’] in this files

- lib/pkp/classes/core/PKPComponentRouter.inc.php:			if (!isset($_SERVER['PATH_INFO'])) return null;
- lib/pkp/classes/core/PKPComponentRouter.inc.php:			$pathInfoParts = explode('/', trim($_SERVER['PATH_INFO'], '/'));
- lib/pkp/classes/core/PKPRequest.inc.php:				$this->_requestPath .= isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '';
- lib/pkp/classes/core/PKPRouter.inc.php:				if (isset($_SERVER['PATH_INFO'])) {
- lib/pkp/classes/core/PKPRouter.inc.php:					$url = $_SERVER['PATH_INFO'];
- lib/pkp/classes/core/APIRouter.inc.php:		if ($pathInfoEnabled && isset($_SERVER['PATH_INFO'])) {
- lib/pkp/classes/core/APIRouter.inc.php:			return explode('/', trim($_SERVER['PATH_INFO'], '/'));
- lib/pkp/classes/core/PKPPageRouter.inc.php:				$id = isset($_SERVER['PATH_INFO'])?$_SERVER['PATH_INFO']:'index';
- lib/pkp/classes/core/PKPPageRouter.inc.php:			if (isset($_SERVER['PATH_INFO'])) {
- lib/pkp/classes/core/PKPPageRouter.inc.php:				$url = $_SERVER['PATH_INFO'];
- lib/pkp/classes/handler/APIHandler.inc.php:			if (!$pathInfoEnabled && !is_null($endpoint) && !isset($_SERVER['PATH_INFO']) && ($path == '/')) {
- lib/pkp/classes/handler/APIHandler.inc.php:				$newUri = $uri->withPath($_SERVER['PATH_INFO']);

Create .htaccess with this content

RewriteRule ^$ /index.php/index [L]
ErrorDocument 404 /404.html