How to create URLs similar to Pastebin, Imgur, Youtube etc.? - php

I'm creating a site (with PHP & MySQL) that takes a user input, generates a random link, and uses that users input on the generated link to show content.
The nearest real-life example would be http://pastebin.com/ - you enter a text input on the homepage, it generates a random link (such as http://pastebin.com/2hf4Dtv7 and then the text you input is permanently displayed on that generated link.
I've been stuck on this problem for what seems like forever. I've managed to get different parts of the problem solved (I think), but I can't seem to get it to work altogether.
Key facts
The user input needs to be available to use on the generated link
A PHP file run.php is what I will use to display content / manipulate the user's input, so somehow needs to be available on the generated link (unless there's another way to do this).
I have a MySQL database that currently has / stores 3 columns: ID (integer, which automatically increments), userinput (varchar, which is set to unique) and pageurl (varchar, which is also set to unique)
The site is using WordPress, but that's not too important as I'm dealing with the PHP / htaccess file(s) directly.
Things I've attempted / managed to do:
I can generate a random string for the url, via <?php echo $randGen ?>. This can be put into <form action="<?php echo $randGen ?>" method="POST"> - This works in the sense that it will open a tab to domain.com/xyz, but that 404s & run.php isn't assigned to the generated link (I'm not sure if the input value is either).
Tried both POST and GET methods in the form. The input data isn't sensitive, so it isn't a huge issue which is used.
Read up on & attempted to use .htaccess rewrite rules / pretty urls, such as RewriteRule ^([0-9a-zA-Z]+)$ run.php?userinput=$1 [NC,L], as well as trying to use [QSA] & &%{QUERY} to keep the user input, but found myself to be way out of my depth.
Attempted to covert the MySQL (auto-incrementing) ID to base64, but aren't sure where to run the PHP script to get it working & also don't understand how to append that random string to the URL, while still showing the users input.
Watched numerous tutorials on how to create pastebin-esque sites / URL shortener sites, to see if I could get any relevant ideas from that - to no avail.

You are almost there, RewriteRule is the way to go.
With this in your apache configuration:
RewriteRule ^([0-9a-zA-Z]+)$ run.php?randurl=$1 [L]
This, in your html page:
<form action="/run.php" method="POST">
Userinput: <input type="text" name="userinput">
You then just need to use the variables $_GET['randurl'] and $_POST['userinput'] in run.php:
if (isset($_POST['userinput'])) { // user adds a new input
// insert into database (userinput, randurl) values ('".$_POST['userinput']."', '".$randGen."')
// redirect the user to the new short URL page:
header('Location: domain.com/'.$randGen);
}
else if (isset($_GET['randurl'])) { // user wants to access the short URL
// retrieve userinput from database:
// select userinput from mydatabasename where randurl = 'domain.com/'.$_GET['randurl']
$sql = "SELECT userinput FROM articles WHERE randurl = '".$_GET[randurl]."'";
$result = $conn->query($sql);
if ($result) {
if ($row = $result->fetch_object()) {
// echo select result in the page
echo($row['userinput']);
}
else
echo("error: fetch_object");
$result->close();
}
else
echo("error: query");
}

Related

how to check if bookmarks exist in html document

I've just designed my first form in HTML and a PHP page to display the results. In the form the user inputs some codes in response to some questions, a bit like a multiple choice, so for example, these are "ABC". The PHP page displays the code to the user as a link, which when clicked will go to a bookmark (a link within the same page) with the ID #ABC. This was achieved with simple manipulation of the PHP variable as follows:
<?php
$code = "ABC"
$part1 = '<a href="mywebpage.php#';
$part2 = '">Go to this code</a>';
$string = $part1.$code.$part2;
echo $string;
?>
(i.e. Link in the page says "go to this code" and when clicked will go to section with bookmark ABC)
This all works fine, but I simply need to know if there is a way of error trapping so that if a bookmark does not exist for the code entered, a message can be displayed to the user instead? Can this be done using the PHP variable, or do I need to use JavaScript? One work around may be to search the web page for the ID "#ABC'. Is it possible to do this? Another option would be to store an array of valid codes on the server then query this before setting the bookmark, but I want to keep it as simple as possible. Any help appreciated, thanks.
What you call a "bookmark" we call a hash. And when you say "go to a bookmark" you mean a hash change. Hash changes do not make an additional request to the server, it is all handled on the client-side, therefore this must be done with JavaScript and not PHP.
So let's just do some simple JavaScript on hash change window.onhashchange that will search for an element with that ID and if it's not found alert something.
window.onhashchange = function(){
if(!document.getElementById(location.hash){
alert("not found");
}
}

How to encrypt product ID in URL

I have a database with just over 800 data.
product table
pid name p_page
1 money money.php
2 gold gold.php
3 .
. .
. .
800 .
I have 2 pages...
product_item.php
<div class="button">
View
</div>`
when you click view the product info is pass to product.php
in here i have
if (isset($_GET['pid'])) {
depending on what product the user clicked on the URL might look like something below but the 44 will change to whatever id
http://www.example.x10.mx/money.php?pid=44
the problem with this, is that money.php have a different layout to the other pages and if I change 44 to 68, the product info will show on the page but the layout will not look good.
My question
what is the best way for me to stop users from being able to change the url.
I want to encrypt all my pid in the url so it will look something like
http://www.example.x10.mx//money.php?sel=the product name here or 4 letters or anything
I just want to take away pid from the url.
Please help me. If you dont understand my question please ask in the comment and try and say what you think you understand.
Edited to show my fetch function
$php = "php/";
$apages = "account/";
$bpages = "booking/";
$gpages = "general/";
$ppages = "product/";
// Global functions
function fetchdir($dir)
{
$protocol = $GLOBALS['protocol'];
$host = $GLOBALS['host'];
($dir == $GLOBALS['apages'] || $dir == $GLOBALS['bpages'] || $dir == $GLOBALS['ppages'] || $dir == $GLOBALS['gpages'] ? $branch = $GLOBALS['pagebranch'] : $branch = $GLOBALS['branch']);
echo $protocol.$host.$branch.$dir;
}
Thanks
p.s. I dont know if this can be done in .htaccess but i think it can be done in php
Some clarification:
I have a url which looks like this
www.example.com/account/product.php?pid=1
the problem with this is that someone can change 1 or any number and if they is a pid in the database with that number it will get the items information and display on the page. Which I don't want to happen because not all product are meant to be display in some pages.
In the papge which i show all my available product. I simple uses a SELECT statement and then echo what I need in some div.
In that page I have a view button.
$stmt = $conn->prepare("SELECT * FROM Product WHERE Type = 'shoes'");
$stmt->execute();
$i = 0;
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $row) {
$id = ($row['pid']);
$product_page ($row['dir_page']);
<div class="button" >
<a href = "<?php fetchdir($apages) ?><?echo $product_page?ProdID=<?php echo $id>" > View</a >
</div >
}
Depending on the page that information is getting sent to when you click on view I use Get method
<?php
if (isset($_GET['pid'])) {
// Connect to the MySQL database
dbconnect();
$id = preg_replace('#[^0-9]#i', '', $_GET['pid']);
}
If you notice in my select statement used type to show only the product which type is shoes. I have other types as well, which as their other pages. Now the problem is if i change the pid to any page that doesn't have a type of shoes or if an in the other pages and enter a pid which type is shoes or anything, the information from that page will still render. Which I don't want to happen.
My question
how can i stop users from changing that pid and even if they change it. they will still be on the same page?
The problem isn't having the PID in the URL, it is having the template name in the URL.
Store the template name in the database (you are doing this already), and use that to determine what HTML to wrap the data in instead of putting it (money.php) in the URL.
Move your templates out of the web root (they shouldn't be hit by users directly), have a single index.php and then include() the template based on the data in the database.
You cannot prevent someone from changing the URL or from requesting arbitrary URLs. Your server (i.e. your app) has to decide how to respond to an invalid request. If you don't want to display certain things publicly, flag them as such in your database, test for that flag and simply refuse to output anything if that flag is hit.
Make the server respond negatively if something doesn't fit your conditions; don't expect the user to behave correctly.
Assuming that PID is a autoincrement value, you can still obfuscate it. Add another column in the table that contains a randomly-generated key (using uniqid or some derivative). Then use that key in your URL. You'll get something like: www.example.com/account/product.php?pid=II8GypI6H93Ij. This doesn't guarantee that someone won't find it, but it's good enough in most instances.
Check for allowance in the Database
Depending on your level of programming skills, in the database you could add a field or a relational table that relates the ID of the pages to allowed page templates (I'm guessing you're talking about templates.)
Then in the code you can make it so the page checks this database to see if the page contents are allowed to show. Something like:
$query1 = "SELECT * FROM Product WHERE Type = 'shoes' and allowedTemplate='1'";
This way you won't have to hardcode everything into the code itself. On the backend (if there is a CMS) then you could have checkboxes indicating the relationships to the templates and prefill them by default.
You'll need to make the site so something with that stuff though.
Your other option
You could use clean urls (which used to be better for SEO) to show real words instead of the IDs. Then you can use .htaccess tricks to convert the URIs to their ID counterparts with a dynamic RewriteMap.

pass a value from one page to another outside querystring and without javascript?

One solution to automatically building navigation for a site is by scanning a folder for documents like this:
foreach(glob('pages/*.pg.php') as $_SITE_NAV_filePath):
$_SITE_NAV_filePath = explode('.pg',pathinfo($_SITE_NAV_filePath,PATHINFO_FILENAME));
$_SITE_NAV_fileName = $_SITE_NAV_filePath[0];
$_SITE_NAV_qv = preg_replace('/([A-Z])/','-$1',$_SITE_NAV_fileName); $_SITE_NAV_qv = trim($_SITE_NAV_qv,'-');
$_SITE_NAV_name = preg_replace('/([A-Z])/',' $1',$_SITE_NAV_fileName);
?>
<li><?=$_SITE_NAV_name?></li>
<?php
endforeach;
This code will turn "AnAwesomePage.pg.php" into a menu item like this :
<li>An Awesome Page</li>
This might be bad practice (?).
Anyway; I don't use this method very often since most of the time the sites have a database, and with that comes better solutions...
But my question is this:
Is there a way to prefix the filename with a integer followed by and underscore (3_AnAwesomePage.pg.php), for sorting order purposes, and pass it somehow to the destination page outside of the querystring and without any async javascript?
I could just explode the filename once again on "_" to get the sort order and store it somewhere, somehow?
This is the code for handeling the page query request:
$_SITE_PAGE['qv'] = $_GET['page'];
if (empty($_SITE_PAGE['qv'])){ $_SITE_PAGE['qv'] = explode('-','Home'); }
else { $_SITE_PAGE['qv'] = explode('-',$_GET['page']); }
$_SITE_PAGE['file'] = 'pages/'.implode($_SITE_PAGE['qv']).'.pg.php';
This code turns "An-Awesome-Page" back into "AnAwesomePage.pg.php" so it's possible to include it with php.
But with a prefix, it's not so easy.
The probliem is; Now there's no way to know what prefix number there was before since it has been stripped away from the query string. So I need to send it somehow along in the "background".
One very bad solution I came up with was to transform the navigation link into a form button and just _POST the prefix interger along with the form. At fist it sounded like a nice solution, but then I realized that once a user refreshes their page, it didn't look very good. And after all, that's not what forms are for either...
Any good solutions out there?
Or some other and better way for dealing with this?
There are two ways to keep that number saved, you can use cookies or php session variables.
But in this case, if user first enter the url in the browser or in a new browser, then he should be taken to default number.
Like you have:
1_first-page.php
2_first-page.php
3_first-page.php
If user enter the url like: domain.com/?page=first-page, you have to take him to 1_first-page.php to any number which you want to be default.

Correct way to use an if statement and a $GET in PHP

Am fairly new to PHP and am making a basic CRUD style management system. I Have an update page and it displays data from a News table, and populates a form with it. The current picture ?(reference) is pulled through and displayed on the form. However if a user wants to change the picture they can press a 'delete' button and then I have written some PHP to display a upload button, set the values in the database for the image to null and hide the delete button, allowing the user to upload a new picture.
The Delete button only removes the reference (path) to the picture from the database, it doesn't delete the actual picture.
This is the HTML control to show the image and delete button. It also shows how the delete button works:
<td align="right">Image 1:</td>
<td align="left"><img src="uploads/newsimages/<?php echo $row["Image"]; ?>" width="230" border="0"> delete</td>
As you can see, when clicked it sets change=imagex and cid= the current news id.
There is then an if statement I have written, but it doesn't seem to only get activated when the delete button is clicked. Because I always get an error that 'cid' is undefined. It is as follows:
<?php
if (isset($_GET['change'] = "image1") {
$query = "UPDATE Table_Name SET Image = '' WHERE NewsID =".$_GET['cid']." ";
}
?>
I am pretty sure my lack of PHP knowledge is letting me down and I am trying to go about this the wrong way, because however I alter the if statement it always gives me an error. First it was cid is undefined so I changed to id but i already use that for something else, another query/function. I hope that all amde sense, can anyone tell me where Im going wrong?
You are missing a parenthesis + you have to specify individually:
if (isset($_GET['change'] = "image1") {
Change to:
if (isset($_GET['change']) && $_GET['change'] == "image1") {
Some more things to consider:
1) Don't use unsanitized values directly from $_GET in a mysql query
WHERE NewsID =".$_GET['cid']."
It is very easy to exploit this with some funky sql injection (see http://xkcd.com/327/ ).
If you are using numeric values for cid, you should cast your $_GET value to integer to prevent sql injection:
$cid = (int)$_GET['cid];
$query = '(...)WHERE NewsID = '.$cid.' limit 1';
Or even better:
$cid = (int)(array_key_exists('cid', $_GET) ? $_GET['cid'] : 0);
if ($cid) {
$query = (...)
}
If you need this kind of sanitizing in different places, you should think about writing a helper function for it to keep your code readable.
2) Don't use GET requests to change data on your server
Imagine a google bot browsing your site and following all those links that you use to delete images. Other scenarios involve users with prefetch plugins for their browsers (e.g. Fasterfox). Also, GET requests may be cached by proxies and browsers, so that the request won't hit the server if you click the link.
The HTTP specification comes with numerous request methods, the most important ones are:
GET to fetch content from the server
PUT to store new information on the server
POST to update existing information on the server
To update your news record (by removing the image) the appropriate method would be POST. To send a POST request, you can use the <form method="POST"> tag.
try this
<?php
if (isset($_GET['change']) && $_GET['change'] == "image1") {
$query = "UPDATE Table_Name SET Image = '' WHERE NewsID =".$_GET['cid']." ";
}
?>

Creating basic PHP script to add lines to a webpage

I'm predominately a Java guy, which is why I need some assistance on what I assume is rather simple to do in PHP (and rather simple with Java too, although perhaps a bit... verbose).
Simply put, I want to construct a webpage which has a list of string items that users have added. At the bottom of the page would be a place in which a user could type "Hello World" in a box for instance and hit a submit button, adding it to the list of items. Adding to the top or the bottom of the list is irrelevant - I can probably tweak that later.
I'm the kind of guy who doesn't just like answers, but at the same time I have no idea where to even start searching. I've done no PHP development before. What sorts of constructs or functions should I be looking at? I own the physical box it'll be running on (it's literally right next to me now) so permissions aren't a restriction, and neither is getting anything else that might help the situation (although I can't see how it would be needed for such a simple script). What sorts of input validation should I be really wary of? This service will be restricted to people who have be given access to a particular section of an apache-based website, so they have to log in to even see this planned page, but I'd like to cover all possibilities.
Additionally, I would perhaps like output to look like
"Hello World" added by user User1
"This is an additional line" added by User2
"Goodbye World" added by user User1
in the future. What should I be looking at to do this?
Update to answer questions:
When it comes to storage of the actual content, I'd be leaning towards a simple file holding each entry line by line, as Col. Shrapnel suggested. A think a database would be overkill, although I do have the wherewithal to implement it. If a user submits "Hello World!" then adding a line to a file that says
"Hello World!" posted by User1
is sufficient.
With regards to authentication, this is already set up in apache's httpd.conf configuration file. Currently this allows access to a certain group of users through an AuthGroupFile entry. This is where the script will be hosted. To access this script, users will have already authenticated themselves with their credentials. The authentication currently works for that section of the site. Really, this is a secondary concern of mine. It is enough that lines are simply added with no record of who said what. This is just sugar on the PHP cake if it can be done easily with what I already have implemented.
Well, yes, in PHP it's quite short.
Assuming Apache based authorization is used
<?
$file = "messages.txt";
if ($_SERVER["REQUEST_METHOD"]=="POST") {
$_POST['mess'] = str_replace(array("\r","\n"),"",$_POST['mess'];
file_put_contents($file, $_POST['mess']." ".$_SERVER["REMOTE_USER"]);
header("Location:".$_SERVER["PHP_SELF"]);
exit;
}
echo nl2br(htmlspecialchars(file_get_contents($file)));
?>
<form method="POST">
<input type="text" name="mess">
<input type="submit">
</form>
You're going to have a few things to do:
Pick a data store. MySQL is a popular choice when working with PHP. It doesn't sound like this'll be high-volume, so most any persistent store would work.
When accepting input, you'll need to sanitize it for insertion into the DB (again, if using MySQL, check the docs), and then you'll execute an INSERT statement to put it into the database.
When displaying the page, you'll connect to the DB (check the docs), query data from the data store, loop over it, and echo each line after sanitizing it of any potentially malicious data.
A short example might be something like:
<?
// Assuming a database named "my_database" with a table called "chat_lines", which has "username", "line", and "timestamp" fields.
$db = mysql_connect("localhost", "username", "password");
mysql_select_db("my_database", $db);
// If data was posted to the script, scrub it and store it in the database.
if($_POST["username"] && $_POST["line"]) {
mysql_query(sprintf("INSERT INTO chat_lines (username, line, timestamp) VALUES (\"%s\", \"%s\", NOW())",
mysql_real_escape_string($_POST["username"]),
mysql_real_escape_string($_POST["line"])
));
}
// Fetch all lines from the database in reverse chronological order
$result = mysql_query("SELECT * FROM chat_lines ORDER BY timestamp DESC");
while($row = mysql_fetch_assoc($result)) {
echo sprintf("<div>%s said %s</div>", strip_tags($result["username"]), strip_tags($result["line"]));
}
?>
<form method="post">
<div>Username: <input type="text" name="username" /></div>
<div>Line: <input type="text" name="line" /></div>
<input type="submit" />
</form>
That example makes assumptions about users being allowed to enter whatever username they want (that is, it doesn't assume to implement the authentication system), the data store and the existence of the table and all that, but should get you started. The PHP documentation is pretty extensive, and can be very useful. In particular, read Getting Started and the Language Reference.

Categories