code:
<?php if ( !defined( 'HABARI_PATH' ) ) { die( 'No direct access' ); }

class AutoP extends Plugin
{

	public function action_init_atom()
	{
		Format::apply( 'autop', 'post_content_atom' );
	}

	public function action_init_theme_any( $theme )
	{
		Format::apply( 'autop', 'post_content_out' );
	}

}

?>

repo_name: DaSourcerer/habari


code:
<?xml version="1.0" encoding="utf-8" ?>
<pluggable type="plugin" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://schemas.habariproject.org/pluggable/0.8">
	<name>AutoParagraph</name>
	<license url="http://www.apache.org/licenses/LICENSE-2.0.html">Apache Software License 2.0</license>

	<author url="http://habariproject.org/">The Habari Community</author>

	<version>0.9</version>
	<url>http://habariproject.org/</url>
	<description><![CDATA[Automatically insert HTML paragraph tags and line breaks.]]></description>

	<copyright>2009</copyright>

	<help>
		<value><![CDATA[

When activated, this plugin modifies the HTML output of the site to include paragraphs and line breaks, where they are placed within post content. It does not modify the original data.

The changes are not saved to the database. If you deactivate this plugin, the new formatting will be lost.

Sample Input

When activated, the plugin will convert line breaks in raw post content, such as the following, into paragraphs.

			This is paragraph one.

This is paragraph two.
This is the second line of paragraph two.

Sample Output

Raw content, such as that above, will be converted into HTML, similar to the following.

			<p>This is paragraph one.</p>
<p>This is paragraph two.<br>This is the second line of paragraph two.</p>
		]]></value>
	</help>

</pluggable>


code:
<?php if ( !defined( 'HABARI_PATH' ) ) { die( 'No direct access' ); } ?>
<form id="month_archive_form" action="">
<fieldset><legend>Browse Archives</legend>

<select name="archive_tags" onchange="window.location =
(document.forms.month_archive_form.archive_tags[document.forms.month_archive_form.archive_tags.selectedIndex].value);">

		<option value=''>by date</option>
		<?php $months = $content->months; foreach( $months as $month ): ?>
	<option value="<?php echo $month[ 'url' ]; ?>"><?php echo $month[ 'display_month' ] . " " . $month[ 'year' ] . $month[ 'count' ];
	?></option>
		<?php endforeach; ?>
</select>
</fieldset>
</form>


code:
<?php if ( !defined( 'HABARI_PATH' ) ) { die( 'No direct access' ); } ?>
<form id="tag_archive_form" action="">
<fieldset><legend>Browse Archives</legend>

<select name="archive_tags" onchange="window.location =
(document.forms.tag_archive_form.archive_tags[document.forms.tag_archive_form.archive_tags.selectedIndex].value);">

		<option value=''>by tag</option>
		<?php $tags = $content->tags; foreach( $tags as $tag ): ?>
			<option value="<?php echo $tag[ 'url' ]; ?>"><?php echo $tag[ 'tag' ] . $tag[ 'count' ];
	?></option>
		<?php endforeach; ?>
</select>
</fieldset>
</form>


code:
<?php if ( !defined( 'HABARI_PATH' ) ) { die( 'No direct access' ); } ?>

	<?php $links = $content->list; foreach( $links as $label => $href): ?>

<a href="<?php echo $label; ?>"><?php echo $href; ?>

	<?php endforeach; ?>


code:
<?php if ( !defined( 'HABARI_PATH' ) ) { die( 'No direct access' ); } ?>

	<?php $months = $content->months; foreach( $months as $month ): ?>

	<a href="<?php echo $month[ 'url' ]; ?>" title="View entries in <?php
		echo $month[ 'display_month' ] . ", " . $month[ 'year' ];
	?>"><?php
		echo $month[ 'display_month' ] . " " . $month[ 'year' ] . $month[ 'count' ];
	?>

	<?php endforeach; ?>


code:
<?php if ( !defined( 'HABARI_PATH' ) ) { die( 'No direct access' ); } ?>

	<?php $comments = $content->recent_comments; foreach( $comments as $comment): ?>

			<a href="<?php echo $comment->url ?>">
				<?php echo $comment->name; ?>
			 on
			<a href="<?php echo $comment->post->permalink; ?>">
				<?php echo $comment->post->title; ?>

	<?php endforeach; ?>


code:
<?php if ( !defined( 'HABARI_PATH' ) ) { die( 'No direct access' ); } ?>

	<?php $posts = $content->recent_posts; foreach( $posts as $post): ?>

			<a href="<?php echo $post->permalink; ?>">
				<?php echo $post->title; ?>

	<?php endforeach; ?>


code:
<?php if ( !defined( 'HABARI_PATH' ) ) { die( 'No direct access' ); }
	Plugins::act( 'theme_searchform_before' );
	echo $content->form;
	Plugins::act( 'theme_searchform_after' );
?>


code:
<?php if ( !defined( 'HABARI_PATH' ) ) { die( 'No direct access' ); } ?>

	<?php $tags = $content->tags; foreach( $tags as $tag ): ?>

	<a href="<?php echo $tag[ 'url' ]; ?>" title="View entries tagged '<?php
		echo $tag[ 'tag' ];
	?>'"><?php
		echo $tag[ 'tag' ] . $tag[ 'count' ];
	?>

	<?php endforeach; ?>


code:
<?php if ( !defined( 'HABARI_PATH' ) ) { die( 'No direct access' ); }
	echo $content->content;
?>


code:
<?php if ( !defined( 'HABARI_PATH' ) ) { die( 'No direct access' ); }

/**
 * Create blocks commonly used by site owners.
 *
 */
class CoreBlocks extends Plugin
{
	private $allblocks = array();

	/**
	 * When the plugin is initialized, register the block templates and set up supporting data.
	 */
	function action_init()
	{

		$this->allblocks = array(
			'recent_comments' => _t( 'Recent Comments' ),
			'recent_posts' => _t( 'Recent Posts' ),
			'monthly_archives' => _t( 'Monthly Archives' ),
			'category_archives' => _t( 'Category Archives' ),
			'tag_archives' => _t( 'Tag Archives' ),
			'meta_links' => _t( 'Meta Links' ),
			'search_form' => _t( 'Search Form' ),
			'text' => _t( 'Text' ),
		);

		foreach ( array_keys( $this->allblocks ) as $blockname ) {
			$this->add_template( "block.$blockname", dirname( __FILE__ ) . "/block.$blockname.php" );
		}
		$this->add_template( "block.dropdown.category_archives", dirname( __FILE__ ) . "/block.dropdown.category_archives.php" );
		$this->add_template( "block.dropdown.tag_archives", dirname( __FILE__ ) . "/block.dropdown.tag_archives.php" );
		$this->add_template( "block.dropdown.monthly_archives", dirname( __FILE__ ) . "/block.dropdown.monthly_archives.php" );
	}

	/**
	 * Encapsulate the list of URLs the block can display
	 * @return array A list of URLs that can be displayed
	 */
	function meta_urls()
	{
		return array(
			_t( 'Site Feed' ) => URL::get( 'atom_feed', array( 'index' => '1' ) ),
			_t( 'Comments Feed' ) => URL::get( 'atom_feed_comments' ),
			'Habari' => 'http://habariproject.org/',
		);
	}

	/**
	 * Add available blocks to the list of possible block types.
	 *
	 * @param array $block_list an Associative array of the internal names and display names of blocks
	 *
	 * @return array The modified $block_list array
	 */
	public function filter_block_list( $block_list )
	{
		$allblocks = $this->allblocks;
		foreach ( $allblocks as $blockname => $nicename ) {
			$block_list[ $blockname ] = _t( $nicename );
		}
		return $block_list;
	}

	/**
	 * Recent Comments
	 *
	 * Allow configuration of the number of recent comments to show
	 *
	 * @param FormUI $form The configuration form for this block
	 * @param Block $block The block instance to be configured
	 */
	public function action_block_form_recent_comments( $form, $block )
	{
		$content = $form->append('text', 'quantity', $block, _t( 'Comments to show:' ) );
	}

	/**
	 * Recent Comments
	 *
	 * Handle recent comment block output
	 *
	 * @param Block $block The block instance to be configured
	 * @param Theme $theme The active theme
	 */
	public function action_block_content_recent_comments( $block, $theme )
	{
		if ( ! $limit = $block->quantity ) {
			$limit = 5;
		};

		$offset = 0;
		$published_posts = 0;
		$valid_comments = array();
		// prevent endless looping if there are fewer comments than $limit
		$comments_remain = true;

		while ( $published_posts < $limit && $comments_remain ) {
			$comments = Comments::get( array(
				'limit' => $limit - $published_posts,
				'status' => Comment::STATUS_APPROVED,
				'type' => Comment::COMMENT,
				'offset' => $offset,
				'orderby' => 'date DESC',
			) );
			// check the posts
			foreach ( $comments as $key => $comment ) {
				if ( ( $comment->post->status ) == Post::status( 'published' ) ) {
					$valid_comments[] = $comments[ $key ];
					++$published_posts;
				}
				++$offset;
			}
			// stop looping if out of comments
			if ( count( $comments ) === 0 ) {
				$comments_remain = false;
			}
		}

		$block->recent_comments = $valid_comments;
	}

	/**
	 * Recent Posts
	 *
	 * Allow configuration of the number of recent posts to show
	 *
	 * @param FormUI $form The configuration form for this block
	 * @param Block $block The block instance to be configured
	 */
	public function action_block_form_recent_posts( $form, $block )
	{
		$content = $form->append('text', 'quantity', $block, _t( 'Posts to show:' ) );

		$content_types = Post::list_active_post_types();

		unset($content_types['any']);

		foreach ( $content_types as $k => $v ) {
			$content_types[ $k ] = Plugins::filter( 'post_type_display', $k, 'plural' );
		}

		$form->append('checkboxes', 'content_types', $block, _t( 'Content Types to Include:' ), $content_types );

	}

	/**
	 * Recent Posts
	 *
	 * Handle recent post block output
	 *
	 * @param Block $block The block instance to be configured
	 * @param Theme $theme The active theme
	 */
	public function action_block_content_recent_posts( $block, $theme )
	{
		if ( ! $limit = $block->quantity ) {
			$limit = 5;
		};

		if ( empty( $block->content_types ) ) {
			$block->content_types = array( 'entry' );
		}

		$block->recent_posts = Posts::get( array(
			'limit' => $limit,
			'status' => 'published',
			'content_type' => $block->content_types,
			'orderby' => 'pubdate DESC',
		) );
	}

	/**
	 * Monthly Archives
	 *
	 * Allow configuration of the monthly archive options
	 *
	 * @param FormUI $form The configuration form for this block
	 * @param Block $block The block instance to be configured
	 */
	public function action_block_form_monthly_archives( $form, $block )
	{
		$content = $form->append( 'checkbox', 'full_names', $block, _t( 'Display full month names:' ) );
		$content = $form->append( 'checkbox', 'show_counts', $block, _t( 'Append post count:' ) );
		$content = $form->append( 'select', 'style', $block, _t( 'Preferred Output Style:' ),
			array('dropdown' => _t( 'Dropdown' ), 'list' => _t( 'List' ) ) );
	}

	/**
	 * Monthly Archives
	 *
	 * Handle monthly archive block output
	 *
	 * @param Block $block The block instance to be configured
	 * @param Theme $theme The active theme
	 */
	public function action_block_content_monthly_archives( $block, $theme )
	{
		$months = array();
		$results = Posts::get( array(
			'content_type' => 'entry',
			'status' => 'published',
			'month_cts' => 1 )
			);

		foreach ( $results as $result ) {
			if ( $block->full_names ) {
				$display_month = HabariDateTime::date_create()->set_date( $result->year, $result->month, 1 )->get( 'F' );
			}
			else {
				$display_month = HabariDateTime::date_create()->set_date( $result->year, $result->month, 1 )->get( 'M' );
			}

			$count = '';
			if ( $block->show_counts ) {
				$count = " (" . $result->ct . ")";
			}

			$result->month = str_pad( $result->month, 2, 0, STR_PAD_LEFT );
			$url = URL::get( 'display_entries_by_date', array( 'year' => $result->year, 'month' => $result->month ) );
			$months[] = array(
				'display_month' => $display_month,
				'count' => $count,
				'year' => $result->year,
				'url' => $url,
				);
		}
		$block->months = $months;
	}

	/**
	 * Monthly Archives
	 *
	 * @param Type $type The block template to be used
	 * @param Block $block The block instance to be configured
	 */
	function filter_block_content_type_monthly_archives( $types, $block )
	{
		array_unshift( $types, $newtype = "block.{$block->style}.{$block->type}" );
		if ( isset( $block->title ) ) {
			array_unshift( $types, "block.{$block->style}.{$block->type}." . Utils::slugify( $block->title ) );
		}
		return $types;
	}

	/**
	 * Tag Archives
	 *
	 * Allow configuration of the tag archive options
	 *
	 * @param FormUI $form The configuration form for this block
	 * @param Block $block The block instance to be configured
	 */
	public function action_block_form_tag_archives( $form, $block )
	{
		$content = $form->append( 'checkbox', 'show_counts', $block, _t( 'Append post count:' ) );
		$content = $form->append( 'select', 'style', $block, _t( 'Preferred Output Style:' ),
			array('dropdown' => _t( 'Dropdown' ), 'list' => _t( 'List' ) ) );
	}

	/**
	 * Tag Archives
	 *
	 * Handle tag archive block output
	 *
	 * @param Block $block The block instance to be configured
	 * @param Theme $theme The active theme
	 */
	public function action_block_content_tag_archives( $block, $theme )
	{
		$tags = array();
		$results = Tags::vocabulary()->get_tree();

		foreach( $results as $result ) {

			$count = '';
			if ( $block->show_counts ) {
				$count = " (" . Posts::count_by_tag( $result->term_display, "published") . ")";
			}

			$url = URL::get( 'display_entries_by_tag', array( 'tag' => $result->term ) );
			$tags[] = array(
				'tag' => $result->term_display,
				'count' => $count,
				'url' => $url,
				);
		}

		$block->tags = $tags;
	}

	/**
	 * Tag Archives
	 *
	 * @param Type $type The block template to be used
	 * @param Block $block The block instance to be configured
	 */
	function filter_block_content_type_tag_archives( $types, $block )
	{
		array_unshift( $types, $newtype = "block.{$block->style}.{$block->type}" );
		if ( isset( $block->title ) ) {
			array_unshift( $types, "block.{$block->style}.{$block->type}." . Utils::slugify( $block->title ) );
		}
		return $types;
	}

	/**
	 * Meta Links
	 *
	 * Allow configuration of the meta links options
	 *
	 * @param FormUI $form The configuration form for this block
	 * @param Block $block The block instance to be configured
	 */
	public function action_block_form_meta_links( $form, $block )
	{
		$content = $form->append('checkboxes', 'links', $block, _t( 'Links to show:' ), array_flip( $this->meta_urls() ) );
	}

	/**
	 * Meta Links
	 *
	 * Handle meta links block output
	 *
	 * @param Block $block The block instance to be configured
	 * @param Theme $theme The active theme
	 */
	public function action_block_content_meta_links( $block, $theme )
	{
		$list = array();
		if ( User::identify()->loggedin ) {
			$list[ Site::get_url( 'logout' ) ] = _t( 'Logout' );
		}
		else {
			$list[ Site::get_url( 'login' ) ] = _t( 'Login' );
		}
		$meta_urls = array_flip( $this->meta_urls() );
		$links = $block->links;
		if ( count( $links ) > 0 ) {
			foreach ( $links as $link ) {
				$list[ $link ] = $meta_urls[ $link ];
			}
		}
		$block->list = $list;
	}

	/**
	 * Search Form
	 *
	 * Allow configuration of the search form options
	 *
	 * @param FormUI $form The configuration form for this block
	 * @param Block $block The block instance to be configured
	 */
	public function action_block_form_search_form( $form, $block )
	{
		$content = $form->append( 'text', 'button', $block, _t( 'Button:' ) );
	}

	/**
	 * Search Form
	 *
	 * Handle search form block output
	 *
	 * @param Block $block The block instance to be configured
	 * @param Theme $theme The active theme
	 */
	public function action_block_content_search_form( $block, $theme )
	{
		$block->form = '<form method="get" id="searchform" action="' . URL::get( 'display_search' ) .
			'">
<input type="text" id="s" name="criteria" value="' . ( isset( $theme->criteria ) ? htmlentities( $theme->criteria, ENT_COMPAT, 'UTF-8' ) : '' ) .
			'"><input type="submit" id="searchsubmit" value="' . ( isset( $block->button ) ? $block->button : _t( 'Search' ) ) . '">
</form>';
	}

	/**
	 * Text
	 *
	 * Display unformatted text without any markup.
	 * If you require HTML output, try the Simple Block plugin instead.
	 *
	 * @param FormUI $form The configuration form for this block
	 * @param Block $block The block instance to be configured
	 * Configuration form with one big textarea. Raw to allow JS/HTML/etc. Insert them at your own peril.
	 */
	public function action_block_form_text( $form, $block )
	{
		$content = $form->append( 'textarea', 'content', $block, _t( 'Content:' ) );
		$content->rows = 5;
	}

	/**
	 * Text
	 *
	 * Display unformatted text without any markup.
	 * If you require HTML output, try the Simple Block plugin instead.
	 *
	 * @param Block $block The block instance to be configured
	 * @param Theme $theme The active theme
	 */
	public function action_block_content_text( $block, $theme )
	{
		return $block;
	}
}
?>


code:
<?xml version="1.0" encoding="utf-8" ?>
<pluggable type="plugin" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://schemas.habariproject.org/pluggable/0.8">
	<name>Core Blocks</name>
	<license url="http://www.apache.org/licenses/LICENSE-2.0.html">Apache Software License 2.0</license>

	<author url="http://habariproject.org/">The Habari Community</author>

	<version>1.0</version>
	<url>http://habariproject.org/</url>
	<description><![CDATA[A collection of blocks for your sidebar or other areas.]]></description>
	<copyright>2011</copyright>
	<help>
		<value><![CDATA[
After activating this plugin, these block types will be available for you to use and configure in the 'Areas' of the Theme admin page.

Recent Comments

Recent Posts

Monthly Archives

Tag Archives

Meta Links

Search Form

Text

Each one has a template file you can copy to your theme and customize.
]]></value>
	</help>
</pluggable>


code:
/*
 * Name: CoreDashModules Stylesheet
 * Author: Habari Community
 * License: Apache License 2.0
 */

/*-- DASHBOARD - LATEST COMMENTS MODULE */

.dashboard .latest-comments-module .item {

}

.dashboard .latest-comments-module .item > span {
	float: left;
}

.dashboard .latest-comments-module .titleanddate {
	margin-top: 5px;
	line-height: 16px;
	color: #999;
}

.dashboard .latest-comments-module ul {
	margin-bottom: 5px;
	line-height: 13px;
	white-space: nowrap;
	text-overflow: ellipsis;
	overflow: hidden;
}

.dashboard .latest-comments-module ul.commentauthors li {
	display: inline;
}

.dashboard .latest-comments-module ul li:after {
	content: ', ';
}

.dashboard .latest-comments-module ul li.last-child:after {
	content: '';
}

.dashboard .latest-comments-module .commentauthors a:hover {
	opacity: 1;
}

.dashboard .latest-comments-module .item span.comments {
	float: right;
}

.dashboard .latest-comments-module .comments {
	line-height: 34px;
	font-size: 24px;
}

/*-- DASHBOARD - POST TYPES AND STATUSES MODULE */
.dashboard .post-types-and-statuses-module .modulecore{
	overflow: auto;
}


code:
<?php if ( !defined( 'HABARI_PATH' ) ) { die( 'No direct access' ); }

/**
 * CoreDashModules - Provides a core set of dashboard modules for the dashboard.
 */

class CoreDashModules extends Plugin
{
	private $theme;

	/**
	 * Add some templates to the theme for the blocks
	 */
	public function action_init()
	{
		$this->add_template( 'dashboard.block.latest_entries', __DIR__ . '/dashboard.block.latest_entries.php' );
		$this->add_template( 'dashboard.block.latest_log_activity', __DIR__ . '/dashboard.block.latest_log_activity.php' );
		$this->add_template( 'dashboard.block.latest_comments', __DIR__ . '/dashboard.block.latest_comments.php' );
		$this->add_template( 'dashboard.block.post_types_statuses', __DIR__ . '/dashboard.block.post_types_statuses.php' );
	}

	/**
	 * Add the blocks this plugin provides to the list of available blocks
	 * @param array $block_list An array of block names, indexed by unique string identifiers
	 * @return array The altered array
	 */
	public function filter_block_list($block_list)
	{
		$block_list['latest_entries'] = _t( 'Latest Entries');
		if (User::identify()->can('manage_all_comments')) {
			$block_list['latest_comments'] = _t( 'Latest Comments');
		}
		if (User::identify()->can('manage_logs')) {
			$block_list['latest_log_activity'] = _t( 'Latest Log Activity');
		}
		$block_list['post_types_statuses'] = _t( 'Post Types and Statuses');
		return $block_list;
	}

	/**
	 * Return a list of blocks that can be used for the dashboard
	 * @param array $block_list An array of block names, indexed by unique string identifiers
	 * @return array The altered array
	 */
	public function filter_dashboard_block_list($block_list)
	{
		return $this->filter_block_list($block_list);
	}

	/**
	 * Produce the content for the latest entries block
	 * @param Block $block The block object
	 * @param Theme $theme The theme that the block will be output with
	 */
	public function action_block_content_latest_entries($block, $theme)
	{
		$block->recent_posts = Posts::get( array( 'status' => 'published', 'limit' => 8, 'type' => Post::type('entry') ) );
		$block->link = URL::get('admin', array('page'=>'posts', 'type'=>Post::type('entry')));
	}

	/**
	 * Produce the content for the latest log activity block
	 * @param Block $block The block object
	 * @param Theme $theme The theme that the block will be output with
	 */
	public function action_block_content_latest_log_activity($block, $theme)
	{
		$params = array(
			'where' => array(
				'user_id' => User::identify()->id
			),
			'orderby' => 'id DESC', /* Otherwise, exactly same timestamp values muck it up... Plus, this is more efficient to sort on the primary key... */
			'limit' => isset($block->logs_number_display) ? $block->logs_number_display : 8,
		);
		$block->logs = EventLog::get( $params );
		$block->link = URL::get('admin', array('page' => 'logs'));
		$block->has_options = true;
	}

	/**
	 * Produce a form for the editing of the log activity block
	 * @param FormUI $form The form to allow editing of this block
	 * @param Block $block The block object to edit
	 */
	public function action_block_form_latest_log_activity($form, $block)
	{
		$form->append( 'text', 'logs_number_display', $block, _t('Number of items') );
		$form->append( 'submit', 'submit', _t('Submit') );
	}

	/**
	 * Produce the content for the Latest Comments block
	 * @param Block $block The block object
	 * @param Theme $theme The theme that the block will be output with
	 */
	public function action_block_content_latest_comments($block, $theme)
	{
		$posts = DB::get_results( 'SELECT * FROM {posts} p WHERE p.id in ( SELECT post_id FROM {comments} WHERE status = ? AND type = ? ORDER BY date DESC, post_id ) LIMIT 5', array( Comment::STATUS_APPROVED, Comment::COMMENT ), 'Post' );
		$latestcomments = array();

		foreach( $posts as $post ) {
			$comments = DB::get_results( 'SELECT * FROM {comments} WHERE post_id = ? AND status = ? AND type = ? ORDER BY date DESC LIMIT 5;', array( $post->id, Comment::STATUS_APPROVED, Comment::COMMENT ), 'Comment' );
			$latestcomments[$post->id] = $comments;
		}

		$block->latestcomments_posts = $posts;
		$block->latestcomments = $latestcomments;
		$block->link = URL::get('admin', array('page' => 'comments'));
	}

	public function action_block_content_post_types_statuses($block, $theme)
	{
		$messages = array();
		$user = User::identify();

		$post_types = Post::list_active_post_types();
		array_shift( $post_types );
		$post_statuses = array_values( Post::list_post_statuses() );
		array_shift( $post_statuses );

		foreach( $post_types as $type => $type_id ) {
			$plural = Plugins::filter( 'post_type_display', $type, 'plural' );
			foreach( $post_statuses as $status => $status_id ) {
				$status_display = MultiByte::ucfirst( Plugins::filter( 'post_status_display', Post::status_name( $status_id ) ) );
				$site_count = Posts::get( array( 'content_type' => $type_id, 'count' => true, 'status' => $status_id ) );
				$user_count = Posts::get( array( 'content_type' => $type_id, 'count' => true, 'status' => $status_id, 'user_id' => $user->id ) );
				$message = array();

				// @locale First variable is the post status, second is the post type
				$message['label'] = _t( '%1$s %2$s', array( $status_display, $plural ) );

				if( ! $site_count ) {
					$message['site_count'] = '';
				}
				else if( $user->cannot( 'post_unpublished' ) && Post::status_name( $status_id ) != 'published' ) {
					$message['site_count'] = '';
				}
				else {
					$message['site_count'] = $site_count;
				}
				$perms = array(
					'post_any' => array( ACL::get_bitmask( 'delete' ), ACL::get_bitmask( 'edit' ) ),
					'own_posts' => array( ACL::get_bitmask( 'delete' ), ACL::get_bitmask( 'edit' ) ),
					'post_' . $type => array( ACL::get_bitmask( 'delete' ), ACL::get_bitmask( 'edit' ) ),
				);
				if ( $user->can_any( $perms ) && $message['site_count'] ) {
					$message['site_count'] = ' 'posts', 'type' => Post::type( $type ), 'status' => $status_id ) ) ) . '">' . Utils::htmlspecialchars( $message['site_count'] ) . '';
				}

				if( ! $user_count ) {
					$message['user_count'] = '';
				}
				else {
					$message['user_count'] = $user_count;
				}
				// @locale First variable is the post status, second is the post type
				$perms = array(
					'own_posts' => array( ACL::get_bitmask( 'delete' ), ACL::get_bitmask( 'edit' ) ),
					'post_' . $type => array( ACL::get_bitmask( 'delete' ), ACL::get_bitmask( 'edit' ) ),
				);
				if ( $user->can_any( $perms )  && $message['user_count'] ) {
					$message['user_count'] = ' 'posts', 'type' => Post::type( $type ), 'status' => $status_id, 'user_id' => $user->id ) ) ) . '">' . Utils::htmlspecialchars( $message['user_count'] ) . '';
				}

				if( $message['site_count'] || $message['user_count'] ) {
					$messages[] = $message;
				}
			}
		}

		$block->messages = $messages;
	}

	/**
	 * filter_dash_module_post_types
	 * Function used to set theme variables to the post types dashboard widget
	 * @param string $module_id
	 * @return string The contents of the module
	 */
	public function filter_dash_module_post_types_and_statuses( $module, $module_id, $theme )
	{
		$messages = array();
		$user = User::identify();

		$post_types = Post::list_active_post_types();
		array_shift( $post_types );
		$post_statuses = array_values( Post::list_post_statuses() );
		array_shift( $post_statuses );

		foreach( $post_types as $type => $type_id ) {
			$plural = Plugins::filter( 'post_type_display', $type, 'plural' );
			foreach( $post_statuses as $status => $status_id ) {
				$status_display = MultiByte::ucfirst( Plugins::filter( 'post_status_display', Post::status_name( $status_id ) ) );
				$site_count = Posts::get( array( 'content_type' => $type_id, 'count' => true, 'status' => $status_id ) );
				$user_count = Posts::get( array( 'content_type' => $type_id, 'count' => true, 'status' => $status_id, 'user_id' => $user->id ) );

				// @locale First variable is the post status, second is the post type
				$message['label'] = _t( '%1$s %2$s', array( $status_display, $plural ) );

				if( ! $site_count ) {
					$message['site_count'] = '';
				}
				else if( $user->cannot( 'post_unpublished' ) && Post::status_name( $status_id ) != 'published' ) {
					$message['site_count'] = '';
				}
				else {
					$message['site_count'] = $site_count;
				}
				$perms = array(
					'post_any' => array( ACL::get_bitmask( 'delete' ), ACL::get_bitmask( 'edit' ) ),
					'own_posts' => array( ACL::get_bitmask( 'delete' ), ACL::get_bitmask( 'edit' ) ),
					'post_' . $type => array( ACL::get_bitmask( 'delete' ), ACL::get_bitmask( 'edit' ) ),
				);
				if ( $user->can_any( $perms ) && $message['site_count'] ) {
					$message['site_count'] = ' 'posts', 'type' => Post::type( $type ), 'status' => $status_id ) ) ) . '">' . Utils::htmlspecialchars( $message['site_count'] ) . '';
				}

				if( ! $user_count ) {
					$message['user_count'] = '';
				}
				else {
					$message['user_count'] = $user_count;
				}
				// @locale First variable is the post status, second is the post type
				$perms = array(
					'own_posts' => array( ACL::get_bitmask( 'delete' ), ACL::get_bitmask( 'edit' ) ),
					'post_' . $type => array( ACL::get_bitmask( 'delete' ), ACL::get_bitmask( 'edit' ) ),
				);
				if ( $user->can_any( $perms )  && $message['user_count'] ) {
					$message['user_count'] = ' 'posts', 'type' => Post::type( $type ), 'status' => $status_id, 'user_id' => $user->id ) ) ) . '">' . Utils::htmlspecialchars( $message['user_count'] ) . '';
				}

				if( $message['site_count'] || $message['user_count'] ) {
					$messages[] = $message;
				}
			}
		}

		$theme->type_messages = $messages;

		$module['title'] = _t( 'Post Types and Statuses' );
		$module['content'] = $theme->fetch( 'dash_posttypes' );
		return $module;
	}

	/**
	* Adds the podcast stylesheet to the admin header,
	* Adds menu items to the Habari silo for mp3 files
	* for each feed so the mp3 can be added to multiple
	* feeds.
	*
	* @param Theme $theme The current theme being used.
	*/
	public function action_admin_header( $theme )
	{
		$vars = Controller::get_handler_vars();
		if( 'dashboard' == $theme->page ) {
			Stack::add( 'admin_stylesheet', array( $this->get_url() . '/coredashmodules.css', 'screen' ), 'coredashmodules', array( 'admin' ) );
		}
	}

}

?>


code:
<?xml version="1.0" encoding="utf-8" ?>
<pluggable type="plugin" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://schemas.habariproject.org/pluggable/0.8">
	<name>Core Dash Modules</name>
	<license url="http://www.apache.org/licenses/LICENSE-2.0.html">Apache Software License 2.0</license>

	<author url="http://habariproject.org/">The Habari Community</author>

	<version>1.1</version>
	<url>http://habariproject.org/</url>
	<description><![CDATA[Provides a core set of dashboard modules for the dashboard.]]></description>

	<copyright>2009</copyright>

	<help>
	<value><![CDATA[

Provides Latest Entries, Latest Log Activity, Latest Comments, and Post Types and Statuses blocks which can be arranged on your admin dashboard.

	]]></value>
	</help>
</pluggable>


code:
<?php if ( !defined( 'HABARI_PATH' ) ) { die( 'No direct access' ); } ?>

		<?php foreach ( $content->latestcomments_posts as $post ): ?>

			<a href="<?php echo $post->permalink; ?>#comments" title="<?php printf(_n('%1$d comment', '%1$d comments', $post->comments->approved->comments->count), $post->comments->approved->comments->count); ?>"><?php echo $post->comments->approved->comments->count; ?>
			<a href="<?php echo $post->permalink; ?>" class="title"><?php echo $post->title; ?> <?php $post->pubdate->out( 'M j' ); ?>

				<?php
				$comment_count = 0;
				foreach( $content->latestcomments[$post->id] as $comment):
					$comment_count++;
					$opa = 'opa' . (100 - $comment_count * 15);
				?>
				<?php /* @locale Time formats according to http://php.net/manual/en/function.date.php */ $ctime = $comment->date->get( _t( 'g:ia' ) ); ?>
				<?php /* @locale Date formats according to http://php.net/manual/en/function.date.php */ $cdate = $comment->date->get( _t( 'F jS, Y' ) ); ?>

<a href="<?php echo $comment->post->permalink; ?>#comment-<?php echo $comment->id; ?>" title="<?php printf( _t( 'Posted at %1$s on %2$s' ), $ctime, $cdate ); ?>" class="<?php echo $opa; ?>"><?php echo $comment->name; ?>

				<?php endforeach; ?>

		<?php endforeach; ?>


code:
<?php if ( !defined( 'HABARI_PATH' ) ) { die( 'No direct access' ); } ?>

		<?php foreach((array)$content->recent_posts as $post): ?>

			<?php /* @locale Time formats according to http://php.net/manual/en/function.date.php */ $ptime = $post->pubdate->get( _t( 'g:i' ) ); ?>
			<?php /* @locale Date formats according to http://php.net/manual/en/function.date.php */ $pdate = $post->pubdate->get( _t( 'F jS, Y' ) ); ?>
			<a href="<?php echo URL::get('display_entries_by_date', array('year' => $post->pubdate->get( 'Y' ), 'month' => $post->pubdate->get( 'm' ), 'day' => $post->pubdate->get( 'd' ) ) ); ?>" title="<?php printf(_t('Posted at %1$s on %2$s'), $ptime, $pdate ); ?>"><?php /* @locale Date formats according to http://php.net/manual/en/function.date.php */ $post->pubdate->out(  _t( 'M j' ) ); ?>
			<a href="<?php URL::out('admin', 'page=publish&id=' . $post->id); ?>" title="<?php printf( _t('Edit \'%s\''), $post->title ); ?>"><?php echo $post->title; ?> <?php _e('by'); ?> <a class="minor" href="<?php Site::out_url('admin'); ?>/user/<?php echo $post->author->username; ?>"><?php echo $post->author->displayname; ?>
			<a href="<?php echo $post->permalink; ?>#comments"><?php echo $post->comments->approved->count; ?>

		<?php endforeach; ?>


code:
<?php if ( !defined( 'HABARI_PATH' ) ) { die( 'No direct access' ); } ?>

		<?php foreach( $content->logs as $log ) { ?>

				<?php /* @locale Date formats according to http://php.net/manual/en/function.date.php */ $log->timestamp->out( _t( 'M j' ) ); ?>
				<?php echo Utils::htmlspecialchars( $log->message ); ?>

		<?php } ?>


code:
<?php if ( !defined( 'HABARI_PATH' ) ) { die( 'No direct access' ); } ?>

			<?php _e( 'Category' ); ?>
			<?php _e( 'Yours' ); ?>
			<?php _e( 'Site' ) ?>

		<?php foreach( $content->messages as $message ) : ?>

			<?php echo $message['label']; ?>
			<?php echo $message['user_count'] ?>
			<?php echo $message['site_count']; ?>

		<?php endforeach; ?>


code:
<?php if ( !defined( 'HABARI_PATH' ) ) { die( 'No direct access' ); }
class flickrAPI
{
	function __construct()
	{
		$this->key = 'cd0ae46b1332aa2bd52ba3063f0db41c';
		$this->secret = '76cf747f70be9029';
		$this->endpoint = 'http://www.flickr.com/services/rest/?';
		$this->authendpoint = 'http://www.flickr.com/services/auth/?';
		$this->uploadendpoint = 'http://api.flickr.com/services/upload/?';
		$this->conntimeout = 20;
	}

	public function sign( $args )
	{
		ksort( $args );
		unset( $args['photo'] );
		$a = '';
		foreach( $args as $key => $value ){
			$a .= $key . $value;
		}
		return md5( $this->secret . $a );
	}

	public function encode( $args )
	{
		$encoded = array();
		foreach ( $args as $key => $value ){
			$encoded[] = urlencode( $key ) . '=' . urlencode( $value );
		}
		return $encoded;
	}

	function call( $method, $args = array () )
	{
		$args = array_merge( array ( 'method' => $method,
				'api_key' => $this->key ), $args );

		ksort( $args );

		$args = array_merge( $args, array ( 'api_sig' => $this->sign( $args ) ) );
		ksort( $args );

		if ( $method == 'upload' ){
			$req = curl_init();
			$args['api_key'] = $this->key;
			$photo = $args['photo'];
			$args['photo'] = '@' . $photo;
			curl_setopt( $req, CURLOPT_URL, $this->uploadendpoint );
			curl_setopt( $req, CURLOPT_TIMEOUT, 0 );
			// curl_setopt($req, CURLOPT_INFILESIZE, filesize($photo));
			// Sign and build request parameters
			curl_setopt( $req, CURLOPT_POSTFIELDS, $args );
			curl_setopt( $req, CURLOPT_CONNECTTIMEOUT, $this->conntimeout );
			curl_setopt( $req, CURLOPT_FOLLOWLOCATION, 1 );
			curl_setopt( $req, CURLOPT_HEADER, 0 );
			curl_setopt( $req, CURLOPT_RETURNTRANSFER, 1 );
			$this->_http_body = curl_exec( $req );

			if ( curl_errno( $req ) ){
				throw new Exception( curl_error( $req ) );
			}

			curl_close( $req );
			$xml = simplexml_load_string( $this->_http_body );
			$this->xml = $xml;
			return $xml;
		}
		else{
			$url = $this->endpoint . implode( '&', $this->encode( $args ) );

			$call = new RemoteRequest( $url );
			$call->set_timeout( 5 );

			try {
				$result = $call->execute();
			}
			catch ( RemoteRequest_Timeout $t ) {
				Session::error( 'Currently unable to connect to Flickr.', 'flickr API' );
				return false;
			}
			catch ( Exception $e ) {
				// at the moment we're using the same error message, though this is more catastrophic
				Session::error( 'Currently unable to connect to Flickr.', 'flickr API' );
				return false;
			}

			$response = $call->get_response_body();
			try{
				$xml = new SimpleXMLElement( $response );
				return $xml;
			}
			catch( Exception $e ) {
				Session::error( 'Unable to process Flickr response.', 'flickr API' );
				return false;
			}
		}
	}
}

class Flickr extends flickrAPI
{
	function __construct( $params = array() )
	{
		parent::__construct( $params );
	}
	// URL building
	function getPhotoURL( $p, $size = 'm', $ext = 'jpg' )
	{
		return "http://static.flickr.com/{$p['server']}/{$p['id']}_{$p['secret']}_{$size}.{$ext}";
	}
	// authentication and approval
	public function getFrob()
	{
		$xml = $this->call( 'flickr.auth.getFrob', array() );
		return $xml->frob;
	}

	public function authLink( $frob )
	{
		$params['api_key'] = $this->key;
		$params['frob'] = $frob;
		$params['perms'] = 'write';
		$params['api_sig'] = md5( $this->secret . 'api_key' . $params['api_key'] . 'frob' . $params['frob'] . 'permswrite' );
		$link = $this->authendpoint . implode( '&', $this->encode( $params ) );
		return $link;
	}

	function getToken( $frob )
	{
		$xml = $this->call( 'flickr.auth.getToken', array( 'frob' => $frob ) );
		return $xml;
	}
	// grab the token from our db.
	function cachedToken()
	{
		$token = Options::get( 'flickr_token_' . User::identify()->id );
		return $token;
	}
	// get publicly available photos
	function getPublicPhotos( $nsid, $extras = '', $per_page = '', $page = '' )
	{
		$params = array( 'user_id' => $nsid );
		if ( $extras ){
			$params['extras'] = $extras;
		}
		if ( $per_page ){
			$params['per_page'] = $per_page;
		}
		if ( $page ){
			$params['page'] = $page;
		}

		$xml = $this->call( 'flickr.people.getPublicPhotos' , $params );
		foreach( $xml->photos->attributes() as $key => $value ){
			$pic[$key] = (string)$value;
		}
		$i = 0;
		foreach( $xml->photos->photo as $photo ){
			foreach( $photo->attributes() as $key => $value ){
				$pic['photos'][(string)$photo['id']][$key] = (string)$value;
			}
			$i++;
		}
		return $pic;
	}
	// Photosets methods
	function photosetsGetList( $nsid = '' )
	{
		$params = array();

		if ( $nsid ){
			$params['user_id'] = $nsid;
		}

		$xml = $this->call( 'flickr.photosets.getList', $params );
		if ( Error::is_error( $xml ) ){
			throw $xml;
		}
		return $xml;
	}

	function photosetsGetInfo( $photoset_id )
	{
		$params = array( 'photoset_id' => $photoset_id );
		$xml = $this->call( 'flickr.photosets.getInfo', $params );
		if ( Error::is_error( $xml ) ){
			throw $xml;
		}
		return $xml;
	}

	function photosetGetPrimary( $p, $size = 'm', $ext = '.jpg' )
	{
		return 'http://static.flickr.com/' . $p['server'] . '/' . $p['primary'] . '_' . $p['secret'] . '_' . $size . $ext;
	}

	function photosetsGetPhotos( $photoset_id )
	{
		$params = array( 'photoset_id' => $photoset_id );
		$xml = $this->call( 'flickr.photosets.getPhotos', $params );
		if ( Error::is_error( $xml ) ){
			throw $xml;
		}
		return $xml;
	}

	function photosRecentlyUpdated()
	{
		$params = array();
		if ( $this->cachedToken() ){
			$params['auth_token'] = $this->cachedToken();
		}

		$params['secret'] = $this->secret;
		$params['min_date'] = time() - 31536000;  // Within the last year
		$params['per_page'] = 10;

		$xml = $this->call( 'flickr.photos.recentlyUpdated', $params );

		if ( Error::is_error( $xml ) ){
			throw $xml;
		}
		return $xml;
	}

	function mediaSearch( $params = array()  )
	{
		if ( $this->cachedToken() ){
			$params['auth_token'] = $this->cachedToken();
		}

		$params['secret'] = $this->secret;
		$params['user_id'] = 'me';
		$params['sort'] = 'date-posted-desc';
		$params['per_page'] = 20;

		$xml = $this->call( 'flickr.photos.search', $params );

		if ( Error::is_error( $xml ) ){
			throw $xml;
		}
		return $xml;
	}

	function photosSearch( $params = array()  )
	{
		if ( $this->cachedToken() ){
			$params['auth_token'] = $this->cachedToken();
		}

		$defaults = array(
			'secret' => $this->secret,
			'user_id' => 'me',
			'sort' => 'date-posted-desc',
			'per_page' => 20,
			'media' => 'photos',
			'extras' => 'original_format',
		);

		$params = array_merge( $defaults, $params );

		$xml = $this->call( 'flickr.photos.search', $params );

		if ( Error::is_error( $xml ) ){
			throw $xml;
		}
		return $xml;
	}

	function videoSearch( $params = array()  )
	{
		if ( $this->cachedToken() ){
			$params['auth_token'] = $this->cachedToken();
		}

		$params['secret'] = $this->secret;
		$params['user_id'] = 'me';
		$params['sort'] = 'date-posted-desc';
		$params['per_page'] = 20;
		$params['media'] = 'videos';

		$xml = $this->call( 'flickr.photos.search', $params );

		if ( Error::is_error( $xml ) ){
			throw $xml;
		}
		return $xml;
	}

	function tagsGetListUser( $userid = null )
	{
		$params = array();
		if ( isset( $userid ) ) {
			$params['user_id'] = $userid;
		}
		$xml = $this->call( 'flickr.tags.getListUser', $params );
		return $xml;
	}

	function photosGetInfo( $photo_id )
	{
		$params = array();
		if ( $this->cachedToken() ){
			$params['auth_token'] = $this->cachedToken();
		}

		$params['photo_id'] = $photo_id;
		$params['secret'] = $this->secret;

		$xml = $this->call( 'flickr.photos.getInfo', $params );

		if ( Error::is_error( $xml ) ){
			throw $xml;
		}

		return $xml;
	}

	function upload( $photo, $title = '', $description = '', $tags = '', $perms = '', $async = 1, &$info = null )
	{
		$store = HABARI_PATH . '/' . Site::get_path( 'user' ) . '/cache';
		if ( !is_dir( $store ) ){
			mkdir( $store, 0777 );
		}
		$params = array( 'auth_token' => $this->cachedToken() );
		$url = InputFilter::parse_url( 'file://' . $photo );
		if ( isset( $url['scheme'] ) ){
			$localphoto = fopen( HABARI_PATH . '/' . $photo, 'r' );
			$store = tempnam( $store, 'G2F' );
			file_put_contents( $store, $localphoto );
			fclose( $localphoto );
			$params['photo'] = $store;
		}
		else{
			$params['photo'] = $photo;
		}

		$info = filesize( $params['photo'] );

		if ( $title ){
			$params['title'] = $title;
		}

		if ( $description ){
			$params['description'] = $description;
		}

		if ( $tags ){
			$params['tags'] = $tags;
		}

		if ( $perms ){
			if ( isset( $perms['is_public'] ) ){
				$params['is_public'] = $perms['is_public'];
			}
			if ( isset( $perms['is_friend'] ) ){
				$params['is_friend'] = $perms['is_friend'];
			}
			if ( isset( $perms['is_family'] ) ){
				$params['is_family'] = $perms['is_family'];
			}
		}

		if ( $async ){
			$params['async'] = $async;
		}
		// call the upload method.
		$xml = $this->call( 'upload', $params );

		if ( $store ){
			unlink( $store );
		}

		if ( Error::is_error( $xml ) ){
			throw $xml;
		}

		if ( $async ){
			return( (string)$xml->ticketid );
		}
		else{
			return( (string)$xml->photoid );
		}
	}

	function photosUploadCheckTickets( $tickets )
	{
		if ( is_array( $tickets ) ){
			foreach( $tickets as $key => $value ){
				if ( $key ){
					$params['tickets'] .= ' ';
				}
				$params['tickets'] .= $value;
			}
		}
		else{
			$params['tickets'] = $tickets;
		}

		$xml = $this->call( 'flickr.photos.upload.checkTickets', $params );
		if ( Error::is_error( $xml ) ){
			throw $xml;
		}

		foreach( $xml->uploader->ticket as $ticket ){
			foreach( $ticket->attributes() as $key => $value ){
				$uptick[(string)$ticket['id']][$key] = (string)$value;
			}
		}
		return $uptick;
	}

	function reflectionGetMethods()
	{
		$params = array();
		$xml = $this->call( 'flickr.reflection.getMethods', $params );
		if ( !$xml ){
			return false;
		}
		$ret = (array)$xml->methods->method;
		return $ret;
	}
}

/**
* Flickr Silo
*/

class FlickrSilo extends Plugin implements MediaSilo
{
	const SILO_NAME = 'Flickr';

	static $cache = array();

	/**
	* Initialize some internal values when plugin initializes
	*/
	public function action_init()
	{
	}

	/**
	* Return basic information about this silo
	*     name- The name of the silo, used as the root directory for media in this silo
	*	  icon- An icon to represent the silo
	*/
	public function silo_info()
	{
		if ( $this->is_auth() ) {
			return array( 'name' => self::SILO_NAME, 'icon' => URL::get_from_filesystem(__FILE__) . '/icon.png' );
		}
		else {
			return array();
		}
	}

	/**
	* Return directory contents for the silo path
	*
	* @param string $path The path to retrieve the contents of
	* @return array An array of MediaAssets describing the contents of the directory
	*/
	public function silo_dir( $path )
	{
		$flickr = new Flickr();
		$results = array();
		$size = Options::get( 'flickrsilo__flickr_size' );

		$section = strtok( $path, '/' );
		switch ( $section ) {
			case 'attrib-sa':
				$xml = $flickr->photosSearch( array( 'user_id' => '', 'license' => '4,5', 'text'=>$_SESSION['flickrsearch'] ) );
				foreach( $xml->photos->photo as $photo ) {

					$props = array();
					foreach( $photo->attributes() as $name => $value ) {
						$props[$name] = (string)$value;
					}
					$props = array_merge( $props, self::element_props( $photo, "http://www.flickr.com/photos/{$photo['owner']}/{$photo['id']}", $size ) );
					$results[] = new MediaAsset(
						self::SILO_NAME . '/photos/' . $photo['id'],
						false,
						$props
					);
				}
				break;

			case 'search':
				$xml = $flickr->photosSearch( array( 'text'=>$_SESSION['flickrsearch'] ) );
				foreach( $xml->photos->photo as $photo ) {

					$props = array();
					foreach( $photo->attributes() as $name => $value ) {
						$props[$name] = (string)$value;
					}
					$props = array_merge( $props, self::element_props( $photo, "http://www.flickr.com/photos/{$_SESSION['nsid']}/{$photo['id']}", $size ) );
					$results[] = new MediaAsset(
						self::SILO_NAME . '/photos/' . $photo['id'],
						false,
						$props
					);
				}
				break;

			case 'photos':
				$xml = $flickr->photosSearch();
				foreach( $xml->photos->photo as $photo ) {

					$props = array();
					foreach( $photo->attributes() as $name => $value ) {
						$props[$name] = (string)$value;
					}
					$props = array_merge( $props, self::element_props( $photo, "http://www.flickr.com/photos/{$_SESSION['nsid']}/{$photo['id']}", $size ) );
					$results[] = new MediaAsset(
						self::SILO_NAME . '/photos/' . $photo['id'],
						false,
						$props
					);
				}
				break;
			case 'videos':
				$xml = $flickr->videoSearch();
				foreach( $xml->photos->photo as $photo ) {

					$props = array();
					foreach( $photo->attributes() as $name => $value ) {
						$props[$name] = (string)$value;
					}
					$props = array_merge( $props, self::element_props( $photo, "http://www.flickr.com/photos/{$_SESSION['nsid']}/{$photo['id']}", $size ) );
					$props['filetype'] = 'flickrvideo';
					$results[] = new MediaAsset(
						self::SILO_NAME . '/photos/' . $photo['id'],
						false,
						$props
					);
				}
				break;
			case 'tags':
				$selected_tag = strtok('/');
				if ( $selected_tag ) {
					$xml = $flickr->photosSearch( array( 'tags'=>$selected_tag ) );
					foreach( $xml->photos->photo as $photo ) {

						$props = array();
						foreach( $photo->attributes() as $name => $value ) {
							$props[$name] = (string)$value;
						}
						$props = array_merge( $props, self::element_props( $photo, "http://www.flickr.com/photos/{$_SESSION['nsid']}/{$photo['id']}", $size ) );
						$results[] = new MediaAsset(
							self::SILO_NAME . '/photos/' . $photo['id'],
							false,
							$props
						);
					}
				}
				else {
					$xml = $flickr->tagsGetListUser( $_SESSION['nsid'] );
					foreach( $xml->who->tags->tag as $tag ) {
						$results[] = new MediaAsset(
							self::SILO_NAME . '/tags/' . (string)$tag,
							true,
							array( 'title' => (string)$tag )
						);
					}
				}
				break;
			case 'sets':
				$selected_set = strtok('/');
				if ( $selected_set ) {
					$xml = $flickr->photosetsGetPhotos( $selected_set );
					foreach( $xml->photoset->photo as $photo ) {

						$props = array();
						foreach( $photo->attributes() as $name => $value ) {
							$props[$name] = (string)$value;
						}
						$props = array_merge( $props, self::element_props( $photo, "http://www.flickr.com/photos/{$_SESSION['nsid']}/{$photo['id']}", $size ) );
						$results[] = new MediaAsset(
							self::SILO_NAME . '/photos/' . $photo['id'],
							false,
							$props
						);
					}
				}
				else {
					$xml = $flickr->photosetsGetList( $_SESSION['nsid'] );
					foreach( $xml->photosets->photoset as $set ) {
						$results[] = new MediaAsset(
							self::SILO_NAME . '/sets/' . (string)$set['id'],
							true,
							array( 'title' => (string)$set->title )
						);
					}
				}
				break;

			case '$search':
				$path = strtok( '/' );
				$dosearch = Utils::slugify( $path );
				$_SESSION['flickrsearch'] = $path;
				$section = $path;

			case '':
				if ( isset( $_SESSION['flickrsearch'] ) ) {
					$results[] = new MediaAsset(
						self::SILO_NAME . '/search',
						true,
						array( 'title' => _t( 'Search' ) )
					);
					$results[] = new MediaAsset(
						self::SILO_NAME . '/attrib-sa',
						true,
						array( 'title' => _t( 'Search CC' ) )
					);
				}
				$results[] = new MediaAsset(
					self::SILO_NAME . '/photos',
					true,
					array('title' => _t( 'Photos' ) )
				);
				$results[] = new MediaAsset(
					self::SILO_NAME . '/videos',
					true,
					array('title' => _t( 'Videos' ) )
				);
				$results[] = new MediaAsset(
					self::SILO_NAME . '/tags',
					true,
					array('title' => _t( 'Tags' ) )
				);
				$results[] = new MediaAsset(
					self::SILO_NAME . '/sets',
					true,
					array('title' => _t( 'Sets' ) )
				);
				break;
		}
		return $results;
	}

	/**
	 * Function that populates the element properties for use in the silo.
	 *
	 * This is to reduce the amount of duplicate code.
	 *
	 * @param array $photo The photo element array
	 * @param string $url The Flickr URL to link to
	 * @param string $size The size of the image to display.
	 * @return array
	 */
	private static function element_props( $photo, $url, $size )
	{
		$props = array();
		$props['url'] = "http://farm{$photo['farm']}.static.flickr.com/{$photo['server']}/{$photo['id']}_{$photo['secret']}{$size}.jpg";
		$props['thumbnail_url'] = "http://farm{$photo['farm']}.static.flickr.com/{$photo['server']}/{$photo['id']}_{$photo['secret']}_m.jpg";
		$props['flickr_url'] = $url;
		$props['filetype'] = 'flickr';
		return $props;
	}

	/**
	* Get the file from the specified path
	*
	* @param string $path The path of the file to retrieve
	* @param array $qualities Qualities that specify the version of the file to retrieve.
	* @return MediaAsset The requested asset
	*/
	public function silo_get( $path, $qualities = null )
	{
		$flickr = new Flickr();
		$results = array();
		$size = Options::get( 'flickrsilo__flickr_size' );
		list($unused, $photoid) = explode( '/', $path );

		$xml = $flickr->photosGetInfo($photoid);
		$photo = $xml->photo;

		$props = array();
		foreach( $photo->attributes() as $name => $value ) {
			$props[$name] = (string)$value;
		}
		$props = array_merge( $props, self::element_props( $photo, "http://www.flickr.com/photos/{$_SESSION['nsid']}/{$photo['id']}", $size ) );
		$result = new MediaAsset(
			self::SILO_NAME . '/photos/' . $photo['id'],
			false,
			$props
		);

		return $result;
	}

	/**
	* Get the direct URL of the file of the specified path
	*
	* @param string $path The path of the file to retrieve
	* @param array $qualities Qualities that specify the version of the file to retrieve.
	* @return string The requested url
	*/
	public function silo_url( $path, $qualities = null )
	{
		$photo = false;
		if ( preg_match( '%^photos/(.+)$%', $path, $matches ) ) {
			$id = $matches[1];
			$photo = self::$cache[$id];
		}

		$size = '';
		if ( isset( $qualities['size'] ) && $qualities['size'] == 'thumbnail' ) {
			$size = '_m';
		}
		$url = "http://farm{$photo['farm']}.static.flickr.com/{$photo['server']}/{$photo['id']}_{$photo['secret']}{$size}.jpg";
		return $url;
	}

	/**
	* Create a new asset instance for the specified path
	*
	* @param string $path The path of the new file to create
	* @return MediaAsset The requested asset
	*/
	public function silo_new( $path )
	{
	}

	/**
	* Store the specified media at the specified path
	*
	* @param string $path The path of the file to retrieve
	* @param MediaAsset $ The asset to store
	*/
	public function silo_put( $path, $filedata )
	{
	}

	/**
	* Delete the file at the specified path
	*
	* @param string $path The path of the file to retrieve
	*/
	public function silo_delete( $path )
	{
	}

	/**
	* Retrieve a set of highlights from this silo
	* This would include things like recently uploaded assets, or top downloads
	*
	* @return array An array of MediaAssets to highlihgt from this silo
	*/
	public function silo_highlights()
	{
	}

	/**
	* Retrieve the permissions for the current user to access the specified path
	*
	* @param string $path The path to retrieve permissions for
	* @return array An array of permissions constants (MediaSilo::PERM_READ, MediaSilo::PERM_WRITE)
	*/
	public function silo_permissions( $path )
	{
	}

	/**
	* Return directory contents for the silo path
	*
	* @param string $path The path to retrieve the contents of
	* @return array An array of MediaAssets describing the contents of the directory
	*/
	public function silo_contents()
	{
		$flickr = new Flickr();
		$token = Options::get( 'flickr_token_' . User::identify()->id );
		$result = $flickr->call( 'flickr.auth.checkToken',
			array( 'api_key' => $flickr->key,
				'auth_token' => $token ) );
		$photos = $flickr->GetPublicPhotos( $result->auth->user['nsid'], null, 5 );
		foreach( $photos['photos'] as $photo ){
			$url = $flickr->getPhotoURL( $photo );
			echo '<img src="' . $url . '" width="150px" alt="' . ( isset( $photo['title'] ) ? $photo['title'] : _t('This photo has no title') ) . '">';
		}
	}

	/**
	* Add actions to the plugin page for this plugin
	* The authorization should probably be done per-user.
	*
	* @param array $actions An array of actions that apply to this plugin
	* @param string $plugin_id The string id of a plugin, generated by the system
	* @return array The array of actions to attach to the specified $plugin_id
	*/
	public function filter_plugin_config( $actions, $plugin_id )
	{
		$flickr_ok = $this->is_auth();

		if ( $flickr_ok ){
			$actions['deauthorize'] = _t( 'De-Authorize' );
		}
		else{
			$actions['authorize'] = _t( 'Authorize' );
		}
		$actions['configure'] = _t( 'Configure' );

		return $actions;
	}

	/**
	 * Respond to the user selecting the authorize action on the plugin page
	 *
	 */
	public function action_plugin_ui_authorize()
	{
		if ( $this->is_auth() ){
			$deauth_url = URL::get( 'admin', array( 'page' => 'plugins', 'configure' => $this->plugin_id(), 'configaction' => 'deauthorize' ) ) . '#plugin_options';
			echo '<p>' . _t( 'You have already successfully authorized Habari to access your Flickr account.') . '</p>';
			echo '<p>' . _t( 'Do you want to ') . '<a href="">' . _t( 'revoke authorization' ) . '</a>?</p>';
		}
		else{
			$flickr = new Flickr();
			$_SESSION['flickr_frob'] = '' . $flickr->getFrob();
			$auth_url = $flickr->authLink( $_SESSION['flickr_frob'] );
			$confirm_url = URL::get( 'admin', array( 'page' => 'plugins', 'configure' => $this->plugin_id(), 'configaction' => 'confirm' ) ) . '#plugin_options';
			echo '<p>' . _t( 'To use this plugin, you must ') . "<a href=\"{$auth_url}\" target=\"_blank\">" . _t( 'authorize Habari to have access to your Flickr account' ) . '</a>.';
			echo '<p>' . _t( 'When you have completed the authorization on Flickr, return here and ') . "<a href=\"$confirm_url\">" . _t( 'confirm that the authorization was successful') . '</a>.';
		}
	}

	/**
	 * Respond to the user selecting the confirm action
	 *
	 */
	public function action_plugin_ui_confirm()
	{

		$flickr = new Flickr();
		if ( !isset( $_SESSION['flickr_frob'] ) ){
			$auth_url = URL::get( 'admin', array( 'page' => 'plugins', 'configure' => $this->plugin_id(), 'configaction' => 'authorize' ) ) . '#plugin_options';
			echo '<p>' . _t( 'Either you have already authorized Habari to access your flickr account, or you have not yet done so.  Please ' ). '<a href="' . $auth_url . '">' . _t( 'try again' ) . '</a></p>';
		}
		else{
			$token = $flickr->getToken( $_SESSION['flickr_frob'] );
			if ( isset( $token->auth->perms ) ){
				Options::set( 'flickr_token_' . User::identify()->id, '' . $token->auth->token );
				echo '<p>' . _t( 'Your authorization was set successfully.' ) . '</p>';
			}
			else{
				echo '<p>' . _t( 'There was a problem with your authorization:' ) . '</p>';
				echo Utils::htmlspecialchars( $token->asXML() );
			}
			unset( $_SESSION['flickr_frob'] );
		}
	}

	/**
	 * Respond to the user selecting the deauthorize action
	 *
	 */
	public function action_plugin_ui_deauthorize()
	{
		Options::set( 'flickr_token_' . User::identify()->id );
		$reauth_url = URL::get( 'admin', array( 'page' => 'plugins', 'configure' => $this->plugin_id(), 'configaction' => 'authorize' ) ) . '#plugin_options';
		echo '<p>' . _t( 'The Flickr Silo Plugin authorization has been deleted.' ) . '<p>';
		echo '<p>' . _t( 'Do you want to ' ) . "<a href=\"{$reauth_url}\">" . _t( 're-authorize this plugin' ) . "</a>?<p>";
	}

	/**
	 * Respond to the user selecting the configure action
	 *
	 */
	public function action_plugin_ui_configure()
	{
		$ui = new FormUI( strtolower( get_class( $this ) ) );
		$ui->append( 'select', 'flickr_size','option:flickrsilo__flickr_size', _t( 'Default size for images in Posts:' ) );
		$ui->flickr_size->options = array( '_s' => _t( 'Square' ) . ' (75x75)', '_t' => _t( 'Thumbnail' ) . ' (100px)', '_m' => _t( 'Small' ) . ' (240px)', '' => _t( 'Medium' ) . ' (500px)', '_b' => _t( 'Large') . ' (1024px)', '_o' => _t( 'Original Size' ) );
		$ui->append('submit', 'save', _t( 'Save' ) );
		$ui->set_option('success_message', _t( 'Options saved' ) );
		$ui->out();
	}

	public function action_admin_footer( $theme )
	{
		if ( Controller::get_var( 'page' ) == 'publish' ) {
			$size = Options::get( 'flickrsilo__flickr_size' );
			switch ( $size ) {
				case '_s':
					$vsizex = 75;
					break;
				case '_t':
					$vsizex = 100;
					break;
				case '_m':
					$vsizex = 240;
					break;
				case '':
					$vsizex = 500;
					break;
				case '_b':
					$vsizex = 1024;
					break;
				case '_o':
					$vsizex = 400;
					break;
			}
			$vsizey = intval( $vsizex/4*3 );

			// Translation strings for used in embedding Javascript.  This is quite messy, but it leads to cleaner code than doing it inline.
			$embed_photo = _t( 'embed_photo' );
			$embed_video = _t( 'embed_video' );
			$thumbnail = _t( 'thumbnail' );
			$title = _t( 'Open in new window' );

			echo <<< FLICKR
			<script type="text/javascript">
				habari.media.output.flickr = {
					{$embed_photo}: function(fileindex, fileobj) {
						habari.editor.insertSelection('<a href="' + fileobj.flickr_url + '"><img alt="' + fileobj.title + '" src="' + fileobj.url + '"></a>');
					}
				}
				habari.media.output.flickrvideo = {
					{$embed_video}: function(fileindex, fileobj) {
						habari.editor.insertSelection('<object type="application/x-shockwave-flash" width="{$vsizex}" height="{$vsizey}" data="http://www.flickr.com/apps/video/stewart.swf?v=49235" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"> <param name="flashvars" value="intl_lang=en-us&photo_secret=' + fileobj.secret + '&photo_id=' + fileobj.id + '&show_info_box=true"></param> <param name="movie" value="http://www.flickr.com/apps/video/stewart.swf?v=49235"></param> <param name="bgcolor" value="#000000"></param> <param name="allowFullScreen" value="true"></param><embed type="application/x-shockwave-flash" src="http://www.flickr.com/apps/video/stewart.swf?v=49235" bgcolor="#000000" allowfullscreen="true" flashvars="intl_lang=en-us&photo_secret=' + fileobj.secret + '&photo_id=' + fileobj.id + '&flickr_show_info_box=true" height="{$vsizey}" width="{$vsizex}"></embed></object>');
					},
					{$thumbnail}: function(fileindex, fileobj) {
						habari.editor.insertSelection('<a href="' + fileobj.flickr_url + '"><img alt="' + fileobj.title + '" src="' + fileobj.url + '"></a>');
					}
				}
				habari.media.preview.flickr = function(fileindex, fileobj) {
					var stats = '';
					return '<div class="mediatitle"><a href="' + fileobj.flickr_url + '" class="medialink" onclick="$(this).attr(\'target\',\'_blank\');" title="{$title}">media</a>' + fileobj.title + '</div><div class="mediathumb"><img src="' + fileobj.thumbnail_url + '"></div><div class="mediastats"> ' + stats + '</div>';
				}
				habari.media.preview.flickrvideo = function(fileindex, fileobj) {
					var stats = '';
					return '<div class="mediatitle"><a href="' + fileobj.flickr_url + '" class="medialink" onclick="$(this).attr(\'target\',\'_blank\');"title="{$title}" >media</a>' + fileobj.title + '</div><div class="mediathumb"><img src="' + fileobj.thumbnail_url + '"></div><div class="mediastats"> ' + stats + '</div>';
				}
			</script>
FLICKR;
		}
	}

	private function is_auth()
	{
		static $flickr_ok = null;
		if ( isset( $flickr_ok ) ){
			return $flickr_ok;
		}

		$flickr_ok = false;
		$token = Options::get( 'flickr_token_' . User::identify()->id );
		if ( $token != '' ){
			$flickr = new Flickr();
			$result = $flickr->call( 'flickr.auth.checkToken', array( 'api_key' => $flickr->key, 'auth_token' => $token ) );
			if ( isset( $result->auth->perms ) ){
				$flickr_ok = true;
				$_SESSION['nsid'] = (string)$result->auth->user['nsid'];
			}
			else{
				Options::set( 'flickr_token_' . User::identify()->id );
				unset( $_SESSION['flickr_token'] );
			}
		}
		return $flickr_ok;
	}

	/**
	 * Provide controls for the media control bar
	 *
	 * @param array $controls Incoming controls from other plugins
	 * @param MediaSilo $silo An instance of a MediaSilo
	 * @param string $path The path to get controls for
	 * @param string $panelname The name of the requested panel, if none then emptystring
	 * @return array The altered $controls array with new (or removed) controls
	 *
	 * @todo This should really use FormUI, but FormUI needs a way to submit forms via ajax
	 */
	public function filter_media_controls( $controls, $silo, $path, $panelname )
	{
		$class = __CLASS__;
		if ( $silo instanceof $class ) {
			unset( $controls['root'] );
			$search_criteria = isset( $_SESSION['flickrsearch'] ) ? htmlentities( $_SESSION['flickrsearch'] ) : '';
			$controls['search']= '<label for="flickrsearch" class="incontent">' ._t( 'Search' ) . '</label><input type="search" id="flickrsearch" placeholder="'. _t( 'Search for photos' ) .'" value="'.$search_criteria.'">
					<script type="text/javascript">
					$(\'#flickrsearch\').keypress(function(e){
						if (e.which == 13){
							habari.media.fullReload();
							habari.media.showdir(\''.FlickrSilo::SILO_NAME.'/$search/\' + $(this).val());
							return false;
						}
					});
					</script>';
		}
		return $controls;
	}

}

?>


code:
<?xml version="1.0" encoding="utf-8" ?>
<pluggable type="plugin" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://schemas.habariproject.org/pluggable/0.8">
	<name>Flickr Media Silo</name>
	<license url="http://www.apache.org/licenses/LICENSE-2.0.html">Apache Software License 2.0</license>

	<author url="http://habariproject.org/">The Habari Community</author>

	<version>1.0</version>
	<url>http://habariproject.org/</url>
	<description><![CDATA[Implements basic Flickr integration.]]></description>

	<copyright>2009</copyright>
</pluggable>


code:
<?php if ( !defined( 'HABARI_PATH' ) ) { die( 'No direct access' ); }

/**
 * Simple file access silo
 *
 * @todo Create some helper functions in a superclass to display panel controls more easily, so that you don't need to include 80 lines of code to build a simple upload form every time.
 */

class HabariSilo extends Plugin implements MediaSilo
{
	protected $root = null;
	protected $url = null;

	const SILO_NAME = 'Habari';

	const DERIV_DIR = '.deriv';

	/**
	 * Initialize some internal values when plugin initializes
	 */
	public function action_init()
	{
		$user_path = HABARI_PATH . '/' . Site::get_path( 'user', true );
		$this->root = $user_path . 'files'; //Options::get('simple_file_root');
		$this->url = Site::get_url( 'user', true ) . 'files';  //Options::get('simple_file_url');
	}

	public function filter_activate_plugin( $ok, $file )
	{
		if ( Plugins::id_from_file( $file ) == Plugins::id_from_file( __FILE__ ) ) {
			if ( !$this->check_files() ) {
				EventLog::log( _t( "Habari Silo activation failed. The web server does not have permission to create the 'files' directory for the Habari Media Silo." ), 'warning', 'plugin' );
				Session::error( _t( "Habari Silo activation failed. The web server does not have permission to create the 'files' directory for the Habari Media Silo." ) );
				$ok = false;
			}
			// Don't bother loading if the gd library isn't active
			if ( !function_exists( 'imagecreatefromjpeg' ) ) {
				EventLog::log( _t( "Habari Silo activation failed. PHP has not loaded the gd imaging library." ), 'warning', 'plugin' );
				Session::error( _t( "Habari Silo activation failed. PHP has not loaded the gd imaging library." ) );
				$ok = false;
			}
		}
		return $ok;
	}

	public function action_plugin_activation( $file )
	{
		// Create required tokens
		ACL::create_token( 'create_directories', _t( 'Create media silo directories' ), 'Administration' );
		ACL::create_token( 'delete_directories', _t( 'Delete media silo directories' ), 'Administration' );
		ACL::create_token( 'upload_media', _t( 'Upload files to media silos' ), 'Administration' );
		ACL::create_token( 'delete_media', _t( 'Delete files from media silos' ), 'Administration' );
	}

	/**
	*
	* @param string $file. The name of the plugin file
	*
	* Delete the special silo permissions if they're no longer
	* being used.
	*/
	public function action_plugin_deactivation( $file ) {
		$silos = Plugins::get_by_interface( 'MediaSilo' );
		if ( count( $silos ) <= 1 ) {
			ACL::destroy_token( 'upload_media' );
			ACL::destroy_token( 'delete_media' );
			ACL::destroy_token( 'create_directories' );
			ACL::destroy_token( 'delete_directories' );
		}
	}

	/**
	 *
	 * Checks if files directory is usable
	 */
	private function check_files() {
		$user_path = HABARI_PATH . '/' . Site::get_path( 'user', true );
		$this->root = $user_path . 'files'; //Options::get('simple_file_root');
		$this->url = Site::get_url( 'user', true ) . 'files';  //Options::get('simple_file_url');

		if ( !is_dir( $this->root ) ) {
			if ( is_writable( $user_path ) ) {
				mkdir( $this->root, 0755 );
			}
			else {
				return false;
			}
		}

		return true;
	}

	/**
	 * Return basic information about this silo
	 *   name- The name of the silo, used as the root directory for media in this silo
	 **/
	public function silo_info()
	{
		return array(
			'name' => self::SILO_NAME,
			'icon' => URL::get_from_filesystem( __FILE__ ) . '/icon.png'
		);
	}

	/**
	 * Return directory contents for the silo path
	 * @param string $path The path to retrieve the contents of
	 * @return array An array of MediaAssets describing the contents of the directory
	 **/
	public function silo_dir( $path )
	{
		if ( !isset( $this->root ) ) {
			return array();
		}

		$path = preg_replace( '%\.{2,}%', '.', $path );
		$results = array();

		$dir = Utils::glob( $this->root . ( $path == '' ? '' : '/' ) . $path . '/*' );

		foreach ( $dir as $item ) {
			if ( substr( basename( $item ), 0, 1 ) == '.' ) {
				continue;
			}
			if ( basename( $item ) == 'desktop.ini' ) {
				continue;
			}

			$file = basename( $item );
			$props = array(
				'title' => basename( $item ),
			);
			if(is_dir($item)) {
				$results[] = new MediaAsset(
					self::SILO_NAME . '/' . $path . ($path == '' ? '' : '/') . basename( $item ),
					is_dir( $item ),
					$props
				);
			}
			else {
				$results[] = $this->silo_get( $path . ($path == '' ? '' : '/') . basename( $item ) );
			}
		}
		//print_r($results);
		return $results;
	}

	/**
	 * Get the file from the specified path
	 * @param string $path The path of the file to retrieve
	 * @param array $qualities Qualities that specify the version of the file to retrieve.
	 * @return MediaAsset The requested asset
	 **/
	public function silo_get( $path, $qualities = null )
	{
		if ( ! isset( $this->root ) ) {
			return false;
		}

		$path = preg_replace( '%\.{2,}%', '.', $path );

		$file = basename( $path );
		$props = array(
			'title' => basename( $path ),
		);
		$realfile = $this->root . '/' . $path;

		$thumbnail_suffix = HabariSilo::DERIV_DIR . '/' . $file . '.thumbnail.jpg';
		$thumbnail_url = $this->url . '/' . dirname( $path ) . ( dirname( $path ) == '' ? '' : '/' ) . $thumbnail_suffix;
		$mimetype = preg_replace(' %[^a-z_0-9]%', '_', Utils::mimetype( $realfile ) );
		$mtime = '';

		if ( !file_exists( dirname( $realfile ) . '/' . $thumbnail_suffix ) ) {
			if ( !$this->create_thumbnail( $realfile ) ) {
				// there is no thumbnail so use icon based on mimetype.
				$icon_path = Plugins::filter( 'habarisilo_icon_base_path', dirname( $this->get_file() ) . '/icons' );
				$icon_url = Plugins::filter( 'habarisilo_icon_base_url', $this->get_url() . '/icons' );

				if ( ( $icons = Utils::glob( $icon_path . '/*.{png,jpg,gif,svg}', GLOB_BRACE ) ) && $mimetype ) {
					$icon_keys = array_map( function($a) {return pathinfo($a, PATHINFO_FILENAME);}, $icons );
					$icons = array_combine( $icon_keys, $icons );
					$icon_filter = function($a, $b) use ($mimetype) {
						return (((strpos($mimetype, $a)===0) ? (strlen($a) / strlen($mimetype)) : 0) >= (((strpos($mimetype, $b)===0)) ? (strlen($b) / strlen($mimetype)) : 0)) ? $a : $b;
					};
					$icon_key = array_reduce( $icon_keys, $icon_filter );
					if ($icon_key) {
						$icon = basename( $icons[$icon_key] );
						$thumbnail_url = $icon_url .'/'. $icon;
					}
					else {
						// couldn't find an icon so use default
						$thumbnail_url = $icon_url .'/default.png';
					}
				}
			}
		}

		// If the asset is an image, obtain the image dimensions
		if ( in_array( $mimetype, array( 'image_jpeg', 'image_png', 'image_gif' ) ) ) {
			list( $props['width'], $props['height'] ) = getimagesize( $realfile );
			$mtime = '?' . filemtime( $realfile );
		}
		$props = array_merge(
			$props,
			array(
				'url' => $this->url . '/' . dirname( $path ) . ( $path == '' ? '' : '/' ) . $file,
				'thumbnail_url' => $thumbnail_url . $mtime,
				'filetype' => $mimetype,
			)
		);

		$asset = new MediaAsset( self::SILO_NAME . '/' . $path, false, $props );
		if ( file_exists( $realfile ) && is_file( $realfile ) ) {
			$asset->content = file_get_contents( $realfile );
		}
		return $asset;
	}

	/**
	 * Create a thumbnail in the derivative directory
	 *
	 * @param string $src_filename The source filename
	 * @param integer $max_width The maximum width of the output image
	 * @param integer $max_height The maximum height of the output image
	 * @return boolean true if the thumbnail creation succeeded
	 */
	private function create_thumbnail( $src_filename, $max_width = Media::THUMBNAIL_WIDTH, $max_height = Media::THUMBNAIL_HEIGHT )
	{
		// Does derivative directory not exist?
		$thumbdir = dirname( $src_filename ) . '/' . HabariSilo::DERIV_DIR . '';
		if ( !is_dir( $thumbdir ) ) {
			// Create the derivative driectory
			if ( !mkdir( $thumbdir, 0755 ) ) {
				// Couldn't make derivative directory
				return false;
			}
		}

		// Get information about the image
		list( $src_width, $src_height, $type, $attr )= getimagesize( $src_filename );

		// Load the image based on filetype
		switch ( $type ) {
		case IMAGETYPE_JPEG:
			$src_img = imagecreatefromjpeg( $src_filename );
			break;
		case IMAGETYPE_PNG:
			$src_img = imagecreatefrompng( $src_filename );
			break;
		case IMAGETYPE_GIF:
			$src_img = imagecreatefromgif ( $src_filename );
			break;
		default:
			return false;
		}
		// Did the image fail to load?
		if ( !$src_img ) {
			return false;
		}

		// Calculate the output size based on the original's aspect ratio
		$y_displacement = 0;
		if ( $src_width / $src_height > $max_width / $max_height ) {
			$thumb_w = $max_width;
			$thumb_h = $src_height * $max_width / $src_width;

		// thumbnail is not full height, position it down so that it will be padded on the
		// top and bottom with black
		$y_displacement = ( $max_height - $thumb_h ) / 2;
		}
		else {
			$thumb_w = $src_width * $max_height / $src_height;
			$thumb_h = $max_height;
		}

		// Create the output image and copy to source to it
		$dst_img = ImageCreateTrueColor( $thumb_w, $max_height );
		imagecopyresampled( $dst_img, $src_img, 0, $y_displacement, 0, 0, $thumb_w, $thumb_h, $src_width, $src_height );

		/* Sharpen before save?
		$sharpenMatrix= array( array(-1, -1, -1), array(-1, 16, -1), array(-1, -1, -1) );
		$divisor= 8;
		$offset= 0;
		imageconvolution( $dst_img, $sharpenMatrix, $divisor, $offset );
		//*/

		// Define the thumbnail filename
		$dst_filename = $thumbdir . '/' . basename( $src_filename ) . ".thumbnail.jpg";

		// Save the thumbnail as a JPEG
		imagejpeg( $dst_img, $dst_filename );

		// Clean up memory
		imagedestroy( $dst_img );
		imagedestroy( $src_img );

		return true;
	}

	/**
	 * Create a new asset instance for the specified path
	 * @param string $path The path of the new file to create
	 * @return MediaAsset The requested asset
	 **/
	public function silo_new( $path )
	{
	}

	/**
	 * Store the specified media at the specified path
	 * @param string $path The path of the file to retrieve
	 * @param MediaAsset $filedata The MediaAsset to store
	 * @return boolean True on success
	 **/
	public function silo_put( $path, $filedata )
	{
		$path = preg_replace('%\.{2,}%', '.', $path);
		$file = $this->root . '/' . $path;

		$result = $filedata->save( $file );
		if ( $result ) {
			$this->create_thumbnail( $file );
		}

		return $result;
	}

	/**
	 * Delete the file at the specified path
	 * @param string $path The path of the file to retrieve
	 **/
	public function silo_delete( $path )
	{
		$file = $this->root . '/' . $path;

		// Delete the file
		$result = unlink( $file );

		// If it's an image, remove the file in .deriv too
		$thumbdir = dirname( $file ) . '/' . HabariSilo::DERIV_DIR . '';
		$thumb = $thumbdir . '/' . basename( $file ) . ".thumbnail.jpg";

		if ( file_exists( $thumbdir ) && file_exists( $thumb ) ) {
			unlink( $thumb );
			// if this is the last thumb, delete the .deriv dir too
			if ( self::isEmptyDir( $thumbdir ) ) {
				rmdir( $thumbdir );
			}
		}
		return $result;
	}

	/**
	 * Retrieve a set of highlights from this silo
	 * This would include things like recently uploaded assets, or top downloads
	 * @return array An array of MediaAssets to highlihgt from this silo
	 **/
	public function silo_highlights()
	{
	}

	/**
	 * Retrieve the permissions for the current user to access the specified path
	 * @param string $path The path to retrieve permissions for
	 * @return array An array of permissions constants (MediaSilo::PERM_READ, MediaSilo::PERM_WRITE)
	 **/
	public function silo_permissions( $path )
	{
	}

	/**
	 * Produce a link for the media control bar that causes a specific path to be displayed
	 *
	 * @param string $path The path to display
	 * @param string $title The text to use for the link in the control bar
	 * @return string The link to create
	 */
	public function link_path( $path, $title = '' )
	{
		if ( $title == '' ) {
			$title = basename( $path );
		}
		return '' . $title . '';
	}

	/**
	 * Produce a link for the media control bar that causes a specific panel to be displayed
	 *
	 * @param string $path The path to pass
	 * @param string $path The panel to display
	 * @param string $title The text to use for the link in the control bar
	 * @return string The link to create
	 */
	public function link_panel( $path, $panel, $title )
	{
		return '' . $title . '';
	}

	/**
	 * Provide controls for the media control bar
	 *
	 * @param array $controls Incoming controls from other plugins
	 * @param MediaSilo $silo An instance of a MediaSilo
	 * @param string $path The path to get controls for
	 * @param string $panelname The name of the requested panel, if none then emptystring
	 * @return array The altered $controls array with new (or removed) controls
	 *
	 * @todo This should really use FormUI, but FormUI needs a way to submit forms via ajax
	 */
	public function filter_media_controls( $controls, $silo, $path, $panelname )
	{
		$class = __CLASS__;
		if ( $silo instanceof $class ) {
			$controls[] = $this->link_path( self::SILO_NAME . '/' . $path, _t( 'Browse' ) );
			if ( User::identify()->can( 'upload_media' ) ) {
				$controls[] = $this->link_panel( self::SILO_NAME . '/' . $path, 'upload', _t( 'Upload' ) );
			}
			if ( User::identify()->can( 'create_directories' ) ) {
				$controls[] = $this->link_panel( self::SILO_NAME . '/' . $path, 'mkdir', _t( 'Create Directory' ) );
			}
			if ( User::identify()->can( 'delete_directories' ) && ( $path && self::isEmptyDir( $this->root . '/' . $path ) ) ) {
				$controls[] = $this->link_panel( self::SILO_NAME . '/' . $path, 'rmdir', _t( 'Delete Directory' ) );
			}
		}
		return $controls;
	}

	/**
	 * Provide requested media panels for this plugin
	 *
	 * Regarding Uploading:
	 * A panel is returned to the media bar that contains a form, an iframe, and a javascript function.
	 * The form allows the user to select a file, and is submitted back to the same URL that produced this panel in the first place.
	 * This has the result of submitting the uploaded file to here when the form is submitted.
	 * To prevent the panel form from reloading the whole publishing page, the form is submitted into the iframe.
	 * An onload event attached to the iframe calls the function.
	 * The function accesses the content of the iframe when it loads, which should contain the results of the request to obtain this panel, which are in JSON format.
	 * The JSON data is passed to the habari.media.jsonpanel() function in media.js to process the data and display the results, just like when displaying a panel normally.
	 *
	 * @param string $panel The HTML content of the panel to be output in the media bar
	 * @param MediaSilo $silo The silo for which the panel was requested
	 * @param string $path The path within the silo (silo root omitted) for which the panel was requested
	 * @param string $panelname The name of the requested panel
	 * @return string The modified $panel to contain the HTML output for the requested panel
	 *
	 * @todo Move the uploaded file from the temporary location to the location indicated by the path field.
	 */
	public function filter_media_panels( $panel, $silo, $path, $panelname)
	{
		$class = __CLASS__;
		if ( $silo instanceof $class ) {
			switch ( $panelname ) {
				case 'mkdir':

					$fullpath = self::SILO_NAME . '/' . $path;

					$form = new FormUI( 'habarisilomkdir' );
					$form->append( 'static', 'ParentDirectory', '
' . _t( 'Parent Directory:' ) . " /{$path}
" );

					// add the parent directory as a hidden input for later validation
					$form->append( 'hidden', 'path', 'null:unused' )->value = $path;
					$form->append( 'hidden', 'action', 'null:unused')->value = $panelname;
					$dir_text_control = $form->append( 'text', 'directory', 'null:unused', _t('What would you like to call the new directory?') );
					$dir_text_control->add_validator( array( $this, 'mkdir_validator' ) );
					$form->append( 'submit', 'submit', _t('Submit') );
					$form->media_panel($fullpath, $panelname, 'habari.media.forceReload();');
					$form->on_success( array( $this, 'dir_success' ) );
					$panel = $form->get(); /* form submission magicallly happens here */

					return $panel;

					break;
				case 'rmdir':
					$fullpath = self::SILO_NAME . '/' . $path;

					$form = new FormUI( 'habarisilormdir' );
					$form->append( 'static', 'RmDirectory', '
' . _t( 'Directory:' ) . " /{$path}
" );

					// add the parent directory as a hidden input for later validation
					$form->append( 'hidden', 'path', 'null:unused' )->value = $path;
					$form->append( 'hidden', 'action', 'null:unused')->value = $panelname;
					$dir_text_control = $form->append( 'static', 'directory', _t( 'Are you sure you want to delete this directory?' ) );
					$form->append( 'submit', 'submit', _t('Delete') );
					$form->media_panel( $fullpath, $panelname, 'habari.media.forceReload();' );
					$form->on_success( array( $this, 'dir_success' ) );
					$panel = $form->get(); /* form submission magicallly happens here */

					return $panel;

					break;
				case 'delete':
					$fullpath = self::SILO_NAME . '/' . $path;

					$form = new FormUI( 'habarisilodelete' );
					$form->append( 'static', 'RmFile', '
' . _t( 'File:' ) . " /{$path}
" );

					// add the parent directory as a hidden input for later validation
					$form->append( 'hidden', 'path', 'null:unused' )->value = $path;
					$dir_text_control = $form->append( 'static', 'directory', '
' . _t( 'Are you sure you want to delete this file?' ) . '
');
					$form->append( 'submit', 'submit', _t('Delete') );
					$form->media_panel( $fullpath, $panelname, 'habari.media.forceReload();' );
					$form->on_success( array( $this, 'do_delete' ) );
					$panel = $form->get();

					return $panel;
					break;
				case 'upload':
					if ( isset( $_FILES['file'] ) ) {
						if ( isset( $_POST['token'] ) && isset( $_POST['token_ts'] ) && self::verify_token( $_POST['token'], $_POST['token_ts'] ) ) {
							$size = Utils::human_size( $_FILES['file']['size'] );
							$panel .= '

' . _t( 'File: ' ) . $_FILES['file']['name'];
							$panel .= ( $_FILES['file']['size'] > 0 ) ? "({$size})" : '';
							$panel .= '
';

							$path = self::SILO_NAME . '/' . preg_replace( '%\.{2,}%', '.', $path ). '/' . $_FILES['file']['name'];
							$asset = new MediaAsset( $path, false );
							$asset->upload( $_FILES['file'] );

							if ( $asset->put() ) {
								$panel .= '
' . _t( 'File added successfully.' ) . '
';
							}
							else {
								$upload_errors = array(
										1 => _t( 'The uploaded file exceeds the upload_max_filesize directive in php.ini.' ),
										2 => _t( 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.' ),
										3 => _t( 'The uploaded file was only partially uploaded.' ),
										4 => _t( 'No file was uploaded.' ),
										6 => _t( 'Missing a temporary folder.' ),
										7 => _t( 'Failed to write file to disk.' ),
										8 => _t( 'A PHP extension stopped the file upload. PHP does not provide a way to ascertain which extension caused the file upload to stop; examining the list of loaded extensions with phpinfo() may help.' ),
									);

								$panel .= '
' . _t( 'File could not be added to the silo.' ) . '
';
								$panel .= '
' . $upload_errors[ $_FILES['file']['error'] ] . '
';
							}

							$panel .= '
' . _t( 'Browse the current silo path.' ) . '

';
						} else {
							$panel .= '
' ._t( 'Suspicious behaviour or too much time has elapsed.  Please upload your file again.' ) . '
';
						}
					}
					else {
						$token_ts = time();
						$token = self::create_token( $token_ts );
						$fullpath = self::SILO_NAME . '/' . $path;
						$form_action = URL::get( 'admin_ajax', array( 'context' => 'media_upload' ) );
						$panel .= <<< UPLOAD_FORM
<form enctype="multipart/form-data" method="post" id="simple_upload" target="simple_upload_frame" action="{$form_action}" class="span-10" style="margin:0px auto;text-align: center">

%s /{$path}

<input type="file" name="file"><input type="submit" name="upload" value="%s">
	<input type="hidden" name="path" value="{$fullpath}">
	<input type="hidden" name="panel" value="{$panelname}">
	<input type="hidden" name="token" value="{$token}">
	<input type="hidden" name="token_ts" value="{$token_ts}">

</form>

UPLOAD_FORM;

					$panel = sprintf( $panel, _t( "Upload to:" ), _t( "Upload" ) );
				}
			}
		}
		return $panel;
	}

	/**
	 * A validator for the mkdir form created with FormUI. Checks to see if the
	 * webserver can write to the parent directory and that the directory does
	 * not already exist.
	 * @param $dir The input from the form
	 * @param $control The FormControl object
	 * @param $form The FormUI object
	 */
	public function mkdir_validator( $dir, $control, $form )
	{
		if ( strpos( $dir, '*' ) !== false || preg_match( '%(?:^|/)\.%', $dir ) ) {
		    return array( _t( "The directory name contains invalid characters: %s.", array( $dir ) ) );
		}

		$path = preg_replace( '%\.{2,}%', '.', $form->path->value );
		$dir = $this->root . ( $path == '' ? '' : '/' ) . $path . '/'. $dir;

		if ( !is_writable( $this->root . '/' . $path ) ) {
			return array( _t( "Webserver does not have permission to create directory: %s.", array( $dir ) ) );
		}
		if ( is_dir( $dir ) ) {
			return array( _t( "Directory: %s already exists.", array( $dir ) ) );
		}

		return array();
	}
	/**
	 * This function performs the mkdir and rmdir actions on submission of the form.
	 * It is called by FormUI's success() method.
	 * @param FormUI $form
	 */
	public function dir_success ( $form )
	{
		$dir = preg_replace( '%\.{2,}%', '.', $form->directory->value );
		$path = preg_replace( '%\.{2,}%', '.', $form->path->value );

		switch ( $form->action->value ) {
			case 'rmdir':
				$dir = $this->root . ( $path == '' ? '' : '/' ) . $path;
				rmdir( $dir );
				$msg = _t( 'Directory Deleted: %s', array( $path ) );
				break;
			case 'mkdir':
				$dir = $this->root . ( $path == '' ? '' : '/' ) . $path . '/'. $dir;
				mkdir( $dir, 0755 );
				$msg = _t ( 'Directory Created: %s', array( $path . '/' . $form->directory->value ) );
				break;
		}

		return '

' . $msg . '

';
	}

	/**
	 * This function takes the path passed from the form and passes it to silo_delete
	 * to delete the file and it's thumbnail if it's an image.
	 *
	 * @param FormUI $form
	 */
	public function do_delete ( $form )
	{
		$path = preg_replace( '%\.{2,}%', '.', $form->path->value );
		$result = $this->silo_delete($path);
		$panel = '
';
		if ( $result ) {
			$panel .= '
' . _t( 'File deleted successfully.' ) . '
';
		} else {
			$panel .= '
' . _t( 'Failed to delete file.' ) . '
';
		}

		$panel .= '
' . _t( 'Browse the current silo path.' ) . '

';

		return $panel;
	}

	/**
	 * This function is used to check if a directory is empty.
	 *
	 * @param string $dir
	 * @return boolean
	 */
	private static function isEmptyDir( $dir )
	{
		return ( ( $files = @scandir( $dir ) ) && count( $files ) <= 2 );
	}

	/**
	 * Create the upload token based on the time string submitted and the UID for this Habari installation.
	 *
	 * @param integer $timestamp
	 * @return string
	 */
	private static function create_token( $timestamp )
	{
		return substr( md5( $timestamp . Options::get( 'GUID' ) ), 0, 10 );
	}

	/**
	 * Verify that the token and timestamp passed are valid.
	 *
	 * @param string $token
	 * @param integer $timestamp
	 *
	 * @TODO By default this gives the user 5 mins to upload a file from the time
	 *       the form is display and the file uploaded.  This should be sufficient,
	 *       but do we a) need this timeout and b) should it be configurable?
	 */
	private static function verify_token( $token, $timestamp )
	{
		if ( $token == self::create_token( $timestamp ) ) {
			if ( ( time() > ( $timestamp ) ) && ( time() < ( $timestamp + 5*60 ) ) ) {
				return true;
			}
		} else {
			return false;
		}
	}

}

?>


code:
<?xml version="1.0" encoding="utf-8" ?>
<pluggable type="plugin" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://schemas.habariproject.org/pluggable/0.8">
	<name>Habari Media Silo</name>
	<license url="http://www.apache.org/licenses/LICENSE-2.0.html">Apache Software License 2.0</license>

	<author url="http://habariproject.org/">The Habari Community</author>

	<version>1.0.1</version>
	<url>http://habariproject.org/</url>
	<description><![CDATA[Provides simple file uploading and embedding functionality.]]></description>

	<copyright>2009</copyright>

	<help>
		<value><![CDATA[

This plugin provides basic media functionality by allowing users to insert into posts images that exist on the server.

Depending on server capabilities, users may also be able to upload new images and create directories for new images on the server.

Upon initialization, this plugin will attempt to create a /user/files directory under your Habari installation. You may need to alter permissions to allow this action.

		]]></value>
	</help>

</pluggable>