<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>patches/model.Tumblr.private.js.txt</filename>
    </added>
    <added>
      <filename>versions/tombloo.0.3.28.xpi</filename>
    </added>
    <added>
      <filename>xpi/chrome/content/library/21_Clipp.js</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,4 +1,4 @@
-shortcutkeys['CTRL + SHIFT + R'] = {
+shortcutkeys[[KEY_ACCEL, 'SHIFT', 'R'].join('+')] = {
 	description : 'Reload Tombloo Environment',
 	execute : function(e){
 		cancel(e);</diff>
      <filename>patches/shortcutkey.reloadEnvironment.js</filename>
    </modified>
    <modified>
      <diff></diff>
      <filename>tombloo.xpi</filename>
    </modified>
    <modified>
      <diff>@@ -2,21 +2,21 @@
 &lt;RDF:RDF xmlns:em=&quot;http://www.mozilla.org/2004/em-rdf#&quot;
          xmlns:NC=&quot;http://home.netscape.com/NC-rdf#&quot;
          xmlns:RDF=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;&gt;
-  &lt;RDF:Seq RDF:about=&quot;rdf:#$iUwd4&quot;&gt;
-    &lt;RDF:li RDF:resource=&quot;rdf:#$jUwd4&quot;/&gt;
+  &lt;RDF:Seq RDF:about=&quot;rdf:#$RJbGT1&quot;&gt;
+    &lt;RDF:li RDF:resource=&quot;rdf:#$SJbGT1&quot;/&gt;
   &lt;/RDF:Seq&gt;
   &lt;RDF:Description RDF:about=&quot;urn:mozilla:extension:tombloo@brasil.to&quot;
-                   em:signature=&quot;MIGTMA0GCSqGSIb3DQEBDQUAA4GBAG0SVQ/fyhfAHcXiqgB2ntyQRyJokuGszUP5C61rRL6wvdqdns50sQ1aF5xgNBNRjPtwnN8iHDjhY26WOVwslXmxsRtbxPU53rz6AxskiRftmaQEPi1ILtZa6nBQcw0K5+VOE2KQBlKpVsbzJhGw3DYn4SEO7T09RgkIQv4qWTNT&quot;&gt;
-    &lt;em:updates RDF:resource=&quot;rdf:#$iUwd4&quot;/&gt;
+                   em:signature=&quot;MIGTMA0GCSqGSIb3DQEBDQUAA4GBAC59j1yMprZY5PVW28SYnMk/amohZjBYWGMtB4hQcUmzIWegY4/8HC2l97UpirEqJPAgH6bqqF6eMI/R9nRwI0Ow1oJ/60J0dkajr1BRPe1KMerNl2fbXjcPb92lo8z86bCk27XFxuGKV3PH585lCCwNR0yeQBJ0tbbhtIF7hTNw&quot;&gt;
+    &lt;em:updates RDF:resource=&quot;rdf:#$RJbGT1&quot;/&gt;
   &lt;/RDF:Description&gt;
-  &lt;RDF:Description RDF:about=&quot;rdf:#$jUwd4&quot;
-                   em:version=&quot;0.3.27&quot;&gt;
-    &lt;em:targetApplication RDF:resource=&quot;rdf:#$mUwd4&quot;/&gt;
+  &lt;RDF:Description RDF:about=&quot;rdf:#$SJbGT1&quot;
+                   em:version=&quot;0.3.28&quot;&gt;
+    &lt;em:targetApplication RDF:resource=&quot;rdf:#$VJbGT1&quot;/&gt;
   &lt;/RDF:Description&gt;
-  &lt;RDF:Description RDF:about=&quot;rdf:#$mUwd4&quot;
+  &lt;RDF:Description RDF:about=&quot;rdf:#$VJbGT1&quot;
                    em:id=&quot;{ec8030f7-c20a-464f-9b0e-13a3a9e97384}&quot;
                    em:minVersion=&quot;3.0&quot;
                    em:maxVersion=&quot;3.1.*&quot;
-                   em:updateLink=&quot;http://github.com/to/tombloo/tree/release/tombloo.xpi?raw=true&quot;
-                   em:updateHash=&quot;sha512:822be9bca5d596970a4227dab44b618c7d8dc25e2f356cb8074e8e623e148d8da978318ecbb3ca31a02f34a4a51b59ce4158aa2932bc6814c385fc1e881550ec&quot; /&gt;
+                   em:updateLink=&quot;http://github.com/to/tombloo/raw/release/tombloo.xpi&quot;
+                   em:updateHash=&quot;sha512:75ffebe01e0a0ee3122f4b23ad56d6a096db6df6eefe40166dadb41c12ebaf497b7a51b95036d4197419e194af8d5305d7d7447a7506e70ea9b893af2d8473b7&quot; /&gt;
 &lt;/RDF:RDF&gt;</diff>
      <filename>update.rdf</filename>
    </modified>
    <modified>
      <diff>@@ -47,6 +47,8 @@
 			&lt;label value=&quot;cxx&quot;           class=&quot;text-link&quot; onclick=&quot;openURL('http://cxx.tumblr.com/')&quot; /&gt;
 			&lt;label value=&quot;Constellation&quot; class=&quot;text-link&quot; onclick=&quot;openURL('http://d.hatena.ne.jp/Constellation/')&quot; /&gt;
 			&lt;label value=&quot;YungSang&quot;      class=&quot;text-link&quot; onclick=&quot;openURL('http://blog.yungsang.com/')&quot; /&gt;
+			&lt;label value=&quot;zorio&quot;         class=&quot;text-link&quot; onclick=&quot;openURL('http://d.hatena.ne.jp/zorio/')&quot; /&gt;
+			&lt;label value=&quot;simonetta&quot;     class=&quot;text-link&quot; onclick=&quot;openURL('http://blog.livedoor.jp/s_i_m_o_n_e_t_t_a/')&quot; /&gt;
 		&lt;/vbox&gt;
 			
 		&lt;label class=&quot;sectionTitle&quot;&gt;&lt;/label&gt;</diff>
      <filename>xpi/chrome/content/about.xul</filename>
    </modified>
    <modified>
      <diff>@@ -12,11 +12,12 @@ var KEY_ACCEL = (AppInfo.OS == 'Darwin')? 'META' : 'CTRL';
 var grobal = this;
 disconnectAll(grobal);
 
-// &#12522;&#12525;&#12540;&#12489;&#12395;&#12424;&#12387;&#12387;&#12390;&#22793;&#26356;&#12373;&#12428;&#12394;&#12356;&#38936;&#22495;&#12434;&#29992;&#24847;&#12377;&#12427;
+// &#12522;&#12525;&#12540;&#12489;&#12395;&#12424;&#12387;&#12390;&#22793;&#26356;&#12373;&#12428;&#12394;&#12356;&#38936;&#22495;&#12434;&#29992;&#24847;&#12377;&#12427;
 // &#12452;&#12505;&#12531;&#12488;&#12395;&#23433;&#23450;&#12375;&#12390;&#12501;&#12483;&#12463;&#12377;&#12427;&#12383;&#12417;&#12394;&#12393;&#12395;&#20351;&#12431;&#12428;&#12427;
 if(typeof(constant)=='undefined')
 	constant = {};
 
+
 // ----[XPCOM]-------------------------------------------------
 function evalInSandbox(js, url){
 	return Components.utils.evalInSandbox(js, Components.utils.Sandbox(url));
@@ -274,6 +275,20 @@ function putContents(file, text, charset){
 		stream.write(text, text.length);
 	});
 }
+	
+/**
+ * &#12481;&#12515;&#12531;&#12493;&#12523;&#12395;&#12463;&#12483;&#12461;&#12540;&#12434;&#20184;&#21152;&#12377;&#12427;&#12290;
+ * Firefox 3.1&#12391;network.cookie.cookieBehavior&#12398;&#20516;&#12395;&#38306;&#12431;&#12425;&#12378;&#12463;&#12483;&#12461;&#12540;&#12364;&#35373;&#23450;&#12373;&#12428;&#12394;&#12367;&#12394;&#12387;&#12383;&#12290;
+ * &#35443;&#32048;&#35519;&#26619;&#20013;&#12290;
+ *
+ * @param {nsIHttpChannel} channel
+ */
+function setCookie(channel){
+	if(!(channel instanceof Ci.nsIHttpChannel))
+		return;
+	
+	channel.setRequestHeader('Cookie', getCookieString(channel.originalURI.host), true);
+}
 
 /**
  * POST/GET&#12398;&#36890;&#20449;&#12434;&#34892;&#12358;&#12290;
@@ -295,14 +310,6 @@ function putContents(file, text, charset){
 function request(url, opts){
 	var d = new Deferred();
 	
-	function setCookie(channel){
-		// &#12469;&#12540;&#12489;&#12497;&#12540;&#12486;&#12451;&#12398;&#12463;&#12483;&#12461;&#12540;&#12434;&#36865;&#20449;&#12377;&#12427;&#12363;?
-		if(getPrefValue('network.cookie.cookieBehavior') != 1)
-			return;
-		
-		channel.setRequestHeader('Cookie', getCookieString(channel.originalURI.host), true);
-	}
-	
 	opts = opts || {};
 	
 	var uri = createURI(url + queryString(opts.queryString, true));
@@ -417,8 +424,7 @@ function request(url, opts){
 				return;
 			}
 			
-			// &#12497;&#12501;&#12457;&#12540;&#12510;&#12531;&#12473;&#12434;&#32771;&#24942;&#12375;broad&#12434;&#20351;&#12431;&#12394;&#12356;
-			setCookie(newChannel.QueryInterface(Ci.nsIHttpChannel));
+			setCookie(newChannel);
 		},
 		
 		// nsIStreamListener
@@ -1015,13 +1021,24 @@ function addAround(target, methodNames, advice){
 	});
 }
 
+/**
+ * &#37197;&#21015;&#12434;&#32080;&#21512;&#12375;&#25991;&#23383;&#21015;&#12434;&#20316;&#25104;&#12377;&#12427;&#12290;
+ * &#31354;&#35201;&#32032;&#12399;&#38500;&#22806;&#12373;&#12428;&#12427;&#12290;
+ * &#37197;&#21015;&#12364;&#31354;&#12398;&#22580;&#21512;&#12399;&#12289;&#31354;&#25991;&#23383;&#21015;&#12364;&#36820;&#12373;&#12428;&#12427;&#12290;
+ * &#37197;&#21015;&#12398;&#20837;&#12428;&#23376;&#12399;&#30452;&#21015;&#21270;&#12373;&#12428;&#12427;&#12290;
+ * 
+ * @param {Array} txts &#25991;&#23383;&#21015;&#37197;&#21015;&#12290;
+ * @param {String} delm &#21306;&#20999;&#12426;&#25991;&#23383;&#21015;&#12290;
+ * @param {Boolean} trimTag &#21508;&#25991;&#23383;&#21015;&#12363;&#12425;HTML&#12479;&#12464;&#12434;&#38500;&#22806;&#12377;&#12427;&#12363;&#12290;
+ * @return {String} &#32080;&#21512;&#12373;&#12428;&#12383;&#25991;&#23383;&#21015;&#12290;
+ */
 function joinText(txts, delm, trimTag){
 	if(!txts)
 		return '';
 	
 	if(delm==null)
 		delm = ',';
-	txts = flattenArray(txts.filter(operator.truth));
+	txts = flattenArray([].concat(txts).filter(operator.truth));
 	return (trimTag? txts.map(methodcaller('trimTag')) : txts).join(delm);
 }
 
@@ -1042,6 +1059,43 @@ function validateFileName(fileName){
 	return fileName.replace(/[\/]+/g, &quot;_&quot;);
 }
 
+/**
+ * Windows&#19978;&#12391;WSH&#12434;&#23455;&#34892;&#12377;&#12427;&#12290;
+ * &#12473;&#12463;&#12522;&#12503;&#12488;&#20869;&#12391;WScript.echo&#12394;&#12393;&#12391;&#20986;&#21147;&#12373;&#12428;&#12383;&#25991;&#23383;&#21015;&#12418;&#36820;&#12426;&#20516;&#12395;&#21547;&#12414;&#12428;&#12427;&#12290;
+ * 
+ * @param {Function} func WSH&#12473;&#12463;&#12522;&#12503;&#12488;&#12290;
+ * @param {Array} args WSH&#12473;&#12463;&#12522;&#12503;&#12488;&#12398;&#24341;&#25968;&#12290; 
+ * @return {String} WSH&#12473;&#12463;&#12522;&#12503;&#12488;&#12398;&#23455;&#34892;&#32080;&#26524;&#12290;
+ */
+function executeWSH(func, args){
+	args = args || [];
+	
+	var bat = getTempFile('bat');
+	var script = getTempFile();
+	var out = new LocalFile(script.path + '.out');
+	
+	putContents(bat, [
+		'cscript //E:JScript //Nologo', 
+		script.path.quote(), 
+		'&gt;', 
+		out.path.quote()].join(' '));
+	putContents(script, 
+		args.map(function(a, i){return 'var ARG_' + i + ' = ' + uneval(a) + ';'}).join('\n') + 
+		'WScript.echo(' + func.toSource() + '(' + 
+		args.map(function(a, i){return 'ARG_' + i}).join(',') + 
+		'));');
+	
+	new Process(bat).run(true, [], 0);
+	
+	var res = getContents(out, 'Shift-JIS').replace(/\s+$/, '');
+	
+	bat.remove(false);
+	script.remove(false);
+	out.remove(false);
+	
+	return res;
+}
+
 
 // ----[State]-------------------------------------------------
 var State = {
@@ -1133,17 +1187,13 @@ Repository.prototype = {
 	},
 	
 	get names(){
-		return reduce(function(memo, i){
-			memo.push(i[0]);
-			return memo;
-		}, this, []);
+		return this.values.map(itemgetter('name'));
 	},
 	
 	get values(){
-		return reduce(function(memo, i){
-			memo.push(i[1]);
-			return memo;
-		}, this, []);
+		return map(itemgetter(1), this).filter(function(v){
+			return v.name;
+		});
 	},
 	
 	clear : function(){
@@ -1174,6 +1224,12 @@ Repository.prototype = {
 		}, this.values, []);
 	},
 	
+	/**
+	 * &#26032;&#12375;&#12356;&#23450;&#32681;&#12434;&#36861;&#21152;&#12377;&#12427;&#12290;
+	 * 
+	 * @param {Array} defs
+	 * @param {String} target &#36861;&#21152;&#23550;&#35937;&#12290;&#12371;&#12398;&#21517;&#21069;&#12398;&#21069;&#12395;&#36861;&#21152;&#12373;&#12428;&#12427;&#12290;
+	 */
 	register : function(defs, target){
 		if(!defs)
 			return;
@@ -1802,6 +1858,7 @@ AbstractSessionService = {
 		delete this.cookie;
 		delete this.user;
 		delete this.token;
+		delete this.password;
 		
 		if(!cookie)
 			return 'none';</diff>
      <filename>xpi/chrome/content/library/01_utility.js</filename>
    </modified>
    <modified>
      <diff>@@ -219,7 +219,7 @@ var Tumblr = update({}, AbstractSessionService, {
 				
 				// Tumblr&#12363;&#12425;&#20182;&#12469;&#12540;&#12499;&#12473;&#12408;&#12509;&#12473;&#12488;&#12377;&#12427;&#12383;&#12417;&#30011;&#20687;URL&#12434;&#21462;&#24471;&#12375;&#12390;&#12362;&#12367;
 				if(form['post[type]']=='photo')
-					form.image = $x('id(&quot;edit_post&quot;)//img[starts-with(@src, &quot;http://media.tumblr.com/&quot;) or starts-with(@src, &quot;http://data.tumblr.com/&quot;)]/@src', doc);
+					form.image = $x('id(&quot;edit_post&quot;)//img[contains(@src, &quot;media.tumblr.com/&quot;) or contains(@src, &quot;data.tumblr.com/&quot;)]/@src', doc);
 			}
 			
 			return form;</diff>
      <filename>xpi/chrome/content/library/20_Tumblr.js</filename>
    </modified>
    <modified>
      <diff>@@ -940,8 +940,15 @@ models.register({
 				function getTags(part){
 					return $x('id(&quot;save-' + part + '-tags&quot;)//a[contains(@class, &quot;tag-list-tag&quot;)]/text()', doc, true);
 				}
-				
 				return {
+					editPage : editPage = 'http://delicious.com/save?url=' + url,
+					form : {
+						item        : $x('id(&quot;title&quot;)', doc).value,
+						description : $x('id(&quot;notes&quot;)', doc).value,
+						tags        : $x('id(&quot;tags&quot;)', doc).value.split(' '),
+						private     : $x('id(&quot;share&quot;)', doc).checked,
+					},
+					
 					duplicated : !!doc.getElementById('delete'),
 					recommended : getTags('reco'), 
 					popular : getTags('pop'),
@@ -1244,28 +1251,37 @@ if(NavBookmarksService){
 	});
 }
 
-models.register({
+
+models.register(update({
 	name : 'Instapaper',
 	ICON : 'chrome://tombloo/skin/instapaper.ico',
-	
+	POST_URL: 'http://www.instapaper.com/edit',
 	check : function(ps){
-		return (/(quote|link)/).test(ps.type) &amp;&amp; !ps.file;
+		return (/(quote|link)/).test(ps.type);
+	},
+	getAuthCookie : function(){
+		return getCookieString('www.instapaper.com', 'pfu');
 	},
-	
 	post : function(ps){
-		return request('http://www.instapaper.com/edit', {
-			redirectionLimit : 0,
-			sendContent : {
-				'bookmark[title]' : ps.item, 
-				'bookmark[url]' : ps.itemUrl,
-				'bookmark[selection]' : joinText([ps.body, ps.description], '\n', true),
-			},
-		}).addCallback(function(res){
-			if(res.channel.URI.asciiSpec.match('login'))
-				throw new Error(getMessage('error.notLoggedin'));
+		var url = this.POST_URL;
+		return this.getSessionValue('token', function(){
+			return request(url).addCallback(function(res){
+				var doc = convertToHTMLDocument(res.responseText);
+				return $x('//input[@id=&quot;form_key&quot;]/@value', doc);
+			});
+		}).addCallback(function(token){
+			return request(url, {
+				redirectionLimit: 0,
+				sendContent: {
+					'form_key': token,
+					'bookmark[url]': ps.itemUrl,
+					'bookmark[title]': ps.item,
+					'bookmark[selection]': joinText([ps.body, ps.description])
+				}
+			});
 		});
-	},
-});
+	}
+}, AbstractSessionService));
 
 
 // http://www.kawa.net/works/ajax/romanize/japanese.html
@@ -1708,9 +1724,16 @@ models.register(update({
 				},
 			})
 		}).addCallback(function(res){
-			var tags = evalInSandbox('(' + res.responseText.extract(/var tags =(.*);$/m) + ')', HatenaBookmark.POST_URL) || {};
+			var tags = evalInSandbox(
+				'(' + res.responseText.extract(/var tags =(.*);$/m) + ')', 
+				HatenaBookmark.POST_URL) || {};
+			
 			return {
 				duplicated : (/bookmarked-confirm/).test(res.responseText),
+				recommended : $x(
+					'id(&quot;recommend-tags&quot;)/span[@class=&quot;tag&quot;]/text()', 
+					convertToHTMLDocument(res.responseText), 
+					true),
 				tags : map(function([tag, info]){
 					return {
 						name      : tag,
@@ -1916,6 +1939,28 @@ models.register({
 	},
 });
 
+models.register({
+	name: 'Femo',
+	ICON: 'http://femo.jp/favicon.ico',
+	POST_URL: 'http://femo.jp/create/post',
+	
+	check: function(ps) {
+		return (/(regular|photo|quote|link|conversation|video)/).test(ps.type) &amp;&amp; !ps.file;
+	},
+	post: function(ps) {
+		return this.addMemo(ps);
+	},
+	addMemo : function(ps){
+		return request(this.POST_URL, {
+			sendContent: {
+				title   : ps.item,
+				text    : joinText([ps.itemUrl, ps.body, ps.description], '\n'),
+				tagtext : joinText(ps.tags, ' '),
+			},
+		});
+	},
+});
+
 
 // &#20840;&#12390;&#12398;&#12469;&#12540;&#12499;&#12473;&#12434;&#12464;&#12525;&#12540;&#12496;&#12523;&#12467;&#12531;&#12486;&#12461;&#12473;&#12488;&#12395;&#32622;&#12367;(&#24460;&#26041;&#20114;&#25563;)
 models.copyTo(this);</diff>
      <filename>xpi/chrome/content/library/20_model.js</filename>
    </modified>
    <modified>
      <diff>@@ -57,7 +57,74 @@ Tombloo.Service.extractors = new Repository([
 			}
 		},
 	},
-		
+	
+	{
+		name: 'ReBlog - Clipp',
+		ICON: 'http://clipp.in/favicon.ico',
+		check: function(ctx) {
+			return this.getLink(ctx);
+		},
+		extract: function(ctx) {
+			var link = this.getLink(ctx);
+			if(!link)
+				return {};
+			
+			var self = this;
+			var endpoint = Clipp.CLIPP_URL + 'bookmarklet' + link;
+			return Clipp.getForm(endpoint).addCallback(function(form) {
+				return update({
+					type: 'link',
+					item: ctx.title,
+					itemUrl: ctx.href,
+					favorite: {
+						name: 'Clipp',
+						endpoint: endpoint,
+						form: form
+					}
+				}, self.convertToParams(form));
+			});
+		},
+		checkEntryPage: function(ctx) {
+			return (/clipp.in\/entry\/(\d+)/).test(ctx.href);
+		},
+		getLink: function(ctx) {
+			return this.checkEntryPage(ctx) ? this.getLinkByPage(currentDocument()) : this.getLinkByTarget(ctx);
+		},
+		getLinkByPage: function(doc) {
+			return $x('//a[contains(@href, &quot;add?reblog=&quot;)]/@href', doc);
+		},
+		getLinkByTarget: function(ctx) {
+			return $x('./ancestor-or-self::div[contains(concat(&quot; &quot;, @class, &quot; &quot;), &quot; item &quot;)]//a[contains(@href, &quot;add?reblog=&quot;)]/@href', ctx.target);
+		},
+		convertToParams: function(form) {
+			if (form.embed_code)
+				return {
+					type: 'video',
+					item: form.title,
+					itemUrl: form.address,
+					body: form.embed_code
+				};
+			else if (form.image_address)
+				return {
+					type: 'photo',
+					item: form.title,
+					itemUrl: form.image_address
+				};
+			else if (form.quote &amp;&amp; form.quote != '&lt;br&gt;')
+				return {
+					type: 'quote',
+					item: form.title,
+					itemUrl: form.address,
+					body: form.quote
+				};
+			return {
+				type: 'link',
+				item: form.title,
+				itemUrl: form.address
+			};
+		}
+	},
+	
 	{
 		name : 'Photo - LDR(FFFFOUND!)',
 		ICON : 'http://reader.livedoor.com/favicon.ico',
@@ -240,25 +307,31 @@ Tombloo.Service.extractors = new Repository([
 			return ctx.href.match('//twitter.com/.*?/(status|statuses)/\\d+');
 		},
 		extract : function(ctx){
-			var body = ctx.selection;
-			if(!body){
-				var content = $x('(//span[@class=&quot;entry-content&quot;])[1]');
-				$x('.//a', content, true).forEach(function(l){l.href = l.href;});
-				body = content.innerHTML.
-					replace(/ (rel|target)=&quot;.+?&quot;/g, '').
-					replace('&lt;a href=&quot;' + ctx.href.replace('/statuses/','/status/') + '&quot;&gt;...&lt;/a&gt;', '');
-			}
-			
-			return {
-				type     : 'quote',
-				item     : ctx.title.substring(0, ctx.title.indexOf(': ')),
-				itemUrl  : ctx.href,
-				body     : body.trim(),
-				favorite : {
-					name : 'Twitter',
-					id   : ctx.href.match(/(status|statuses)\/(\d+)/)[2],
-				},
-			}
+			return (ctx.selection? 
+				succeed(ctx.selection) : 
+				request(ctx.href).addCallback(function(res){
+					var doc = convertToHTMLDocument(res.responseText);
+					var content = $x('(//span[@class=&quot;entry-content&quot;])[1]', doc);
+					
+					$x('.//a', content, true).forEach(function(l){l.href = l.href;});
+					body = content.innerHTML.
+						replace(/ (rel|target)=&quot;.+?&quot;/g, '').
+						replace('&lt;a href=&quot;' + ctx.href.replace('/statuses/','/status/') + '&quot;&gt;...&lt;/a&gt;', '');
+					
+					return body;
+				})
+			).addCallback(function(body){
+				return {
+					type     : 'quote',
+					item     : ctx.title.substring(0, ctx.title.indexOf(': ')),
+					itemUrl  : ctx.href,
+					body     : body.trim(),
+					favorite : {
+						name : 'Twitter',
+						id   : ctx.href.match(/(status|statuses)\/(\d+)/)[2],
+					},
+				};
+			});
 		},
 	},
 	
@@ -465,6 +538,21 @@ Tombloo.Service.extractors = new Repository([
 		},
 	},
 	
+  {
+    name: 'ReBlog - Dashboard iPhone',
+    ICON: 'chrome://tombloo/skin/reblog.ico',
+    check: function(ctx){
+      return (/(tumblr\.com)\/iphone/).test(ctx.href) &amp;&amp; this.getLink(ctx);
+    },
+    extract : function(ctx){
+      return Tombloo.Service.extractors.ReBlog.extractByLink(ctx, this.getLink(ctx));
+    },
+    getLink : function(ctx){
+      var link = $x('./ancestor-or-self::li[starts-with(normalize-space(@id), &quot;post&quot;)]//a[contains(concat(&quot; &quot;,normalize-space(@class),&quot; &quot;),&quot; permalink &quot;)]', ctx.target);
+      return link &amp;&amp; link.href;
+    }
+  },
+  
 	{
 		name : 'ReBlog - Mosaic',
 		ICON : 'chrome://tombloo/skin/reblog.ico',
@@ -493,7 +581,7 @@ Tombloo.Service.extractors = new Repository([
 		
 		RE : new RegExp('^http://(?:.+?.)?static.flickr.com/\\d+?/(\\d+?)_.*'),
 		getImageId : function(ctx){
-			if(ctx.host == 'flickr.com' &amp;&amp; ctx.target.src.match('spaceball.gif')){
+			if(/flickr\.com/.test(ctx.host) &amp;&amp; ctx.target.src.match('spaceball.gif')){
 				removeElement(ctx.target);
 				
 				if(currentDocument().elementFromPoint){
@@ -667,7 +755,7 @@ Tombloo.Service.extractors = new Repository([
 		name : 'Photo - Picasa',
 		ICON : 'http://picasaweb.google.com/favicon.ico',
 		check : function(ctx){
-			return ctx.host == 'picasaweb.google.com' &amp;&amp; ctx.onImage;
+			return (/picasaweb\.google\./).test(ctx.host) &amp;&amp; ctx.onImage;
 		},
 		extract : function(ctx){
 			var item = $x('//span[@class=&quot;gphoto-context-current&quot;]/text()') || $x('//div[@class=&quot;lhcl_albumtitle&quot;]/text()') || '';
@@ -831,12 +919,11 @@ Tombloo.Service.extractors = new Repository([
 			return ctx.href.match(/share-image\.com\/gallery\//) &amp;&amp; this.getImage();
 		},
 		extract : function(ctx){
-			return request(this.getImage()).addCallback(function(res){
-				return {
-					type    : 'photo',
-					item    : ctx.title,
-					itemUrl : res.channel.URI.spec, 
+			return request(this.getImage()).addBoth(function(res){
+				ctx.target = {
+					src : (res instanceof Error? res.message : res).channel.URI.spec,
 				}
+				return Tombloo.Service.extractors['Photo - Upload from Cache'].extract(ctx);
 			});
 		},
 		getImage : function(){
@@ -945,6 +1032,7 @@ Tombloo.Service.extractors = new Repository([
 			'keep4u.ru/imgs/',
 			'/www.toofly.com/userGallery/',
 			'/www.dru.pl/',
+			'adugle.com/shareimagebig/',
 		],
 		check : function(ctx){
 			return ctx.onImage;</diff>
      <filename>xpi/chrome/content/library/31_Tombloo.Service.extractors.js</filename>
    </modified>
    <modified>
      <diff>@@ -127,7 +127,7 @@ resizer[dir=&quot;bottomright&quot;] {
 }
 
 #titlebar .widget{
-	cursor: default !important;
+	cursor: default;
 	margin-left: 10px;
 }
 </diff>
      <filename>xpi/chrome/content/quickPostForm.css</filename>
    </modified>
    <modified>
      <diff>@@ -346,6 +346,20 @@ FormPanel.prototype = {
 		signal(this, 'post');
 	},
 	
+	populateFields : function(ps){
+		if(!ps)
+			return;
+		
+		var self = this;
+		items(ps).forEach(function([name, value]){
+			var field = self.fields[name];
+			if(!field || !value)
+				return;
+			
+			field.value = value;
+		});
+	},
+	
 	createForm : function(){
 		var elmForm = this.elmForm;
 		var self = this;
@@ -417,6 +431,7 @@ FormPanel.prototype = {
 	addWidgetToTitlebar : function(elm){
 		addElementClass(elm, 'widget');
 		insertSiblingNodesBefore(document.getElementById('titleSpace'), elm);
+		return elm;
 	},
 	
 	toggleDetail : function(){
@@ -466,6 +481,10 @@ function EditableLabel(elmBox){
 }
 
 EditableLabel.prototype = {
+	set value(value){
+		return this.elmTextbox.value = value;
+	},
+	
 	get value(){
 		return this.elmTextbox.value;
 	},
@@ -575,13 +594,19 @@ function TagsPanel(elmPanel, formPanel){
 				
 				if(self.suggest){
 					self.showSuggestions(res);
-					self.finishLoading();
 				}
 				
-				if(res.duplicated)
-					self.showBookmarked();
+				if(res.duplicated){
+					self.formPanel.populateFields(res.form);
+					self.showBookmarked(res.editPage);
+				}
 			}).addErrback(function(e){
+				setTimeout(function(){
+					alert(self.tagProvider + ': ' + e.message);
+				}, 50);
 				error(e);
+			}).addBoth(function(){
+				self.finishLoading();
 			});
 		}
 	}, false);
@@ -592,6 +617,10 @@ function TagsPanel(elmPanel, formPanel){
 TagsPanel.prototype = {
 	elmTags : {},
 	
+	set value(values){
+		return this.elmCompletion.value = joinText(values, ' ');
+	},
+	
 	get value(){
 		return this.elmCompletion.values;
 	},
@@ -635,6 +664,7 @@ TagsPanel.prototype = {
 	showSuggestions : function(res){
 		var self = this;
 		withDocument(document, function(){
+			
 			// input&#12452;&#12505;&#12531;&#12488;&#12391;&#39640;&#36895;&#12395;&#12481;&#12455;&#12483;&#12463;&#12434;&#12377;&#12427;&#24517;&#35201;&#12364;&#12354;&#12427;&#12383;&#12417;&#12495;&#12483;&#12471;&#12517;&#12391;&#25345;&#12388;
 			self.elmTags = {};
 			
@@ -657,13 +687,20 @@ TagsPanel.prototype = {
 		});
 	},
 	
-	showBookmarked : function(){
+	showBookmarked : function(editPage){
 		var self = this;
 		withDocument(document, function(){
-			self.formPanel.addWidgetToTitlebar(IMAGE({
+			var elmStar = self.formPanel.addWidgetToTitlebar(IMAGE({
 				tooltiptext : getMessage('label.bookmarked'),
 				src : 'chrome://tombloo/skin/star.png',
 			}));
+			
+			if(editPage){
+				elmStar.style.cursor = 'pointer';
+				elmStar.addEventListener('click', function(){
+					addTab(editPage);
+				}, true);
+			}
 		});
 	},
 	
@@ -924,6 +961,10 @@ DescriptionBox.prototype = {
 		this.elmBox.hidden = this.hidden;
 	},
 	
+	set value(value){
+		return this.elmDescription.value = value;
+	},
+	
 	get value(){
 		return this.elmDescription.value;
 	},</diff>
      <filename>xpi/chrome/content/quickPostForm.js</filename>
    </modified>
    <modified>
      <diff>@@ -287,11 +287,14 @@ try {
 	is(repo.find('A|D').length, 2);
 	is(repo.find(/A|D/).length, 2);
 	
+	repo.extract = function(){};
 	repo.register({
 		name  : 'GHI',
 		check : function(c){},
 	}, 'DEF');
 	is(repo.names.join(), 'ABC,GHI,DEF', '&#36884;&#20013;&#12395;&#36861;&#21152;&#12391;&#12365;&#12427;&#12363;');
+	ok(repo.extract, '&#23450;&#32681;&#20197;&#22806;&#12398;&#12487;&#12540;&#12479;&#12364;&#28040;&#12360;&#12394;&#12356;&#12363;');
+	
 	
 	ok(getDataDir().exists(), '&#12487;&#12540;&#12479;&#12487;&#12451;&#12524;&#12463;&#12488;&#12522;&#12364;&#23384;&#22312;&#12377;&#12427;&#12363;');
 	</diff>
      <filename>xpi/chrome/content/test/test_utility.html</filename>
    </modified>
    <modified>
      <diff>@@ -6,7 +6,7 @@
 		&lt;em:id&gt;tombloo@brasil.to&lt;/em:id&gt;
 		&lt;em:type&gt;2&lt;/em:type&gt;
 		&lt;em:name&gt;Tombloo&lt;/em:name&gt;
-		&lt;em:version&gt;0.3.27&lt;/em:version&gt;
+		&lt;em:version&gt;0.3.28&lt;/em:version&gt;
 		&lt;em:creator&gt;to&lt;/em:creator&gt;
 		&lt;em:description&gt;&lt;/em:description&gt;
 		&lt;em:optionsURL&gt;chrome://tombloo/content/prefs.xul&lt;/em:optionsURL&gt;</diff>
      <filename>xpi/install.rdf</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>5be0c60b9fddac3c330c5f95bb73de567848dcf1</id>
    </parent>
    <parent>
      <id>6267c222a6bc78a8311bd2299dada9cdd211f53a</id>
    </parent>
  </parents>
  <author>
    <name>to</name>
    <email>ryutaro.kamitsu@gmail.com</email>
  </author>
  <url>http://github.com/to/tombloo/commit/4d5eacb51f4b757e9d3583fe3c15ed802f857817</url>
  <id>4d5eacb51f4b757e9d3583fe3c15ed802f857817</id>
  <committed-date>2009-01-18T00:17:14-08:00</committed-date>
  <authored-date>2009-01-18T00:17:14-08:00</authored-date>
  <message>Merge commit 'origin/master' into release</message>
  <tree>605282f71e7fbf4edec8b034a28fd0b842723361</tree>
  <committer>
    <name>to</name>
    <email>ryutaro.kamitsu@gmail.com</email>
  </committer>
</commit>
