Hyperlink multi-level sub-directories through index.php? structure - php

I'm trying to create a hyperlink structure that can access multi-level sub folders. For now, I can access my hyperlinks with only one-level (php) directory, such like index.php?content=about (whereas 'about' is about.php).
What I want to do is to create a filing system for a larger website with multi-level sub-directories like the following example,
index.php?blog/category/process/. I don't know if there is a symbol that replaces html symbol / (slash for directory) but for PHP directories. I tried different ways of accessing files inside multi-level sub-directories, such as putting the ? (question mark). It was all hypothetically experimental. If I use the slash, such in the form 'blog/category/process/filename.php', I get a 404 Not Found error.
There is the following PHP script inside function.php, that gets the content from the URL, if there is no content, it sets a default and if there is content, it sanitizes data against hacking:
function loadContent($where, $default='') {
$content = filter_input(INPUT_GET, $where, FILTER_SANITIZE_STRING);
$default = filter_var($default, FILTER_SANITIZE_STRING);
$content = (empty($content)) ? $default : $content;
if ($content) {
$html = include 'content/'.$content.'.php';
return $html;
}
}
function loadIncludes($where, $default='includes/') {
$includes = filter_input(INPUT_GET, $where, FILTER_SANITIZE_STRING);
$default = filter_var($default, FILTER_SANITIZE_STRING);
if($includes) {
$html = include 'includes/'.$includes.'.php';
return $html;
}
}
The link to the document inside 'blog/category/process/filename.php' shows up (where it was '404 Error' before, but the header and the css files do not work. They are not been picked up.
Please note:
My website structure is
Header (one header picked up by index.php?)
Content (multiple content=filename.php)
Footer
index.php looks like this:
<?php
require ('includes/function.php');
require ('includes/init.php'); /* init.php picks up the header */
?>
<div class="clearboth"></div>
<!-- ******** HOMEPAGE ********** -->
<?php loadContent('content', 'home'); ?>
<div class="clearboth"></div>
<!-- ******** FOOTER ********** -->
<?php include ('content/footer.php'); ?>
I found the solution on the structure of the multi-level sub-directories through index.php? that also picks up the CSS, which is as follows:
<a href="index.php?content=blog/category/process/filename">
(leave out the extension .php followed after 'filename')
Thank you for all your help!

<?php
/* FOLDERS STRUCTURE
$_SERVER['DOCUMENT_ROOT'] = C:/Server/www/music; // YES Windows :)
THIS FILE = folders.php
C:/Server/www/music
C:/Server/www/music/files/
C:/Server/www/music/files/folder1/
C:/Server/www/music/files/folder1/folder2/myfile.jpeg
*/
$root = $_SERVER['DOCUMENT_ROOT'];
$requestURI = $_SERVER['REQUEST_URI'];
$startFolder = '/files/';
preg_match('/\?/', $requestURI) ? list($requestURI, $fileToFind) = explode('?', $_SERVER['REQUEST_URI']) : exit('Bad request');
$file = $root.$startFolder.$fileToFind;
if(file_exists($file)){
//YOUR CODE
}
else {
header("HTTP/1.0 404 Not Found");
}
// Usage = http://music.com/folders.php?/folder1/folder2/myfile.jpeg
?>
Read those questions I had asked before. I hope it will help you
.htaccess : Redirect all http requests to one file whitout 404 resp. code
Use PHP to rewrite URLS?
Note that you may play with http headers header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found"); or header($_SERVER["SERVER_PROTOCOL"]." 200 Ok"); In case the file exists or not
Active your imagination...

I found the solution on the hyperlink structure of a multi-level sub-directories through index.php? that also picks up the CSS, and does not issue a 404 Error, which is as follows:
<a href="index.php?content=blog/category/process/filename">
descriptive header
</a>
(note: remember to leave out the extension .php followed after 'filename')

Related

How to prevent people from accessing source videos without logining in?

I am trying to make a login that would give you access to some videos, pictures, and other files. I can do this with php and a get request (www.example.com/foo?video1) and making sure they have a cookie of some sort, but I am unsure how to prevent someone from just typing in the link of the source files (www.example.com/videos/video1.mp4). I need away to prevent people from accessing the source files.
System:
macOS Sierra 10.12.6
Apache
Thanks,
Josh
Put the source files in some directory that is not public, or use an HTAccess.
Then, use file_get_contents() and echo to spit out the video.
It might look something like this:
getvideo.php?video=test
<?php
if($_SESSION["username"]!==null)//whatever auth mechanism
{
if(file_exists("videos/". str_replace( [ '\\', '.', '/'], '', $_GET["video"] ). ".mp4"))
{
header("Content-Type: video/mp4");
readfile("videos/". str_replace( [ '\\', '.', '/'], '', $_GET["video"] ). ".mp4");
}
else
{
header("HTTP/1.1 404 Not Found");
}
}
else
{
header("HTTP/1.1 401 Unauthorized");
}
exit;
?>
Here's an idea if you're using Apache.
Make sure the Rewrite module is turned on.
Create a .htaccess file in your videos directory with the following content:
RewriteEngine On
RewriteRule . video.php?video=$1
Now, create a file named video.php with something like this:
<?php
/**
* require your login / db files here
* and check if the user is logged in,
* if it isn't redirect back or whatever you need
*/
$video = $_GET['video'];
$video = str_replace('..', '', $video); // prevent ../../file
if (file_exists($video)) {
header('Content-type: ' . mime_content_type($video));
echo file_get_contents($video);
} else {
// 404...
}
Now you can call yoursite.com/videos/video.mp4 and place your video files in the videos directory.

How to use GET & Include to dynamically PHP files from diff directory

I am very new to PHP, just learning it. need help in the code.
I have organised my php pages to be included in diff folder - content & security.
Now I want to include the pages from these folders using GET and include function in PHP.
Below is my code for including the file: It works fine only for content directory.
please let me what I need to change in the index.php code and my menu.php
index.php code:
include "/templates/header.php";
include "templates/menu.php";
include "/templates/splash.php";
// Set the default name
$action = "home_index";
// Specify some disallowed paths
$disallowed_paths = array('header', 'menu', 'splash', 'bottom_page', 'footer');
if (!empty($_GET['action']))
{
$tmp_action = basename($_GET['action']);
// If it's not a disallowed path, and if the file exists, update $action
if (!in_array($tmp_action, $disallowed_paths) && file_exists ("content/{$tmp_action}.php"))
$action = $tmp_action;
}
// Include $action
include "/content/$action.php";
include "/templates/bottom_page.php";
include "/templates/footer.php";
?>
below is my code for menu.php:
<ul>
<li class="first current_page_item">Homepage</li>
<li>Products</li>
<li>Services</li>
\<li>About</li>
<li>Contact</li>
<?php
if(isset($_SESSION['username']) && $_SESSION['username']== true){
echo '<li> Logout</li>';
}else{
echo '<li class="last">Login</li>';
}
?>
</ul>
include "/content/$action.php";
^---
include() works at the filesystem level, and has absolutely NO idea what your site's document root is. Since your include path starts with /, PHP is starting the search for your file at the root of the server's filesystem, not the root of your site.
e.g. you're doing the equivalent of
include c:\content\$action
when it should be
include c:\path\to\website\document\root\content\$action

Website Structure for Small Site without DB

I'm trying to setup a system to minimize complexity for people updating the site as I will not be the main person updating daily content AND also provide clean URLs.
Since I am unable to use a DB, all of the content resides in one of two base folders (/private/content OR /private/utilities). For normal daily updates, the utilities (contains the page wrapper - header, nav, footer, etc.) folder wouldn't need to be accessed. This minimizes the amount of visible code to the daily editor.
I've created an array ($allowedContent) that has the list of valid sections that are accessible. The code tests against that array to verify that the user is not attempting to access inappropriate content. With the code below, these requests would be successful. Everything else would fail.
www.example.com/
www.example.com/popup/*
www.example.com/test
www.example.com/hello
www.example.com/foobar
My question is:
Is there anything that sticks out as a problem with this approach?
.htaccess
RewriteEngine On
# Rules
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php
PHP
// parse the URL
$requestURI = explode('/', $_SERVER['REQUEST_URI']);
//print_r ($requestURI);
// a list of non-restricted dynamic content
$allowedContent = array("test", "hello", "foobar");
$allowAccess = false; // assume hackers :o
// determine the section
if (!$requestURI[1]) { // none defined - use root/home
$section = 'home';
$skin = true;
$allowAccess = true;
} elseif ($requestURI[1] == 'popup') { // popup - no skin
$section = $requestURI[2];
$skin = false;
$allowAccess = true;
} else {
if (in_array($requestURI[1], $allowedContent)) { // verify that the requested content is allowed / prevent someone from trying to hack the site
$section = $requestURI[1];
$skin = true;
$allowAccess = true;
} else { // this would be either a 404 or a user trying to access a restricted directory
echo "evil laugh"; // obviously, this would change to a 404 redirect
}
}
Added code where content is called
// call the relevant content pieces
if ($allowAccess == true) {
if ($skin == true ) {
// call wrapper part 1
include $_SERVER['DOCUMENT_ROOT'] . '/private/utilities/wrapperOpen.php';
// call aside
include $_SERVER['DOCUMENT_ROOT'] . '/private/utilities/header.php';
// call aside
include $_SERVER['DOCUMENT_ROOT'] . '/private/utilities/aside.php';
}
// call CONTENT (based on section)
include $_SERVER['DOCUMENT_ROOT'] . '/private/content/' . $section . '/index.php';
if ($skin == true ) {
// call branding
include $_SERVER['DOCUMENT_ROOT'] . '/private/utilities/branding.php';
// call footer
include $_SERVER['DOCUMENT_ROOT'] . '/private/utilities/footer.php';
// call wrapper part 2
include $_SERVER['DOCUMENT_ROOT'] . '/private/utilities/wrapperClose.php';
}
}
this would work.
you coyuld also look into using xml to store data, but you need to keep watch over system memory usage and loading time if the files get too large. sosplit them up where possible.
can’t you talk them into using a database? webhosting with database is cheap.

Configuring HTMLPurifier to display external links as plain text

I am trying to configure HTMLPurifier to only display external links as plain text. I used DisplayLinkURI option but it display all links as a plain text. is there any configuration for that? here is my code:
$mySite='mysite';
$externalSite='external';
require_once 'include/htmlpurifier/library/HTMLPurifier.auto.php';
$Config = HTMLPurifier_Config::createDefault();
$Config->set('AutoFormat.DisplayLinkURI', true);
$purifier = new HTMLPurifier($Config);
$mySite= $purifier->purify($mySite);
$externalSite=$purifier->purify($externalSite);
echo $mySite;
echo $externalSite;
The output is
<a>mysite</a> (http://www.mysite.com/)
<a>external</a> (http://www.external.com/)
I want the output to be like this:
mysite
<a>external</a> (http://www.external.com/)
Update:
I want to keep external links for images without change. I only need to convert hyperlinks to plain text.
I believe this is the one you're looking for
http://htmlpurifier.org/live/configdoc/plain.html#URI.DisableExternal
There's an option named URI.DisableExternal and AutoFormat.Linkify. Set them both to TRUE and see what happens.
http://htmlpurifier.org/live/configdoc/plain.html#URI.DisableExternal
http://htmlpurifier.org/live/configdoc/plain.html#AutoFormat.Linkify
And AutoFormat.DisplayLinkURI disables all the links. I suggest you use both the above instead of AutoFormat.DisplayLinkURI.
http://htmlpurifier.org/live/configdoc/plain.html#AutoFormat.DisplayLinkURI
Ok, I succeeded to add a custom injector to HTMLPurifier, here it is:
First, Create a "DisplayRemoteLinkURI.php" in "include\htmlpurifier\library\HTMLPurifier\Injector" and write this in it
<?php
class HTMLPurifier_Injector_DisplayRemoteLinkURI extends HTMLPurifier_Injector
{
public $name = 'DisplayRemoteLinkURI';
public $needed = array('a');
public function handleElement(&$token) {
}
public function handleEnd(&$token) {
if (isset($token->start->attr['href'])){
$url = $token->start->attr['href'];
if($this->is_remote($url)){
unset($token->start->attr['href']);
$token = array($token, new HTMLPurifier_Token_Text(" ($url)"));
}
} else {
// nothing to display
}
}
public function is_remote($path){
$urlvar = parse_url($path);
$remote_schemes = array("mailto");
$local_schemes = array("javascript");
if(in_array($urlvar["scheme"],$remote_schemes)){
return true;
}else if(in_array($urlvar["scheme"],$local_schemes)){
return false;
}else{
if(empty($urlvar["host"]) || $urlvar["host"]==$_SERVER["HTTP_HOST"]){
return false;
}else{
return true;
}
}
}
}
?>
And then create another file named "AutoFormat.DisplayRemoteLinkURI.txt" in "include\htmlpurifier\library\HTMLPurifier\ConfigSchema\schema" and add this :
AutoFormat.DisplayRemoteLinkURI
TYPE: bool
VERSION: 3.2.0
DEFAULT: false
--DESCRIPTION--
<p>
This directive turns on the in-text display of Remote URIs in <a> tags, and disables
those links. For example, example becomes
example (<a>http://example.com</a>).
</p>
--# vim: et sw=4 sts=4
After that, Add this line
require 'HTMLPurifier/Injector/DisplayRemoteLinkURI.php';
under
require 'HTMLPurifier/Injector/DisplayLinkURI.php';
in include\htmlpurifier\library\HTMLPurifier.includes.php
Then, Add this line
require_once $__dir . '/HTMLPurifier/Injector/DisplayRemoteLinkURI.php';
under
require_once $__dir . '/HTMLPurifier/Injector/DisplayLinkURI.php';
in include\htmlpurifier\library\HTMLPurifier.safe-includes.php
After these edits, if your files are at local, run cmd.exe and go to your php directory. Then run "include/HTMLPurifier/maintenance/generate-schema-cache.php" from php.exe.
Or if you want to do this via browser, rename your .htaccess file inside "include/HTMLPurifier/maintenance/" to something else for a while, then add this line inside "generate-schema-cache.php" on the first line after the <?php tag;
php_set_env("PHP_IS_CLI",true);
and then run this file from browser. After you see "Saving schema.. done!", rename your .htaccess file back.
Then in your script, use "AutoFormat.DisplayRemoteLinkURI" as config, and voila!
Note that the is_remote() function inside the first file I gave here might be not so good, and I couldn't find a script that checks if a link is remote or local, so you might alter it later if you need.

Populate an unordered list from a list of PHP files

The Situation:
I have a Projects page with a content area and a sidebar. I want the sidebar to contain a dynamic list of projects. The content area has an div with the id "post".
I have a subfolder containing .php files corresponding to projects that contain html content about each project.
The Challenge:
I would like the sidebar to generate an unordered list based on the filenames of the php files (or if possible, an h1 element inside each php file).
When clicked, I would like each of the items in this unordered list to populate the div id "post" in the content area with the contents of the php file to which it corresponds.
Is this possible?
I know it would be easier with a CMS like Wordpress, but I want to know how to do it without an SQL database if possible. Keep in mind, I know almost nothing about PHP. I have stuck to html/css so far.
The Solution:
function getfiles($dir){
if(!is_dir($dir))
return false;
$dirhandle = opendir($dir);
$files = array();
while($entry = readdir($dirhandle)){
if($entry!='.' && $entry!='..' && !is_dir($dir.'/'.$entry))
$files[]=$entry;
}
return $files;
}
Returns an array of the files. There are three special entries in a directory that aren't files. . refers to the directory it's in. .. refers to the parent directory. Finally, there are other directories. So far as I know, everything else is a file.
And then:
function createlist($dir){
if(!$files=getfiles($dir))
return false;
?>
<script type="text/javascript" >
function getcontent(xthis) {
var httpRequest;
makeRequest(xthis.href);
function makeRequest(url) {
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
httpRequest = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
try {
httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
try {
httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {}
}
}
if (!httpRequest) {
return false;
}
httpRequest.onreadystatechange = putContents;
httpRequest.open('GET', url);
httpRequest.send();
}
function putContents() {
if (httpRequest.readyState === 4) {
if (httpRequest.status === 200) {
document.getElementById("post").innerHTML=httpRequest.responseText;
} else {
return false;
}
}
}
}
</script>
<?PHP
echo "<ul>\n";
foreach($files as $file){
echo "\t<li><a onclick=\"getcontent(this);return false;\" href=".$dir."/$file>$file</a></li>\n";
}
echo "</ul>";
return true;
}
Ajax functions courtesy of https://developer.mozilla.org/en/AJAX/Getting_Started.
Listing Files
# index.php
<?php
if( $files = glob('/path/to/directory/*.php') )
{
?>
<ul id="sidebar">
<?php
foreach( $files as $path_raw )
{
$file_raw = basename($path_raw);
$file_safe = htmlentities($file_raw);
$file_urlsafe = urlencode($file_raw);
?>
<li><a class="file-link" href="/post.php?file=<?php echo $file_urlsafe; ?>"><?php echo $file_safe; ?></a></li>
</ul>
<?php
}
To locate the files, we will want to use glob(). In this case, pass in a path to a directory (/path/to/directory) and a filename pattern (*.php) to find all '.php' files in the specified directory.
glob() returns an array, so we will need to iterate over the result using foreach.
Since we are providing an absolute path to the directory where the files are located, glob() will return an array of absolute paths, so we will need to use basename() to strip off the directory info and just get the filename.
Although unusual, it is possible for filenames to have unsafe characters in them, so we need to escape the values using urlencode() for URL strings (the href for the anchor tag) and htmlentities() otherwise (the text of the anchor tag).
Reading Files
The link in the unordered list references a file named post.php under the web server's document root.
# post.php
<?php
$basedir = '/path/to/directory';
if( empty($_GET['file']) )
{
// Handle error condition: no filename provided.
}
$file_raw = $_GET['file'];
$file_safe = basename($file_raw);
if( ! is_file($file_safe) )
{
// Handle error condition: file does not exist or is not a file.
}
elseif( ! is_readable($file_safe) )
{
// Handle error condition: file exists, but is not readable (probably permissions issue).
}
passthru($file_safe);
post.php Expects a $_GET value named file to be provided (taken care of by clicking on one of the links in the sidebar). It is important to note a couple of things:
Web browsers are capable of requesting any URL, so we cannot assume that the user arrived at post.php by clicking on a sidebar link, so we must check a few things:
The file value might be missing (we can check for this by using empty()).
The file value might have a different value than we were expecting (in this case, we will use basename() to ensure that we are dealing with a filename and not an injected path).
Even if the file value is valid, it might reference a path that is not actually a file, or it points to a file that the webserver cannot access (we check for these cases by using is_file() and is_readable(), respectively).
Finally, once we are sure that the file value points to a valid file, we send its contents to the web browser using passthru().
The Javascript
The only thing left to do is to use some Javascript so that clicking on one of the sidebar links displays the contents in the #post div. I will use jQuery here for brevity:
# index.php
(function($){
$(function(){
var post = $('#post');
$('#sidebar a.file-link').click(function( e ){
post.load($(this).attr('href'));
e.preventDefault();
});
});
})(jQuery);
This code leverages the .load() method, which executes an ajax call and replaces the selected element with the content from that request.
We use .click() to set the ajax call to only trigger when the user clicks on one of the links in the sidebar, and we determine which URL to go to by calling .attr() on the clicked link to extract its href attribute.
Note that we use the event's preventDefault method rather than returning false to avoid potential for unwanted side effects.

Categories