author | Michael Krelin <hacker@klever.net> | 2006-09-26 19:21:57 (UTC) |
---|---|---|
committer | Michael Krelin <hacker@klever.net> | 2006-09-26 19:21:57 (UTC) |
commit | c5ea6ff7abd6e376ae151c9724d24f6fe156766e (patch) (side-by-side diff) | |
tree | 0df2e4ecf02f89c4b85d1950b5c6f4fd2f67f9bd /content | |
parent | 5207247fdc837ae9de1d81db903f6cd92532595e (diff) | |
download | fireflix-c5ea6ff7abd6e376ae151c9724d24f6fe156766e.zip fireflix-c5ea6ff7abd6e376ae151c9724d24f6fe156766e.tar.gz fireflix-c5ea6ff7abd6e376ae151c9724d24f6fe156766e.tar.bz2 |
Initial import into public repository0.0
git-svn-id: http://svn.klever.net/kin/fireflix/trunk@159 fe716a7a-6dde-0310-88d9-d003556173a8
-rw-r--r-- | content/Makefile.am | 22 | ||||
-rw-r--r-- | content/about.xul | 45 | ||||
-rw-r--r-- | content/autoconf.dtd.in | 3 | ||||
-rw-r--r-- | content/background.jpeg | bin | 0 -> 880 bytes | |||
-rw-r--r-- | content/browser.xul | 19 | ||||
-rw-r--r-- | content/copying.xul | 14 | ||||
-rw-r--r-- | content/fireflix-panel.xul | 252 | ||||
-rw-r--r-- | content/fireflix.css | 90 | ||||
-rw-r--r-- | content/fireflix.js | 878 | ||||
-rw-r--r-- | content/flickr.js | 403 | ||||
-rw-r--r-- | content/generated-content.js | 17 | ||||
-rw-r--r-- | content/generated-content.xul | 20 | ||||
-rw-r--r-- | content/icons/16x16/fireflix.png | bin | 0 -> 926 bytes | |||
-rw-r--r-- | content/icons/32x32/fireflix.png | bin | 0 -> 2017 bytes | |||
-rw-r--r-- | content/md5.js | 154 | ||||
-rw-r--r-- | content/photoset-props.js | 81 | ||||
-rw-r--r-- | content/photoset-props.xul | 38 |
17 files changed, 2036 insertions, 0 deletions
diff --git a/content/Makefile.am b/content/Makefile.am new file mode 100644 index 0000000..8548400 --- a/dev/null +++ b/content/Makefile.am @@ -0,0 +1,22 @@ +xpichromecontent_DATA = \ + autoconf.dtd \ + browser.xul about.xul fireflix-panel.xul photoset-props.xul \ + generated-content.xul \ + photoset-props.js fireflix.js flickr.js md5.js \ + generated-content.js \ + fireflix.css \ + background.jpeg + +sized_icons = \ + $(addsuffix .png, \ + fireflix \ + ) + +nobase_xpichromecontent_DATA = \ + $(addprefix icons/, \ + $(addprefix 16x16/,${sized_icons}) \ + $(addprefix 32x32/,${sized_icons}) \ + ) + +EXTRA_DIST = \ + ${xpichromecontent_DATA} ${nobase_xpichromecontent_DATA} diff --git a/content/about.xul b/content/about.xul new file mode 100644 index 0000000..1cb13d4 --- a/dev/null +++ b/content/about.xul @@ -0,0 +1,45 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> +<?xml-stylesheet href="fireflix.css" type="text/css"?> +<!DOCTYPE window SYSTEM "chrome://fireflix/locale/fireflix.dtd"> +<window + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + id="aboutFireflix" title="&aboutFireflix;" + orient="vertical" + width="400" height="200" + > + + <hbox class="about wholething" flex="1"> + <hbox flex="1" class="insides"> + <vbox> + <spacer flex="1"/> + <image src="icons/32x32/fireflix.png" width="32" height="32" /> + <spacer flex="1"/> + </vbox> + <groupbox flex="1" class="text" orient="vertical"> + <spacer flex="2"/> + <hbox> + <spacer flex="1"/> + <label value="Fireflix &autoconf.version;" class="title"/> + <spacer flex="1"/> + </hbox> + <spacer flex="1"/> + <hbox> + <label value="Copyright © 2006 "/> + <label value="Klever Group" class="link" + onclick="window.openDialog('chrome://browser/content/browser.xul','_blank','chrome,all,dialog=no','http://www.klever.net/',null,null)" /> + </hbox> + <spacer flex="2"/> + </groupbox> + <vbox> + <spacer flex="10" /> + <button label="&about.license.label;" tooltiptext="&about.license.tip;" + oncommand="window.openDialog('chrome://fireflix/content/copying.xul','copying')" /> + <spacer flex="2" /> + <button label="OK" oncommand="window.close()"/> + <spacer flex="1" /> + </vbox> + </hbox> + </hbox> + +</window> diff --git a/content/autoconf.dtd.in b/content/autoconf.dtd.in new file mode 100644 index 0000000..e4ad217 --- a/dev/null +++ b/content/autoconf.dtd.in @@ -0,0 +1,3 @@ +<!ENTITY autoconf.version "@VERSION@"> +<!ENTITY autoconf.package "@PACKAGE@"> +<!ENTITY autoconf.copying "@COPYING@"> diff --git a/content/background.jpeg b/content/background.jpeg Binary files differnew file mode 100644 index 0000000..43684f7 --- a/dev/null +++ b/content/background.jpeg diff --git a/content/browser.xul b/content/browser.xul new file mode 100644 index 0000000..aaff443 --- a/dev/null +++ b/content/browser.xul @@ -0,0 +1,19 @@ +<?xml version="1.0"?> +<!DOCTYPE overlay SYSTEM "chrome://fireflix/locale/fireflix.dtd"> +<overlay id="fireflixOverlay" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" > + + <menupopup id="viewSidebarMenu"> + <menuitem observes="viewFireflixSidebar" /> + </menupopup> + + <broadcasterset id="mainBroadcasterSet"> + <broadcaster id="viewFireflixSidebar" + autoCheck="false" label="&browser.sidebar.label;" + type="checkbox" group="sidebar" + sidebarurl="chrome://fireflix/content/fireflix-panel.xul" + sidebartitle="&browser.sidebar.title;" + oncommand="toggleSidebar('viewFireflixSidebar')" /> + </broadcasterset> +</overlay> + diff --git a/content/copying.xul b/content/copying.xul new file mode 100644 index 0000000..179dca5 --- a/dev/null +++ b/content/copying.xul @@ -0,0 +1,14 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> +<?xml-stylesheet href="fireflix.css" type="text/css"?> +<!DOCTYPE dialog SYSTEM "chrome://fireflix/locale/fireflix.dtd"> +<dialog + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + id="copying" title="©ing.title;" orient="vertical" + buttons="accept"> + + <div xmlns="http://www.w3.org/1999/xhtml"> + &autoconf.copying; + </div> + +</dialog> diff --git a/content/fireflix-panel.xul b/content/fireflix-panel.xul new file mode 100644 index 0000000..9953761 --- a/dev/null +++ b/content/fireflix-panel.xul @@ -0,0 +1,252 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> +<?xml-stylesheet href="fireflix.css" type="text/css"?> +<!DOCTYPE page SYSTEM "chrome://fireflix/locale/fireflix.dtd"> +<page + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + id="fireflixwindow" title="Fireflix" + onload="fireflix.init()" + orient="vertical" + ondragover="nsDragAndDrop.dragOver(event,fireflix.uploadObserver)" + ondragdrop="nsDragAndDrop.drop(event,fireflix.uploadObserver)" + > + + <script src="chrome://global/content/nsDragAndDrop.js"/> + <script src="chrome://global/content/nsTransferable.js"/> + <script type="application/x-javascript" src="md5.js" /> + <script type="application/x-javascript" src="flickr.js" /> + <script type="application/x-javascript" src="fireflix.js" /> + + <stringbundleset> + <stringbundle id="loc_strings" src="chrome://fireflix/locale/fireflix.properties" /> + </stringbundleset> + + <commandset id="cmdset_search"> + <command id="cmd_search" label="&panel.search.cmd_search.label;" + oncommand="fireflix.foundphotos.search_photos()"/> + <command id="cmd_search_open" label="&panel.search.cmd_search_open.label;" + oncommand="fireflix.foundphotos.on_cmd_open(event)" /> + </commandset> + + <commandset id="cmdset_sets"> + <command id="cmd_refresh_sets" label="&panel.sets.cmd_refresh_sets;" + oncommand="fireflix.on_refresh_sets()" /> + <command id="cmd_set_props" label="&panel.sets.cmd_properties;" + oncommand="fireflix.on_set_props()" disabled="true" /> + </commandset> + + <popupset> + <popup id="sets_menu"> + <menuitem command="cmd_set_props"/> + <menuitem command="cmd_refresh_sets"/> + <menuseparator/> + <menu label="&panel.sets.generate_html;" id="sets_html_menu"/> + </popup> + </popupset> + + <commandset id="cmdset_uploads"> + <command id="cmd_uploads_clear" label="&panel.uploads.clear.label;" + oncommand="fireflix.uploads.on_clear()" /> + <command id="cmd_uploads_upload" label="&panel.uploads.upload.label;" + oncommand="fireflix.uploads.on_upload()" /> + <command id="cmd_uploads_remove" label="&panel.uploads.remove.label;" + oncommand="fireflix.uploads.on_remove()" /> + <command id="cmd_uploads_add" label="&panel.uploads.add.label;" + oncommand="fireflix.uploads.on_add()" /> + </commandset> + + <popupset> + <popup id="uploads_menu"> + <menuitem command="cmd_uploads_add"/> + <menuitem command="cmd_uploads_clear"/> + <menuitem command="cmd_uploads_remove"/> + <menuseparator/> + <menuitem command="cmd_uploads_upload"/> + <menuseparator/> + <menu label="&panel.uploads.generate_html;" id="uploads_html_menu"/> + </popup> + </popupset> + + <vbox class="wholething" flex="1"> + + <groupbox> + <caption label="&panel.auth_info;"/> + <hbox> + <label id="auth_info" value="&panel.no_auth_info;" flex="1" disabled="true"/> + <button id="b_auth" label="&panel.auth_button;" oncommand="fireflix.on_auth()"/> + <button id="b_auth_done" label="&panel.auth_complete_button;" hidden="true" + oncommand="fireflix.on_auth_done()"/> + <button label="&panel.flickr_button.label;" + tooltiptext="&panel.flickr_button.tip;" + oncommand="fireflix.openTab('http://www.flickr.com/')" /> + </hbox> + </groupbox> + + <tabbox flex="1" id="fireflix_tabs"> + + <tabs> + <tab label="&panel.tabs.search;"/> + <tab label="&panel.tabs.sets;"/> + <tab label="&panel.tabs.tags;" hidden="true"/> <!-- TODO: --> + <tab id="tab_upload" label="&panel.tabs.upload;"/> + </tabs> + + <tabpanels flex="1"> + + <tabpanel id="tabpanel_search" flex="1"> + <vbox flex="1"> + <groupbox class="search_params" orient="vertical" onkeypress="if(event.keyCode==event.DOM_VK_RETURN) fireflix.foundphotos.search_photos()"> + <hbox> + <label control="search_for" value="&panel.search.search_for.label;" + accesskey="s"/> + <textbox id="search_for" flex="1"/> + </hbox> + <hbox> + <checkbox id="search_tags" label="&panel.search.mode.tagsonly.label;" + tooltiptext="&panel.search.mode.tagsonly.tip;" checked="false" + accesskey="t" /> + <checkbox id="search_mine" label="&panel.search.mode.mine.label;" checked="true" accesskey="m"/> + <spacer flex="1"/> + <button command="cmd_search"/> + </hbox> + </groupbox> + <tree id="searchresults" rows="4" flex="1" + onselect="fireflix.foundphotos.on_select()" + ondblclick="fireflix.foundphotos.on_cmd_open(event)" + onkeypress="if(event.keyCode==event.DOM_VK_RETURN) + fireflix.foundphotos.on_cmd_open(event)"> + <treecols> + <treecol id="sr_title" label="&panel.search.col.title.label;" flex="2" crop="end" align="start" /> + </treecols> + <treechildren/> + </tree> + <groupbox id="searchresult_props" orient="horizontal" hidden="true"> + <vbox width="100" pack="center"> + <hbox pack="center"> + <image id="search_photo"/> + </hbox> + </vbox> + <vbox flex="1"> + <label id="searchresult_title"/> + <textbox flex="1" multiline="true" class="plain" readonly="true" id="searchresult_description"/> + <hbox pack="end"> + <button command="cmd_search_open"/> + </hbox> + </vbox> + </groupbox> + </vbox> + </tabpanel> + + <tabpanel id="tabpanel_sets" flex="1" + onkeypress="if(event.keyCode==event.DOM_VK_RETURN) + document.getElementById('setphotos').focus()"> + <vbox flex="1"> + <tree id="setslist" rows="4" onselect="fireflix.photosets.on_select()" + flex="1" context="sets_menu" + > + <treecols> + <treecol id="sl_name" label="&panel.sets.name.label;" flex="4" crop="end" align="start" tooltiptext="&panel.sets.name.tip;"/> + <splitter class="tree-splitter" /> + <treecol id="sl_photos" label="&panel.sets.photos.label;" flex="1" align="end" tooltiptext="&panel.sets.photos.tip;" /> + </treecols> + <treechildren/> + </tree> + <hbox> + <button command="cmd_refresh_sets" /> + <button command="cmd_set_props" /> + </hbox> + <tree id="setphotos" rows="4" onselect="fireflix.photoset.on_select()" + flex="1"> + <treecols> + <treecol id="sp_title" label="&panel.setphotos.title.label;" flex="1" crop="end" align="start" tooltiptext="&panel.setphotos.title.tip;" /> + <splitter class="tree-splitter" /> + <treecol id="sp_taken" label="&panel.setphotos.taken.label;" crop="end" align="start" tooltiptext="&panel.setphotos.taken.tip;" hidden="true" /> + <treecol id="sp_upload" label="&panel.setphotos.upload.label;" crop="end" align="start" tooltiptext="&panel.setphotos.upload.tip;" hidden="true" /> + </treecols> + <treechildren/> + </tree> + <groupbox id="set_photo_props" orient="horizontal"> + <vbox width="100" pack="center"> + <hbox pack="center"> + <image id="set_photo" hidden="true"/> + </hbox> + </vbox> + <spacer flex="1"/> + </groupbox> + </vbox> + </tabpanel> + + <tabpanel id="tabpanel_tags"> + <listbox id="tagslist" rows="8" flex="1"> + <listhead> + <listheader label="&panel.tagslist.tag.label;"/> + </listhead> + <listcols> + <listcol flex="1"/> + </listcols> + </listbox> + </tabpanel> + + <tabpanel id="tabpanel_upload"> + <vbox flex="1"> + <tree id="uploadlist" rows="8" flex="1" + onselect="fireflix.uploads.selectionChanged()" + context="uploads_menu"> + <treecols> + <treecol id="up_file" label="&panel.uploadlist.file.label;" flex="4" crop="start" align="start"/> + <splitter class="tree-splitter" /> + <treecol id="up_title" label="&panel.uploadlist.title.label;" flex="5" crop="end" align="start" /> + <splitter class="tree-splitter" /> + <treecol id="up_status" label="&panel.uploadlist.status.label;" flex="1" crop="end" align="start" /> + </treecols> + <treechildren/> + </tree> + <progressmeter id="upload_progress" mode="undetermined" hidden="true" /> + <groupbox id="upload_file_props" orient="horizontal" hidden="true"> + <image id="upload_file_preview" width="100" height="100" /> + <grid flex="1"> + <columns> + <column/> + <column flex="1"/> + </columns> + <rows> + <row> + <label control="upload_filename" + value="&panel.upload_props.filename.label;" /> + <textbox id="upload_filename" + oninput="fireflix.uploads.propsToSel('filename')"/> + </row> + <row> + <label control="upload_title" value="&panel.upload_props.title.label;" /> + <textbox id="upload_title" + oninput="fireflix.uploads.propsToSel('title')"/> + </row> + <row> + <label control="uplod_tags" value="&panel.upload_props.tags.label;" /> + <textbox id="upload_tags" + oninput="fireflix.uploads.propsToSel('tags')"/> + </row> + <!-- TODO: description, public, friend, family --> + </rows> + </grid> + </groupbox> + <hbox> + <button command="cmd_uploads_add" /> + <spacer flex="1"/> + <button command="cmd_uploads_remove" /> + <spacer flex="1"/> + <button command="cmd_uploads_clear" /> + </hbox> + <hbox pack="center"> + <button command="cmd_uploads_upload" flex="1"/> + </hbox> + </vbox> + </tabpanel> + + </tabpanels> + + </tabbox> + + </vbox> + +</page> diff --git a/content/fireflix.css b/content/fireflix.css new file mode 100644 index 0000000..188f48e --- a/dev/null +++ b/content/fireflix.css @@ -0,0 +1,90 @@ +.generated.wholething, +.about.wholething, +tabbox, tabpanels, tabpanel { + background: url("background.jpeg"); +} +tabpanels { + padding: 0px; +} + +tree { + margin-top: 2px; + background: rgb(12,167,0); + color: rgb(255,255,0); + font-size: 90%; +} +tree treechildren { /* for windows */ + background: rgb(12,167,0); +} + +tree#uploadlist treechildren::-moz-tree-cell-text(pending) { +} +tree#uploadlist treechildren::-moz-tree-cell-text(completed) { + color: white; +} +tree#uploadlist treechildren::-moz-tree-row(failed) { + background: yellow; +} +tree#uploadlist treechildren::-moz-tree-cell-text(failed) { + color: red; +} +tree#uploadlist treechildren::-moz-tree-cell-text(uploading) { + font-weight: bold; +} + +groupbox#searchresult_props, +groupbox.search_params, +groupbox#upload_file_props, +groupbox#set_props, +groupbox#set_photo_props { + background: white; +} + +groupbox#upload_file_props label { + text-align: right; +} + +image#set_photo, image#set_primary { + border: black 1px solid; +} + +.about .insides { + margin: 1ex; +} +.about .text { + border: yellow solid 1px; + background: green; +} +.about .title { + font-size: 300%; + font-weight: bold; + color: yellow; +} +.about .link { + text-decoration: underline; + color: white; + cursor: pointer; +} + +menuitem.menuhead { + background: gray; + color: black; + font-weight: bold; +} + +label#searchresult_description { + font-weight: bold; +} +textbox#searchresult_description { + padding: 1px 3px !important; + background: white; +} + +#copying div { + margin: 1ex 1em; + font-family: courier, monospace; + font-size: 9pt; + padding: 2px; + border: dotted 1px gray; + background: white; +} diff --git a/content/fireflix.js b/content/fireflix.js new file mode 100644 index 0000000..9518480 --- a/dev/null +++ b/content/fireflix.js @@ -0,0 +1,878 @@ +function splitascii(s) { + var rv=''; + for(var i=0;i<s.length;++i) { + var w = s.charCodeAt(i); + rv += String.fromCharCode( + w&0xff, (w>>8)&0xff ); + } + return rv; +} + + +var fireflix = { + flickr: new Flickr(), + init: function() { + this.loc_strings = document.getElementById('loc_strings'); + this.build_menus(); + this.cmd_set_props = document.getElementById('cmd_set_props'); + this.foundphotos.init(this); + this.photosets.init(this); + this.photoset.init(this); + this.uploads.init(this); + this.uploadObserver.init(this); + this.flickr.api_key = '9c43cd66947a57e6f29db1a9da3f72e3'; + this.flickr.api_shs = '9c33c9e2f0f0cfd5'; + this.flickr.prefs_root = 'net.klever.kin.fireflix'; + this.flickr.load_token(); + document.getElementById('setslist').view = this.photosets; + document.getElementById('setphotos').view = this.photoset; + document.getElementById('uploadlist').view = this.uploads; + this.flickr.no_auth_info_label = document.getElementById('auth_info').value; + if(this.flickr.token) { + this.refresh_stuff(); + document.getElementById('auth_info').value = + this.flickr.user.fullname+' ['+this.flickr.user.username+']'; + document.getElementById('auth_info').disabled = false; + document.getElementById('b_auth').hidden = true; + } + }, + on_auth: function() { + var _this = this; + this.flickr.authorize_0( + function() { + document.getElementById('b_auth').hidden = true; + document.getElementById('b_auth_done').hidden = false; + }, function(x,s,c,m) { + _this.flickr_failure(x,s,c,m); + } + ); + }, + on_auth_done: function() { + document.getElementById('b_auth_done').hidden = true; + var _this = this; + this.flickr.authorize_1( + function() { + _this.flickr.save_token(); + _this.refresh_stuff(); + document.getElementById('auth_info').value = + _this.flickr.user.fullname+' ['+_this.flickr.user.username+']'; + document.getElementById('auth_info').disabled = false; + }, function(x,s,c,m) { + document.getElementById('b_auth').hidden = false; + _this.flickr_failure(x,s,c,m); + } + ); + }, + + refresh_sets: function() { this.photosets.refresh_sets(); }, + refresh_stuff: function() { + this.refresh_sets(); + this.refresh_user_tags(); + }, + + /* photoset treeview */ + photoset: { + photos: new Array(), + fireflix: null, + init: function(f) { + this.fireflix = f; + }, + rowCount: 0, + getCellText: function(r,c) { + var p = this.photos[r]; + if(c.id=='sp_title') return p.title; + if(c.id=='sp_taken') return p.datetaken; + if(c.id=='sp_upload') return p.dateupload; /* TODO: unixtime conversion */ + return c.id; + }, + setTree: function(t) { this.tree = t }, + isContainer: function(r) { return false; }, + isSeparator: function(r) { return false; }, + isSorted: function(r) { return false; }, + getLevel: function(r) { return 0; }, + getImageSrc: function(r,c) { return null }, + getRowProperties: function(r,p) {}, + getCellProperties: function(cid,cel,p) {}, + getColumnProperties: function(cid,cel,p) { }, + cycleHeader: function(cid,e) { }, + getParentIndex: function(r) { return -1; }, + drop: function(r,o) { }, + canDropBeforeAfter: function(r,b) { return false }, + + importXPR: function(xp) { + this.tree.beginUpdateBatch(); + this.photos = new Array(); + var n; while(n=xp.iterateNext()) { + this.photos.push(new Photo(n)); + } + this.rowCount = this.photos.length; + this.tree.endUpdateBatch(); + }, + load_photos: function(psid) { + var _this = this; + this.fireflix.flickr.api_call( + { + method: 'flickr.photosets.getPhotos', + auth_token: 'default', + photoset_id: psid, + extras: 'license,date_upload,date_taken,owner_name,icon_server,original_format,last_update' + }, function(xr) { + var x = xr.responseXML; + var xp = x.evaluate( + '/rsp/photoset/photo', x, null, + XPathResult.ORDERED_NODE_ITERATOR_TYPE, null ); + _this.importXPR(xp); + }, function(x,s,c,m) { + _this.fireflix.flickr_failure(x,s,c,m); + } + ); + }, + on_select: function() { + if(this.selection.count==1) { + var p = this.photos[this.selection.currentIndex]; + document.getElementById('set_photo').src = + this.fireflix.flickr.get_photo_url(p.server,p.id,p.secret,'t'); + document.getElementById('set_photo').hidden = false; + }else{ + document.getElementById('set_photo').hidden = true; + } + } + }, + + /* photosets treeview */ + photosets: { + sets: new Array(), + fireflix: null, + init: function(f) { + this.fireflix = f; + }, + rowCount: 0, + getCellText: function(r,c) { + var s = this.sets[r]; + if(c.id=='sl_name') return s.title; + if(c.id=='sl_photos') return s.photos; + return c.id; + }, + setTree: function(t) { this.tree = t }, + isContainer: function(r) { return false; }, + isSeparator: function(r) { return false; }, + isSorted: function() { return false; }, + getLevel: function(r) { return 0; }, + getImageSrc: function(r,c) { return null }, + getRowProperties: function(r,p) {}, + getCellProperties: function(cid,cel,p) { }, + getColumnProperties: function(cid,cel,p) { }, + cycleHeader: function(cid,e) { }, + getParentIndex: function(r) { return -1; }, + drop: function(r,o) { }, + canDropBeforeAfter: function(r,b) { return false }, + + importXPR: function(xp) { + this.tree.beginUpdateBatch(); + this.sets = new Array(); + var n; while(n=xp.iterateNext()) { + this.sets.push(new Photoset(n)); + } + this.rowCount = this.sets.length; + this.tree.endUpdateBatch(); + }, + refresh_sets: function() { + var _this = this; + this.fireflix.flickr.api_call( + { + method: 'flickr.photosets.getList', + auth_token: 'default' + }, function(xr) { + var x = xr.responseXML; + var xp = x.evaluate( + '/rsp/photosets/photoset', x, null, + XPathResult.ORDERED_NODE_ITERATOR_TYPE, null ); + _this.importXPR(xp); + }, function(x,s,c,m) { + _this.fireflix.flickr_failure(x,s,c,m); + } + ); + }, + on_select: function() { + if(this.selection.count==1) { + this.fireflix.cmd_set_props.setAttribute('disabled','false'); + var s = this.sets[this.selection.currentIndex]; + this.fireflix.photoset.load_photos(s.id); + }else{ + this.fireflix.cmd_set_props.setAttribute('disabled','true'); + } + } + }, + + refresh_user_tags: function() { + var lb = document.getElementById('tagslist'); + var _this = this; + this.flickr.api_call( + { + method: 'flickr.tags.getListUser', + auth_token: 'default', + }, function(xr) { + var x = xr.responseXML; + var xp = x.evaluate( + '/rsp/who/tags/tag', x, null, + XPathResult.ORDERED_NODE_ITERATOR_TYPE, null ); + // TODO: clear list + var n; while(n=xp.iterateNext()) { + lb.appendItem(n.firstChild.nodeValue); + } + }, function(x,s,c,m) { + _this.flickr_failure(x,s,c,m); + } + ); + }, + + uploadObserver: { + fireflix: null, + init: function(f) { + this.fireflix = f; + }, + getSupportedFlavours: function() { + var rv = new FlavourSet(); + rv.appendFlavour('application/x-moz-file','nsIFile'); + rv.appendFlavour('application/x-moz-url'); + rv.appendFlavour('text/uri-list'); + rv.appendFlavour('text/unicode'); + return rv; + }, + canHandleMultipleItems: true, + onDragOver: function(ev,fl,sess) { + return true; + }, + onDrop: function(ev,dd,s) { + var ldf = null; + for(var i in dd.dataList) { + var di = dd.dataList[i]; + var dif = di.first; + if( + ldf==null + || ldf.flavour.contentType!=dif.flavour.contentType + || ldf.contentLength!=dif.contentLength + || ldf.data!=dif.data ) + this.drop_item(ev,di,s); + ldf = dif; + } + }, + drop_item: function(ev,di,s) { + var d = di.first; + switch(d.flavour.contentType) { + case 'text/unicode': + this.drop_urilist(ev,d.data,s); + break; + case 'application/x-moz-file': + this.fireflix.uploads.add(d.data.path); + document.getElementById('fireflix_tabs').selectedTab + = document.getElementById('tab_upload'); + break; + case 'text/uri-list': + // is it ascii or could it be utf8? + this.drop_urilist(ev,splitascii(d.data),s); + break; + default: alert(d.flavour.contentType+':'+d.data); break; + }; + }, + drop_urilist: function(ev,ul,s) { + // TODO: check for being a file? + var us = decodeURIComponent(ul).split(/[\r\n]/); + for(var ui in us) + if(/\S/.test(us[ui])) + this.fireflix.uploads.add(us[ui]); + document.getElementById('fireflix_tabs').selectedTab + = document.getElementById('tab_upload'); + } + }, + + uploads: { + fireflix: null, + init: function(f) { + this.fireflix=f; + this.upload_filename = document.getElementById('upload_filename'); + this.upload_title = document.getElementById('upload_title'); + this.upload_file_preview = document.getElementById('upload_file_preview'); + this.upload_file_props = document.getElementById('upload_file_props'); + this.upload_progress = document.getElementById('upload_progress'); + this.upload_tags = document.getElementById('upload_tags'); + }, + files: new Array(), + rowCount: 0, + getCellText: function(r,c) { + var f = this.files[r]; + if(c.id=='up_file') return f.file; + if(c.id=='up_title') return f.title; + if(c.id=='up_status') return f.state; + return c.id; + }, + setTree: function(t) { this.tree = t }, + isContainer: function(r) { return false; }, + isSeparator: function(r) { return false; }, + isSorted: function(r) { return false; }, + getLevel: function(r) { return 0; }, + getImageSrc: function(r,c) { return null }, + getRowProperties: function(r,p) { + try { + if(!Components) return; + }catch(e) { return } + var f = this.files[r]; + var as = Components.classes['@mozilla.org/atom-service;1']. + getService(Components.interfaces.nsIAtomService); + p.AppendElement(as.getAtom(f.state)); + }, + getCellProperties: function(r,c,p) { this.getRowProperties(r,p); }, + getColumnProperties: function(c,p) { }, + cycleHeader: function(cid,e) { }, + getParentIndex: function(r) { return -1; }, + drop: function(r,o) { }, + canDropBeforeAfter: function(r,b) { return false }, + + add: function(f) { + if(f.indexOf('file:/')==0) { + f = f.substr(5); + while(f.substr(0,2)=='//') { // XXX: not very performant, is it? ;-) + f = f.substr(1); + } + } + var t = f; + var ls = t.lastIndexOf('/'); + if(ls>0) t = t.substr(ls+1); + ls = t.lastIndexOf('\\'); + if(ls>0) t = t.substr(ls+1); + var ld = t.lastIndexOf('.'); + if(ld>0) t = t.substr(0,ld); + this.files.push( { + file: f, + title: t, + tags: '', + state: 'pending' + } ); + this.rowCount = this.files.length; + this.tree.rowCountChanged(this.rowCount-1,1); + }, + + upload_worker: function() { + for(var f in this.files) { + if(this.files[f].state=='pending') { + var ff = this.files[f]; + dump('upload '+ff.file+'\n'); + this.on_file_upload(ff); + ff.state='uploading'; + this.tree.invalidate(); + var _this = this; + this.fireflix.flickr.upload_file( + ff.file, { title: ff.title, tags: ff.tags }, + function(x,p) { + ff.photoid = p; + _this.batch_ids.push(p); + ff.state='completed'; + _this.tree.invalidate(); + window.setTimeout(_this.upload_to,0,_this); + }, function(x,s,c,m) { + ff.state='failed'; + ff.flickr_errcode = c; + ff.flickr_errmsg = m; + _this.tree.invalidate(); + window.setTimeout(_this.upload_to,0,_this); + } + ); + return; + } + } + dump('uploading done\n'); + this.on_finish_upload(); + }, + upload_to: function(_this) { _this.upload_worker(); }, + on_file_upload: function(f) { + document.getElementById('cmd_uploads_upload').setAttribute('disabled','true'); + for(var fi in this.files) { + if(this.files[fi].file==f.file) { + this.tree.ensureRowIsVisible(fi); + this.selection.rangedSelect(fi,fi,false); + this.selection.currentIndex = fi; + this.selToProps(); + break; + } + } + }, + on_finish_upload: function() { + if(this.batch_ids.length) { + var psn = prompt(this.fireflix.loc_strings.getString('postUploadPhotoset')); + if(psn!=null) { + var pids = this.batch_ids.join(','); + var ppid = this.batch_ids[0]; + var _this = this; + this.fireflix.flickr.api_call( + { + method: 'flickr.photosets.create', + auth_token: 'default', + title: psn, + primary_photo_id: ppid + }, function(x) { + var npid = + x.responseXML.getElementsByTagName('photoset').item(0).getAttribute('id'); + _this.fireflix.flickr.api_call( + { + method: 'flickr.photosets.editPhotos', + auth_token: 'default', + photoset_id: npid, + primary_photo_id: ppid, + photo_ids: pids + }, function(x) { + _this.fireflix.refresh_sets(); + }, function(x,s,c,m) { + _this.fireflix.flickr_failure(x,s,c,m); + } + ); + }, function(x,s,c,m) { + _this.fireflix.flickr_failure(x,s,c,m); + } + ); + } + } + this.selection.clearSelection(); + document.getElementById('cmd_uploads_upload').setAttribute('disabled','false'); + this.upload_progress.setAttribute('hidden','true'); + }, + + clear_list: function() { + this.tree.beginUpdateBatch(); + this.rowCount = 0; + this.files = new Array(); + this.tree.endUpdateBatch(); + this.selToProps(); + }, + selectionChanged: function() { + this.selToProps(); + }, + disableProps: function() { + this.upload_filename.value=''; + this.upload_filename.disabled = true; + this.upload_title.value=''; + this.upload_title.disabled = true; + this.upload_file_preview.src = null; + this.upload_file_props.hidden = true; + this.upload_tags.value=''; + this.upload_tags.disabled = true; + }, + selToProps: function() { + if(!this.selection.count) { + this.disableProps(); + }else if(this.selection.count==1) { + var f=this.files[this.selection.currentIndex]; + if(f==null || f.state!='pending') { + this.disableProps(); + }else{ + this.upload_filename.value = f.file; + this.upload_filename.disabled = false; + this.upload_title.value = f.title; + this.upload_title.disabled = false; + this.upload_file_preview.src = 'file:///'+f.file; + this.upload_file_props.hidden = false; + this.upload_tags.value = f.tags; + this.upload_tags.disabled = false; + } + }else{ + var ftitle = null; var onetitle = true; + var ftags = null; var onetag = true; + var fs = 0; + for(var ff in this.files) { + if(this.selection.isSelected(ff) && this.files[ff].state=='pending' ) { + ++fs; + if(ftitle==null) { + ftitle = this.files[ff].title; + }else if(ftitle!=this.files[ff].title) { + onetitle = false; + } + if(ftags==null) { + ftags = this.files[ff].tags; + }else if(ftags!=this.files[ff].tags) { + onetag = false; + } + } + } + if(fs) { + this.upload_filename.value=''; + this.upload_filename.disabled = true; + if(onetitle) + this.upload_title.value = ftitle; + this.upload_title.disabled = false; + if(onetag) + this.upload_tags.value = ftags; + this.upload_tags.disabled = false; + this.upload_file_preview.src = null; + this.upload_file_props.hidden = false; + }else + this.disableProps(); + } + }, + propsToSel: function(prop) { + if(this.selection.count<=0) return; + for(var ff in this.files) { + if(this.selection.isSelected(ff) && this.files[ff].state=='pending') { + if(prop=='filename') + this.files[ff].file = this.upload_filename.value; + if(prop=='title') + this.files[ff].title = this.upload_title.value; + if(prop=='tags') + this.files[ff].tags = this.upload_tags.value; + this.tree.invalidateRow(ff); + } + } + }, + + on_upload: function() { + this.selToProps(); + this.batch_ids = new Array(); + this.upload_progress.value=0; + this.upload_progress.setAttribute('hidden','false'); + this.upload_worker(); + }, + on_clear: function() { + this.clear_list(); + }, + on_remove: function() { + if(this.selection.count) { + this.tree.beginUpdateBatch(); + for(var i=this.files.length-1;i>=0;--i) { + if(this.selection.isSelected(i)) { + this.files.splice(i,1); + this.rowCount--; + } + } + this.tree.endUpdateBatch(); + this.selection.clearSelection(); + } + }, + on_add: function() { + var ifp = Components.interfaces.nsIFilePicker; + var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(ifp); + fp.init(window, "Select a File", ifp.modeOpenMultiple); + fp.appendFilters(ifp.filterImages); + var rv = fp.show(); + if(rv==ifp.returnOK) { + var ff = fp.files; + while(ff.hasMoreElements()) { + var f = ff.getNext(); + f.QueryInterface(Components.interfaces.nsIFile); + this.add(f.path); + } + } + } + }, + + on_set_props: function() { + var pset = this.photosets.sets[this.photosets.selection.currentIndex]; + window.openDialog( + "chrome://fireflix/content/photoset-props.xul", + null, "dependent,modal,dialog,chrome", this, + pset ); + if(pset.dirty) { + var _this = this; + this.flickr.api_call( + { + method: 'flickr.photosets.editMeta', + auth_token: 'default', + photoset_id: pset.id, + title: pset.title, + description: pset.description + }, function(xr) { + pset.dirty = false; + _this.flickr.api_call( + { + method: 'flickr.photosets.getPhotos', + auth_token: 'default', + photoset_id: pset.id + }, function(xr) { + var x = xr.responseXML; + var xp = x.evaluate( + '/rsp/photoset/photo', x, null, + XPathResult.ORDERED_NODE_ITERATOR_TYPE, null ); + var phids = new Array(); + var priph = null; + var n; while(n=xp.iterateNext()) { + var pid = n.getAttribute('id'); + phids.push( pid ); + if(pid==pset.primary && n.getAttribute('isprimary')!='1') + priph = pid; + } + if(priph) { + _this.flickr.api_call( + { + method: 'flickr.photosets.editPhotos', + auth_token: 'default', + photoset_id: pset.id, + primary_photo_id: priph, + photo_ids: phids.join(',') + }, function() { }, function(x,s,c,m) { /* flickr.photosets.editPhotos */ + _this.flickr_failure(x,s,c,m); + } + ); + } + }, function(x,s,c,m) { /* flickr.photosets.getPhotos */ + _this.flickr_failure(x,s,c,m); + } + ); + }, function(x,s,c,m) { /* flickr.photosets.editMeta */ + _this.flickr_failure(x,s,c,m); + } + ); + } + }, + on_refresh_sets: function() { + this.refresh_sets(); + }, + on_cmd_sets_html: function(csfx,ev) { + var uti = csfx.charAt(0); var utl = csfx.charAt(1); + var rv = this.build_html(this.photoset.photos,uti,utl); + this.popup_content(rv); + }, + + on_cmd_uploads_html: function(csfx,ev) { + var uti = csfx.charAt(0); var utl = csfx.charAt(1); + var pids = new Array(); + for(var f in this.uploads.files) { + if(this.uploads.selection.isSelected(f)) + if(this.uploads.files[f].photoid) + pids.push(this.uploads.files[f].photoid); + } + var pp = this.uploads.rowCount*2; if(pp>500) pp = 500; + var _this = this; + this.flickr.api_call( + { + method: 'flickr.photos.search', + auth_token: 'default', + extras: 'original_format', + user_id: 'me', + per_page: pp + }, + function(xr) { + var x = xr.responseXML; + var rv = ''; + for(var pn in pids) { + var p = pids[pn]; + var pp = new Photo(xp_node('/rsp/photos/photo[@id='+p+']',x)); + rv += _this.photo_html(pp,uti,utl)+'\n'; + } + _this.popup_content(rv); + }, function(x,s,c,m) { + _this.flickr_failure(x,s,c,m); + } + ); + }, + + /* + * + */ + foundphotos: { + fireflix: null, + init: function(f) { + this.fireflix = f; + this.search_for = document.getElementById('search_for'); + this.search_tags= document.getElementById('search_tags'); + this.search_mine = document.getElementById('search_mine'); + document.getElementById('searchresults').view = this; + this.searchresult_props = document.getElementById('searchresult_props'); + this.search_photo = document.getElementById('search_photo'); + this.searchresult_title = document.getElementById('searchresult_title'); + this.searchresult_description = document.getElementById('searchresult_description'); + }, + photos: new Array(), + rowCount: 0, + getCellText: function(r,c) { + var p = this.photos[r]; + if(c.id=='sr_title') return p.title; + return c.id; + }, + setTree: function(t) { this.tree = t }, + isContainer: function(r) { return false }, + isSeparator: function(r) { return false }, + isSorted: function(r) { return false }, + getLevel: function(r) { return 0 }, + getImageSrc: function(r,c) { return null }, + getRowProperties: function(r,p) { }, + getCellProperties: function(cid,cel,p) { }, + getColumnProperties: function(cid,cel,p) { }, + cycleHeader: function(cid,e) { }, + getParentIndex: function(r) { return -1 }, + drop: function(r,o) { }, + canDropBeforeAfter: function(r,b) { return false }, + + importXPR: function(xp) { + this.selection.clearSelection(); + this.selection.currentIndex = -1; + this.searchresult_props.hidden = true; + this.tree.beginUpdateBatch(); + this.photos = new Array(); + var n; while(n=xp.iterateNext()) { + this.photos.push(new Photo(n)); + } + this.rowCount = this.photos.length; + this.tree.endUpdateBatch(); + }, + search_photos: function() { + var pars = { + method: 'flickr.photos.search', + auth_token: 'default', + extras: 'license,date_upload,date_taken,owner_name,icon_server,original_format,last_update,geo' + }; + if(this.search_mine.checked) + pars.user_id='me'; + if(this.search_tags.checked) { + pars.tags=this.search_for.value.split(/ +/).join(','); + }else{ + pars.text=this.search_for.value; + } + var _this = this; + this.fireflix.flickr.api_call( pars, + function(xr) { + var x = xr.responseXML; + var xp = x.evaluate( + '/rsp/photos/photo', x, null, + XPathResult.ORDERED_NODE_ITERATOR_TYPE, null ); + _this.importXPR(xp); + _this.on_select(); + }, function(x,s,c,m) { + _this.fireflix.flickr_failure(x,s,c,m); + } + ); + }, + on_select: function() { + if(this.selection.currentIndex<0) { + this.searchresult_props.hidden = true; + }else{ + var p = this.photos[this.selection.currentIndex]; + if(!p) { + this.searchresult_props.hidden = true; + }else{ + this.search_photo.src = this.fireflix.flickr.make_photo_url(p,'t'); + this.searchresult_title.value = p.title; + this.searchresult_description.value = null; + if(p.description==null && p.description==undefined) { + var pid = p.id; + var ci = this.selection.currentIndex; + var _this = this; + this.fireflix.flickr.api_call( + { + method: 'flickr.photos.getInfo', + auth_token: 'default', + photo_id: p.id, + secret: p.secret + }, function(xr) { + var pp = _this.photos[ci]; + if(ci==_this.selection.currentIndex && pp.id==pid) { + var n = xp_node('/rsp/photo',xr.responseXML); + pp.fromNode_(n); + _this.searchresult_description.value=pp.description?pp.description:null; + } + }, function(x,s,c,m) { + _this.fireflix.flickr_failure(x,s,c,m); + } + ); + this.searchresult_props.hidden = false; + }else{ + this.searchresult_description.value=p.description?p.description:null; + } + } + } + }, + on_cmd_open: function(ev) { + if(this.selection.currentIndex<0) + return; + var p = this.photos[this.selection.currentIndex]; + if(!p.id) + return; + this.fireflix.openTab(this.fireflix.flickr.make_photo_url(p,'p')); + } + }, + + photo_html: function(p,i,l) { + // TODO: add alt/title when possible + var rv = + '<a href="'+this.flickr.make_photo_url(p,l)+'">' + + '<img src="'+this.flickr.make_photo_url(p,i)+'" />'+ + '</a>'; + return rv; + }, + build_html: function(photos,uti,utl) { + var rv = ''; + for(var i in photos) { + var p = photos[i]; + rv += this.photo_html(p,utl,uti)+'\n'; + } + return rv; + }, + + popup_content: function(s) { + window.openDialog( + "chrome://fireflix/content/generated-content.xul", + null, "dialog,chrome", this, s ); + }, + copy_to_clipboard: function(s) { + var ch = Components.classes["@mozilla.org/widget/clipboardhelper;1"] + .getService(Components.interfaces.nsIClipboardHelper); + ch.copyString(s); + }, + openTab: function(l) { + var wm = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService( + Components.interfaces.nsIWindowMediator ); + var bw = wm.getMostRecentWindow('navigator:browser'); + var b = bw.getBrowser(); + var t = b.addTab(l); + b.selectedTab = t; + }, + + build_menus: function() { + this.append_html_menu( + document.getElementById('sets_html_menu'), + 'stm_','m_bop','cmdset_sets','cmd_sets_html' + ); + this.append_html_menu( + document.getElementById('uploads_html_menu'), + 'stm_','m_bop','cmdset_uploads','cmd_uploads_html' + ); + return; + }, + append_html_menu: function(m,imgt,lnkt,csid,cpfx) { + var mp = m.appendChild(document.createElement('menupopup')); + var t; + t=mp.appendChild(document.createElement('menuitem')); + t.setAttribute('label',this.loc_strings.getString('menutitle_Images')); + t.setAttribute('class','menuhead');t.setAttribute('disabled','true'); + mp.appendChild(document.createElement('menuseparator')); + var cs = document.getElementById(csid); + for(var iti=0;iti<imgt.length;++iti) { + t = mp.appendChild(document.createElement('menu')); + t.setAttribute('label',this.loc_strings.getString('urltype_'+imgt.charAt(iti))); + var smp = t.appendChild(document.createElement('menupopup')); + t=smp.appendChild(document.createElement('menuitem')); + t.setAttribute('label',this.loc_strings.getString('menutitle_Links')); + t.setAttribute('class','menuhead');t.setAttribute('disabled','true'); + smp.appendChild(document.createElement('menuseparator')); + for(var lti=0;lti<lnkt.length;++lti) { + var csfx = imgt.charAt(iti)+lnkt.charAt(lti); + t=smp.appendChild(document.createElement('menuitem')); + t.setAttribute('label',this.loc_strings.getString('urltype_'+lnkt.charAt(lti))); + t.setAttribute('command',cpfx+'_'+csfx); + t=cs.appendChild(document.createElement('command')); + t.setAttribute('id',cpfx+'_'+csfx); + t.setAttribute('oncommand','fireflix.on_'+cpfx+"('"+csfx+"',event)"); + } + } + return mp; + }, + + flickr_failure: function(x,s,c,m) { + if(c==98) { // Invalid auth token + this.flickr.reset_token(); + document.getElementById('auth_info').value = this.no_auth_info_label; + document.getElementById('auth_info').disabled = true; + document.getElementById('b_auth').hidden = false; + return; + } + // TODO: is that beauty + alert('flickr api call failed\n'+c+' '+m); + } + +}; diff --git a/content/flickr.js b/content/flickr.js new file mode 100644 index 0000000..3554796 --- a/dev/null +++ b/content/flickr.js @@ -0,0 +1,403 @@ +/* + * Photoset + */ + +function Photoset(s) { + if(s instanceof Photoset) { + for(var p in s) this[p]=s[p]; + }else + this.fromNode(s); +} +Photoset.prototype = { + id: null, + primary: null, + secret: null, + server: null, + photos: null, + title: null, + description: null, + fromNode: function(n) { + this.id = n.getAttribute('id'); + this.primary = n.getAttribute('primary'); + this.secret = n.getAttribute('secret'); + this.server = n.getAttribute('server'); + this.photos = n.getAttribute('photos'); + this.title = n.getElementsByTagName('title').item(0).firstChild.nodeValue; + this.description = n.getElementsByTagName('description').item(0).firstChild; + if(this.description) this.description = this.description.nodeValue; + } +}; + +/* + * Photo + */ +function Photo(s) { + if(s instanceof Photo) { + for(var p in s) this[p]=s[p]; + }else + this.fromNode(s); +} +Photo.prototype = { + id: null, secret: null, + server: null, + title: null, + isprimary: null, + license: null, + dateupload: null, datetaken: null, datetakengranularity: null, + ownername: null, + iconserver: null, + originalformat: null, + lastupdate: null, + fromNode: function(n) { + this.id = n.getAttribute('id'); this.secret = n.getAttribute('secret'); + this.server = n.getAttribute('server'); + this.title = n.getAttribute('title'); + this.isprimary = n.getAttribute('isprimary'); + this.license = n.getAttribute('license'); + this.dateupload = n.getAttribute('dateupload'); + this.datetaken = n.getAttribute('datetaken'); this.datetakengranularity = n.getAttribute('datetakengranularity'); + this.ownername = n.getAttribute('ownername'); + this.iconserver = n.getAttribute('iconserver'); + this.originalformat = n.getAttribute('originalformat'); + this.lastupdate = n.getAttribute('lastupdate'); + }, + fromNode_: function(n) { + var t; + // TODO: @rotation @isfavorite + this.owner = {}; + t = n.getElementsByTagName('owner').item(0); + if(t) { + this.owner.nsid=t.getAttribute('nsid'); + this.owner.username=t.getAttribute('username'); + this.owner.realname=t.getAttribute('realname'); + this.owner.location=t.getAttribute.location; + } + t = n.getElementsByTagName('description').item(0); + if(t && t.firstChild) { + this.description = t.firstChild.nodeValue; + } + // TODO: visibility/@ispublic visibility/@isfriend visibility/@isfamily + // TODO: dates/@posted dates/@taken dates/@takengranularity dates/@lastupdate + // TODO: permissions/@permcomment permsiions/@permaddmeta + // TODO: editability/@canaddcomment editability/@canaddmeta + // TODO: comments + // TODO: notes/note/@id notes/note/@author notes/note/@authorname + // TODO: notes/note/@x notes/note/@y notes/note/@w notes/note/@h + // TODO: notes/note + // TODO: tags/tag/@id tags/tag/@author tags/tag/@raw tags/tag + // TODO: urls/url/@type urls/url + } +}; + +function toutf8(ucode) { + var rv = ''; + for(var i=0;i<ucode.length;++i) { + var cc = ucode.charCodeAt(i); + if(cc<=0x7F) + rv += ucode.charAt(i); + else if(cc<=0x7ff) + rv += String.fromCharCode( + 0xc0|((cc>> 6)&0x1f), + 0x80|( cc &0x3f) ); + else if(cc<=0xffff) + rv += String.fromCharCode( + 0xe0|((cc>>12)&0x0f), + 0x80|((cc>> 6)&0x3f), + 0x80|( cc &0x3f) ); + else if(cc<=0x1fffff) + rv += String.fromCharCode( + 0xf0|((cc>>18)&0x07), + 0x80|((cc>>12)&0x3f), + 0x80|((cc>> 6)&0x3f), + 0x80|( cc &0x3f) ); + else if(cc<=0x03ffffff) + rv += String.fromCharCode( + 0xf8|((cc>>24)&0x03), + 0x80|((cc>>18)&0x3f), + 0x80|((cc>>12)&0x3f), + 0x80|((cc>> 6)&0x3f), + 0x80|( cc &0x3f) ); + else if(cc<=0x7fffffff) + rv += String.fromCharCode( + 0xfc|((cc>>30)&0x01), + 0x80|((cc>>24)&0x3f), + 0x80|((cc>>18)&0x3f), + 0x80|((cc>>12)&0x3f), + 0x80|((cc>> 6)&0x3f), + 0x80|( cc &0x3f) ); + } + return rv; +} +function xp_str(xp,x) { + var rv = x.evaluate( + xp, x, null, XPathResult.STRING_TYPE, null ); + return rv.stringValue; +} +function xp_node(xp,x) { + var rv = x.evaluate( + xp, x, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ); + return rv.singleNodeValue; +} + +function Flickr() { } +Flickr.prototype = { + + rest_url: 'http://www.flickr.com/services/rest/', + auth_url: 'http://flickr.com/services/auth/', + photo_url: 'http://static.flickr.com/', + photos_url: 'http://www.flickr.com/photos/', + upload_url: 'http://www.flickr.com/services/upload/', + + api_sig: function(paramstr) { + return MD5(toutf8(this.api_shs+paramstr)); + }, + api_call_url: function(params,url) { + params.api_key = this.api_key; + var pp = new Array(); + for(var p in params) { + pp.push(p); + } + var pstr = ''; + var rv = (url?url:this.rest_url)+'?'; + for(var p in pp.sort()) { + var pn = pp[p]; + pstr += pn+params[pn]; + rv += pn+'='+params[pn]+'&'; + } + rv += 'api_sig='+this.api_sig(pstr); + return rv; + }, + api_call: function(params, on_success, on_failure) { + if(params.auth_token == 'default') + params.auth_token = this.token; + var x = new XMLHttpRequest(); + x.open("GET",this.api_call_url(params)); + x.onreadystatechange=function() { + if(x.readyState!=4) return false; + if(x.status==200) { + var stat = x.responseXML.firstChild.getAttribute('stat'); + if(stat=='ok') { + if(on_success) on_success(x); + }else{ + var e = x.responseXML.getElementsByTagName('err').item(0); + var ecode = e.getAttribute('code'); + var emsg = e.getAttribute('msg'); + dump(params.method+' failed: '+ecode+' '+emsg+'\n'); + if(on_failure) on_failure(x,stat,ecode,emsg); + } + }else{ + if(on_failure) on_failure(x); + } + return true; + } + x.send(null); + return true; + }, + + frob: null, + authorize_0: function(on_s, on_f) { + var _this = this; + this.api_call( + { method: 'flickr.auth.getFrob' }, + function(x) { + _this.frob = xp_str('/rsp/frob',x.responseXML); + var u = _this.api_call_url( + { frob: _this.frob, perms: 'delete' }, _this.auth_url ); + var wm = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService( + Components.interfaces.nsIWindowMediator ); + var bw = wm.getMostRecentWindow('navigator:browser'); + var b = bw.getBrowser(); + var t = b.addTab(u); + b.selectedTab = t; + if(on_s) on_s(); + }, function(x,s,c,m) { + if(on_f) on_f(x,s,c,m); + } + ); + }, + token: null, + perms: null, + user: null, + authorize_1: function(on_s, on_f) { + var _this = this; + this.api_call( + { method: 'flickr.auth.getToken', frob: this.frob }, + function(x) { + _this.token = xp_str('/rsp/auth/token',x.responseXML); + _this.perms = xp_str('/rsp/auth/perms',x.responseXML); + var u = xp_node('/rsp/auth/user',x.responseXML); + _this.user = { + nsid: u.getAttribute('nsid'), + username: u.getAttribute('username'), + fullname: u.getAttribute('fullname') + }; + if(on_s) on_s(x); + }, function(x,s,c,m) { + if(on_f) on_f(x,s,c,m); + } + ); + }, + + prefs: Components.classes['@mozilla.org/preferences-service;1'].getService( + Components.interfaces.nsIPrefBranch + ), + prefs_root: 'net.klever.kin.flickr', + save_token: function() { + // TODO: don't clear when there's nothing to clear or catch exceptions + if(this.token) + this.prefs.setCharPref(this.prefs_root+'.auth_token',this.token); + else + this.prefs.clearUserPref(this.prefs_root+'.auth_token'); + if(this.perms) + this.prefs.setCharPref(this.prefs_root+'.auth_perms',this.perms); + else + this.prefs.clearUserPref(this.prefs_root+'.auth_perms'); + if(this.user && this.user.nsid!=null && this.user.nsid!=undefined) + this.prefs.setCharPref(this.prefs_root+'.auth_user.nsid',this.user.nsid); + else + this.prefs.clearUserPref(this.prefs_root+'.auth_user.nsid'); + if(this.user && this.user.username!=null && this.user.username!=undefined) + this.prefs.setCharPref(this.prefs_root+'.auth_user.username',this.user.username); + else + this.prefs.clearUserPref(this.prefs_root+'.auth_user.username'); + if(this.user && this.user.fullname!=null && this.user.fullname!=undefined) + this.prefs.setCharPref(this.prefs_root+'.auth_user.fullname',this.user.fullname); + else + this.prefs.clearUserPref(this.prefs_root+'.auth_user.fullname'); + }, + _reset_token: function() { + this.token = null; this.perms = null; this.user = null; + return false; + }, + load_token: function() { + try { + if(this.prefs.getPrefType(this.prefs_root+'.auth_token')!=this.prefs.PREF_STRING) + return this._reset_token(); + this.token = this.prefs.getCharPref(this.prefs_root+'.auth_token'); + if(this.prefs.getPrefType(this.prefs_root+'.auth_perms')!=this.prefs.PREF_STRING) + return this._reset_token(); + this.perms = this.prefs.getCharPref(this.prefs_root+'.auth_perms'); + if(this.prefs.getPrefType(this.prefs_root+'.auth_user.nsid')!=this.prefs.PREF_STRING) + return this._reset_token(); + this.user = new Object(); + this.user.nsid = this.prefs.getCharPref(this.prefs_root+'.auth_user.nsid'); + if(this.prefs.getPrefType(this.prefs_root+'.auth_user.username')!=this.prefs.PREF_STRING) + return this._reset_token(); + this.user.username = this.prefs.getCharPref(this.prefs_root+'.auth_user.username'); + if(this.prefs.getPrefType(this.prefs_root+'.auth_user.fullname')!=this.prefs.PREF_STRING) + return this._reset_token(); + this.user.fullname = this.prefs.getCharPref(this.prefs_root+'.auth_user.fullname'); + }catch(e) { return this._reset_token(); } + return true; + }, + reset_token: function() { + this._reset_token(); + this.save_token(); + }, + + get_photo_url: function(ser,id,sec,sfx,ext) { + var rv = this.photo_url + ser + '/' + id + '_' + sec; + if(sfx && sfx!='_') rv += '_'+sfx; + rv += ext?'.'+ext:'.jpg'; + return rv; + }, + get_image_url: function(o,sfx) { + return this.get_photo_url( + o.server, + (o instanceof Photoset)? o.primary : o.id, + o.secret, + sfx, + (sfx=='o')?o.originalformat:null + ); + }, + get_photo_page_url: function(p) { + if(p instanceof Photo) // TODO: half wrong, what if no owner? + return this.photos_url + (p.owner.nsid?p.owner.nsid:this.user.nsid) + '/' + p.id; + else // TODO: take owner into account? + return this.photos_url + this.user.nsid + '/' + p; + }, + make_photo_url: function(p,sfx) { + if(sfx=='p') + return this.get_photo_page_url(p); + else + return this.get_image_url(p,sfx); + }, + + upload_file: function(f,fa,on_success,on_failure) { + try { + var fi = Components.classes["@mozilla.org/file/local;1"] + .createInstance(Components.interfaces.nsILocalFile); + fi.initWithPath( f ); + var st = Components.classes["@mozilla.org/network/file-input-stream;1"] + .createInstance(Components.interfaces.nsIFileInputStream); + st.init(fi,0x01,00004,null); + var bis = Components.classes["@mozilla.org/binaryinputstream;1"] + .createInstance(Components.interfaces.nsIBinaryInputStream); + bis.setInputStream(st); + + // allocate and initialize temp storage string + var pbs = Components.classes["@mozilla.org/storagestream;1"] + .createInstance(Components.interfaces.nsIStorageStream); + pbs.init(1024,10000000,null); + // create output stream + var pbos = pbs.getOutputStream(0); + // and a binaryoutputstream interface + var pbbos = Components.classes["@mozilla.org/binaryoutputstream;1"] + .createInstance(Components.interfaces.nsIBinaryOutputStream); + pbbos.setOutputStream(pbos); + + /* create POST body */ + var boundarytoken = 'kadaroloongazaduviaxamma'; + var boundary = '--'+boundarytoken; + var b = ''; + + var parms = { api_key: this.api_key, auth_token: this.token }; + for(var p in fa) parms[p] = fa[p]; + var pns = new Array(); + for(var p in parms) pns.push(p); + var pstr = ''; + for(var p in pns.sort()) { + var pn = pns[p]; + pstr += pn+parms[pn]; + b += boundary+'\nContent-Disposition: form-data; name="'+pn+'"\n\n'+toutf8(parms[pn])+'\n'; + } + b += boundary+'\nContent-Disposition: form-data; name="api_sig"\n\n'+this.api_sig(pstr)+'\n'; + b += boundary+'\nContent-Disposition: form-data; name="photo"; filename="'+f+'"\nContent-Type: image/jpeg\nContent-Transfer-Encoding: binary\n\n'; + pbbos.writeBytes(b,b.length); + var bisbytes = bis.available(); + pbbos.writeBytes(bis.readBytes(bisbytes),bisbytes); + pbbos.writeBytes('\n'+boundary+'--',3+boundary.length); bis.close(); st.close(); + + pbbos.close(); pbos.close(); + + var x = new XMLHttpRequest(); + x.open("POST",this.upload_url); + x.setRequestHeader('Content-Type', 'multipart/form-data; boundary="'+boundarytoken+'"'); + x.setRequestHeader('Connection','close'); + x.setRequestHeader('Content-Length',b.length); + x.onreadystatechange=function() { + if(x.readyState!=4) return false; + if(x.status==200) { + var stat = x.responseXML.firstChild.getAttribute('stat'); + if(stat=='ok') { + var pid = xp_str('/rsp/photoid',x.responseXML); + if(on_success) on_success(x,pid); + }else{ + var e = x.responseXML.getElementsByTagName('err').item(0); + var ecode = e.getAttribute('code'); + var emsg = e.getAttribute('msg'); + dump('upload failed: '+ecode+' '+emsg+'\n'); + if(on_failure) on_failure(x,stat,ecode,emsg); + } + }else{ + if(on_failure) on_failure(x); + } + return true; + }; + x.send(pbs.newInputStream(0)); + }catch(e) { + if(on_failure) on_failure(e,null,-1,e.message); + } + } + +}; diff --git a/content/generated-content.js b/content/generated-content.js new file mode 100644 index 0000000..0ad08bb --- a/dev/null +++ b/content/generated-content.js @@ -0,0 +1,17 @@ +var generated = { + fireflix: null, + data: null, + + init: function() { + this.fireflix = window.arguments[0]; + this.data = window.arguments[1]; + this.databox = document.getElementById('data'); + this.databox.value = this.data; + this.databox.select(); + }, + copy: function() { + var ch = Components.classes["@mozilla.org/widget/clipboardhelper;1"] + .getService(Components.interfaces.nsIClipboardHelper); + ch.copyString(this.data); + } +}; diff --git a/content/generated-content.xul b/content/generated-content.xul new file mode 100644 index 0000000..2a91efa --- a/dev/null +++ b/content/generated-content.xul @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> +<?xsml-stylesheet href="fireflix.css" type="text/css"?> +<!DOCTYPE dialog SYSTEM "chrome://fireflix/locale/fireflix.dtd"> +<dialog + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + id="generated_content" + buttons="accept" + defaultbutton="accept" + title="&generated.title;" + onload="generated.init()" + > + + <script src="generated-content.js" type="application/x-javascript"/> + + <vbox class="generated wholething" flex="1"> + <textbox flex="1" minheight="300" minwidth="300" id="data" multiline="true" readonly="true" /> + <button id="copy" label="&generated.copy;" oncommand="generated.copy()" /> + </vbox> +</dialog> diff --git a/content/icons/16x16/fireflix.png b/content/icons/16x16/fireflix.png Binary files differnew file mode 100644 index 0000000..377ab28 --- a/dev/null +++ b/content/icons/16x16/fireflix.png diff --git a/content/icons/32x32/fireflix.png b/content/icons/32x32/fireflix.png Binary files differnew file mode 100644 index 0000000..374ebbd --- a/dev/null +++ b/content/icons/32x32/fireflix.png diff --git a/content/md5.js b/content/md5.js new file mode 100644 index 0000000..f22db2b --- a/dev/null +++ b/content/md5.js @@ -0,0 +1,154 @@ +/* MD5 Message-Digest Algorithm - JavaScript
+' MODIFICATION HISTORY:
+' 1.0 16-Feb-2001 - Phil Fresle (sales@frez.co.uk) - Initial Version (VB/ASP code)
+' 1.0 21-Feb-2001 - Enrico Mosanghini (erik504@yahoo.com) - JavaScript porting
+*/
+function MD5(sMessage) {
+ function RotateLeft(lValue, iShiftBits) { return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits)); }
+ function AddUnsigned(lX,lY) {
+ var lX4,lY4,lX8,lY8,lResult;
+ lX8 = (lX & 0x80000000);
+ lY8 = (lY & 0x80000000);
+ lX4 = (lX & 0x40000000);
+ lY4 = (lY & 0x40000000);
+ lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
+ if (lX4 & lY4) return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
+ if (lX4 | lY4) {
+ if (lResult & 0x40000000) return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
+ else return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
+ } else return (lResult ^ lX8 ^ lY8);
+ }
+ function F(x,y,z) { return (x & y) | ((~x) & z); }
+ function G(x,y,z) { return (x & z) | (y & (~z)); }
+ function H(x,y,z) { return (x ^ y ^ z); }
+ function I(x,y,z) { return (y ^ (x | (~z))); }
+ function FF(a,b,c,d,x,s,ac) {
+ a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
+ return AddUnsigned(RotateLeft(a, s), b);
+ }
+ function GG(a,b,c,d,x,s,ac) {
+ a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
+ return AddUnsigned(RotateLeft(a, s), b);
+ }
+ function HH(a,b,c,d,x,s,ac) {
+ a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
+ return AddUnsigned(RotateLeft(a, s), b);
+ }
+ function II(a,b,c,d,x,s,ac) {
+ a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
+ return AddUnsigned(RotateLeft(a, s), b);
+ }
+ function ConvertToWordArray(sMessage) {
+ var lWordCount;
+ var lMessageLength = sMessage.length;
+ var lNumberOfWords_temp1=lMessageLength + 8;
+ var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
+ var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
+ var lWordArray=Array(lNumberOfWords-1);
+ var lBytePosition = 0;
+ var lByteCount = 0;
+ while ( lByteCount < lMessageLength ) {
+ lWordCount = (lByteCount-(lByteCount % 4))/4;
+ lBytePosition = (lByteCount % 4)*8;
+ lWordArray[lWordCount] = (lWordArray[lWordCount] | (sMessage.charCodeAt(lByteCount)<<lBytePosition));
+ lByteCount++;
+ }
+ lWordCount = (lByteCount-(lByteCount % 4))/4;
+ lBytePosition = (lByteCount % 4)*8;
+ lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition);
+ lWordArray[lNumberOfWords-2] = lMessageLength<<3;
+ lWordArray[lNumberOfWords-1] = lMessageLength>>>29;
+ return lWordArray;
+ }
+ function WordToHex(lValue) {
+ var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;
+ for (lCount = 0;lCount<=3;lCount++) {
+ lByte = (lValue>>>(lCount*8)) & 255;
+ WordToHexValue_temp = "0" + lByte.toString(16);
+ WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);
+ }
+ return WordToHexValue;
+ }
+ var x=Array();
+ var k,AA,BB,CC,DD,a,b,c,d
+ var S11=7, S12=12, S13=17, S14=22;
+ var S21=5, S22=9 , S23=14, S24=20;
+ var S31=4, S32=11, S33=16, S34=23;
+ var S41=6, S42=10, S43=15, S44=21;
+ // Steps 1 and 2. Append padding bits and length and convert to words
+ x = ConvertToWordArray(sMessage);
+ // Step 3. Initialise
+ a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
+ // Step 4. Process the message in 16-word blocks
+ for (k=0;k<x.length;k+=16) {
+ AA=a; BB=b; CC=c; DD=d;
+ a=FF(a,b,c,d,x[k+0], S11,0xD76AA478);
+ d=FF(d,a,b,c,x[k+1], S12,0xE8C7B756);
+ c=FF(c,d,a,b,x[k+2], S13,0x242070DB);
+ b=FF(b,c,d,a,x[k+3], S14,0xC1BDCEEE);
+ a=FF(a,b,c,d,x[k+4], S11,0xF57C0FAF);
+ d=FF(d,a,b,c,x[k+5], S12,0x4787C62A);
+ c=FF(c,d,a,b,x[k+6], S13,0xA8304613);
+ b=FF(b,c,d,a,x[k+7], S14,0xFD469501);
+ a=FF(a,b,c,d,x[k+8], S11,0x698098D8);
+ d=FF(d,a,b,c,x[k+9], S12,0x8B44F7AF);
+ c=FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1);
+ b=FF(b,c,d,a,x[k+11],S14,0x895CD7BE);
+ a=FF(a,b,c,d,x[k+12],S11,0x6B901122);
+ d=FF(d,a,b,c,x[k+13],S12,0xFD987193);
+ c=FF(c,d,a,b,x[k+14],S13,0xA679438E);
+ b=FF(b,c,d,a,x[k+15],S14,0x49B40821);
+ a=GG(a,b,c,d,x[k+1], S21,0xF61E2562);
+ d=GG(d,a,b,c,x[k+6], S22,0xC040B340);
+ c=GG(c,d,a,b,x[k+11],S23,0x265E5A51);
+ b=GG(b,c,d,a,x[k+0], S24,0xE9B6C7AA);
+ a=GG(a,b,c,d,x[k+5], S21,0xD62F105D);
+ d=GG(d,a,b,c,x[k+10],S22,0x2441453);
+ c=GG(c,d,a,b,x[k+15],S23,0xD8A1E681);
+ b=GG(b,c,d,a,x[k+4], S24,0xE7D3FBC8);
+ a=GG(a,b,c,d,x[k+9], S21,0x21E1CDE6);
+ d=GG(d,a,b,c,x[k+14],S22,0xC33707D6);
+ c=GG(c,d,a,b,x[k+3], S23,0xF4D50D87);
+ b=GG(b,c,d,a,x[k+8], S24,0x455A14ED);
+ a=GG(a,b,c,d,x[k+13],S21,0xA9E3E905);
+ d=GG(d,a,b,c,x[k+2], S22,0xFCEFA3F8);
+ c=GG(c,d,a,b,x[k+7], S23,0x676F02D9);
+ b=GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A);
+ a=HH(a,b,c,d,x[k+5], S31,0xFFFA3942);
+ d=HH(d,a,b,c,x[k+8], S32,0x8771F681);
+ c=HH(c,d,a,b,x[k+11],S33,0x6D9D6122);
+ b=HH(b,c,d,a,x[k+14],S34,0xFDE5380C);
+ a=HH(a,b,c,d,x[k+1], S31,0xA4BEEA44);
+ d=HH(d,a,b,c,x[k+4], S32,0x4BDECFA9);
+ c=HH(c,d,a,b,x[k+7], S33,0xF6BB4B60);
+ b=HH(b,c,d,a,x[k+10],S34,0xBEBFBC70);
+ a=HH(a,b,c,d,x[k+13],S31,0x289B7EC6);
+ d=HH(d,a,b,c,x[k+0], S32,0xEAA127FA);
+ c=HH(c,d,a,b,x[k+3], S33,0xD4EF3085);
+ b=HH(b,c,d,a,x[k+6], S34,0x4881D05);
+ a=HH(a,b,c,d,x[k+9], S31,0xD9D4D039);
+ d=HH(d,a,b,c,x[k+12],S32,0xE6DB99E5);
+ c=HH(c,d,a,b,x[k+15],S33,0x1FA27CF8);
+ b=HH(b,c,d,a,x[k+2], S34,0xC4AC5665);
+ a=II(a,b,c,d,x[k+0], S41,0xF4292244);
+ d=II(d,a,b,c,x[k+7], S42,0x432AFF97);
+ c=II(c,d,a,b,x[k+14],S43,0xAB9423A7);
+ b=II(b,c,d,a,x[k+5], S44,0xFC93A039);
+ a=II(a,b,c,d,x[k+12],S41,0x655B59C3);
+ d=II(d,a,b,c,x[k+3], S42,0x8F0CCC92);
+ c=II(c,d,a,b,x[k+10],S43,0xFFEFF47D);
+ b=II(b,c,d,a,x[k+1], S44,0x85845DD1);
+ a=II(a,b,c,d,x[k+8], S41,0x6FA87E4F);
+ d=II(d,a,b,c,x[k+15],S42,0xFE2CE6E0);
+ c=II(c,d,a,b,x[k+6], S43,0xA3014314);
+ b=II(b,c,d,a,x[k+13],S44,0x4E0811A1);
+ a=II(a,b,c,d,x[k+4], S41,0xF7537E82);
+ d=II(d,a,b,c,x[k+11],S42,0xBD3AF235);
+ c=II(c,d,a,b,x[k+2], S43,0x2AD7D2BB);
+ b=II(b,c,d,a,x[k+9], S44,0xEB86D391);
+ a=AddUnsigned(a,AA); b=AddUnsigned(b,BB); c=AddUnsigned(c,CC); d=AddUnsigned(d,DD);
+ }
+ // Step 5. Output the 128 bit digest
+ var temp= WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d);
+ return temp.toLowerCase();
+}
diff --git a/content/photoset-props.js b/content/photoset-props.js new file mode 100644 index 0000000..43dc1b9 --- a/dev/null +++ b/content/photoset-props.js @@ -0,0 +1,81 @@ + +var psetprops = { + fireflix: null, + photoset: null, + pripic: null, + + settitle: null, setdesc: null, + primarypic: null, + photos: new Array(), + init: function() { + this.fireflix = window.arguments[0]; + this.photoset = window.arguments[1]; + this.settitle = document.getElementById('set_title'); + this.settitle.value = this.photoset.title; + this.setdesc = document.getElementById('set_desc'); + this.setdesc.value = this.photoset.description; + this.primarypic = document.getElementById('primary_picture'); + this.primarypic.src = + this.fireflix.flickr.get_image_url( this.photoset, 't' ); + this.primarypic.hidden = false; + this.picslist = document.getElementById('primary_picture_list'); + + var _this = this; + this.fireflix.flickr.api_call( + { + method: 'flickr.photosets.getPhotos', + auth_token: 'default', + photoset_id: this.photoset.id + }, function(xr) { + var x = xr.responseXML; + var xp = x.evaluate( + '/rsp/photoset/photo', x, null, + XPathResult.ORDERED_NODE_ITERATOR_TYPE, null ); + _this.picslist.removeAllItems(); _this.photos= new Array(); + var n; while(n=xp.iterateNext()) { + _this.photos.push( + { + id: n.getAttribute('id'), + secret: n.getAttribute('secret'), + server: n.getAttribute('server') + } + ); + var ni = _this.picslist.appendItem( + n.getAttribute('title'), _this.photos.length-1 + ); + ni.setAttribute('command','cmd_select_picture'); + if(n.getAttribute('isprimary')==1) { + _this.picslist.selectedItem = ni; + _this.pripic = _this.photos[_this.photos.length-1]; + } + } + _this.picslist.hidden = false; + }, function() { } + ); + }, + on_select_picture: function(ev) { + var epic = ev.explicitOriginalTarget; + this.picslist.selectedItem = epic; + var pic = this.photos[this.picslist.selectedItem.value]; + this.pripic = pic; + this.primarypic.src = + this.fireflix.flickr.get_photo_url( + pic.server, + pic.id, + pic.secret, + 't' + ); + }, + on_accept: function() { + this.photoset.title = + document.getElementById('set_title').value; + this.photoset.description = + document.getElementById('set_desc').value; + this.photoset.server = this.pripic.server; + this.photoset.primary = this.pripic.id; + this.photoset.secret = this.pripic.secret; + this.photoset.dirty = true; + return; + } +}; + diff --git a/content/photoset-props.xul b/content/photoset-props.xul new file mode 100644 index 0000000..e8f6d13 --- a/dev/null +++ b/content/photoset-props.xul @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="utf-8"?> +<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> +<?xsml-stylesheet href="fireflix.css" type="text/css"?> +<!DOCTYPE dialog SYSTEM "chrome://fireflix/locale/fireflix.dtd"> +<dialog + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + id="photoset_props" + buttons="accept,cancel" + defaultbutton="accept" + title="&photosetprops.title;" + onload="psetprops.init()" + ondialogaccept="psetprops.on_accept()" + > + + <script src="photoset-props.js" type="application/x-javascript"/> + + <commandset> + <command id="cmd_select_picture" + oncommand="psetprops.on_select_picture(event)"/> + </commandset> + + <hbox class="wholething"> + <vbox> + <menulist id="primary_picture_list" hidden="true" sizetopopup="always"/> + <hbox pack="center"> + <box width="100" pack="center"> + <image id="primary_picture" hidden="true"/> + </box> + </hbox> + </vbox> + <vbox flex="1" minwidth="300"> + <label control="set_title" value="&photosetprops.set_title.label;"/> + <textbox id="set_title" /> + <label control="set_desc" value="&photosetprops.set_desc.label;"/> + <textbox id="set_desc" multiline="true" rows="5" /> + </vbox> + </hbox> +</dialog> |