Text Based Article System

With PHP

December 5, 2009
<?PHP
/*--------------------------------------------------------------------------\
| These lines will get the information from the URL, for handling the data. |
| There is some filtering here to avoid some kinds of attacks.              |
| To reduce processing time, the POST variables are only handled when the   |
| script is in "post" mode.                                                 |
\--------------------------------------------------------------------------*/
$mode = $_GET['mode'];
$articleID = preg_replace("/[^0-9]/i", "", $_GET['id']);


/*--------------------------------------------------------------------------\
| SWITCH selects the variable that CASE will use. Here, we're using CASE to |
| determine what mode we're in. This allows us to use only one script to    |
| handle an entire system -- easy for updates, and cleaner for your htdocs  |
| folder.
\--------------------------------------------------------------------------*/
SWITCH ($mode)
     {
     CASE "add":
          {
          /*--------------------------------------------------------------------------\
          | Here, we'll generate the form that people will create an article in.      |
          | The action= portion tells the script to point to itself, but in post mode |
          | This allows you to name your file whatever you like.                      |
          \--------------------------------------------------------------------------*/
          echo "
          <form action='" . $_SERVER['PHP_SELF'] . "?mode=post' method='post'>
               <label>Title:</label> <input type='text' name='title' /><br />
               <label>Author:</label> <input type='text' name='author' /><br />
               <label>Body:</label> <textarea cols='25' rows=20' name='body'></textarea><br /><br />
               <input type='submit' value='Add Article' />
          </form>";
          break;
          }
     CASE "view":
          {
          /*--------------------------------------------------------------------------\
          | Here, the script will open the article, and do some basic formatting to   |
          | the layout. Also convert the [br]s to <br />s.                            |
          \--------------------------------------------------------------------------*/
          if (file_exists($articleID . ".txt"))
               {
               $file = fopen($articleID . ".txt","r");
               $title = trim(fgets($file));
               $author = trim(fgets($file));
               $time = trim(fgets($file));
               $body = str_ireplace("[br]", "<br />", trim(fgets($file)));
               fclose($file);
               echo "<h1>" . $title . "</h1><hr />Posted By: " . $author . "<hr />" . $body;
               }
          else
               {
               echo "Oops! That article doesn't exist!";
               }
          break;
          }
     CASE "post":
          {
          /*--------------------------------------------------------------------------\
          | This is where the code starts getting complex. Here, we're writting to a  |
          | text file, but we have to make sure the data is safe to post.     We'll start |
          | by cleaning out and formatting the variables first.                       |
          \--------------------------------------------------------------------------*/
          $title = strip_tags($_POST['title']);
          $author = strip_tags($_POST['author']);
          $body = str_replace("\r\n", "",str_ireplace("<br />", "[br]",nl2br(strip_tags($_POST['body']))));
          /*--------------------------------------------------------------------------\
          | As you can see, the filtering for $body is the most complicated. What all |
          | those extra parts do, is convert "newlines" (or when you pressed enter in |
          | the textbox) to a pseudo-tag [br]. This makes it safe to put into your    |
          | text file database, because each field is seperated by an ENTER               |
          \--------------------------------------------------------------------------*/
          
          /*--------------------------------------------------------------------------\
          | Below, we're going to use a UNIX timestamp to name the text file, which   |
          | will become the ID of the file, and help us assess the time it was posted |
          \--------------------------------------------------------------------------*/
          $posttime = time();
          
          if (file_exists($posttime . ".txt"))
               {
               /*--------------------------------------------------------------------------\
               | Because we're using the timestamp as the filename, it is possible that    |
               | two people could post at the same time. This is called a "race condition" |
               | and is quite a problem for programmers. You could use a random number,    |
               | but then there's more of a risk of overwritting other files. This code    |
               | checks to see if the file exists, and if it does, it asks the author to   |
               | resubmit, thus giving it a new ID number due to the new timestamp.        |
               \--------------------------------------------------------------------------*/
               echo "OOPS! Minor error, please hit back and try again!";
               die;
               }
          /*--------------------------------------------------------------------------\
          | Okay, now we're going to actually write the file. As you can see, there's |
          | a \r\n at the end of each file. For Windows servers, this means "return   |
          | carriage" and "new line"...Kinda like a typewritter. For Unix based       |
          | servers, change it to \r, and Macintosh servers, change to \n.            |
          \--------------------------------------------------------------------------*/
          $file = fopen($posttime . ".txt","w");
               fwrite ($file, $title . "\r\n");
               fwrite ($file, $author . "\r\n");
               fwrite ($file, $posttime . "\r\n");
               fwrite ($file, $body . "\r\n");
          fclose($file);

          /*--------------------------------------------------------------------------\
          | Alright, our article is now saved. If you open the text file, you'll see  |
          | something like this:                                                      |
          |   File Based Article System                                                           |
          |   robert-lerner.com                                                                    |
          |   12345678                                                                             |
          |   Hello![br] In this article, we'll show you how to:[br] Use PHP...          |
          | Next, we have to create an INDEX file. We'll APPEND the new article:      |
          \--------------------------------------------------------------------------*/
          $file = fopen("index.txt","a");
               fwrite ($file, $posttime . "\r\n");
               fwrite ($file, $title . "\r\n");
               fwrite ($file, $author . "\r\n");
          fclose($file);
          
          /*--------------------------------------------------------------------------\
          | Now that it's all set, we'll give the author a link to their article.         |
          \--------------------------------------------------------------------------*/
          echo "Thanks for your article! You can view it <a href='" . $_SERVER['PHP_SELF'] . "?id=" . $posttime . "&amp;mode=view'>Here</a>!";
          break;
          }
     DEFAULT:
          {
          /*--------------------------------------------------------------------------\
          | When no MODE is specified, the SWITCH statement defaults to the DEFAULT   |
          | area. Here, we'll show an index of the articles made -- that way your     |
          | user's aren't left guessing the ID of a particular article.               |
          \--------------------------------------------------------------------------*/
          
          echo "<a href='" . $_SERVER['PHP_SELF'] . "?mode=add'><strong>Add an Article</strong></a><br /><br />";
          
          if (file_exists("index.txt"))
               {
               echo "
               <table width='50%' border='1' cellspacing='0' align='center'>
                    <tr>
                         <th>Title</th>
                         <th width='20%'>Posted By:</th>
                    </tr>";
               
               /*--------------------------------------------------------------------------\
               | Here, we're going to open the index file, and format it into a table.     |
               | Remember that the POSTTIME is also the ID, so we'll exploit that here.    |
               | There is also a $cnt variable -- this counts the articles, and puts that  |
               | at the bottom of the table.                                                            |
               \--------------------------------------------------------------------------*/
               $file = fopen("index.txt","r");
               while (!feof($file))
                    {
                    $id = trim(fgets($file));
                    $title = trim(fgets($file));
                    $author = trim(fgets($file));
                    if ($id!="")
                         {
                         echo "<tr><td><a href='" . $_SERVER['PHP_SELF'] . "?id=" . $id . "&amp;mode=view'>" . $title . "</a></td><td>" . $author . "</td></tr>";
                         $cnt++;
                         }
                    }
               fclose($file);
               echo "</table>" . $cnt . " article(s) in our database.";
               }
          else
               {
               /*--------------------------------------------------------------------------\
               | If there is no index file, let them know here.                            |
               \--------------------------------------------------------------------------*/
               echo "Oops! Seems like we don't have any articles yet. Please add one!";
               }
               
               
          break;
          }
     }
?>