/**
 * Return the contents of the physical template file from the website private folder or from theme folder.
 *
 * The file is determined by the URL requested and the information in the database.
 *
 * @return string $template
 */
function nvweb_template_load($template_id = null)
{
    global $current;
    global $DB;
    global $website;
    $template = '';
    if (empty($template_id)) {
        $template_id = $current['template'];
    }
    if (!empty($template_id)) {
        $template = new template();
        $template->load($template_id);
        if (!$template->enabled) {
            nvweb_clean_exit();
        }
        if ($template->permission == 2) {
            nvweb_clean_exit();
        } else {
            if ($template->permission == 1 && empty($_SESSION['APP_USER#' . APP_UNIQUE])) {
                nvweb_clean_exit();
            }
        }
        if (file_exists($template->file)) {
            $template->file_contents = @file_get_contents($template->file);
        } else {
            if (file_exists(NAVIGATE_PRIVATE . '/' . $website->id . '/templates/' . $template->file)) {
                $template->file_contents = @file_get_contents(NAVIGATE_PRIVATE . '/' . $website->id . '/templates/' . $template->file);
            } else {
                $template->file_contents = 'NV error: template file not found! (' . $template->file . ')';
            }
        }
    }
    return $template;
}
Example #2
0
function nvweb_votes_event($event, $html)
{
    global $webuser;
    global $website;
    global $current;
    $code = '';
    $js = '';
    if ($event == 'before_parse') {
        if ($_REQUEST['plugin'] == 'nv_votes') {
            if (empty($webuser->id)) {
                echo json_encode(array('error' => 'no_webuser'));
            } else {
                $status = webuser_vote::update_object_votes($webuser->id, $_POST['object'], $_POST['object_id'], $_POST['score'], true);
                if ($status === 'already_voted') {
                    echo json_encode(array('error' => 'already_voted'));
                } else {
                    if ($status === true) {
                        echo json_encode(array('ok' => 'true'));
                    } else {
                        if (!$status) {
                            echo json_encode(array('error' => 'error'));
                        }
                    }
                }
            }
            nvweb_clean_exit();
        } else {
            // add jquery from CDN if not already loaded
            if (strpos($html, 'jquery') === false) {
                $code = '<script language="javascript" type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>' . "\n";
            }
            $js = '
				function nvweb_votes_plugin_vote(value, callback)
				{
					jQuery.ajax({
						type: "POST",
						url: "' . $website->absolute_path() . '/' . $current['route'] . '?plugin=nv_votes",
						data: {
							score: value,
							object: "' . $current['type'] . '",
							object_id: "' . $current['id'] . '"
						},
						success: function(data)
						{
							if(callback)
								callback(data);
						},
						dataType: "json"
					});	
				}
			';
            nvweb_after_body("html", $code);
            nvweb_after_body("js", $js);
        }
    }
    return $html;
}
function nvweb_route_parse($route = "")
{
    global $website;
    global $DB;
    global $current;
    global $session;
    global $theme;
    global $events;
    global $dictionary;
    // node route types
    if (substr($route, 0, 5) == 'node/') {
        $node = substr($route, 5);
        $route = 'node';
    }
    switch ($route) {
        case 'object':
            nvweb_object();
            nvweb_clean_exit();
            break;
        case 'nvajax':
            nvweb_ajax();
            nvweb_clean_exit();
            break;
        case 'nvtags':
        case 'nvsearch':
            $current['template'] = 'search';
            break;
        case 'nv.webuser/verify':
            $hash = $_REQUEST['hash'];
            $email = filter_var($_REQUEST['email'], FILTER_VALIDATE_EMAIL);
            if (!empty($hash) && !empty($email)) {
                $ok = webuser::email_verification($email, $hash);
                if ($ok) {
                    $session['nv.webuser/verify:email_confirmed'] = time();
                }
            }
            nvweb_clean_exit(NVWEB_ABSOLUTE . $website->homepage());
            break;
        case 'node':
            if ($node > 0) {
                $current['id'] = $node;
                $DB->query('SELECT * FROM nv_items 
							 WHERE id = ' . protect($current['id']) . '
							   AND website = ' . $website->id);
                $current['object'] = $DB->first();
                // let's count a hit (except admin)
                if ($current['navigate_session'] != 1 && !nvweb_is_bot()) {
                    $DB->execute(' UPDATE nv_items SET views = views + 1 
								   WHERE id = ' . $current['id'] . ' 
									 AND website = ' . $website->id);
                }
                $current['type'] = 'item';
                $current['template'] = $current['object']->template;
                if ($current['navigate_session'] == 1 && !empty($_REQUEST['template'])) {
                    $current['template'] = $_REQUEST['template'];
                }
            }
            break;
        case 'sitemap.xml':
            nvweb_webget_load('sitemap');
            echo nvweb_sitemap(array('mode' => 'xml'));
            nvweb_clean_exit();
            break;
            // redirect to home page of the current website
        // redirect to home page of the current website
        case 'nvweb.home':
        case 'nv.home':
            header('location: ' . NVWEB_ABSOLUTE . $website->homepage());
            nvweb_clean_exit();
            break;
            // webservice endpoint via XML-RPC calls
        // webservice endpoint via XML-RPC calls
        case 'xmlrpc':
            $events->trigger('nvweb', 'xmlrpc', array('route' => '/' . $route));
            // if no extension processes the call, use the integrated XML-RPC parser
            nvweb_xmlrpc();
            nvweb_clean_exit();
            break;
            // empty path
        // empty path
        case '':
        case '/':
        case 'nv.empty':
            if ($website->empty_path_action == 'homepage_noredirect') {
                $route = $website->homepage();
                if (strpos($route, '/') === 0) {
                    $route = substr($route, 1);
                }
            } else {
                $route = "";
                $website->wrong_path_action = $website->empty_path_action;
            }
            // do NOT break this case, continue processing as wrong_path action
            // no special route (or already processed), look for the path on navigate routing table
        // do NOT break this case, continue processing as wrong_path action
        // no special route (or already processed), look for the path on navigate routing table
        default:
            $DB->query('SELECT * FROM nv_paths 
						 WHERE path = ' . protect('/' . $route) . ' 
						   AND website = ' . $website->id . '
						 ORDER BY id DESC');
            $rs = $DB->result();
            if (empty($rs)) {
                // no valid route found
                switch ($website->wrong_path_action) {
                    case 'homepage':
                    case 'homepage_redirect':
                        header('location: ' . NVWEB_ABSOLUTE . $website->homepage());
                        nvweb_clean_exit();
                        break;
                    case 'http_404':
                        header("HTTP/1.0 404 Not Found");
                        nvweb_clean_exit();
                        break;
                    case 'theme_404':
                        $current['template'] = 'not_found';
                        $current['type'] = 'structure';
                        $current['id'] = 0;
                        $current['object'] = new structure();
                        return;
                        break;
                    case 'website_path':
                        $redirect_url = nvweb_template_convert_nv_paths($website->wrong_path_redirect);
                        header('location: ' . $redirect_url);
                        nvweb_clean_exit();
                        break;
                    case 'blank':
                    default:
                        nvweb_clean_exit();
                        break;
                }
            } else {
                // route found!
                // let's count a hit (except admin)
                if ($current['navigate_session'] != 1 && !nvweb_is_bot()) {
                    $DB->execute(' UPDATE nv_paths SET views = views + 1 
								   WHERE id = ' . $rs[0]->id . ' 
								     AND website = ' . $website->id);
                }
                // set the properties found
                // set the default language for this route
                if (!isset($_REQUEST['lang'])) {
                    $current['lang'] = $rs[0]->lang;
                    $session['lang'] = $rs[0]->lang;
                    // force reloading the dictionary
                    $dictionary = nvweb_dictionary_load();
                }
                $current['type'] = $rs[0]->type;
                $current['id'] = $rs[0]->object_id;
                // look for the template associated with this item
                if ($current['type'] == 'structure') {
                    $obj = new structure();
                    $obj->load($current['id']);
                    // check if it is a direct access to a "jump to another branch" path
                    if ($obj->dictionary[$current['lang']]['action-type'] == 'jump-branch') {
                        $current['id'] = $obj->dictionary[$current['lang']]['action-jump-branch'];
                        $obj = new structure();
                        $obj->load($current['id']);
                        header('location: ' . NVWEB_ABSOLUTE . $obj->paths[$current['lang']]);
                        nvweb_clean_exit();
                    } else {
                        if ($obj->dictionary[$current['lang']]['action-type'] == 'jump-item') {
                            $current['id'] = $obj->dictionary[$current['lang']]['action-jump-item'];
                            $obj = new item();
                            $obj->load($current['id']);
                            header('location: ' . NVWEB_ABSOLUTE . $obj->paths[$current['lang']]);
                            nvweb_clean_exit();
                        }
                    }
                    $current['object'] = $obj;
                    $current['category'] = $current['id'];
                    if ($current['navigate_session'] != 1 && !nvweb_is_bot()) {
                        $DB->execute(' UPDATE nv_structure SET views = views + 1 
									    WHERE id = ' . protect($current['id']) . ' 
										  AND website = ' . $website->id);
                    }
                } else {
                    if ($current['type'] == 'item') {
                        $DB->query('SELECT * FROM nv_items 
								 WHERE id = ' . protect($current['id']) . '
								   AND website = ' . $website->id);
                        $current['object'] = $DB->first();
                        // let's count a hit (except admin)
                        if ($current['navigate_session'] != 1 && !nvweb_is_bot()) {
                            $DB->execute(' UPDATE nv_items SET views = views + 1 
									   WHERE id = ' . $current['id'] . ' 
									     AND website = ' . $website->id);
                        }
                    } else {
                        if ($current['type'] == 'feed') {
                            $out = feed::generate_feed($current['id']);
                            if ($current['navigate_session'] != 1 && !nvweb_is_bot()) {
                                $DB->execute(' UPDATE nv_feeds SET views = views + 1
                                           WHERE id = ' . $current['id'] . '
                                             AND website = ' . $website->id);
                            }
                            echo $out;
                            nvweb_clean_exit();
                        } else {
                            // path exists, but the object type is unknown
                            // maybe the path belongs to an extension?
                            $events->trigger('nvweb', 'routes', array('path' => $rs[0]));
                        }
                    }
                }
                $current['template'] = $current['object']->template;
            }
            break;
    }
}
Example #4
0
function nvweb_blocks_render_poll($object)
{
    global $current;
    global $webgets;
    global $session;
    $webget = 'blocks';
    nvweb_blocks_init();
    if ($object->class != 'poll') {
        return;
    }
    if (!isset($session['polls'][$object->id])) {
        $session['polls'][$object->id] = false;
    }
    if ($_GET['poll_vote'] == $object->id && !empty($_POST['vote'])) {
        // submit vote and show results
        if (empty($session['polls'][$object->id])) {
            foreach ($object->trigger[$current['lang']] as $i => $answer) {
                if ($answer['code'] == $_POST['vote']) {
                    $object->trigger[$current['lang']][$i]['votes'] = $object->trigger[$current['lang']][$i]['votes'] + 1;
                }
            }
            $object->save();
            $session['polls'][$object->id] = true;
        }
        $out = nvweb_blocks_render_poll_results($object);
        echo $out;
        nvweb_clean_exit();
    } else {
        if ($_GET['poll_result'] == $object->id) {
            echo nvweb_blocks_render_poll_results($object);
            nvweb_clean_exit();
        } else {
            if (!empty($session['polls'][$object->id])) {
                $out = '<div class="block-poll ' . $object->type . '-' . $object->id . '" data-id="' . $object->id . '">';
                $out .= nvweb_blocks_render_poll_results($object);
                $out .= '</div>';
            } else {
                $out = '<div class="block-poll ' . $object->type . '-' . $object->id . '" data-id="' . $object->id . '">';
                $out .= '<form action="?" method="post" id="block_poll_' . $object->type . '-' . $object->id . '_form">';
                foreach ($object->trigger[$current['lang']] as $answer) {
                    $out .= '<div class="block-poll-answer">';
                    $out .= '   <input type="radio" id="' . $object->type . '-' . $object->id . '-answer-' . $answer['code'] . '" name="' . $object->type . '-' . $object->id . '-answer" value="' . $answer['code'] . '" />';
                    $out .= '   <label for="' . $object->type . '-' . $object->id . '-answer-' . $answer['code'] . '">' . $answer['title'] . '</label>';
                    $out .= '</div>';
                }
                $out .= '<div class="block-poll-actions">';
                $out .= '   <input type="submit" id="' . $object->type . '-' . $object->id . '-submit" value="' . $webgets[$webget]['translations']["vote"] . '" />';
                $out .= '   <input type="button" value="' . $webgets[$webget]['translations']["results"] . '" />';
                $out .= '</div>';
                $out .= '</form>';
                $out .= '</div>';
                nvweb_after_body("js", '
            function block_poll_' . $object->id . '_vote()
            {
                if(document.querySelector("input[name=\\"' . $object->type . '-' . $object->id . '-answer\\"]:checked"))
                {
                    var vote_value = document.querySelector("input[name=\\"' . $object->type . '-' . $object->id . '-answer\\"]:checked").value;

                    var request = new XMLHttpRequest();
                    request.open("POST", "?poll_vote=' . $object->id . '", true);
                    request.setRequestHeader("Content-type","application/x-www-form-urlencoded");

                    request.onreadystatechange = function() {
                      if (this.readyState === 4) {
                        if (this.status >= 200 && this.status < 400)
                        {
                            var resp = this.responseText;
                            document.querySelector(".' . $object->type . '-' . $object->id . '").innerHTML = resp;
                        }
                        else
                        {
                          // Error
                        }
                      }
                    };

                    request.send("poll=' . $object->id . '&vote=" + vote_value);
                    request = null;

                    return false;
                }
                else
                    return false;
            }

            function block_poll_' . $object->id . '_result()
            {
                var request = new XMLHttpRequest();
                request.open("GET", "?poll_result=' . $object->id . '", true);

                request.onreadystatechange = function() {
                  if (this.readyState === 4) {
                    if (this.status >= 200 && this.status < 400)
                    {
                        var resp = this.responseText;
                        document.querySelector(".' . $object->type . '-' . $object->id . '").innerHTML = resp;
                    }
                    else
                    {
                      // Error
                    }
                  }
                };

                request.send();
                request = null;

                return false;
            }

            document.querySelector("form[id=block_poll_' . $object->type . '-' . $object->id . '_form]").onsubmit = block_poll_' . $object->id . '_vote;
            document.querySelector(".block-poll-actions input[type=button]").onclick = block_poll_' . $object->id . '_result;
        ');
            }
        }
    }
    return $out;
}
Example #5
0
 $current['webuser'] = $session['webuser'];
 setlocale(LC_ALL, $website->languages[$session['lang']]['system_locale']);
 date_default_timezone_set($webuser->timezone ? $webuser->timezone : $website->default_timezone);
 // help developers to find problems
 if ($current['navigate_session'] == 1 && APP_DEBUG) {
     error_reporting(E_ALL ^ E_NOTICE);
     ini_set('display_errors', true);
 }
 // parse route
 nvweb_route_parse($current['route']);
 $permission = nvweb_check_permission();
 // if no preview & permission not allowed
 // if preview but no navigate_session active
 if ($_REQUEST['preview'] == 'true' && $current['navigate_session'] != 1 || empty($_REQUEST['preview']) && !$permission) {
     nvweb_route_parse('***nv.not_allowed***');
     nvweb_clean_exit();
 }
 $template = nvweb_template_load();
 $events->trigger('theme', 'template_load', array('template' => &$template));
 if (empty($template)) {
     throw new Exception('Navigate CMS: no template found!');
 }
 // parse the special tag "include"
 // also convert curly brackets tags {{nv object=""}} to <nv object="" /> version
 // we do it now because new nv tags could be added before parsing the whole html
 $html = nvweb_template_parse_special($template->file_contents);
 $current['plugins_called'] = nvweb_plugins_called_in_template($html);
 $html = nvweb_plugins_event('before_parse', $html);
 $html = nvweb_theme_settings($html);
 $html = nvweb_template_parse_lists($html);
 $html = nvweb_template_parse($html);
Example #6
0
function nv_plugin_init()
{
    global $DB;
    global $webuser;
    global $config;
    global $website;
    global $current;
    global $dictionary;
    global $session;
    global $events;
    global $idn;
    // create database connection
    $DB = new database();
    if (!$DB->connect()) {
        die(APP_NAME . ' # ERROR<br /> ' . $DB->get_last_error());
    }
    // global exception catcher
    try {
        $idn = new idna_convert();
        // which website do we have to load?
        $url = nvweb_self_url();
        if (!empty($_REQUEST['wid'])) {
            $website = new website();
            $website->load(intval($_REQUEST['wid']));
        } else {
            $website = nvweb_load_website_by_url($url);
        }
        if ($website->permission == 2 || $website->permission == 1 && empty($_SESSION['APP_USER#' . APP_UNIQUE])) {
            nvweb_clean_exit();
        }
        // global helper variables
        $session = array();
        // user session
        $webuser = new webuser();
        $nvweb_absolute = empty($website->protocol) ? 'http://' : $website->protocol;
        if (!empty($website->subdomain)) {
            $nvweb_absolute .= $website->subdomain . '.';
        }
        $nvweb_absolute .= $website->domain . $website->folder;
        define('NVWEB_ABSOLUTE', $nvweb_absolute);
        define('NVWEB_OBJECT', $nvweb_absolute . '/object');
        if (!defined('NAVIGATE_URL')) {
            define('NAVIGATE_URL', NAVIGATE_PARENT . NAVIGATE_FOLDER);
        }
        if (!isset($_SESSION['nvweb.' . $website->id])) {
            $_SESSION['nvweb.' . $website->id] = array();
            $session['lang'] = nvweb_country_language();
        } else {
            $session = $_SESSION['nvweb.' . $website->id];
            if (empty($session['lang'])) {
                $session['lang'] = nvweb_country_language();
            }
        }
        if (isset($_REQUEST['lang'])) {
            $session['lang'] = $_REQUEST['lang'];
        }
        if (!empty($session['webuser'])) {
            $webuser->load($session['webuser']);
        } else {
            if (!empty($_COOKIE["webuser"])) {
                $webuser->load_by_hash($_COOKIE['webuser']);
            }
        }
        @setlocale(LC_ALL, $website->languages[$session['lang']]['system_locale']);
        // remove the "folder" part of the route
        $route = '';
        if (!empty($_REQUEST['route'])) {
            $route = $_REQUEST['route'];
            // remove the "folder" part of the route (only if this url is really under a folder)
            if (!empty($website->folder) && strpos('/' . $route, $website->folder) === 0) {
                $route = substr('/' . $route, strlen($website->folder) + 1);
            }
        }
        // global data across webgets
        $current = array('lang' => $session['lang'], 'route' => $route, 'object' => '', 'template' => '', 'category' => '', 'webuser' => @$session['webuser'], 'navigate_session' => !empty($_SESSION['APP_USER#' . APP_UNIQUE]), 'html_after_body' => array(), 'js_after_body' => array());
        $dictionary = nvweb_dictionary_load();
        $_SESSION['nvweb.' . $website->id] = $session;
    } catch (Exception $e) {
        ?>
		<html>
			<body>
				ERROR
				<br /><br />
				<?php 
        echo $e->getMessage();
        ?>
			</body>
		</html>
		<?php 
    }
    $events = new events();
    nvweb_plugins_load();
    $events->extension_backend_bindings();
}
function nvweb_object($ignoreEnabled = false, $ignorePermissions = false)
{
    global $website;
    global $DB;
    session_write_close();
    ob_end_clean();
    $item = new file();
    header('Cache-Control: private');
    header('Pragma: private');
    $type = @$_REQUEST['type'];
    $id = @$_REQUEST['id'];
    if (!empty($id)) {
        if (is_numeric($id)) {
            $item->load($id);
        } else {
            $item->load($_REQUEST['id']);
        }
    }
    if (empty($type) && !empty($item->type)) {
        $type = $item->type;
    }
    // if the type requested is not a special type, check its access permissions
    if (!in_array($type, array("blank", "transparent", "flag"))) {
        $enabled = nvweb_object_enabled($item);
        if (!$enabled && !$ignorePermissions) {
            $type = 'not_allowed';
        }
    }
    switch ($type) {
        case 'not_allowed':
            header("HTTP/1.0 405 Method Not Allowed");
            break;
        case 'blank':
        case 'transparent':
            $path = NAVIGATE_PATH . '/img/transparent.gif';
            header('Content-Disposition: attachment; filename="transparent.gif"');
            header('Content-Type: image/gif');
            header('Content-Disposition: inline; filename="transparent.gif"');
            header("Content-Transfer-Encoding: binary\n");
            $etag = base64_encode($path . filemtime($path));
            header('ETag: "' . $etag . '"');
            // check the browser cache and stop downloading again the file
            $cached = file::cacheHeaders(filemtime($path), $etag);
            if (!$cached) {
                readfile($path);
            }
            break;
        case 'flag':
            if ($_REQUEST['code'] == 'ca') {
                $_REQUEST['code'] = 'catalonia';
            }
            header('Content-Disposition: attachment; filename="' . $_REQUEST['code'] . '.png"');
            header('Content-Type: image/png');
            header('Content-Disposition: inline; filename="' . $_REQUEST['code'] . '.png"');
            header("Content-Transfer-Encoding: binary\n");
            $path = NAVIGATE_PATH . '/img/icons/flags/' . $_REQUEST['code'] . '.png';
            if (!file_exists($path)) {
                $path = NAVIGATE_PATH . '/img/transparent.gif';
            }
            $etag = base64_encode($path . filemtime($path));
            header('ETag: "' . $etag . '"');
            // check the browser cache and stop downloading again the file
            $cached = file::cacheHeaders(filemtime($path), $etag);
            if (!$cached) {
                readfile($path);
            }
            break;
        case 'image':
        case 'img':
            if (!$item->enabled && !$ignoreEnabled) {
                nvweb_clean_exit();
            }
            $path = $item->absolute_path();
            $etag_add = '';
            // calculate aspect ratio if width or height are given...
            $width = intval(@$_REQUEST['width']) + 0;
            $height = intval(@$_REQUEST['height']) + 0;
            // check size requested and ignore the empty values (or equal to zero)
            if (empty($width)) {
                $width = "";
            }
            if (empty($height)) {
                $height = "";
            }
            // get target quality (only for jpeg thumbnails!)
            $quality = $_REQUEST['quality'];
            if (empty($quality)) {
                $quality = 95;
            }
            $resizable = true;
            if ($item->mime == 'image/gif') {
                $resizable = !file::is_animated_gif($path);
            }
            if ((!empty($width) || !empty($height)) && ($resizable || @$_REQUEST['force_resize'] == 'true')) {
                $border = $_REQUEST['border'] == 'false' ? false : true;
                $path = file::thumbnail($item, $width, $height, $border, NULL, $quality);
                if (empty($path)) {
                    die;
                }
                $etag_add = '-' . $width . '-' . $height . '-' . $border . '-' . $quality;
                $item->name = $width . 'x' . $height . '-' . $item->name;
                $item->size = filesize($path);
                $item->mime = 'image/png';
                if (strpos(basename($path), '.jpg') !== false) {
                    $item->mime = 'image/jpeg';
                }
            }
            $etag = base64_encode($item->id . '-' . $item->name . '-' . $item->date_added . '-' . filesize($path) . '-' . filemtime($path) . '-' . $item->permission . $etag_add);
            header('ETag: "' . $etag . '"');
            header('Content-type: ' . $item->mime);
            header("Content-Length: " . $item->size);
            if (empty($_REQUEST['disposition'])) {
                $_REQUEST['disposition'] = 'inline';
            }
            header('Content-Disposition: ' . $_REQUEST['disposition'] . '; filename="' . $item->name . '"');
            // check the browser cache and stop downloading again the file
            $cached = file::cacheHeaders(filemtime($path), $etag);
            if (!$cached) {
                readfile($path);
            }
            break;
        case 'archive':
        case 'video':
        case 'file':
        default:
            if (!$item->enabled && !$ignoreEnabled) {
                nvweb_clean_exit();
            }
            $path = NAVIGATE_PRIVATE . '/' . $website->id . '/files/' . $item->id;
            $etag_add = '';
            clearstatcache();
            $etag = base64_encode($item->id . '-' . $item->name . '-' . $item->date_added . '-' . filemtime($path) . '-' . $item->permission . $etag_add);
            header('ETag: "' . $etag . '"');
            header('Content-type: ' . $item->mime);
            header("Accept-Ranges: bytes");
            if (empty($_REQUEST['disposition'])) {
                $_REQUEST['disposition'] = 'attachment';
            }
            header('Content-Disposition: ' . $_REQUEST['disposition'] . '; filename="' . $item->name . '"');
            // check the browser cache and stop downloading again the file
            $cached = file::cacheHeaders(filemtime($path), $etag);
            if (!$cached) {
                $range = 0;
                $size = filesize($path);
                if (isset($_SERVER['HTTP_RANGE'])) {
                    list($a, $range) = explode("=", $_SERVER['HTTP_RANGE']);
                    str_replace($range, "-", $range);
                    $size2 = $size - 1;
                    $new_length = $size - $range;
                    header("HTTP/1.1 206 Partial Content");
                    header("Content-Length: {$new_length}");
                    header("Content-Range: bytes {$range}{$size2}/{$size}");
                } else {
                    $size2 = $size - 1;
                    header("Content-Range: bytes 0-{$size2}/{$size}");
                    header("Content-Length: " . $size);
                }
                $fp = fopen($path, "rb");
                if (is_resource($fp)) {
                    @fseek($fp, $range);
                    while (!@feof($fp) && connection_status() == 0) {
                        set_time_limit(0);
                        print @fread($fp, 1024 * 1024);
                        // 1 MB per second
                        flush();
                        ob_flush();
                        sleep(1);
                    }
                    fclose($fp);
                }
            }
            break;
    }
    session_write_close();
    if ($DB) {
        $DB->disconnect();
    }
    exit;
}