<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -43,10 +43,10 @@
 				&lt;/thead&gt;
 				&lt;tbody&gt;
 				{% for post in posts.paginated %}
-					&lt;tr id=&quot;post_$post.id&quot; class=&quot;post $post.status{% if loop.last %} last{% endif %}&quot;&gt;
+					&lt;tr id=&quot;post_$post.id&quot; class=&quot;post $post.status_class{% if loop.last %} last{% endif %}&quot;&gt;
 						&lt;td class=&quot;main&quot;&gt;&lt;a href=&quot;$post.url&quot;&gt;${ post.title | truncate }&lt;/a&gt;&lt;/td&gt;
 						&lt;td&gt;${ post.created_at | strftime }&lt;/td&gt;
-						&lt;td&gt;${ post.status | replace(&quot;_&quot;, &quot; &quot;) | title | translate }&lt;/td&gt;
+						&lt;td&gt;$post.status_name&lt;/td&gt;
 						&lt;td&gt;$post.user.login&lt;/td&gt;
 						${ trigger.call(&quot;manage_posts_column&quot;, post) }
 {% if post.editable and post.deletable %}</diff>
      <filename>admin/layout/pages/manage_posts.twig</filename>
    </modified>
    <modified>
      <diff>@@ -52,11 +52,16 @@
 							&lt;label for=&quot;status&quot;&gt;${ &quot;Status&quot; | translate }&lt;/label&gt;
 							&lt;select name=&quot;status&quot; id=&quot;status&quot;&gt;
 {% if route.action == &quot;edit_post&quot; %}
-								&lt;option value=&quot;draft&quot;{% if post.status == &quot;draft&quot; %} selected=&quot;selected&quot;{% endif %}&gt;${ &quot;Draft&quot; | translate }&lt;/option&gt;
+								&lt;option value=&quot;draft&quot;${ post.status | option_selected(&quot;draft&quot;) }&gt;${ &quot;Draft&quot; | translate }&lt;/option&gt;
 {% endif %}
-								&lt;option value=&quot;public&quot;{% if post.status == &quot;public&quot; %} selected=&quot;selected&quot;{% endif %}&gt;${ &quot;Public&quot; | translate }&lt;/option&gt;
-								&lt;option value=&quot;private&quot;{% if post.status == &quot;private&quot; %} selected=&quot;selected&quot;{% endif %}&gt;${ &quot;Private&quot; | translate }&lt;/option&gt;
-								&lt;option value=&quot;registered_only&quot;{% if post.status == &quot;registered_only&quot; %} selected=&quot;selected&quot;{% endif %}&gt;${ &quot;Registered Only&quot; | translate }&lt;/option&gt;
+								&lt;option value=&quot;public&quot;${ post.status | option_selected(&quot;public&quot;) }&gt;${ &quot;Public&quot; | translate }&lt;/option&gt;
+								&lt;option value=&quot;private&quot;${ post.status | option_selected(&quot;private&quot;) }&gt;${ &quot;Private&quot; | translate }&lt;/option&gt;
+								&lt;option value=&quot;registered_only&quot;${ post.status | option_selected(&quot;registered_only&quot;) }&gt;${ &quot;Registered Only&quot; | translate }&lt;/option&gt;
+								&lt;optgroup label=&quot;${ &quot;Group&quot; | translate }&quot;&gt;
+									{% for group in groups %}
+									&lt;option value=&quot;{$group.id}&quot;${ post.status | option_selected(&quot;{&quot;~ group.id ~&quot;}&quot;) }&gt;${ group.name | escape }&lt;/option&gt;
+									{% endfor %}
+								&lt;/optgroup&gt;
 							&lt;/select&gt;
 						&lt;/p&gt;
 						{% endif %}</diff>
      <filename>admin/layout/partials/post_fields.twig</filename>
    </modified>
    <modified>
      <diff>@@ -989,4 +989,7 @@ img.smiley {
 	font-weight: bold;
 	color: #bbb;
 }
+.group_prefix {
+	color: #999;
+}
 /* @end */</diff>
      <filename>admin/style.css</filename>
    </modified>
    <modified>
      <diff>@@ -203,7 +203,10 @@
 			}
 		}
 
-		public function check_viewing_page($i_have_the_power = false) {
+		public function check_viewing_page() {
+			if (!INDEX)
+				return;
+
 			global $page;
 
 			$config = Config::current();
@@ -220,11 +223,14 @@
 				foreach ($valids as $page)
 					if ($page-&gt;url == end($this-&gt;arg))
 						return list($_GET['url'], $this-&gt;action) = array($page-&gt;url, &quot;page&quot;);
-			} elseif ($i_have_the_power)
+			} elseif (!preg_match(&quot;/^\((clean|url)\)\/?$/&quot;, $config-&gt;post_url)) # This is the last route parse.
 				return $this-&gt;action = fallback($this-&gt;arg[0], &quot;index&quot;);
 		}
 
-		public function check_viewing_post($i_have_the_power = false) {
+		public function check_viewing_post() {
+			if (!INDEX)
+				return;
+
 			$config = Config::current();
 
 			if (!empty($this-&gt;action))
@@ -259,11 +265,14 @@
 					return $this-&gt;action = &quot;view&quot;;
 			}
 
-			if ($i_have_the_power)
+			if (preg_match(&quot;/^\((clean|url)\)\/?$/&quot;, $config-&gt;post_url)) # This is the last route parse.
 				return $this-&gt;action = fallback($this-&gt;arg[0], &quot;index&quot;);
 		}
 
 		public function check_custom_routes() {
+			if (!INDEX)
+				return;
+
 			$config = Config::current();
 
 			# Custom pages added by Modules, Feathers, Themes, etc.</diff>
      <filename>includes/class/Route.php</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,14 @@
 &lt;?php
+	# File: Query
+	# See Also:
+	#     &lt;Query&gt;
+	require_once INCLUDES_DIR.&quot;/class/Query.php&quot;;
+
+	# File: QueryBuilder
+	# See Also:
+	#     &lt;QueryBuilder&gt;
+	require_once INCLUDES_DIR.&quot;/class/QueryBuilder.php&quot;;
+
 	/**
 	 * Class: SQL
 	 * Contains the database settings and functions for interacting with the SQL database.
@@ -298,22 +308,25 @@
 		 * Escapes a string, escaping things like $1 and C:\foo\bar so that they don't get borked by the preg_replace.
 		 * This also handles calling the SQL connection method's &quot;escape_string&quot; functions.
 		 */
-		public function escape($string) {
+		public function escape($string, $quotes = true) {
 			switch(SQL::current()-&gt;method()) {
 				case &quot;pdo&quot;:
-					$string = $this-&gt;db-&gt;quote($string);
+					$string = ltrim(rtrim($this-&gt;db-&gt;quote($string), &quot;'&quot;), &quot;'&quot;);
 					break;
 				case &quot;mysqli&quot;:
-					$string = &quot;'&quot;.$this-&gt;db-&gt;escape_string($string).&quot;'&quot;;
+					$string = $this-&gt;db-&gt;escape_string($string);
 					break;
 				case &quot;mysql&quot;:
-					$string = &quot;'&quot;.mysql_real_escape_string($string).&quot;'&quot;;
+					$string = mysql_real_escape_string($string);
 					break;
 			}
 
 			$string = str_replace('\\', '\\\\', $string);
 			$string = str_replace('$', '\$', $string);
 
+			if ($quotes)
+				$string = &quot;'&quot;.$string.&quot;'&quot;;
+
 			return $string;
 		}
 </diff>
      <filename>includes/class/SQL.php</filename>
    </modified>
    <modified>
      <diff>@@ -23,7 +23,7 @@
 
 	# Constant: DEBUG
 	# Should Chyrp use debugging processes?
-	define('DEBUG', false);
+	define('DEBUG', true);
 
 	# Fallback all these definitions.
 	if (!defined('JAVASCRIPT')) define('JAVASCRIPT', false);
@@ -87,16 +87,20 @@
 	if (!file_exists(INCLUDES_DIR.&quot;/config.yaml.php&quot;))
 		redirect(&quot;install.php&quot;);
 
-	require_once INCLUDES_DIR.&quot;/class/Query.php&quot;;
-	require_once INCLUDES_DIR.&quot;/class/QueryBuilder.php&quot;;
+	# Libraries
+	require_once INCLUDES_DIR.&quot;/lib/gettext/gettext.php&quot;;
+	require_once INCLUDES_DIR.&quot;/lib/gettext/streams.php&quot;;
 	require_once INCLUDES_DIR.&quot;/lib/YAML.php&quot;;
 
+	# File: Config
+	# See Also:
+	#     &lt;Config&gt;
 	require_once INCLUDES_DIR.&quot;/class/Config.php&quot;;
-	require_once INCLUDES_DIR.&quot;/class/SQL.php&quot;;
 
-	# Translation stuff
-	require_once INCLUDES_DIR.&quot;/lib/gettext/gettext.php&quot;;
-	require_once INCLUDES_DIR.&quot;/lib/gettext/streams.php&quot;;
+	# File: SQL
+	# See Also:
+	#     &lt;SQL&gt;
+	require_once INCLUDES_DIR.&quot;/class/SQL.php&quot;;
 
 	set_timezone($config-&gt;timezone);
 
@@ -287,6 +291,7 @@
 	                         !empty($_GET['action']) and
 	                         $_GET['action'] == &quot;theme_preview&quot; and
 	                         !empty($_GET['theme'])));
+
 	$theme = PREVIEWING ? $_GET['theme'] : $config-&gt;theme;
 
 	# Constant: THEME_DIR
@@ -304,20 +309,18 @@
 
 	header(&quot;Content-type: &quot;.(INDEX ? fallback($theme-&gt;type, &quot;text/html&quot;) : &quot;text/html&quot;).&quot;; charset=UTF-8&quot;);
 
-	if (INDEX) {
-		$route-&gt;check_custom_routes();
+	$route-&gt;check_custom_routes();
 
-		# If the post viewing URL is the same as the page viewing URL, check for viewing a page first.
-		if (preg_match(&quot;/^\((clean|url)\)\/?$/&quot;, $config-&gt;post_url)) {
-			$route-&gt;check_viewing_page();
-			$route-&gt;check_viewing_post(true);
-		} else {
-			$route-&gt;check_viewing_page(true);
-			$route-&gt;check_viewing_post();
-		}
+	# If the post viewing URL is the same as the page viewing URL, check for viewing a page first.
+	if (preg_match(&quot;/^\((clean|url)\)\/?$/&quot;, $config-&gt;post_url)) {
+		$route-&gt;check_viewing_page();
+		$route-&gt;check_viewing_post();
+	} else {
+		$route-&gt;check_viewing_post();
+		$route-&gt;check_viewing_page();
+	}
 
-		$trigger-&gt;call(&quot;runtime&quot;);
-	} elseif (ADMIN)
+	if (INDEX or ADMIN)
 		$trigger-&gt;call(&quot;runtime&quot;);
 
 	# Array: $statuses
@@ -329,7 +332,8 @@
 	if ($visitor-&gt;group()-&gt;can(&quot;view_private&quot;))
 		$statuses[] = &quot;private&quot;;
 
-	Post::$private = &quot;status IN ('&quot;.implode(&quot;', '&quot;, $statuses).&quot;')&quot;;
+	Post::$private = &quot;(status IN ('&quot;.implode(&quot;', '&quot;, $statuses).&quot;') OR&quot;.
+	                 &quot; status LIKE '%{&quot;.$visitor-&gt;group()-&gt;id.&quot;}%')&quot;;
 	Post::$enabled_feathers = &quot;feather IN ('&quot;.implode(&quot;', '&quot;, $config-&gt;enabled_feathers).&quot;')&quot;;
 
 	# Load the translation engine</diff>
      <filename>includes/common.php</filename>
    </modified>
    <modified>
      <diff>@@ -34,6 +34,7 @@
 
 			$this-&gt;context[&quot;feathers&quot;]       = $feathers;
 			$this-&gt;context[&quot;feather&quot;]        = $feathers[$_GET['feather']];
+			$this-&gt;context[&quot;groups&quot;]         = Group::find(array(&quot;order&quot; =&gt; &quot;id ASC&quot;));
 		}
 
 		/**
@@ -88,6 +89,9 @@
 
 			$post = $feathers[$_POST['feather']]-&gt;submit();
 
+			if (!$post-&gt;redirect)
+				$post-&gt;redirect = &quot;/admin/?action=write_post&quot;;
+
 			if (!isset($_POST['bookmarklet']))
 				Flash::notice(__(&quot;Post created!&quot;), $post-&gt;redirect);
 			else
@@ -194,6 +198,25 @@
 			                                                         &quot;drafts&quot; =&gt; true,
 			                                                         &quot;where&quot; =&gt; $where,
 			                                                         &quot;params&quot; =&gt; $params)), 25);
+
+			foreach ($this-&gt;context[&quot;posts&quot;]-&gt;paginated as &amp;$post) {
+				if (preg_match_all(&quot;/\{([0-9]+)\}/&quot;, $post-&gt;status, $matches)) {
+					$groups = array();
+					$groupClasses = array();
+
+					foreach ($matches[1] as $id) {
+						$group = new Group($id);
+						$groups[] = &quot;&lt;span class=\&quot;group_prefix\&quot;&gt;Group:&lt;/span&gt; &quot;.$group-&gt;name;
+						$groupClasses[] = &quot;group-&quot;.$id;
+					}
+
+					$post-&gt;status_name = join(&quot;, &quot;, $groups);
+					$post-&gt;status_class = join(&quot; &quot;, $groupClasses);
+				} else {
+					$post-&gt;status_name = camelize($post-&gt;status, true);
+					$post-&gt;status_class = $post-&gt;status;
+				}
+			}
 		}
 
 		/**</diff>
      <filename>includes/controller/Admin.php</filename>
    </modified>
    <modified>
      <diff>@@ -36,7 +36,7 @@
 			if (!XML_RPC) {
 				$visitor = Visitor::current();
 				$private = (isset($options[&quot;drafts&quot;]) and $options[&quot;drafts&quot;] and $visitor-&gt;group()-&gt;can(&quot;view_draft&quot;)) ?
-				               str_replace(&quot;')&quot;, &quot;', 'draft')&quot;, self::$private) :
+				               str_replace(&quot;') OR&quot;, &quot;', 'draft') OR&quot;, self::$private) :
 				               self::$private;
 
 				$options[&quot;where&quot;][] = self::$enabled_feathers;
@@ -76,7 +76,7 @@
 			if (!XML_RPC) {
 				$visitor = Visitor::current();
 				$private = (isset($options[&quot;drafts&quot;]) and $options[&quot;drafts&quot;] and $visitor-&gt;group()-&gt;can(&quot;view_draft&quot;)) ?
-				               str_replace(&quot;')&quot;, &quot;', 'draft')&quot;, self::$private) :
+				               str_replace(&quot;') OR&quot;, &quot;', 'draft') OR&quot;, self::$private) :
 				               self::$private ;
 
 				$options[&quot;where&quot;][] = self::$enabled_feathers;</diff>
      <filename>includes/model/Post.php</filename>
    </modified>
    <modified>
      <diff>@@ -3,6 +3,9 @@ require &quot;net/http&quot;
 require &quot;rubygems&quot;
 require &quot;hpricot&quot;
 
+`rm -Rfv uploads/*`
+`mysql -f --user=root -D chyrp -e 'TRUNCATE TABLE chyrp_posts; TRUNCATE TABLE chyrp_pages; TRUNCATE TABLE chyrp_comments; TRUNCATE TABLE chyrp_tags;' &gt; /dev/null`
+
 FUZZER = {
   :textarea =&gt; &quot;Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nullam urna. Vivamus nisl. Mauris iaculis rutrum elit. Cras ornare congue mi. Nullam mi quam, luctus dapibus, euismod ut, dapibus sed, dui. Praesent est lectus, rutrum ac, blandit vitae, hendrerit at, massa. Morbi mauris purus, lobortis vel, commodo vitae, aliquet vehicula, ante. Nunc commodo. Pellentesque vel lacus. Quisque eros. Maecenas et quam. Curabitur eget justo a ante dignissim dapibus. Sed et lacus. Suspendisse potenti. Vivamus ipsum mi, blandit vitae, scelerisque a, pellentesque vitae, nisl. Donec vitae est et est egestas laoreet. Vestibulum commodo elit ut nisl. Nullam volutpat nisi non elit. Morbi sapien eros, ornare et, dapibus id, mattis id, nibh. Suspendisse ut nisl id est scelerisque faucibus.\n\nPraesent viverra felis nec justo. Duis gravida tempor massa. Aliquam lobortis tortor eu purus. Phasellus volutpat, justo eget molestie rhoncus, nibh tortor suscipit justo, non vehicula tortor tortor id sapien. Vivamus quis nisl et neque ullamcorper viverra. Vestibulum accumsan, elit luctus auctor fermentum, lorem tellus dignissim odio, a lobortis magna nulla eget arcu. Phasellus vel erat at dolor sagittis luctus. Nulla facilisi. In eros eros, molestie sit amet, ornare a, fermentum et, dui. Vivamus vel turpis quis diam iaculis dapibus. Nunc lacinia. Integer commodo, urna interdum imperdiet pretium, libero nulla pellentesque turpis, in ultrices neque tortor at arcu. Sed mollis odio eget mauris ultricies bibendum. Vivamus malesuada metus vel arcu. Nam sit amet metus. Pellentesque quis felis non nibh adipiscing adipiscing.&quot;,
   :text =&gt; &quot;Test Input&quot;
@@ -17,29 +20,64 @@ HEADERS = {
   &quot;User-Agent&quot; =&gt; &quot;tester.rb&quot;
 }
 
+POSTS = {
+  :text =&gt; {
+    &quot;title&quot; =&gt; &quot;Test Text Post&quot;,
+    &quot;body&quot; =&gt; FUZZER[:textarea]
+  },
+  :quote =&gt; {
+    &quot;quote&quot; =&gt; FUZZER[:textarea].split(&quot;. &quot;)[0] + &quot;.&quot;,
+    &quot;source&quot; =&gt; &quot;Chyrp Tester&quot;
+  },
+  :chat =&gt; {
+    &quot;title&quot; =&gt; &quot;Test Chat Post&quot;,
+    &quot;dialogue&quot; =&gt; &quot;Person: Hi!\nMe (me): Hello!\nPerson: How are you?\nMe: Great, thanks! And you?\nPerson: FUCKING AWESOME.&quot;
+  },
+  :link =&gt; {
+    &quot;name&quot; =&gt; &quot;Google Search&quot;,
+    &quot;source&quot; =&gt; &quot;http://google.com/&quot;,
+    &quot;description&quot; =&gt; &quot;I can't believe how long I've gone without finding this site.&quot;
+  }
+}
+
 class Chyrp &lt; Test::Unit::TestCase
   def test_add_post
-    resp, write = get &quot;/admin/?action=write_post&quot;
+    POSTS.each do |feather, attrs|
+      resp, write = get &quot;/admin/?action=write_post&amp;feather=&quot;+ feather.to_s
 
-    page = Hpricot(write)
+      page = Hpricot(write)
 
-    post (page/&quot;form&quot;).attr(&quot;action&quot;), form_fuzz(page/&quot;form&quot;)
+      form_fuzz(page/&quot;form&quot;).each do |key, val|
+        attrs[key] = val unless attrs.has_key? key
+      end
+
+      attrs['feather'] = feather.to_s
+
+      post (page/&quot;form&quot;).attr(&quot;action&quot;), attrs
+    end
   end
 
   def test_add_draft
-    resp, write = get &quot;/admin/?action=write_post&quot;
+    POSTS.each do |feather, attrs|
+      resp, write = get &quot;/admin/?action=write_post&amp;feather=&quot;+ feather.to_s
 
-    page = Hpricot(write)
+      page = Hpricot(write)
 
-    data = form_fuzz(page/&quot;form&quot;)
-    data['draft'] = &quot;true&quot;
+      form_fuzz(page/&quot;form&quot;).each do |key, val|
+        attrs[key] = val unless attrs.has_key? key
+      end
+
+      attrs['feather'] = feather.to_s
+      attrs['draft'] = &quot;true&quot;
 
-    post (page/&quot;form&quot;).attr(&quot;action&quot;), data
+      post (page/&quot;form&quot;).attr(&quot;action&quot;), attrs
+    end
   end
 
   def test_view_post
     resp, page = test_index
     page = Hpricot(page)
+    return unless page =~ /class=&quot;post /
 
     post_url = (page/&quot;.post:first/h2/a&quot;).attr(&quot;href&quot;)
 
@@ -58,7 +96,10 @@ class Chyrp &lt; Test::Unit::TestCase
     resp, page = test_index
     page = Hpricot(page)
 
-    page_url = (page/&quot;#sidebar/ul:nth(0)/li:nth(0)/a&quot;).attr(&quot;href&quot;)
+    first_page = (page/&quot;#sidebar/ul:nth(0)/li:nth(0)/a&quot;)
+    return unless first_page
+
+    page_url = first_page.attr(&quot;href&quot;)
 
     get page_url
   end
@@ -125,6 +166,7 @@ class Chyrp &lt; Test::Unit::TestCase
 
   def test_pagination
     resp, page = get(&quot;/page/2/&quot;)
+    return unless page =~ /class=&quot;post /
     assert_match /Page 2 of /, page, &quot;No pagination links displayed.&quot;
   end
 
@@ -174,33 +216,16 @@ class Chyrp &lt; Test::Unit::TestCase
     end
 
     def form_fuzz form
-      data = {}
+      data = form_get form
 
       (form/&quot;*[@name]&quot;).each do |field|
-        if field['type'] == &quot;hidden&quot; or (field.name != &quot;textarea&quot; and field['value'] != &quot;&quot;) or (field.name == &quot;textarea&quot; and !field.empty?)
-          if field.name == &quot;select&quot;
-            selected = (field/&quot;option[@selected]&quot;)
-            option = selected.length &gt; 0 ? selected : (field/&quot;option:nth(0)&quot;)
-            data[field['name']] = option.attr(&quot;value&quot;)
-          elsif field.name != &quot;button&quot;
-            if field['type'] == &quot;checkbox&quot;
-              data[field['name']] = (field['checked'] || &quot;no&quot;) == &quot;checked&quot; ? &quot;1&quot; : &quot;0&quot;
-            else
-              data[field['name']] = field['value'] || field.html
-            end
-          end
-          next
-        end
+        next unless data[field['name']].nil? or data[field['name']].empty?
 
         if field.name == &quot;textarea&quot;
           data[field['name']] = FUZZER[:textarea]
         elsif field.name == &quot;input&quot;
-          next if field['name'] == &quot;trackbacks&quot;
-          if field['name'] == &quot;slug&quot;
-            data[field['name']] = &quot;test-slug&quot;
-          else
-            data[field['name']] = FUZZER[:text]
-          end
+          next if field['type'] != &quot;text&quot; or field['name'] == &quot;trackbacks&quot; or field['name'] == &quot;slug&quot;
+          data[field['name']] = FUZZER[:text]
         end
       end
 </diff>
      <filename>tester.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>a3d1c5c28f03588ac451190abd4957e766f56a19</id>
    </parent>
  </parents>
  <author>
    <name>Alex Suraci</name>
    <email>i.am@toogeneric.com</email>
  </author>
  <url>http://github.com/vito/chyrp/commit/40723b52d084891ccc2a05f46b9a191a885668c8</url>
  <id>40723b52d084891ccc2a05f46b9a191a885668c8</id>
  <committed-date>2008-09-06T22:17:22-07:00</committed-date>
  <authored-date>2008-09-06T22:17:22-07:00</authored-date>
  <message>* Group-specific post statuses. [#156 state:resolved]
* More common.php cleanups.
* Tester improvements.
* SQL-&gt;escape can be set to not auto-wrap with quotes with the first (bool) argument.</message>
  <tree>c50a3dddf0376f9434409956c388e195250c989f</tree>
  <committer>
    <name>Alex Suraci</name>
    <email>i.am@toogeneric.com</email>
  </committer>
</commit>
