├── admin
├── logout.php
├── menu.php
├── login.php
├── add-category.php
├── categories.php
├── users.php
├── index.php
├── edit-category.php
├── add-user.php
├── edit-user.php
├── add-post.php
└── edit-post.php
├── README.md
├── .htaccess
├── includes
├── functions.php
└── config.php
├── sidebar.php
├── classes
├── class.user.php
├── class.paginator.php
└── class.password.php
├── viewpost.php
├── index.php
├── style
├── main.css
└── normalize.css
├── archives.php
├── catpost.php
└── db.sql
/admin/logout.php:
--------------------------------------------------------------------------------
1 | logout();
7 | header('Location: index.php');
8 |
9 | ?>
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Creating a blog from scratch with PHP - Part 6 Pagination
2 | =============
3 |
4 | These files acompany the tutorial: [Creating a blog from scratch with PHP - Part 6 Pagination](http://daveismyname.com/creating-a-blog-from-scratch-with-php-part-6-pagination-bp)
--------------------------------------------------------------------------------
/.htaccess:
--------------------------------------------------------------------------------
1 | RewriteEngine On
2 | RewriteBase /simple-blog-part-5-sidebar-categories-and-archives/
3 |
4 | RewriteRule ^c-(.*)$ catpost.php?id=$1 [L]
5 | RewriteRule ^a-(.*)-(.*)$ archives.php?month=$1&year=$2 [L]
6 |
7 | RewriteCond %{REQUEST_FILENAME} !-d [NC]
8 | RewriteCond %{REQUEST_FILENAME} !-f [NC]
9 | RewriteRule ^(.*)$ viewpost.php?id=$1 [QSA,L]
--------------------------------------------------------------------------------
/admin/menu.php:
--------------------------------------------------------------------------------
1 |
Blog
2 | Logged in as =$_SESSION['username'];?>
3 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/includes/functions.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/sidebar.php:
--------------------------------------------------------------------------------
1 | Recent Posts
2 |
3 |
4 |
5 | query('SELECT postTitle, postSlug FROM blog_posts_seo ORDER BY postID DESC LIMIT 5');
7 | while($row = $stmt->fetch()){
8 | echo ''.$row['postTitle'].' ';
9 | }
10 | ?>
11 |
12 |
13 | Catgories
14 |
15 |
16 |
17 | query('SELECT catTitle, catSlug FROM blog_cats ORDER BY catID DESC');
19 | while($row = $stmt->fetch()){
20 | echo ''.$row['catTitle'].' ';
21 | }
22 | ?>
23 |
24 |
25 | Archives
26 |
27 |
28 |
29 | query("SELECT Month(postDate) as Month, Year(postDate) as Year FROM blog_posts_seo GROUP BY Month(postDate), Year(postDate) ORDER BY postDate DESC");
31 | while($row = $stmt->fetch()){
32 | $monthName = date("F", mktime(0, 0, 0, $row['Month'], 10));
33 | $slug = 'a-'.$row['Month'].'-'.$row['Year'];
34 | echo "$monthName ";
35 | }
36 | ?>
37 |
--------------------------------------------------------------------------------
/includes/config.php:
--------------------------------------------------------------------------------
1 | setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
13 |
14 |
15 | //set timezone
16 | date_default_timezone_set('Europe/London');
17 |
18 | //load classes as needed
19 | function __autoload($class) {
20 |
21 | $class = strtolower($class);
22 |
23 | //if call from within assets adjust the path
24 | $classpath = 'classes/class.'.$class . '.php';
25 | if ( file_exists($classpath)) {
26 | require_once $classpath;
27 | }
28 |
29 | //if call from within admin adjust the path
30 | $classpath = '../classes/class.'.$class . '.php';
31 | if ( file_exists($classpath)) {
32 | require_once $classpath;
33 | }
34 |
35 | //if call from within admin adjust the path
36 | $classpath = '../../classes/class.'.$class . '.php';
37 | if ( file_exists($classpath)) {
38 | require_once $classpath;
39 | }
40 |
41 | }
42 |
43 | $user = new User($db);
44 |
45 | include('functions.php');
46 | ?>
--------------------------------------------------------------------------------
/classes/class.user.php:
--------------------------------------------------------------------------------
1 | _db = $db;
13 | }
14 |
15 | public function is_logged_in(){
16 | if(isset($_SESSION['loggedin']) && $_SESSION['loggedin'] == true){
17 | return true;
18 | }
19 | }
20 |
21 | private function get_user_hash($username){
22 |
23 | try {
24 |
25 | $stmt = $this->_db->prepare('SELECT MemberID, username, password FROM blog_members WHERE username = :username');
26 | $stmt->execute(array('username' => $username));
27 |
28 | return $stmt->fetch();
29 |
30 | } catch(PDOException $e) {
31 | echo ''.$e->getMessage().'
';
32 | }
33 | }
34 |
35 |
36 | public function login($username,$password){
37 |
38 | $user = $this->get_user_hash($username);
39 |
40 | if($this->password_verify($password,$user['password']) == 1){
41 |
42 | $_SESSION['loggedin'] = true;
43 | $_SESSION['memberID'] = $user['memberID'];
44 | $_SESSION['username'] = $user['username'];
45 | return true;
46 | }
47 | }
48 |
49 |
50 | public function logout(){
51 | session_destroy();
52 | }
53 |
54 | }
55 |
56 |
57 | ?>
58 |
--------------------------------------------------------------------------------
/admin/login.php:
--------------------------------------------------------------------------------
1 | is_logged_in() ){ header('Location: index.php'); }
8 | ?>
9 |
10 |
11 |
12 |
13 | Admin Login
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | login($username,$password)){
30 |
31 | //logged in return to index page
32 | header('Location: index.php');
33 | exit;
34 |
35 |
36 | } else {
37 | $message = '
Wrong username or password
';
38 | }
39 |
40 | }//end if submit
41 |
42 | if(isset($message)){ echo $message; }
43 | ?>
44 |
45 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/viewpost.php:
--------------------------------------------------------------------------------
1 | prepare('SELECT postID, postTitle, postCont, postDate FROM blog_posts_seo WHERE postSlug = :postSlug');
6 | $stmt->execute(array(':postSlug' => $_GET['id']));
7 | $row = $stmt->fetch();
8 |
9 | //if post does not exists redirect user.
10 | if($row['postID'] == ''){
11 | header('Location: ./');
12 | exit;
13 | }
14 |
15 | ?>
16 |
17 |
18 |
19 |
20 | Blog -
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
Blog
29 |
30 |
Blog Index
31 |
32 |
33 |
34 | ';
36 | echo '
'.$row['postTitle'].' ';
37 | echo '
Posted on '.date('jS M Y H:i:s', strtotime($row['postDate'])).' in ';
38 |
39 | $stmt2 = $db->prepare('SELECT catTitle, catSlug FROM blog_cats, blog_post_cats WHERE blog_cats.catID = blog_post_cats.catID AND blog_post_cats.postID = :postID');
40 | $stmt2->execute(array(':postID' => $row['postID']));
41 |
42 | $catRow = $stmt2->fetchAll(PDO::FETCH_ASSOC);
43 |
44 | $links = array();
45 | foreach ($catRow as $cat)
46 | {
47 | $links[] = "".$cat['catTitle']." ";
48 | }
49 | echo implode(", ", $links);
50 |
51 | echo '
';
52 | echo '
'.$row['postCont'].'
';
53 | echo '
';
54 | ?>
55 |
56 |
57 |
58 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/admin/add-category.php:
--------------------------------------------------------------------------------
1 | is_logged_in()){ header('Location: login.php'); }
6 | ?>
7 |
8 |
9 |
10 |
11 | Admin - Add Category
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Categories Index
21 |
22 |
Add Category
23 |
24 | prepare('INSERT INTO blog_cats (catTitle,catSlug) VALUES (:catTitle, :catSlug)') ;
45 | $stmt->execute(array(
46 | ':catTitle' => $catTitle,
47 | ':catSlug' => $catSlug
48 | ));
49 |
50 | //redirect to index page
51 | header('Location: categories.php?action=added');
52 | exit;
53 |
54 | } catch(PDOException $e) {
55 | echo $e->getMessage();
56 | }
57 |
58 | }
59 |
60 | }
61 |
62 | //check for any errors
63 | if(isset($error)){
64 | foreach($error as $error){
65 | echo '
'.$error.'
';
66 | }
67 | }
68 | ?>
69 |
70 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/index.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Blog
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
Blog
16 |
17 |
18 |
19 |
20 | query('SELECT postID FROM blog_posts_seo');
26 |
27 | //pass number of records to
28 | $pages->set_total($stmt->rowCount());
29 |
30 | $stmt = $db->query('SELECT postID, postTitle, postSlug, postDesc, postDate FROM blog_posts_seo ORDER BY postID DESC '.$pages->get_limit());
31 | while($row = $stmt->fetch()){
32 |
33 | echo '
';
34 | echo '
Posted on '.date('jS M Y H:i:s', strtotime($row['postDate'])).' in ';
35 |
36 | $stmt2 = $db->prepare('SELECT catTitle, catSlug FROM blog_cats, blog_post_cats WHERE blog_cats.catID = blog_post_cats.catID AND blog_post_cats.postID = :postID');
37 | $stmt2->execute(array(':postID' => $row['postID']));
38 |
39 | $catRow = $stmt2->fetchAll(PDO::FETCH_ASSOC);
40 |
41 | $links = array();
42 | foreach ($catRow as $cat)
43 | {
44 | $links[] = "".$cat['catTitle']." ";
45 | }
46 | echo implode(", ", $links);
47 |
48 | echo '
';
49 | echo '
'.$row['postDesc'].'
';
50 | echo '
Read More
';
51 | }
52 |
53 | echo $pages->page_links();
54 |
55 | } catch(PDOException $e) {
56 | echo $e->getMessage();
57 | }
58 | ?>
59 |
60 |
61 |
62 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/admin/categories.php:
--------------------------------------------------------------------------------
1 | is_logged_in()){ header('Location: login.php'); }
7 |
8 | //show message from add / edit page
9 | if(isset($_GET['delcat'])){
10 |
11 | $stmt = $db->prepare('DELETE FROM blog_cats WHERE catID = :catID') ;
12 | $stmt->execute(array(':catID' => $_GET['delcat']));
13 |
14 | header('Location: categories.php?action=deleted');
15 | exit;
16 | }
17 |
18 | ?>
19 |
20 |
21 |
22 |
23 | Admin
24 |
25 |
26 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | Category '.$_GET['action'].'.';
46 | }
47 | ?>
48 |
49 |
50 |
51 | Title
52 | Action
53 |
54 | query('SELECT catID, catTitle, catSlug FROM blog_cats ORDER BY catTitle DESC');
58 | while($row = $stmt->fetch()){
59 |
60 | echo '';
61 | echo ''.$row['catTitle'].' ';
62 | ?>
63 |
64 |
65 | Edit |
66 | Delete
67 |
68 |
69 | ';
71 |
72 | }
73 |
74 | } catch(PDOException $e) {
75 | echo $e->getMessage();
76 | }
77 | ?>
78 |
79 |
80 |
Add Category
81 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/admin/users.php:
--------------------------------------------------------------------------------
1 | is_logged_in()){ header('Location: login.php'); }
7 |
8 | //show message from add / edit page
9 | if(isset($_GET['deluser'])){
10 |
11 | //if user id is 1 ignore
12 | if($_GET['deluser'] !='1'){
13 |
14 | $stmt = $db->prepare('DELETE FROM blog_members WHERE memberID = :memberID') ;
15 | $stmt->execute(array(':memberID' => $_GET['deluser']));
16 |
17 | header('Location: users.php?action=deleted');
18 | exit;
19 |
20 | }
21 | }
22 |
23 | ?>
24 |
25 |
26 |
27 |
28 | Admin - Users
29 |
30 |
31 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | User '.$_GET['action'].'.';
51 | }
52 | ?>
53 |
54 |
55 |
56 | Username
57 | Email
58 | Action
59 |
60 | query('SELECT memberID, username, email FROM blog_members ORDER BY username');
64 | while($row = $stmt->fetch()){
65 |
66 | echo '';
67 | echo ''.$row['username'].' ';
68 | echo ''.$row['email'].' ';
69 | ?>
70 |
71 |
72 | Edit
73 |
74 | | Delete
75 |
76 |
77 |
78 | ';
80 |
81 | }
82 |
83 | } catch(PDOException $e) {
84 | echo $e->getMessage();
85 | }
86 | ?>
87 |
88 |
89 |
Add User
90 |
91 |
92 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/admin/index.php:
--------------------------------------------------------------------------------
1 | is_logged_in()){ header('Location: login.php'); }
7 |
8 | //show message from add / edit page
9 | if(isset($_GET['delpost'])){
10 |
11 | $stmt = $db->prepare('DELETE FROM blog_posts_seo WHERE postID = :postID') ;
12 | $stmt->execute(array(':postID' => $_GET['delpost']));
13 |
14 | //delete post categories.
15 | $stmt = $db->prepare('DELETE FROM blog_post_cats WHERE postID = :postID');
16 | $stmt->execute(array(':postID' => $_GET['delpost']));
17 |
18 | header('Location: index.php?action=deleted');
19 | exit;
20 | }
21 |
22 | ?>
23 |
24 |
25 |
26 |
27 | Admin
28 |
29 |
30 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | Post '.$_GET['action'].'.';
50 | }
51 | ?>
52 |
53 |
54 |
55 | Title
56 | Date
57 | Action
58 |
59 | query('SELECT postID, postTitle, postDate FROM blog_posts_seo ORDER BY postID DESC');
63 | while($row = $stmt->fetch()){
64 |
65 | echo '';
66 | echo ''.$row['postTitle'].' ';
67 | echo ''.date('jS M Y', strtotime($row['postDate'])).' ';
68 | ?>
69 |
70 |
71 | Edit |
72 | Delete
73 |
74 |
75 | ';
77 |
78 | }
79 |
80 | } catch(PDOException $e) {
81 | echo $e->getMessage();
82 | }
83 | ?>
84 |
85 |
86 |
Add Post
87 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/admin/edit-category.php:
--------------------------------------------------------------------------------
1 | is_logged_in()){ header('Location: login.php'); }
6 | ?>
7 |
8 |
9 |
10 |
11 | Admin - Edit Category
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Categories Index
21 |
22 |
Edit Category
23 |
24 |
25 | prepare('UPDATE blog_cats SET catTitle = :catTitle, catSlug = :catSlug WHERE catID = :catID') ;
50 | $stmt->execute(array(
51 | ':catTitle' => $catTitle,
52 | ':catSlug' => $catSlug,
53 | ':catID' => $catID
54 | ));
55 |
56 | //redirect to index page
57 | header('Location: categories.php?action=updated');
58 | exit;
59 |
60 | } catch(PDOException $e) {
61 | echo $e->getMessage();
62 | }
63 |
64 | }
65 |
66 | }
67 |
68 | ?>
69 |
70 |
71 | ';
76 | }
77 | }
78 |
79 | try {
80 |
81 | $stmt = $db->prepare('SELECT catID, catTitle FROM blog_cats WHERE catID = :catID') ;
82 | $stmt->execute(array(':catID' => $_GET['id']));
83 | $row = $stmt->fetch();
84 |
85 | } catch(PDOException $e) {
86 | echo $e->getMessage();
87 | }
88 |
89 | ?>
90 |
91 |
100 |
101 |
102 |
103 |
104 |
105 |
--------------------------------------------------------------------------------
/style/main.css:
--------------------------------------------------------------------------------
1 | #wrapper {
2 | margin:auto;
3 | width:960px;
4 | }
5 |
6 | #main {
7 | float:left;
8 | width:640px;
9 | margin-right:20px;
10 | }
11 |
12 | #sidebar {
13 | float:right;
14 | width:300px;
15 | }
16 |
17 | #login {
18 | border: 1px solid #AEAEAE;
19 | margin: 100px auto 0;
20 | padding: 0;
21 | width: 300px;
22 | }
23 |
24 | #adminmenu {
25 | padding-left: 0;
26 | }
27 |
28 | #adminmenu li {
29 | float: left;
30 | list-style: none;
31 | margin-right: 20px;
32 | }
33 |
34 | .clear {
35 | clear: both;
36 | }
37 |
38 | .error {
39 | padding: 0.75em;
40 | margin: 0.75em;
41 | border: 1px solid #990000;
42 | max-width: 400px;
43 | color: #990000;
44 | background-color: #FDF0EB;
45 | -moz-border-radius: 0.5em;
46 | -webkit-border-radius: 0.5em;
47 | }
48 |
49 | p,li {
50 | color: #555555;
51 | font-size: 16px;
52 | line-height: 1.5em;
53 | }
54 |
55 | a {
56 | color: #EF1F2F;
57 | text-decoration: none;
58 | }
59 |
60 | form input {
61 | border: 1px solid #999999;
62 | border-bottom-color: #cccccc;
63 | border-right-color: #cccccc;
64 | padding: 5px;
65 | font-family: Arial, Helvetica, sans-serif;
66 | font-size: 1.0em;
67 | margin: 2px;
68 | }
69 |
70 | table {width:98%; text-align:left; border:1px solid #DDDDDD; font-size:12px; color:#000;background:#fff; margin-bottom:10px;}
71 | table th {background-color:#E5E5E5; border:1px solid #BBBBBB; padding:3px 6px; font-weight:normal; color:#000;}
72 | table tr td {border:1px solid #DDDDDD; padding:5px 6px;}
73 | table tr.alt td {background-color:#E2E2E2;}
74 | table tr:hover {background-color:#F0F0F0; color:#000;}
75 |
76 | /* PAGINATION */
77 |
78 | .pagination {
79 | clear: both;
80 | padding-bottom: 10px;
81 | padding-top: 10px;
82 | }
83 | .pagination a {
84 | border: 1px solid #D5D5D5;
85 | color: #666666;
86 | font-size: 11px;
87 | font-weight: bold;
88 | height: 25px;
89 | padding: 4px 8px;
90 | text-decoration: none;
91 | margin:2px;
92 | }
93 | .pagination a:hover, .pagination a:active {
94 | background:#efefef;
95 | }
96 | .pagination span.current {
97 | background-color: #687282;
98 | border: 1px solid #D5D5D5;
99 | color: #ffffff;
100 | font-size: 11px;
101 | font-weight: bold;
102 | height: 25px;
103 | padding: 4px 8px;
104 | text-decoration: none;
105 | margin:2px;
106 | }
107 | .pagination span.disabled {
108 | border: 1px solid #EEEEEE;
109 | color: #DDDDDD;
110 | margin: 2px;
111 | padding: 2px 5px;
112 | }
113 |
--------------------------------------------------------------------------------
/archives.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Blog - Archives
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
Blog
16 |
17 |
Blog Index
18 |
19 |
20 |
21 | prepare('SELECT postID FROM blog_posts_seo WHERE postDate >= :from AND postDate <= :to');
36 | $stmt->execute(array(
37 | ':from' => $from,
38 | ':to' => $to
39 | ));
40 |
41 | //pass number of records to
42 | $pages->set_total($stmt->rowCount());
43 |
44 | $stmt = $db->prepare('SELECT postID, postTitle, postSlug, postDesc, postDate FROM blog_posts_seo WHERE postDate >= :from AND postDate <= :to ORDER BY postID DESC '.$pages->get_limit());
45 | $stmt->execute(array(
46 | ':from' => $from,
47 | ':to' => $to
48 | ));
49 | while($row = $stmt->fetch()){
50 |
51 | echo '
';
52 | echo '
Posted on '.date('jS M Y H:i:s', strtotime($row['postDate'])).' in ';
53 |
54 | $stmt2 = $db->prepare('SELECT catTitle, catSlug FROM blog_cats, blog_post_cats WHERE blog_cats.catID = blog_post_cats.catID AND blog_post_cats.postID = :postID');
55 | $stmt2->execute(array(':postID' => $row['postID']));
56 |
57 | $catRow = $stmt2->fetchAll(PDO::FETCH_ASSOC);
58 |
59 | $links = array();
60 | foreach ($catRow as $cat)
61 | {
62 | $links[] = "".$cat['catTitle']." ";
63 | }
64 | echo implode(", ", $links);
65 |
66 | echo '
';
67 | echo '
'.$row['postDesc'].'
';
68 | echo '
Read More
';
69 | }
70 |
71 | echo $pages->page_links("a-$month-$year&");
72 |
73 | } catch(PDOException $e) {
74 | echo $e->getMessage();
75 | }
76 | ?>
77 |
78 |
79 |
80 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/admin/add-user.php:
--------------------------------------------------------------------------------
1 | is_logged_in()){ header('Location: login.php'); }
6 | ?>
7 |
8 |
9 |
10 |
11 | Admin - Add User
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
User Admin Index
21 |
22 |
Add User
23 |
24 | password_hash($_POST['password'], PASSWORD_BCRYPT);
56 |
57 | try {
58 |
59 | //insert into database
60 | $stmt = $db->prepare('INSERT INTO blog_members (username,password,email) VALUES (:username, :password, :email)') ;
61 | $stmt->execute(array(
62 | ':username' => $username,
63 | ':password' => $hashedpassword,
64 | ':email' => $email
65 | ));
66 |
67 | //redirect to index page
68 | header('Location: users.php?action=added');
69 | exit;
70 |
71 | } catch(PDOException $e) {
72 | echo $e->getMessage();
73 | }
74 |
75 | }
76 |
77 | }
78 |
79 | //check for any errors
80 | if(isset($error)){
81 | foreach($error as $error){
82 | echo '
'.$error.'
';
83 | }
84 | }
85 | ?>
86 |
87 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/catpost.php:
--------------------------------------------------------------------------------
1 | prepare('SELECT catID,catTitle FROM blog_cats WHERE catSlug = :catSlug');
5 | $stmt->execute(array(':catSlug' => $_GET['id']));
6 | $row = $stmt->fetch();
7 |
8 | //if post does not exists redirect user.
9 | if($row['catID'] == ''){
10 | header('Location: ./');
11 | exit;
12 | }
13 |
14 | ?>
15 |
16 |
17 |
18 |
19 | Blog -
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
Blog
28 |
Posts in
29 |
30 |
Blog Index
31 |
32 |
33 |
34 | prepare('SELECT blog_posts_seo.postID FROM blog_posts_seo, blog_post_cats WHERE blog_posts_seo.postID = blog_post_cats.postID AND blog_post_cats.catID = :catID');
40 | $stmt->execute(array(':catID' => $row['catID']));
41 |
42 | //pass number of records to
43 | $pages->set_total($stmt->rowCount());
44 |
45 | $stmt = $db->prepare('
46 | SELECT
47 | blog_posts_seo.postID, blog_posts_seo.postTitle, blog_posts_seo.postSlug, blog_posts_seo.postDesc, blog_posts_seo.postDate
48 | FROM
49 | blog_posts_seo,
50 | blog_post_cats
51 | WHERE
52 | blog_posts_seo.postID = blog_post_cats.postID
53 | AND blog_post_cats.catID = :catID
54 | ORDER BY
55 | postID DESC
56 | '.$pages->get_limit());
57 | $stmt->execute(array(':catID' => $row['catID']));
58 | while($row = $stmt->fetch()){
59 |
60 | echo '
';
61 | echo '
';
62 | echo '
Posted on '.date('jS M Y H:i:s', strtotime($row['postDate'])).' in ';
63 |
64 | $stmt2 = $db->prepare('SELECT catTitle, catSlug FROM blog_cats, blog_post_cats WHERE blog_cats.catID = blog_post_cats.catID AND blog_post_cats.postID = :postID');
65 | $stmt2->execute(array(':postID' => $row['postID']));
66 |
67 | $catRow = $stmt2->fetchAll(PDO::FETCH_ASSOC);
68 |
69 | $links = array();
70 | foreach ($catRow as $cat)
71 | {
72 | $links[] = "".$cat['catTitle']." ";
73 | }
74 | echo implode(", ", $links);
75 |
76 | echo '
';
77 | echo '
'.$row['postDesc'].'
';
78 | echo '
Read More
';
79 | echo '
';
80 |
81 | }
82 |
83 | echo $pages->page_links('c-'.$_GET['id'].'&');
84 |
85 | } catch(PDOException $e) {
86 | echo $e->getMessage();
87 | }
88 |
89 | ?>
90 |
91 |
92 |
93 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
--------------------------------------------------------------------------------
/admin/edit-user.php:
--------------------------------------------------------------------------------
1 | is_logged_in()){ header('Location: login.php'); }
6 | ?>
7 |
8 |
9 |
10 |
11 | Admin - Edit User
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
User Admin Index
21 |
22 |
Edit User
23 |
24 |
25 | 0){
39 |
40 | if($password ==''){
41 | $error[] = 'Please enter the password.';
42 | }
43 |
44 | if($passwordConfirm ==''){
45 | $error[] = 'Please confirm the password.';
46 | }
47 |
48 | if($password != $passwordConfirm){
49 | $error[] = 'Passwords do not match.';
50 | }
51 |
52 | }
53 |
54 |
55 | if($email ==''){
56 | $error[] = 'Please enter the email address.';
57 | }
58 |
59 | if(!isset($error)){
60 |
61 | try {
62 |
63 | if(isset($password)){
64 |
65 | $hashedpassword = $user->password_hash($password, PASSWORD_BCRYPT);
66 |
67 | //update into database
68 | $stmt = $db->prepare('UPDATE blog_members SET username = :username, password = :password, email = :email WHERE memberID = :memberID') ;
69 | $stmt->execute(array(
70 | ':username' => $username,
71 | ':password' => $hashedpassword,
72 | ':email' => $email,
73 | ':memberID' => $memberID
74 | ));
75 |
76 |
77 | } else {
78 |
79 | //update database
80 | $stmt = $db->prepare('UPDATE blog_members SET username = :username, email = :email WHERE memberID = :memberID') ;
81 | $stmt->execute(array(
82 | ':username' => $username,
83 | ':email' => $email,
84 | ':memberID' => $memberID
85 | ));
86 |
87 | }
88 |
89 |
90 | //redirect to index page
91 | header('Location: users.php?action=updated');
92 | exit;
93 |
94 | } catch(PDOException $e) {
95 | echo $e->getMessage();
96 | }
97 |
98 | }
99 |
100 | }
101 |
102 | ?>
103 |
104 |
105 | ';
110 | }
111 | }
112 |
113 | try {
114 |
115 | $stmt = $db->prepare('SELECT memberID, username, email FROM blog_members WHERE memberID = :memberID') ;
116 | $stmt->execute(array(':memberID' => $_GET['id']));
117 | $row = $stmt->fetch();
118 |
119 | } catch(PDOException $e) {
120 | echo $e->getMessage();
121 | }
122 |
123 | ?>
124 |
125 |
143 |
144 |
145 |
146 |
147 |
148 |
--------------------------------------------------------------------------------
/admin/add-post.php:
--------------------------------------------------------------------------------
1 | is_logged_in()){ header('Location: login.php'); }
6 | ?>
7 |
8 |
9 |
10 |
11 | Admin - Add Post
12 |
13 |
14 |
15 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
Blog Admin Index
33 |
34 |
Add Post
35 |
36 | prepare('INSERT INTO blog_posts_seo (postTitle,postSlug,postDesc,postCont,postDate) VALUES (:postTitle, :postSlug, :postDesc, :postCont, :postDate)') ;
65 | $stmt->execute(array(
66 | ':postTitle' => $postTitle,
67 | ':postSlug' => $postSlug,
68 | ':postDesc' => $postDesc,
69 | ':postCont' => $postCont,
70 | ':postDate' => date('Y-m-d H:i:s')
71 | ));
72 | $postID = $db->lastInsertId();
73 |
74 | //add categories
75 | if(is_array($catID)){
76 | foreach($_POST['catID'] as $catID){
77 | $stmt = $db->prepare('INSERT INTO blog_post_cats (postID,catID)VALUES(:postID,:catID)');
78 | $stmt->execute(array(
79 | ':postID' => $postID,
80 | ':catID' => $catID
81 | ));
82 | }
83 | }
84 |
85 | //redirect to index page
86 | header('Location: index.php?action=added');
87 | exit;
88 |
89 | } catch(PDOException $e) {
90 | echo $e->getMessage();
91 | }
92 |
93 | }
94 |
95 | }
96 |
97 | //check for any errors
98 | if(isset($error)){
99 | foreach($error as $error){
100 | echo '
'.$error.'
';
101 | }
102 | }
103 | ?>
104 |
105 |
143 |
144 |
145 |
--------------------------------------------------------------------------------
/admin/edit-post.php:
--------------------------------------------------------------------------------
1 | is_logged_in()){ header('Location: login.php'); }
6 | ?>
7 |
8 |
9 |
10 |
11 | Admin - Edit Post
12 |
13 |
14 |
15 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
Blog Admin Index
33 |
34 |
Edit Post
35 |
36 |
37 | prepare('UPDATE blog_posts_seo SET postTitle = :postTitle, postSlug = :postSlug, postDesc = :postDesc, postCont = :postCont WHERE postID = :postID') ;
70 | $stmt->execute(array(
71 | ':postTitle' => $postTitle,
72 | ':postSlug' => $postSlug,
73 | ':postDesc' => $postDesc,
74 | ':postCont' => $postCont,
75 | ':postID' => $postID
76 | ));
77 |
78 | //delete all items with the current postID
79 | $stmt = $db->prepare('DELETE FROM blog_post_cats WHERE postID = :postID');
80 | $stmt->execute(array(':postID' => $postID));
81 |
82 | if(is_array($catID)){
83 | foreach($_POST['catID'] as $catID){
84 | $stmt = $db->prepare('INSERT INTO blog_post_cats (postID,catID)VALUES(:postID,:catID)');
85 | $stmt->execute(array(
86 | ':postID' => $postID,
87 | ':catID' => $catID
88 | ));
89 | }
90 | }
91 |
92 | //redirect to index page
93 | header('Location: index.php?action=updated');
94 | exit;
95 |
96 | } catch(PDOException $e) {
97 | echo $e->getMessage();
98 | }
99 |
100 | }
101 |
102 | }
103 |
104 | ?>
105 |
106 |
107 | ';
112 | }
113 | }
114 |
115 | try {
116 |
117 | $stmt = $db->prepare('SELECT postID, postTitle, postDesc, postCont FROM blog_posts_seo WHERE postID = :postID') ;
118 | $stmt->execute(array(':postID' => $_GET['id']));
119 | $row = $stmt->fetch();
120 |
121 | } catch(PDOException $e) {
122 | echo $e->getMessage();
123 | }
124 |
125 | ?>
126 |
127 |
128 | '>
129 |
130 | Title
131 | '>
132 |
133 | Description
134 |
135 |
136 | Content
137 |
138 |
139 |
140 | Categories
141 |
142 | query('SELECT catID, catTitle FROM blog_cats ORDER BY catTitle');
145 | while($row2 = $stmt2->fetch()){
146 |
147 | $stmt3 = $db->prepare('SELECT catID FROM blog_post_cats WHERE catID = :catID AND postID = :postID') ;
148 | $stmt3->execute(array(':catID' => $row2['catID'], ':postID' => $row['postID']));
149 | $row3 = $stmt3->fetch();
150 |
151 | if($row3['catID'] == $row2['catID']){
152 | $checked = 'checked=checked';
153 | } else {
154 | $checked = null;
155 | }
156 |
157 | echo " ".$row2['catTitle']." ";
158 | }
159 |
160 | ?>
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
--------------------------------------------------------------------------------
/classes/class.paginator.php:
--------------------------------------------------------------------------------
1 | _instance = $instance;
58 | $this->_perPage = $perPage;
59 | $this->set_instance();
60 | }
61 |
62 | /**
63 | * get_start
64 | *
65 | * creates the starting point for limiting the dataset
66 | * @return numeric
67 | */
68 | private function get_start(){
69 | return ($this->_page * $this->_perPage) - $this->_perPage;
70 | }
71 |
72 | /**
73 | * set_instance
74 | *
75 | * sets the instance parameter, if numeric value is 0 then set to 1
76 | *
77 | * @var numeric
78 | */
79 | private function set_instance(){
80 | $this->_page = (int) (!isset($_GET[$this->_instance]) ? 1 : $_GET[$this->_instance]);
81 | $this->_page = ($this->_page == 0 ? 1 : $this->_page);
82 | }
83 |
84 | /**
85 | * set_total
86 | *
87 | * collect a numberic value and assigns it to the totalRows
88 | *
89 | * @var numeric
90 | */
91 | public function set_total($_totalRows){
92 | $this->_totalRows = $_totalRows;
93 | }
94 |
95 | /**
96 | * get_limit
97 | *
98 | * returns the limit for the data source, calling the get_start method and passing in the number of items perp page
99 | *
100 | * @return string
101 | */
102 | public function get_limit(){
103 | return "LIMIT ".$this->get_start().",$this->_perPage";
104 | }
105 |
106 | /**
107 | * page_links
108 | *
109 | * create the html links for navigating through the dataset
110 | *
111 | * @var sting $path optionally set the path for the link
112 | * @var sting $ext optionally pass in extra parameters to the GET
113 | * @return string returns the html menu
114 | */
115 | public function page_links($path='?',$ext=null)
116 | {
117 | $adjacents = "2";
118 | $prev = $this->_page - 1;
119 | $next = $this->_page + 1;
120 | $lastpage = ceil($this->_totalRows/$this->_perPage);
121 | $lpm1 = $lastpage - 1;
122 |
123 | $pagination = "";
124 | if($lastpage > 1)
125 | {
126 | $pagination .= "\n";
193 | }
194 |
195 |
196 | return $pagination;
197 | }
198 | }
--------------------------------------------------------------------------------
/classes/class.password.php:
--------------------------------------------------------------------------------
1 | 31) {
41 | trigger_error(sprintf("password_hash(): Invalid bcrypt cost parameter specified: %d", $cost), E_USER_WARNING);
42 | return null;
43 | }
44 | }
45 | // The length of salt to generate
46 | $raw_salt_len = 16;
47 | // The length required in the final serialization
48 | $required_salt_len = 22;
49 | $hash_format = sprintf("$2y$%02d$", $cost);
50 | break;
51 | default :
52 | trigger_error(sprintf("password_hash(): Unknown password hashing algorithm: %s", $algo), E_USER_WARNING);
53 | return null;
54 | }
55 | if (isset($options['salt'])) {
56 | switch (gettype($options['salt'])) {
57 | case 'NULL' :
58 | case 'boolean' :
59 | case 'integer' :
60 | case 'double' :
61 | case 'string' :
62 | $salt = (string)$options['salt'];
63 | break;
64 | case 'object' :
65 | if (method_exists($options['salt'], '__tostring')) {
66 | $salt = (string)$options['salt'];
67 | break;
68 | }
69 | case 'array' :
70 | case 'resource' :
71 | default :
72 | trigger_error('password_hash(): Non-string salt parameter supplied', E_USER_WARNING);
73 | return null;
74 | }
75 | if (strlen($salt) < $required_salt_len) {
76 | trigger_error(sprintf("password_hash(): Provided salt is too short: %d expecting %d", strlen($salt), $required_salt_len), E_USER_WARNING);
77 | return null;
78 | } elseif (0 == preg_match('#^[a-zA-Z0-9./]+$#D', $salt)) {
79 | $salt = str_replace('+', '.', base64_encode($salt));
80 | }
81 | } else {
82 | $buffer = '';
83 | $buffer_valid = false;
84 | if (function_exists('mcrypt_create_iv') && !defined('PHALANGER')) {
85 | $buffer = mcrypt_create_iv($raw_salt_len, MCRYPT_DEV_URANDOM);
86 | if ($buffer) {
87 | $buffer_valid = true;
88 | }
89 | }
90 | if (!$buffer_valid && function_exists('openssl_random_pseudo_bytes')) {
91 | $buffer = openssl_random_pseudo_bytes($raw_salt_len);
92 | if ($buffer) {
93 | $buffer_valid = true;
94 | }
95 | }
96 | if (!$buffer_valid && is_readable('/dev/urandom')) {
97 | $f = fopen('/dev/urandom', 'r');
98 | $read = strlen($buffer);
99 | while ($read < $raw_salt_len) {
100 | $buffer .= fread($f, $raw_salt_len - $read);
101 | $read = strlen($buffer);
102 | }
103 | fclose($f);
104 | if ($read >= $raw_salt_len) {
105 | $buffer_valid = true;
106 | }
107 | }
108 | if (!$buffer_valid || strlen($buffer) < $raw_salt_len) {
109 | $bl = strlen($buffer);
110 | for ($i = 0; $i < $raw_salt_len; $i++) {
111 | if ($i < $bl) {
112 | $buffer[$i] = $buffer[$i] ^ chr(mt_rand(0, 255));
113 | } else {
114 | $buffer .= chr(mt_rand(0, 255));
115 | }
116 | }
117 | }
118 | $salt = str_replace('+', '.', base64_encode($buffer));
119 | }
120 | $salt = substr($salt, 0, $required_salt_len);
121 |
122 | $hash = $hash_format . $salt;
123 |
124 | $ret = crypt($password, $hash);
125 |
126 | if (!is_string($ret) || strlen($ret) <= 13) {
127 | return false;
128 | }
129 |
130 | return $ret;
131 | }
132 |
133 | /**
134 | * Get information about the password hash. Returns an array of the information
135 | * that was used to generate the password hash.
136 | *
137 | * array(
138 | * 'algo' => 1,
139 | * 'algoName' => 'bcrypt',
140 | * 'options' => array(
141 | * 'cost' => 10,
142 | * ),
143 | * )
144 | *
145 | * @param string $hash The password hash to extract info from
146 | *
147 | * @return array The array of information about the hash.
148 | */
149 | function password_get_info($hash) {
150 | $return = array('algo' => 0, 'algoName' => 'unknown', 'options' => array(), );
151 | if (substr($hash, 0, 4) == '$2y$' && strlen($hash) == 60) {
152 | $return['algo'] = PASSWORD_BCRYPT;
153 | $return['algoName'] = 'bcrypt';
154 | list($cost) = sscanf($hash, "$2y$%d$");
155 | $return['options']['cost'] = $cost;
156 | }
157 | return $return;
158 | }
159 |
160 | /**
161 | * Determine if the password hash needs to be rehashed according to the options provided
162 | *
163 | * If the answer is true, after validating the password using password_verify, rehash it.
164 | *
165 | * @param string $hash The hash to test
166 | * @param int $algo The algorithm used for new password hashes
167 | * @param array $options The options array passed to password_hash
168 | *
169 | * @return boolean True if the password needs to be rehashed.
170 | */
171 | function password_needs_rehash($hash, $algo, array $options = array()) {
172 | $info = password_get_info($hash);
173 | if ($info['algo'] != $algo) {
174 | return true;
175 | }
176 | switch ($algo) {
177 | case PASSWORD_BCRYPT :
178 | $cost = isset($options['cost']) ? $options['cost'] : 10;
179 | if ($cost != $info['options']['cost']) {
180 | return true;
181 | }
182 | break;
183 | }
184 | return false;
185 | }
186 |
187 | /**
188 | * Verify a password against a hash using a timing attack resistant approach
189 | *
190 | * @param string $password The password to verify
191 | * @param string $hash The hash to verify against
192 | *
193 | * @return boolean If the password matches the hash
194 | */
195 | public function password_verify($password, $hash) {
196 | if (!function_exists('crypt')) {
197 | trigger_error("Crypt must be loaded for password_verify to function", E_USER_WARNING);
198 | return false;
199 | }
200 | $ret = crypt($password, $hash);
201 | if (!is_string($ret) || strlen($ret) != strlen($hash) || strlen($ret) <= 13) {
202 | return false;
203 | }
204 |
205 | $status = 0;
206 | for ($i = 0; $i < strlen($ret); $i++) {
207 | $status |= (ord($ret[$i]) ^ ord($hash[$i]));
208 | }
209 |
210 | return $status === 0;
211 | }
212 |
213 | }
--------------------------------------------------------------------------------
/db.sql:
--------------------------------------------------------------------------------
1 | # Dump of table blog_cats
2 | # ------------------------------------------------------------
3 |
4 | DROP TABLE IF EXISTS `blog_cats`;
5 |
6 | CREATE TABLE `blog_cats` (
7 | `catID` int(11) unsigned NOT NULL AUTO_INCREMENT,
8 | `catTitle` varchar(255) DEFAULT NULL,
9 | `catSlug` varchar(255) DEFAULT NULL,
10 | PRIMARY KEY (`catID`)
11 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
12 |
13 | LOCK TABLES `blog_cats` WRITE;
14 | /*!40000 ALTER TABLE `blog_cats` DISABLE KEYS */;
15 |
16 | INSERT INTO `blog_cats` (`catID`, `catTitle`, `catSlug`)
17 | VALUES
18 | (1,'General','general'),
19 | (2,'Development','development'),
20 | (5,'Misc','misc'),
21 | (4,'Testing','testing');
22 |
23 | /*!40000 ALTER TABLE `blog_cats` ENABLE KEYS */;
24 | UNLOCK TABLES;
25 |
26 |
27 | # Dump of table blog_members
28 | # ------------------------------------------------------------
29 |
30 | DROP TABLE IF EXISTS `blog_members`;
31 |
32 | CREATE TABLE `blog_members` (
33 | `memberID` int(11) unsigned NOT NULL AUTO_INCREMENT,
34 | `username` varchar(255) DEFAULT NULL,
35 | `password` varchar(255) DEFAULT NULL,
36 | `email` varchar(255) DEFAULT NULL,
37 | PRIMARY KEY (`memberID`)
38 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
39 |
40 | LOCK TABLES `blog_members` WRITE;
41 | /*!40000 ALTER TABLE `blog_members` DISABLE KEYS */;
42 |
43 | INSERT INTO `blog_members` (`memberID`, `username`, `password`, `email`)
44 | VALUES
45 | (1,'Demo','$2a$12$TF8u1maUr5kADc42g1FB0ONJDEtt24ue.UTIuP13gij5AHsg5f5s2','demo@demo.com');
46 |
47 | /*!40000 ALTER TABLE `blog_members` ENABLE KEYS */;
48 | UNLOCK TABLES;
49 |
50 |
51 | # Dump of table blog_post_cats
52 | # ------------------------------------------------------------
53 |
54 | DROP TABLE IF EXISTS `blog_post_cats`;
55 |
56 | CREATE TABLE `blog_post_cats` (
57 | `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
58 | `postID` int(11) DEFAULT NULL,
59 | `catID` int(11) DEFAULT NULL,
60 | PRIMARY KEY (`id`)
61 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
62 |
63 | LOCK TABLES `blog_post_cats` WRITE;
64 | /*!40000 ALTER TABLE `blog_post_cats` DISABLE KEYS */;
65 |
66 | INSERT INTO `blog_post_cats` (`id`, `postID`, `catID`)
67 | VALUES
68 | (25,2,5),
69 | (21,6,4),
70 | (24,2,1),
71 | (4,3,2),
72 | (20,6,1),
73 | (16,1,2);
74 |
75 | /*!40000 ALTER TABLE `blog_post_cats` ENABLE KEYS */;
76 | UNLOCK TABLES;
77 |
78 |
79 | # Dump of table blog_posts_seo
80 | # ------------------------------------------------------------
81 |
82 | DROP TABLE IF EXISTS `blog_posts_seo`;
83 |
84 | CREATE TABLE `blog_posts_seo` (
85 | `postID` int(11) unsigned NOT NULL AUTO_INCREMENT,
86 | `postTitle` varchar(255) DEFAULT NULL,
87 | `postSlug` varchar(255) DEFAULT NULL,
88 | `postDesc` text,
89 | `postCont` text,
90 | `postDate` datetime DEFAULT NULL,
91 | PRIMARY KEY (`postID`)
92 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
93 |
94 | LOCK TABLES `blog_posts_seo` WRITE;
95 | /*!40000 ALTER TABLE `blog_posts_seo` DISABLE KEYS */;
96 |
97 | INSERT INTO `blog_posts_seo` (`postID`, `postTitle`, `postSlug`, `postDesc`, `postCont`, `postDate`)
98 | VALUES
99 | (1,'Bendless Love','bendless-love','That\'s right, baby. I ain\'t your loverboy Flexo, the guy you love so much. You even love anyone pretending to be him! Interesting. No, wait, the other thing: tedious. Hey, guess what you\'re accessories to. The alien mothership is in orbit here. If we can hit that bullseye, the rest of the dominoes will fall like a house of cards. Checkmate.
','The Mutants Are Revolting \r\nWe don\'t have a brig. And until then, I can never die? We need rest. The spirit is willing, but the flesh is spongy and bruised. And yet you haven\'t said what I told you to say! How can any of us trust you?
\r\n\r\nOh, but you can. But you may have to metaphorically make a deal with the devil. And by \"devil\", I mean Robot Devil. And by \"metaphorically\", I mean get your coat. \r\nBender?! You stole the atom. \r\nI was having the most wonderful dream. Except you were there, and you were there, and you were there! \r\n \r\nThe Series Has Landed \r\nFry! Stay back! He\'s too powerful! No. We\'re on the top. Fry, you can\'t just sit here in the dark listening to classical music.
\r\nFuture Stock \r\nDoes anybody else feel jealous and aroused and worried? We\'re also Santa Claus! You\'re going back for the Countess, aren\'t you? Well, let\'s just dump it in the sewer and say we delivered it.
\r\n\r\nSpare me your space age technobabble, Attila the Hun! \r\nYou guys realize you live in a sewer, right? \r\nI guess if you want children beaten, you have to do it yourself. \r\nYeah. Give a little credit to our public schools. \r\n \r\nThe Why of Fry \r\nWho are you, my warranty?! Shinier than yours, meatbag. Dr. Zoidberg, that doesn\'t make sense. But, okay! Yes, except the Dave Matthews Band doesn\'t rock.
','2013-05-29 00:00:00'),
100 | (2,'That Darn Katz!','that-darn-katz','Wow! A superpowers drug you can just rub onto your skin? You\'d think it would be something you\'d have to freebase. Fry, you can\'t just sit here in the dark listening to classical music. And yet you haven\'t said what I told you to say! How can any of us trust you?
','Xmas Story \r\nIt must be wonderful. Does anybody else feel jealous and aroused and worried? Is today\'s hectic lifestyle making you tense and impatient? Soothe us with sweet lies. That\'s right, baby. I ain\'t your loverboy Flexo, the guy you love so much. You even love anyone pretending to be him!
\r\n\r\nGoodbye, friends. I never thought I\'d die like this. But I always really hoped. \r\nThey\'re like sex, except I\'m having them! \r\nCome, Comrade Bender! We must take to the streets! \r\n \r\nAnthology of Interest I \r\nHey, whatcha watching? They\'re like sex, except I\'m having them! Well I\'da done better, but it\'s plum hard pleading a case while awaiting trial for that there incompetence. Yes, except the Dave Matthews Band doesn\'t rock. I suppose I could part with \'one\' and still be feared…
\r\nTeenage Mutant Leela\'s Hurdles \r\nOh, but you can. But you may have to metaphorically make a deal with the devil. And by \"devil\", I mean Robot Devil. And by \"metaphorically\", I mean get your coat. Please, Don-Bot… look into your hard drive, and open your mercy file! It\'s a T. It goes \"tuh\". I guess if you want children beaten, you have to do it yourself.
\r\n\r\nSpare me your space age technobabble, Attila the Hun! \r\nWell, thanks to the Internet, I\'m now bored with sex. Is there a place on the web that panders to my lust for violence? \r\n \r\nThe Farnsworth Parabox \r\nWow! A superpowers drug you can just rub onto your skin? You\'d think it would be something you\'d have to freebase. We need rest. The spirit is willing, but the flesh is spongy and bruised. It must be wonderful.
','2013-06-05 23:10:35'),
101 | (3,'How Hermes Requisitioned His Groove Back','how-hermes-requistioned-his-groove-back','You\'re going back for the Countess, aren\'t you? Wow! A superpowers drug you can just rub onto your skin? You\'d think it would be something you\'d have to freebase. Now Fry, it\'s been a few years since medical school, so remind me. Disemboweling in your species: fatal or non-fatal? I don\'t want to be rescued. Leela, are you alright? You got wanged on the head.
','The Luck of the Fryrish \r\nProfessor, make a woman out of me. I am the man with no name, Zapp Brannigan! Good man. Nixon\'s pro-war and pro-family. The alien mothership is in orbit here. If we can hit that bullseye, the rest of the dominoes will fall like a house of cards. Checkmate. Fry, you can\'t just sit here in the dark listening to classical music.
\r\n\r\nWho are those horrible orange men? \r\nIs today\'s hectic lifestyle making you tense and impatient? \r\n \r\nLethal Inspection \r\nOh, but you can. But you may have to metaphorically make a deal with the devil. And by \"devil\", I mean Robot Devil. And by \"metaphorically\", I mean get your coat. No. We\'re on the top. Does anybody else feel jealous and aroused and worried? Well I\'da done better, but it\'s plum hard pleading a case while awaiting trial for that there incompetence. It must be wonderful.
\r\nWhere No Fan Has Gone Before \r\nWho are those horrible orange men? Bender, we\'re trying our best. Please, Don-Bot… look into your hard drive, and open your mercy file! Wow! A superpowers drug you can just rub onto your skin? You\'d think it would be something you\'d have to freebase. WINDMILLS DO NOT WORK THAT WAY! GOOD NIGHT! Look, last night was a mistake.
\r\n\r\nI\'m sorry, guys. I never meant to hurt you. Just to destroy everything you ever believed in. \r\nStop it, stop it. It\'s fine. I will \'destroy\' you! \r\nYou guys realize you live in a sewer, right? \r\n \r\nFear of a Bot Planet \r\nWhy yes! Thanks for noticing. Hey, guess what you\'re accessories to. Yes, except the Dave Matthews Band doesn\'t rock. Take me to your leader! Daddy Bender, we\'re hungry.
','2013-06-05 23:20:24'),
102 | (6,'The Cyber House Rules','the-cyber-house-rules','You guys realize you live in a sewer, right? Uh, is the puppy mechanical in any way? Come, Comrade Bender! We must take to the streets! I daresay that Fry has discovered the smelliest object in the known universe! Good news, everyone! There\'s a report on TV with some very bad news!
','The Luck of the Fryrish \r\nProfessor, make a woman out of me. I am the man with no name, Zapp Brannigan! Good man. Nixon\'s pro-war and pro-family. The alien mothership is in orbit here. If we can hit that bullseye, the rest of the dominoes will fall like a house of cards. Checkmate. Fry, you can\'t just sit here in the dark listening to classical music.
\r\n\r\nWho are those horrible orange men? \r\nIs today\'s hectic lifestyle making you tense and impatient? \r\n \r\nLethal Inspection \r\nOh, but you can. But you may have to metaphorically make a deal with the devil. And by \"devil\", I mean Robot Devil. And by \"metaphorically\", I mean get your coat. No. We\'re on the top. Does anybody else feel jealous and aroused and worried? Well I\'da done better, but it\'s plum hard pleading a case while awaiting trial for that there incompetence. It must be wonderful.
\r\nWhere No Fan Has Gone Before \r\nWho are those horrible orange men? Bender, we\'re trying our best. Please, Don-Bot… look into your hard drive, and open your mercy file! Wow! A superpowers drug you can just rub onto your skin? You\'d think it would be something you\'d have to freebase. WINDMILLS DO NOT WORK THAT WAY! GOOD NIGHT! Look, last night was a mistake.
\r\n\r\nI\'m sorry, guys. I never meant to hurt you. Just to destroy everything you ever believed in. \r\nStop it, stop it. It\'s fine. I will \'destroy\' you! \r\nYou guys realize you live in a sewer, right? \r\n \r\nFear of a Bot Planet \r\nWhy yes! Thanks for noticing. Hey, guess what you\'re accessories to. Yes, except the Dave Matthews Band doesn\'t rock. Take me to your leader! Daddy Bender, we\'re hungry.
','2013-06-06 08:28:35');
--------------------------------------------------------------------------------
/style/normalize.css:
--------------------------------------------------------------------------------
1 | /*! normalize.css 2012-07-07T09:50 UTC - http://github.com/necolas/normalize.css */
2 |
3 | /* ==========================================================================
4 | HTML5 display definitions
5 | ========================================================================== */
6 |
7 | /*
8 | * Corrects `block` display not defined in IE6/7/8/9 & FF3.
9 | */
10 |
11 | article,
12 | aside,
13 | details,
14 | figcaption,
15 | figure,
16 | footer,
17 | header,
18 | hgroup,
19 | nav,
20 | section,
21 | summary {
22 | display: block;
23 | }
24 |
25 | /*
26 | * Corrects `inline-block` display not defined in IE6/7/8/9 & FF3.
27 | */
28 |
29 | audio,
30 | canvas,
31 | video {
32 | display: inline-block;
33 | *display: inline;
34 | *zoom: 1;
35 | }
36 |
37 | /*
38 | * Prevents modern browsers from displaying `audio` without controls.
39 | * Remove excess height in iOS5 devices.
40 | */
41 |
42 | audio:not([controls]) {
43 | display: none;
44 | height: 0;
45 | }
46 |
47 | /*
48 | * Addresses styling for `hidden` attribute not present in IE7/8/9, FF3, S4.
49 | * Known issue: no IE6 support.
50 | */
51 |
52 | [hidden] {
53 | display: none;
54 | }
55 |
56 | /* ==========================================================================
57 | Base
58 | ========================================================================== */
59 |
60 | /*
61 | * 1. Corrects text resizing oddly in IE6/7 when body `font-size` is set using
62 | * `em` units.
63 | * 2. Prevents iOS text size adjust after orientation change, without disabling
64 | * user zoom.
65 | */
66 |
67 | html {
68 | font-size: 100%; /* 1 */
69 | -webkit-text-size-adjust: 100%; /* 2 */
70 | -ms-text-size-adjust: 100%; /* 2 */
71 | }
72 |
73 | /*
74 | * Addresses `font-family` inconsistency between `textarea` and other form
75 | * elements.
76 | */
77 |
78 | html,
79 | button,
80 | input,
81 | select,
82 | textarea {
83 | font-family: sans-serif;
84 | }
85 |
86 | /*
87 | * Addresses margins handled incorrectly in IE6/7.
88 | */
89 |
90 | body {
91 | margin: 0;
92 | }
93 |
94 | /* ==========================================================================
95 | Links
96 | ========================================================================== */
97 |
98 | /*
99 | * Addresses `outline` inconsistency between Chrome and other browsers.
100 | */
101 |
102 | a:focus {
103 | outline: thin dotted;
104 | }
105 |
106 | /*
107 | * Improves readability when focused and also mouse hovered in all browsers.
108 | * people.opera.com/patrickl/experiments/keyboard/test
109 | */
110 |
111 | a:active,
112 | a:hover {
113 | outline: 0;
114 | }
115 |
116 | /* ==========================================================================
117 | Typography
118 | ========================================================================== */
119 |
120 | /*
121 | * Addresses font sizes and margins set differently in IE6/7.
122 | * Addresses font sizes within `section` and `article` in FF4+, Chrome, S5.
123 | */
124 |
125 | h1 {
126 | font-size: 2em;
127 | margin: 0.67em 0;
128 | }
129 |
130 | h2 {
131 | font-size: 1.5em;
132 | margin: 0.83em 0;
133 | }
134 |
135 | h3 {
136 | font-size: 1.17em;
137 | margin: 1em 0;
138 | }
139 |
140 | h4 {
141 | font-size: 1em;
142 | margin: 1.33em 0;
143 | }
144 |
145 | h5 {
146 | font-size: 0.83em;
147 | margin: 1.67em 0;
148 | }
149 |
150 | h6 {
151 | font-size: 0.75em;
152 | margin: 2.33em 0;
153 | }
154 |
155 | /*
156 | * Addresses styling not present in IE7/8/9, S5, Chrome.
157 | */
158 |
159 | abbr[title] {
160 | border-bottom: 1px dotted;
161 | }
162 |
163 | /*
164 | * Addresses style set to `bolder` in FF3+, S4/5, Chrome.
165 | */
166 |
167 | b,
168 | strong {
169 | font-weight: bold;
170 | }
171 |
172 | blockquote {
173 | margin: 1em 40px;
174 | }
175 |
176 | /*
177 | * Addresses styling not present in S5, Chrome.
178 | */
179 |
180 | dfn {
181 | font-style: italic;
182 | }
183 |
184 | /*
185 | * Addresses styling not present in IE6/7/8/9.
186 | */
187 |
188 | mark {
189 | background: #ff0;
190 | color: #000;
191 | }
192 |
193 | /*
194 | * Addresses margins set differently in IE6/7.
195 | */
196 |
197 | p,
198 | pre {
199 | margin: 1em 0;
200 | }
201 |
202 | /*
203 | * Corrects font family set oddly in IE6, S4/5, Chrome.
204 | * en.wikipedia.org/wiki/User:Davidgothberg/Test59
205 | */
206 |
207 | code,
208 | kbd,
209 | pre,
210 | samp {
211 | font-family: monospace, serif;
212 | _font-family: 'courier new', monospace;
213 | font-size: 1em;
214 | }
215 |
216 | /*
217 | * Improves readability of pre-formatted text in all browsers.
218 | */
219 |
220 | pre {
221 | white-space: pre;
222 | white-space: pre-wrap;
223 | word-wrap: break-word;
224 | }
225 |
226 | /*
227 | * Addresses CSS quotes not supported in IE6/7.
228 | */
229 |
230 | q {
231 | quotes: none;
232 | }
233 |
234 | /*
235 | * Addresses `quotes` property not supported in S4.
236 | */
237 |
238 | q:before,
239 | q:after {
240 | content: '';
241 | content: none;
242 | }
243 |
244 | small {
245 | font-size: 75%;
246 | }
247 |
248 | /*
249 | * Prevents `sub` and `sup` affecting `line-height` in all browsers.
250 | * gist.github.com/413930
251 | */
252 |
253 | sub,
254 | sup {
255 | font-size: 75%;
256 | line-height: 0;
257 | position: relative;
258 | vertical-align: baseline;
259 | }
260 |
261 | sup {
262 | top: -0.5em;
263 | }
264 |
265 | sub {
266 | bottom: -0.25em;
267 | }
268 |
269 | /* ==========================================================================
270 | Lists
271 | ========================================================================== */
272 |
273 | /*
274 | * Addresses margins set differently in IE6/7.
275 | */
276 |
277 | dl,
278 | menu,
279 | ol,
280 | ul {
281 | margin: 1em 0;
282 | }
283 |
284 | dd {
285 | margin: 0 0 0 40px;
286 | }
287 |
288 | /*
289 | * Addresses paddings set differently in IE6/7.
290 | */
291 |
292 | menu,
293 | ol,
294 | ul {
295 | padding: 0 0 0 40px;
296 | }
297 |
298 | /*
299 | * Corrects list images handled incorrectly in IE7.
300 | */
301 |
302 | nav ul,
303 | nav ol {
304 | list-style: none;
305 | list-style-image: none;
306 | }
307 |
308 | /* ==========================================================================
309 | Embedded content
310 | ========================================================================== */
311 |
312 | /*
313 | * 1. Removes border when inside `a` element in IE6/7/8/9, FF3.
314 | * 2. Improves image quality when scaled in IE7.
315 | * code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/
316 | */
317 |
318 | img {
319 | border: 0; /* 1 */
320 | -ms-interpolation-mode: bicubic; /* 2 */
321 | }
322 |
323 | /*
324 | * Corrects overflow displayed oddly in IE9.
325 | */
326 |
327 | svg:not(:root) {
328 | overflow: hidden;
329 | }
330 |
331 | /* ==========================================================================
332 | Figures
333 | ========================================================================== */
334 |
335 | /*
336 | * Addresses margin not present in IE6/7/8/9, S5, O11.
337 | */
338 |
339 | figure {
340 | margin: 0;
341 | }
342 |
343 | /* ==========================================================================
344 | Forms
345 | ========================================================================== */
346 |
347 | /*
348 | * Corrects margin displayed oddly in IE6/7.
349 | */
350 |
351 | form {
352 | margin: 0;
353 | }
354 |
355 | /*
356 | * Define consistent border, margin, and padding.
357 | */
358 |
359 | fieldset {
360 | border: 1px solid #c0c0c0;
361 | margin: 0 2px;
362 | padding: 0.35em 0.625em 0.75em;
363 | }
364 |
365 | /*
366 | * 1. Corrects color not being inherited in IE6/7/8/9.
367 | * 2. Corrects text not wrapping in FF3.
368 | * 3. Corrects alignment displayed oddly in IE6/7.
369 | */
370 |
371 | legend {
372 | border: 0; /* 1 */
373 | padding: 0;
374 | white-space: normal; /* 2 */
375 | *margin-left: -7px; /* 3 */
376 | }
377 |
378 | /*
379 | * 1. Corrects font size not being inherited in all browsers.
380 | * 2. Addresses margins set differently in IE6/7, FF3+, S5, Chrome.
381 | * 3. Improves appearance and consistency in all browsers.
382 | */
383 |
384 | button,
385 | input,
386 | select,
387 | textarea {
388 | font-size: 100%; /* 1 */
389 | margin: 0; /* 2 */
390 | vertical-align: baseline; /* 3 */
391 | *vertical-align: middle; /* 3 */
392 | }
393 |
394 | /*
395 | * Addresses FF3/4 setting `line-height` on `input` using `!important` in the
396 | * UA stylesheet.
397 | */
398 |
399 | button,
400 | input {
401 | line-height: normal;
402 | }
403 |
404 | /*
405 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
406 | * and `video` controls.
407 | * 2. Corrects inability to style clickable `input` types in iOS.
408 | * 3. Improves usability and consistency of cursor style between image-type
409 | * `input` and others.
410 | * 4. Removes inner spacing in IE7 without affecting normal text inputs.
411 | * Known issue: inner spacing remains in IE6.
412 | */
413 |
414 | button,
415 | html input[type="button"], /* 1 */
416 | input[type="reset"],
417 | input[type="submit"] {
418 | -webkit-appearance: button; /* 2 */
419 | cursor: pointer; /* 3 */
420 | *overflow: visible; /* 4 */
421 | }
422 |
423 | /*
424 | * Re-set default cursor for disabled elements.
425 | */
426 |
427 | button[disabled],
428 | input[disabled] {
429 | cursor: default;
430 | }
431 |
432 | /*
433 | * 1. Addresses box sizing set to content-box in IE8/9.
434 | * 2. Removes excess padding in IE8/9.
435 | * 3. Removes excess padding in IE7.
436 | * Known issue: excess padding remains in IE6.
437 | */
438 |
439 | input[type="checkbox"],
440 | input[type="radio"] {
441 | box-sizing: border-box; /* 1 */
442 | padding: 0; /* 2 */
443 | *height: 13px; /* 3 */
444 | *width: 13px; /* 3 */
445 | }
446 |
447 | /*
448 | * 1. Addresses `appearance` set to `searchfield` in S5, Chrome.
449 | * 2. Addresses `box-sizing` set to `border-box` in S5, Chrome (include `-moz`
450 | * to future-proof).
451 | */
452 |
453 | input[type="search"] {
454 | -webkit-appearance: textfield; /* 1 */
455 | -moz-box-sizing: content-box;
456 | -webkit-box-sizing: content-box; /* 2 */
457 | box-sizing: content-box;
458 | }
459 |
460 | /*
461 | * Removes inner padding and search cancel button in S5, Chrome on OS X.
462 | */
463 |
464 | input[type="search"]::-webkit-search-cancel-button,
465 | input[type="search"]::-webkit-search-decoration {
466 | -webkit-appearance: none;
467 | }
468 |
469 | /*
470 | * Removes inner padding and border in FF3+.
471 | */
472 |
473 | button::-moz-focus-inner,
474 | input::-moz-focus-inner {
475 | border: 0;
476 | padding: 0;
477 | }
478 |
479 | /*
480 | * 1. Removes default vertical scrollbar in IE6/7/8/9.
481 | * 2. Improves readability and alignment in all browsers.
482 | */
483 |
484 | textarea {
485 | overflow: auto; /* 1 */
486 | vertical-align: top; /* 2 */
487 | }
488 |
489 | /* ==========================================================================
490 | Tables
491 | ========================================================================== */
492 |
493 | /*
494 | * Remove most spacing between table cells.
495 | */
496 |
497 | table {
498 | border-collapse: collapse;
499 | border-spacing: 0;
500 | }
--------------------------------------------------------------------------------