Issues (982)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * COPS (Calibre OPDS PHP Server) class file
4
 *
5
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6
 * @author     Sébastien Lucas <[email protected]>
7
 */
8
9
require 'config.php';
10
11
define ('VERSION', '1.1.1');
12
define ('DB', 'db');
13
date_default_timezone_set($config['default_timezone']);
14
15
16
function useServerSideRendering()
17
{
18 3
    global $config;
19 3
    return preg_match('/' . $config['cops_server_side_render'] . '/', $_SERVER['HTTP_USER_AGENT']);
20
}
21
22
function serverSideRender($data)
23
{
24
    // Get the templates
25 2
    $theme = getCurrentTemplate ();
26 2
    $header = file_get_contents('templates/' . $theme . '/header.html');
27 2
    $footer = file_get_contents('templates/' . $theme . '/footer.html');
28 2
    $main = file_get_contents('templates/' . $theme . '/main.html');
29 2
    $bookdetail = file_get_contents('templates/' . $theme . '/bookdetail.html');
30 2
    $page = file_get_contents('templates/' . $theme . '/page.html');
31
32
    // Generate the function for the template
33 2
    $template = new doT ();
34 2
    $dot = $template->template ($page, array ('bookdetail' => $bookdetail,
35 2
                                              'header' => $header,
36 2
                                              'footer' => $footer,
37 2
                                              'main' => $main));
38
    // If there is a syntax error in the function created
39
    // $dot will be equal to FALSE
40 2
    if (!$dot) {
41
        return FALSE;
42
    }
43
    // Execute the template
44 2
    if (!empty ($data)) {
45
        return $dot ($data);
46
    }
47
48 2
    return NULL;
49
}
50
51
function getQueryString()
52
{
53 18
    if (isset($_SERVER['QUERY_STRING'])) {
54 16
        return $_SERVER['QUERY_STRING'];
55
    }
56 2
    return "";
57
}
58
59
function notFound()
60
{
61
    header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found');
62
    header('Status: 404 Not Found');
63
64
    $_SERVER['REDIRECT_STATUS'] = 404;
65
}
66
67
function getURLParam($name, $default = NULL)
68
{
69 134
    if (!empty ($_GET) && isset($_GET[$name]) && $_GET[$name] != '') {
70 34
        return $_GET[$name];
71
    }
72 122
    return $default;
73
}
74
75
function getCurrentOption($option)
76
{
77 100
    global $config;
78 100
    if (isset($_COOKIE[$option])) {
79 2
        if (isset($config ['cops_' . $option]) && is_array ($config ['cops_' . $option])) {
80
            return explode (',', $_COOKIE[$option]);
81
        } else {
82 2
            return $_COOKIE[$option];
83
        }
84
    }
85 98
    if (isset($config ['cops_' . $option])) {
86 98
        return $config ['cops_' . $option];
87
    }
88
89
    return '';
90
}
91
92
function getCurrentCss()
93
{
94 2
    return 'templates/' . getCurrentTemplate () . '/styles/style-' . getCurrentOption('style') . '.css';
95
}
96
97
function getCurrentTemplate()
98
{
99 4
    return getCurrentOption ('template');
100
}
101
102
function getUrlWithVersion($url)
103
{
104 69
    return $url . '?v=' . VERSION;
105
}
106
107
function xml2xhtml($xml)
108
{
109
    return preg_replace_callback('#<(\w+)([^>]*)\s*/>#s', function($m) {
110 37
        $xhtml_tags = array('br', 'hr', 'input', 'frame', 'img', 'area', 'link', 'col', 'base', 'basefont', 'param');
111 37
        if (in_array($m[1], $xhtml_tags)) {
112 34
            return '<' . $m[1] . $m[2] . ' />';
113
        } else {
114 37
            return '<' . $m[1] . $m[2] . '></' . $m[1] . '>';
115
        }
116 37
    }, $xml);
117
}
118
119
function display_xml_error($error)
120
{
121
    $return = '';
122
    $return .= str_repeat('-', $error->column) . "^\n";
123
124
    switch ($error->level) {
125
        case LIBXML_ERR_WARNING:
126
            $return .= 'Warning ' . $error->code . ': ';
127
            break;
128
         case LIBXML_ERR_ERROR:
129
            $return .= 'Error ' . $error->code . ': ';
130
            break;
131
        case LIBXML_ERR_FATAL:
132
            $return .= 'Fatal Error ' . $error->code . ': ';
133
            break;
134
    }
135
136
    $return .= trim($error->message) .
137
               "\n  Line: " . $error->line .
138
               "\n  Column: " . $error->column;
139
140
    if ($error->file) {
141
        $return .= "\n  File: " . $error->file;
142
    }
143
144
    return "$return\n\n--------------------------------------------\n\n";
145
}
146
147
function are_libxml_errors_ok()
148
{
149 37
    $errors = libxml_get_errors();
150
151 37
    foreach ($errors as $error) {
152
        if ($error->code == 801) return false;
153 37
    }
154 37
    return true;
155
}
156
157
function html2xhtml($html)
158
{
159 37
    $doc = new DOMDocument();
160 37
    libxml_use_internal_errors(true);
161
162 37
    $doc->loadHTML('<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body>' .
163 37
                        $html  . '</body></html>'); // Load the HTML
164 37
    $output = $doc->saveXML($doc->documentElement); // Transform to an Ansi xml stream
165 37
    $output = xml2xhtml($output);
166 37
    if (preg_match ('#<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></meta></head><body>(.*)</body></html>#ms', $output, $matches)) {
167 37
        $output = $matches [1]; // Remove <html><body>
168 37
    }
169
    /*
170
    // In case of error with summary, use it to debug
171
    $errors = libxml_get_errors();
172
173
    foreach ($errors as $error) {
174
        $output .= display_xml_error($error);
175
    }
176
    */
177
178 37
    if (!are_libxml_errors_ok ()) $output = 'HTML code not valid.';
179
180 37
    libxml_use_internal_errors(false);
181 37
    return $output;
182
}
183
184
/**
185
 * This method is a direct copy-paste from
186
 * http://tmont.com/blargh/2010/1/string-format-in-php
187
 */
188
function str_format($format)
189
{
190 116
    $args = func_get_args();
191 116
    $format = array_shift($args);
192
193 116
    preg_match_all('/(?=\{)\{(\d+)\}(?!\})/', $format, $matches, PREG_OFFSET_CAPTURE);
194 116
    $offset = 0;
195 116
    foreach ($matches[1] as $data) {
196 116
        $i = $data[0];
197 116
        $format = substr_replace($format, @$args[$i], $offset + $data[1] - 1, 2 + strlen($i));
198 116
        $offset += strlen(@$args[$i]) - 2 - strlen($i);
199 116
    }
200
201 116
    return $format;
202
}
203
204
/**
205
 * Get all accepted languages from the browser and put them in a sorted array
206
 * languages id are normalized : fr-fr -> fr_FR
207
 * @return array of languages
208
 */
209
function getAcceptLanguages()
210
{
211 16
    $langs = array();
212
213 16
    if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
214
        // break up string into pieces (languages and q factors)
215 16
        $accept = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
216 16 View Code Duplication
        if (preg_match('/^(\w{2})-\w{2}$/', $accept, $matches)) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
217
            // Special fix for IE11 which send fr-FR and nothing else
218 3
            $accept = $accept . ',' . $matches[1] . ';q=0.8';
219 3
        }
220 16
        preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $accept, $lang_parse);
221
222 16
        if (count($lang_parse[1])) {
223 16
            $langs = array();
224 16
            foreach ($lang_parse[1] as $lang) {
225
                // Format the language code (not standard among browsers)
226 16
                if (strlen($lang) == 5) {
227 11
                    $lang = str_replace('-', '_', $lang);
228 11
                    $splitted = preg_split('/_/', $lang);
229 11
                    $lang = $splitted[0] . '_' . strtoupper($splitted[1]);
230 11
                }
231 16
                array_push($langs, $lang);
232 16
            }
233
            // create a list like "en" => 0.8
234 16
            $langs = array_combine($langs, $lang_parse[4]);
235
236
            // set default to 1 for any without q factor
237 16
            foreach ($langs as $lang => $val) {
238 16
                if ($val === '') $langs[$lang] = 1;
239 16
            }
240
241
            // sort list based on value
242 16
            arsort($langs, SORT_NUMERIC);
243 16
        }
244 16
    }
245
246 16
    return $langs;
247
}
248
249
/**
250
 * Find the best translation file possible based on the accepted languages
251
 * @return array of language and language file
252
 */
253
function getLangAndTranslationFile()
254
{
255 17
    global $config;
256 17
    $langs = array();
257 17
    $lang = 'en';
258 17
    if (!empty($config['cops_language'])) {
259
        $lang = $config['cops_language'];
260
    }
261 17
    elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
262 16
        $langs = getAcceptLanguages();
263 16
    }
264
    //echo var_dump($langs);
265 17
    $lang_file = NULL;
266 17
    foreach ($langs as $language => $val) {
267 16
        $temp_file = dirname(__FILE__). '/lang/Localization_' . $language . '.json';
268 16
        if (file_exists($temp_file)) {
269 16
            $lang = $language;
270 16
            $lang_file = $temp_file;
271 16
            break;
272
        }
273 17
    }
274 17
    if (empty ($lang_file)) {
275 3
        $lang_file = dirname(__FILE__). '/lang/Localization_' . $lang . '.json';
276 3
    }
277 17
    return array($lang, $lang_file);
278
}
279
280
/**
281
 * This method is based on this page
282
 * http://www.mind-it.info/2010/02/22/a-simple-approach-to-localization-in-php/
283
 */
284
function localize($phrase, $count=-1, $reset=false)
285
{
286 136
    global $config;
287 136
    if ($count == 0)
288 136
        $phrase .= '.none';
289 136
    if ($count == 1)
290 136
        $phrase .= '.one';
291 136
    if ($count > 1)
292 136
        $phrase .= '.many';
293
294
    /* Static keyword is used to ensure the file is loaded only once */
295 136
    static $translations = NULL;
296 136
    if ($reset) {
297 16
        $translations = NULL;
298 16
    }
299
    /* If no instance of $translations has occured load the language file */
300 136
    if (is_null($translations)) {
301 17
        $lang_file_en = NULL;
302 17
        list ($lang, $lang_file) = getLangAndTranslationFile();
303 17
        if ($lang != 'en') {
304 1
            $lang_file_en = dirname(__FILE__). '/lang/' . 'Localization_en.json';
305 1
        }
306
307 17
        $lang_file_content = file_get_contents($lang_file);
308
        /* Load the language file as a JSON object and transform it into an associative array */
309 17
        $translations = json_decode($lang_file_content, true);
310
311
        /* Clean the array of all unfinished translations */
312 17
        foreach (array_keys ($translations) as $key) {
313 17
            if (preg_match ('/^##TODO##/', $key)) {
314
                unset ($translations [$key]);
315
            }
316 17
        }
317 17
        if (!is_null($lang_file_en)) {
318 1
            $lang_file_content = file_get_contents($lang_file_en);
319 1
            $translations_en = json_decode($lang_file_content, true);
320 1
            $translations = array_merge ($translations_en, $translations);
321 1
        }
322 17
    }
323 136
    if (array_key_exists ($phrase, $translations)) {
324 136
        return $translations[$phrase];
325
    }
326 3
    return $phrase;
327
}
328
329
function addURLParameter($urlParams, $paramName, $paramValue)
330
{
331 61
    if (empty ($urlParams)) {
332 51
        $urlParams = '';
333 51
    }
334 61
    $start = '';
335 61
    if (preg_match ('#^\?(.*)#', $urlParams, $matches)) {
336 15
        $start = '?';
337 15
        $urlParams = $matches[1];
338 15
    }
339 61
    $params = array();
340 61
    parse_str($urlParams, $params);
341 61
    if (empty ($paramValue) && $paramValue != 0) {
342
        unset ($params[$paramName]);
343
    } else {
344 61
        $params[$paramName] = $paramValue;
345
    }
346 61
    return $start . http_build_query($params);
347
}
348
349
function useNormAndUp()
350
{
351 144
    global $config;
352 144
    return $config ['cops_normalized_search'] == '1';
353
}
354
355
function normalizeUtf8String($s)
356
{
357 8
    include_once 'transliteration.php';
358 8
    return _transliteration_process($s);
359
}
360
361
function normAndUp($s)
362
{
363 7
    return mb_strtoupper(normalizeUtf8String($s), 'UTF-8');
364
}
365