Test Setup Failed
Pull Request — master (#488)
by
unknown
03:18
created

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.2.0');
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
    }
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
    }
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)
0 ignored issues
show
The parameter $format is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
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
    }
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
        }
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
                }
231 16
                array_push($langs, $lang);
232
            }
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
            }
240
241
            // sort list based on value
242 16
            arsort($langs, SORT_NUMERIC);
243
        }
244
    }
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
    }
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
    }
274 17
    if (empty ($lang_file)) {
275 3
        $lang_file = dirname(__FILE__). '/lang/Localization_' . $lang . '.json';
276
    }
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 3
        $phrase .= '.none';
289 136
    if ($count == 1)
290 64
        $phrase .= '.one';
291 136
    if ($count > 1)
292 67
        $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
    }
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
        }
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 17
                unset ($translations [$key]);
315
            }
316
        }
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
        }
322
    }
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
    }
334 61
    $start = '';
335 61
    if (preg_match ('#^\?(.*)#', $urlParams, $matches)) {
336 15
        $start = '?';
337 15
        $urlParams = $matches[1];
338
    }
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