├── 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 ├── classes ├── class.user.php └── class.password.php ├── style ├── main.css └── normalize.css ├── index.php ├── viewpost.php ├── catpost.php └── db.sql /admin/logout.php: -------------------------------------------------------------------------------- 1 | logout(); 7 | header('Location: index.php'); 8 | 9 | ?> -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Simple Blog part 4: Categories 2 | ============= 3 | 4 | These files acompany the tutorial: [Creating a blog from scratch with PHP - Part 4 Categories](http://daveismyname.com/creating-a-blog-from-scratch-with-php-part-4-categories-bp) 5 | -------------------------------------------------------------------------------- /.htaccess: -------------------------------------------------------------------------------- 1 | RewriteEngine On 2 | RewriteBase /simple-blog-part-4-categories/ 3 | 4 | RewriteRule ^c-(.*)$ catpost.php?id=$1 [L] 5 | 6 | RewriteCond %{REQUEST_FILENAME} !-d [NC] 7 | RewriteCond %{REQUEST_FILENAME} !-f [NC] 8 | RewriteRule ^(.*)$ viewpost.php?id=$1 [QSA,L] -------------------------------------------------------------------------------- /admin/menu.php: -------------------------------------------------------------------------------- 1 |

Blog

2 |

Logged in as

3 | 10 |
11 |
12 | -------------------------------------------------------------------------------- /includes/functions.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /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 |
46 |

47 |

48 |

49 |
50 | 51 |
52 | 53 | 54 | -------------------------------------------------------------------------------- /style/main.css: -------------------------------------------------------------------------------- 1 | #wrapper { 2 | margin:auto; 3 | width:900px; 4 | } 5 | 6 | #login { 7 | border: 1px solid #AEAEAE; 8 | margin: 100px auto 0; 9 | padding: 0; 10 | width: 300px; 11 | } 12 | 13 | #adminmenu { 14 | padding-left: 0; 15 | } 16 | 17 | #adminmenu li { 18 | float: left; 19 | list-style: none; 20 | margin-right: 20px; 21 | } 22 | 23 | .clear { 24 | clear: both; 25 | } 26 | 27 | .error { 28 | padding: 0.75em; 29 | margin: 0.75em; 30 | border: 1px solid #990000; 31 | max-width: 400px; 32 | color: #990000; 33 | background-color: #FDF0EB; 34 | -moz-border-radius: 0.5em; 35 | -webkit-border-radius: 0.5em; 36 | } 37 | 38 | p,li { 39 | color: #555555; 40 | font-size: 16px; 41 | line-height: 1.5em; 42 | } 43 | 44 | a { 45 | color: #EF1F2F; 46 | text-decoration: none; 47 | } 48 | 49 | form input { 50 | border: 1px solid #999999; 51 | border-bottom-color: #cccccc; 52 | border-right-color: #cccccc; 53 | padding: 5px; 54 | font-family: Arial, Helvetica, sans-serif; 55 | font-size: 1.0em; 56 | margin: 2px; 57 | } 58 | 59 | table {width:98%; text-align:left; border:1px solid #DDDDDD; font-size:12px; color:#000;background:#fff; margin-bottom:10px;} 60 | table th {background-color:#E5E5E5; border:1px solid #BBBBBB; padding:3px 6px; font-weight:normal; color:#000;} 61 | table tr td {border:1px solid #DDDDDD; padding:5px 6px;} 62 | table tr.alt td {background-color:#E2E2E2;} 63 | table tr:hover {background-color:#F0F0F0; color:#000;} 64 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Blog 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 |

Blog

15 |
16 | 17 | query('SELECT postID, postTitle, postSlug, postDesc, postDate FROM blog_posts_seo ORDER BY postID DESC'); 21 | while($row = $stmt->fetch()){ 22 | 23 | echo '
'; 24 | echo '

'.$row['postTitle'].'

'; 25 | echo '

Posted on '.date('jS M Y H:i:s', strtotime($row['postDate'])).' in '; 26 | 27 | $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'); 28 | $stmt2->execute(array(':postID' => $row['postID'])); 29 | 30 | $catRow = $stmt2->fetchAll(PDO::FETCH_ASSOC); 31 | 32 | $links = array(); 33 | foreach ($catRow as $cat) 34 | { 35 | $links[] = "".$cat['catTitle'].""; 36 | } 37 | echo implode(", ", $links); 38 | 39 | echo '

'; 40 | echo '

'.$row['postDesc'].'

'; 41 | echo '

Read More

'; 42 | echo '
'; 43 | 44 | } 45 | 46 | } catch(PDOException $e) { 47 | echo $e->getMessage(); 48 | } 49 | ?> 50 | 51 |
52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /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 - <?php echo $row['postTitle'];?> 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 |

Blog

29 |
30 |

Blog Index

31 | 32 | 33 | '; 35 | echo '

'.$row['postTitle'].'

'; 36 | echo '

Posted on '.date('jS M Y H:i:s', strtotime($row['postDate'])).' in '; 37 | 38 | $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'); 39 | $stmt2->execute(array(':postID' => $row['postID'])); 40 | 41 | $catRow = $stmt2->fetchAll(PDO::FETCH_ASSOC); 42 | 43 | $links = array(); 44 | foreach ($catRow as $cat) 45 | { 46 | $links[] = "".$cat['catTitle'].""; 47 | } 48 | echo implode(", ", $links); 49 | 50 | echo '

'; 51 | echo '

'.$row['postCont'].'

'; 52 | echo '
'; 53 | ?> 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /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)') ; 47 | $stmt->execute(array( 48 | ':catTitle' => $catTitle, 49 | ':catSlug' => $catSlug 50 | )); 51 | 52 | //redirect to index page 53 | header('Location: categories.php?action=added'); 54 | exit; 55 | 56 | } catch(PDOException $e) { 57 | echo $e->getMessage(); 58 | } 59 | 60 | } 61 | 62 | } 63 | 64 | //check for any errors 65 | if(isset($error)){ 66 | foreach($error as $error){ 67 | echo '

'.$error.'

'; 68 | } 69 | } 70 | ?> 71 | 72 |
73 | 74 |


75 | '>

76 | 77 |

78 | 79 |
80 | 81 |
82 | -------------------------------------------------------------------------------- /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 | 52 | 53 | 54 | query('SELECT catID, catTitle, catSlug FROM blog_cats ORDER BY catTitle DESC'); 58 | while($row = $stmt->fetch()){ 59 | 60 | echo ''; 61 | echo ''; 62 | ?> 63 | 64 | 68 | 69 | '; 71 | 72 | } 73 | 74 | } catch(PDOException $e) { 75 | echo $e->getMessage(); 76 | } 77 | ?> 78 |
TitleAction
'.$row['catTitle'].' 65 | Edit | 66 | Delete 67 |
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 | 57 | 58 | 59 | 60 | query('SELECT memberID, username, email FROM blog_members ORDER BY username'); 64 | while($row = $stmt->fetch()){ 65 | 66 | echo ''; 67 | echo ''; 68 | echo ''; 69 | ?> 70 | 71 | 77 | 78 | '; 80 | 81 | } 82 | 83 | } catch(PDOException $e) { 84 | echo $e->getMessage(); 85 | } 86 | ?> 87 |
UsernameEmailAction
'.$row['username'].''.$row['email'].' 72 | Edit 73 | 74 | | Delete 75 | 76 |
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 | 56 | 57 | 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 ''; 67 | echo ''; 68 | ?> 69 | 70 | 74 | 75 | '; 77 | 78 | } 79 | 80 | } catch(PDOException $e) { 81 | echo $e->getMessage(); 82 | } 83 | ?> 84 |
TitleDateAction
'.$row['postTitle'].''.date('jS M Y', strtotime($row['postDate'])).' 71 | Edit | 72 | Delete 73 |
85 | 86 |

Add Post

87 | 88 |
89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /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 - <?php echo $row['catTitle'];?> 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 |

Blog

28 |

Posts in

29 |
30 |

Blog Index

31 | 32 | prepare(' 36 | SELECT 37 | blog_posts_seo.postID, blog_posts_seo.postTitle, blog_posts_seo.postSlug, blog_posts_seo.postDesc, blog_posts_seo.postDate 38 | FROM 39 | blog_posts_seo, 40 | blog_post_cats 41 | WHERE 42 | blog_posts_seo.postID = blog_post_cats.postID 43 | AND blog_post_cats.catID = :catID 44 | ORDER BY 45 | postID DESC 46 | '); 47 | $stmt->execute(array(':catID' => $row['catID'])); 48 | while($row = $stmt->fetch()){ 49 | 50 | echo '
'; 51 | echo '

'.$row['postTitle'].'

'; 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 | echo '
'; 70 | 71 | } 72 | 73 | } catch(PDOException $e) { 74 | echo $e->getMessage(); 75 | } 76 | 77 | ?> 78 | 79 |
80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /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') ; 52 | $stmt->execute(array( 53 | ':catTitle' => $catTitle, 54 | ':catSlug' => $catSlug, 55 | ':catID' => $catID 56 | )); 57 | 58 | //redirect to index page 59 | header('Location: categories.php?action=updated'); 60 | exit; 61 | 62 | } catch(PDOException $e) { 63 | echo $e->getMessage(); 64 | } 65 | 66 | } 67 | 68 | } 69 | 70 | ?> 71 | 72 | 73 | '; 78 | } 79 | } 80 | 81 | try { 82 | 83 | $stmt = $db->prepare('SELECT catID, catTitle FROM blog_cats WHERE catID = :catID') ; 84 | $stmt->execute(array(':catID' => $_GET['id'])); 85 | $row = $stmt->fetch(); 86 | 87 | } catch(PDOException $e) { 88 | echo $e->getMessage(); 89 | } 90 | 91 | ?> 92 | 93 |
94 | '> 95 | 96 |


97 | '>

98 | 99 |

100 | 101 |
102 | 103 |
104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /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($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 |
88 | 89 |


90 | '>

91 | 92 |


93 | '>

94 | 95 |


96 | '>

97 | 98 |


99 | '>

100 | 101 |

102 | 103 |
104 | 105 |
106 | -------------------------------------------------------------------------------- /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 |
126 | '> 127 | 128 |


129 | '>

130 | 131 |


132 |

133 | 134 |


135 |

136 | 137 |


138 | '>

139 | 140 |

141 | 142 |
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)') ; 67 | $stmt->execute(array( 68 | ':postTitle' => $postTitle, 69 | ':postSlug' => $postSlug, 70 | ':postDesc' => $postDesc, 71 | ':postCont' => $postCont, 72 | ':postDate' => date('Y-m-d H:i:s') 73 | )); 74 | $postID = $db->lastInsertId(); 75 | 76 | //add categories 77 | if(is_array($catID)){ 78 | foreach($_POST['catID'] as $catID){ 79 | $stmt = $db->prepare('INSERT INTO blog_post_cats (postID,catID)VALUES(:postID,:catID)'); 80 | $stmt->execute(array( 81 | ':postID' => $postID, 82 | ':catID' => $catID 83 | )); 84 | } 85 | } 86 | 87 | //redirect to index page 88 | header('Location: index.php?action=added'); 89 | exit; 90 | 91 | } catch(PDOException $e) { 92 | echo $e->getMessage(); 93 | } 94 | 95 | } 96 | 97 | } 98 | 99 | //check for any errors 100 | if(isset($error)){ 101 | foreach($error as $error){ 102 | echo '

'.$error.'

'; 103 | } 104 | } 105 | ?> 106 | 107 |
108 | 109 |


110 | '>

111 | 112 |


113 |

114 | 115 |


116 |

117 | 118 |
119 | Categories 120 | 121 | query('SELECT catID, catTitle FROM blog_cats ORDER BY catTitle'); 124 | while($row2 = $stmt2->fetch()){ 125 | 126 | if(isset($_POST['catID'])){ 127 | 128 | $checked = null; 129 | 130 | if(in_array($row2['catID'], $_POST['catID'])){ 131 | $checked="checked='checked'"; 132 | }else{ 133 | $checked = null; 134 | } 135 | } 136 | 137 | echo " ".$row2['catTitle']."
"; 138 | } 139 | 140 | ?> 141 | 142 |
143 | 144 |

145 | 146 |
147 | 148 |
149 | -------------------------------------------------------------------------------- /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') ; 72 | $stmt->execute(array( 73 | ':postTitle' => $postTitle, 74 | ':postSlug' => $postSlug, 75 | ':postDesc' => $postDesc, 76 | ':postCont' => $postCont, 77 | ':postID' => $postID 78 | )); 79 | 80 | //delete all items with the current postID 81 | $stmt = $db->prepare('DELETE FROM blog_post_cats WHERE postID = :postID'); 82 | $stmt->execute(array(':postID' => $postID)); 83 | 84 | if(is_array($catID)){ 85 | foreach($_POST['catID'] as $catID){ 86 | $stmt = $db->prepare('INSERT INTO blog_post_cats (postID,catID)VALUES(:postID,:catID)'); 87 | $stmt->execute(array( 88 | ':postID' => $postID, 89 | ':catID' => $catID 90 | )); 91 | } 92 | } 93 | 94 | //redirect to index page 95 | header('Location: index.php?action=updated'); 96 | exit; 97 | 98 | } catch(PDOException $e) { 99 | echo $e->getMessage(); 100 | } 101 | 102 | } 103 | 104 | } 105 | 106 | ?> 107 | 108 | 109 | '; 114 | } 115 | } 116 | 117 | try { 118 | 119 | $stmt = $db->prepare('SELECT postID, postTitle, postDesc, postCont FROM blog_posts_seo WHERE postID = :postID') ; 120 | $stmt->execute(array(':postID' => $_GET['id'])); 121 | $row = $stmt->fetch(); 122 | 123 | } catch(PDOException $e) { 124 | echo $e->getMessage(); 125 | } 126 | 127 | ?> 128 | 129 |
130 | '> 131 | 132 |


133 | '>

134 | 135 |


136 |

137 | 138 |


139 |

140 | 141 |
142 | Categories 143 | 144 | query('SELECT catID, catTitle FROM blog_cats ORDER BY catTitle'); 147 | while($row2 = $stmt2->fetch()){ 148 | 149 | $stmt3 = $db->prepare('SELECT catID FROM blog_post_cats WHERE catID = :catID AND postID = :postID') ; 150 | $stmt3->execute(array(':catID' => $row2['catID'], ':postID' => $row['postID'])); 151 | $row3 = $stmt3->fetch(); 152 | 153 | if($row3['catID'] == $row2['catID']){ 154 | $checked = 'checked=checked'; 155 | } else { 156 | $checked = null; 157 | } 158 | 159 | echo " ".$row2['catTitle']."
"; 160 | } 161 | 162 | ?> 163 | 164 |
165 | 166 |

167 | 168 | 169 | 170 |
171 | 172 |
173 | 174 | 175 | 176 | -------------------------------------------------------------------------------- /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 | 14 | INSERT INTO `blog_cats` (`catID`, `catTitle`, `catSlug`) 15 | VALUES 16 | (1,'General','general'), 17 | (2,'Development','development'), 18 | (5,'Misc','misc'), 19 | (4,'Testing','testing'); 20 | 21 | 22 | # Dump of table blog_members 23 | # ------------------------------------------------------------ 24 | 25 | DROP TABLE IF EXISTS `blog_members`; 26 | 27 | CREATE TABLE `blog_members` ( 28 | `memberID` int(11) unsigned NOT NULL AUTO_INCREMENT, 29 | `username` varchar(255) DEFAULT NULL, 30 | `password` varchar(255) DEFAULT NULL, 31 | `email` varchar(255) DEFAULT NULL, 32 | PRIMARY KEY (`memberID`) 33 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 34 | 35 | INSERT INTO `blog_members` (`memberID`, `username`, `password`, `email`) 36 | VALUES 37 | (1,'Demo','$2a$12$TF8u1maUr5kADc42g1FB0ONJDEtt24ue.UTIuP13gij5AHsg5f5s2','demo@demo.com'); 38 | 39 | 40 | # Dump of table blog_post_cats 41 | # ------------------------------------------------------------ 42 | 43 | DROP TABLE IF EXISTS `blog_post_cats`; 44 | 45 | CREATE TABLE `blog_post_cats` ( 46 | `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 47 | `postID` int(11) DEFAULT NULL, 48 | `catID` int(11) DEFAULT NULL, 49 | PRIMARY KEY (`id`) 50 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8; 51 | 52 | INSERT INTO `blog_post_cats` (`id`, `postID`, `catID`) 53 | VALUES 54 | (25,2,5), 55 | (21,6,4), 56 | (24,2,1), 57 | (4,3,2), 58 | (20,6,1), 59 | (16,1,2); 60 | 61 | # Dump of table blog_posts_seo 62 | # ------------------------------------------------------------ 63 | 64 | DROP TABLE IF EXISTS `blog_posts_seo`; 65 | 66 | CREATE TABLE `blog_posts_seo` ( 67 | `postID` int(11) unsigned NOT NULL AUTO_INCREMENT, 68 | `postTitle` varchar(255) DEFAULT NULL, 69 | `postSlug` varchar(255) DEFAULT NULL, 70 | `postDesc` text, 71 | `postCont` text, 72 | `postDate` datetime DEFAULT NULL, 73 | PRIMARY KEY (`postID`) 74 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 75 | 76 | INSERT INTO `blog_posts_seo` (`postID`, `postTitle`, `postSlug`, `postDesc`, `postCont`, `postDate`) 77 | VALUES 78 | (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\n

We 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\n

The Series Has Landed

\r\n

Fry! 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\n

Future Stock

\r\n

Does 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\n
  1. Spare me your space age technobabble, Attila the Hun!
  2. \r\n
  3. You guys realize you live in a sewer, right?
  4. \r\n
  5. I guess if you want children beaten, you have to do it yourself.
  6. \r\n
  7. Yeah. Give a little credit to our public schools.
  8. \r\n
\r\n
The Why of Fry
\r\n

Who 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'), 79 | (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\n

It 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\n

Anthology of Interest I

\r\n

Hey, 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\n

Teenage Mutant Leela\'s Hurdles

\r\n

Oh, 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\n
  1. Spare me your space age technobabble, Attila the Hun!
  2. \r\n
  3. Well, thanks to the Internet, I\'m now bored with sex. Is there a place on the web that panders to my lust for violence?
  4. \r\n
\r\n
The Farnsworth Parabox
\r\n

Wow! 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'), 80 | (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\n

Professor, 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\n

Lethal Inspection

\r\n

Oh, 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\n

Where No Fan Has Gone Before

\r\n

Who 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\n
  1. I\'m sorry, guys. I never meant to hurt you. Just to destroy everything you ever believed in.
  2. \r\n
  3. Stop it, stop it. It\'s fine. I will \'destroy\' you!
  4. \r\n
  5. You guys realize you live in a sewer, right?
  6. \r\n
\r\n
Fear of a Bot Planet
\r\n

Why 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'), 81 | (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\n

Professor, 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\n

Lethal Inspection

\r\n

Oh, 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\n

Where No Fan Has Gone Before

\r\n

Who 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\n
  1. I\'m sorry, guys. I never meant to hurt you. Just to destroy everything you ever believed in.
  2. \r\n
  3. Stop it, stop it. It\'s fine. I will \'destroy\' you!
  4. \r\n
  5. You guys realize you live in a sewer, right?
  6. \r\n
\r\n
Fear of a Bot Planet
\r\n

Why 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'); 82 | -------------------------------------------------------------------------------- /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 | } --------------------------------------------------------------------------------