f-spot r3646 - in trunk: . extensions extensions/DefaultExporters extensions/PicasaWebExport extensions/PicasaWebExport/google-sharp po src
- From: sdelcroix svn gnome org
- To: svn-commits-list gnome org
- Subject: f-spot r3646 - in trunk: . extensions extensions/DefaultExporters extensions/PicasaWebExport extensions/PicasaWebExport/google-sharp po src
- Date: Fri, 8 Feb 2008 15:37:14 +0000 (GMT)
Author: sdelcroix
Date: Fri Feb 8 15:37:13 2008
New Revision: 3646
URL: http://svn.gnome.org/viewvc/f-spot?rev=3646&view=rev
Log:
2008-02-08 Stphane Delcroix <sdelcroix novell com>
Patch from lorenzo to addin-ify picasawebexport
Added:
trunk/extensions/PicasaWebExport/
trunk/extensions/PicasaWebExport/Makefile.am
trunk/extensions/PicasaWebExport/PicasaWebExport.addin.xml
trunk/extensions/PicasaWebExport/PicasaWebExport.cs
trunk/extensions/PicasaWebExport/PicasaWebExport.glade
trunk/extensions/PicasaWebExport/google-sharp/
trunk/extensions/PicasaWebExport/google-sharp/AlbumAccess.cs
trunk/extensions/PicasaWebExport/google-sharp/AssemblyInfo.cs
trunk/extensions/PicasaWebExport/google-sharp/Authentication.cs
trunk/extensions/PicasaWebExport/google-sharp/CaptchaException.cs
trunk/extensions/PicasaWebExport/google-sharp/CreateAlbumException.cs
trunk/extensions/PicasaWebExport/google-sharp/DeleteAlbumException.cs
trunk/extensions/PicasaWebExport/google-sharp/GDataApi.cs
trunk/extensions/PicasaWebExport/google-sharp/GoogleConnection.cs
trunk/extensions/PicasaWebExport/google-sharp/GoogleService.cs
trunk/extensions/PicasaWebExport/google-sharp/Makefile.am
trunk/extensions/PicasaWebExport/google-sharp/MultipartRequest.cs
trunk/extensions/PicasaWebExport/google-sharp/NoCheckCertificatePolicy.cs
trunk/extensions/PicasaWebExport/google-sharp/PicasaAlbum.cs
trunk/extensions/PicasaWebExport/google-sharp/PicasaAlbumCollection.cs
trunk/extensions/PicasaWebExport/google-sharp/PicasaPicture.cs
trunk/extensions/PicasaWebExport/google-sharp/PicasaPictureCollection.cs
trunk/extensions/PicasaWebExport/google-sharp/PicasaWeb.cs
trunk/extensions/PicasaWebExport/google-sharp/UploadPictureException.cs
trunk/extensions/PicasaWebExport/google-sharp/UploadProgressEventArgs.cs
trunk/extensions/PicasaWebExport/google-sharp/UploadProgressEventHandler.cs
trunk/extensions/PicasaWebExport/google-sharp/XmlUtil.cs
Removed:
trunk/src/PicasaWebExport.cs
Modified:
trunk/ChangeLog
trunk/Makefile.include
trunk/configure.in
trunk/extensions/ChangeLog
trunk/extensions/DefaultExporters/DefaultExporters.addin.xml
trunk/extensions/Makefile.am
trunk/po/POTFILES.in
trunk/po/POTFILES.skip
trunk/src/Makefile.am
trunk/src/Preferences.cs
trunk/src/f-spot.glade
Modified: trunk/Makefile.include
==============================================================================
--- trunk/Makefile.include (original)
+++ trunk/Makefile.include Fri Feb 8 15:37:13 2008
@@ -9,7 +9,6 @@
DIR_DOCS = $(top_builddir)/docs
DIR_EXTENSIONS = $(top_builddir)/extensions
DIR_GLITZ = $(top_builddir)/glitz-sharp/src
-DIR_GOOGLE = $(top_builddir)/google-sharp
DIR_GPHOTO2 = $(top_builddir)/libgphoto2-sharp
DIR_ICONS = $(top_builddir)/icons
DIR_JPEGTRAN = $(top_builddir)/libjpegtran
Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in (original)
+++ trunk/configure.in Fri Feb 8 15:37:13 2008
@@ -265,7 +265,6 @@
dbus-sharp/Makefile
dbus-sharp-glib/Makefile
docs/Makefile
-google-sharp/Makefile
gnome-keyring-sharp/Makefile
icons/Makefile
libeog/Makefile
@@ -300,6 +299,8 @@
extensions/FolderExport/Makefile
extensions/SmugMugExport/SmugMugNet/Makefile
extensions/SmugMugExport/Makefile
+extensions/PicasaWebExport/Makefile
+extensions/PicasaWebExport/google-sharp/Makefile
f-spot.pc
f-spot.spec
f-spot.desktop.in
Modified: trunk/extensions/DefaultExporters/DefaultExporters.addin.xml
==============================================================================
--- trunk/extensions/DefaultExporters/DefaultExporters.addin.xml (original)
+++ trunk/extensions/DefaultExporters/DefaultExporters.addin.xml Fri Feb 8 15:37:13 2008
@@ -1,5 +1,5 @@
<Addin namespace="FSpot"
- version="1.5"
+ version="1.6"
name="Default Exporters"
description="This extension contains all the default exporters for f-spot. Most of them will be moved out of this extension in the future, and, at that time, this extension will be deprecated."
author="F-Spot team"
@@ -8,10 +8,9 @@
category="Export">
<Dependencies>
- <Addin id="Core" version="0.4.0.0"/>
+ <Addin id="Core" version="0.4.2.0"/>
</Dependencies>
<Extension path = "/FSpot/Menus/Exports">
- <ExportMenuItem id="PicasaWeb" _label = "_PicasaWeb..." class = "FSpot.GoogleExport" />
</Extension>
</Addin>
Modified: trunk/extensions/Makefile.am
==============================================================================
--- trunk/extensions/Makefile.am (original)
+++ trunk/extensions/Makefile.am Fri Feb 8 15:37:13 2008
@@ -3,6 +3,7 @@
GalleryExport \
FlickrExport \
FolderExport \
+ PicasaWebExport \
SmugMugExport \
DefaultExporters
Added: trunk/extensions/PicasaWebExport/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/extensions/PicasaWebExport/Makefile.am Fri Feb 8 15:37:13 2008
@@ -0,0 +1,58 @@
+include $(top_srcdir)/Makefile.include
+
+PLUGIN_NAME = PicasaWebExport
+
+PLUGIN_MANIFEST = $(PLUGIN_NAME).addin.xml
+
+PLUGIN_ASSEMBLY = $(PLUGIN_NAME).dll
+
+PLUGIN_SOURCES = \
+ $(srcdir)/PicasaWebExport.cs
+
+REFS = \
+ -r:../../src/f-spot.exe \
+ -r:../../src/FSpot.Core.dll \
+ -r:../../src/FSpot.Utils.dll \
+ -r:../../semweb/SemWeb.dll \
+ -r:google-sharp/Mono.Google.dll \
+ $(LINK_KEYRING) \
+ -r:System.Web \
+ -r:Mono.Posix
+
+PKGS = \
+ -pkg:gnome-vfs-sharp-2.0 \
+ -pkg:gtk-sharp-2.0 \
+ -pkg:glade-sharp-2.0
+
+SUBDIRS = \
+ google-sharp
+
+RESOURCES = \
+ -resource:$(srcdir)/$(PLUGIN_MANIFEST) \
+ -resource:$(srcdir)/$(PLUGIN_NAME).glade
+
+all: $(PLUGIN_ASSEMBLY)
+
+mpack: $(PLUGIN_ASSEMBLY)
+ mautil p $(PLUGIN_ASSEMBLY)
+
+$(PLUGIN_ASSEMBLY): $(PLUGIN_SOURCES) $(PLUGIN_MANIFEST)
+ $(CSC_LIB) -out:$@ $(PLUGIN_SOURCES) $(REFS) $(PKGS) $(ASSEMBLIES) $(RESOURCES)
+
+plugindir = $(pkglibdir)/extensions
+
+install-data-hook:
+ rm -f $(plugindir)/$(PLUGIN_NAME).addin.xml
+
+plugin_DATA = \
+ $(PLUGIN_ASSEMBLY)
+
+EXTRA_DIST = \
+ $(PLUGIN_SOURCES) \
+ $(PLUGIN_MANIFEST) \
+ $(PLUGIN_NAME).glade
+
+CLEANFILES = \
+ $(PLUGIN_ASSEMBLY) \
+ $(PLUGIN_ASSEMBLY).mdb \
+ *.mpack
Added: trunk/extensions/PicasaWebExport/PicasaWebExport.addin.xml
==============================================================================
--- (empty file)
+++ trunk/extensions/PicasaWebExport/PicasaWebExport.addin.xml Fri Feb 8 15:37:13 2008
@@ -0,0 +1,17 @@
+<Addin namespace="FSpot"
+ version="1.0"
+ name="PicasaWeb Export"
+ description="This extension allows you to export your photos to PicasaWeb."
+ author="F-Spot team"
+ url="http://f-spot.org"
+ defaultEnabled="true"
+ category="Export">
+
+ <Dependencies>
+ <Addin id="Core" version="0.4.0.0"/>
+ </Dependencies>
+
+ <Extension path = "/FSpot/Menus/Exports">
+ <ExportMenuItem id="PicasaWeb" _label = "_PicasaWeb..." class = "FSpotGoogleExport.GoogleExport" />
+ </Extension>
+</Addin>
Added: trunk/extensions/PicasaWebExport/PicasaWebExport.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/PicasaWebExport/PicasaWebExport.cs Fri Feb 8 15:37:13 2008
@@ -0,0 +1,944 @@
+/*
+ * PicasaWebExport.cs
+ *
+ * Authors:
+ * Stephane Delcroix <stephane delcroix org>
+ *
+ * Copyright (C) 2006 Stephane Delcroix
+ */
+
+using System;
+using System.Net;
+using System.IO;
+using System.Text;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Web;
+using Mono.Unix;
+
+using FSpot;
+using FSpot.Filters;
+using FSpot.Widgets;
+using FSpot.Utils;
+using FSpot.UI.Dialog;
+
+using Gnome.Keyring;
+
+using Mono.Google;
+using Mono.Google.Picasa;
+
+namespace FSpotGoogleExport {
+ public class GoogleAccount {
+
+ private string username;
+ private string password;
+ private string token;
+ private string unlock_captcha;
+ private GoogleConnection connection;
+ private PicasaWeb picasa;
+
+ public GoogleAccount (string username, string password)
+ {
+ this.username = username;
+ this.password = password;
+ }
+
+ public GoogleAccount (string username, string password, string token, string unlock_captcha)
+ {
+ this.username = username;
+ this.password = password;
+ this.token = token;
+ this.unlock_captcha = unlock_captcha;
+ }
+
+ public PicasaWeb Connect ()
+ {
+ System.Console.WriteLine ("GoogleAccount.Connect()");
+ GoogleConnection conn = new GoogleConnection (GoogleService.Picasa);
+ ServicePointManager.CertificatePolicy = new NoCheckCertificatePolicy ();
+ if (unlock_captcha == null || token == null)
+ conn.Authenticate(username, password);
+ else {
+ conn.Authenticate(username, password, token, unlock_captcha);
+ token = null;
+ unlock_captcha = null;
+ }
+ connection = conn;
+ PicasaWeb picasa = new PicasaWeb(conn);
+ this.picasa = picasa;
+ return picasa;
+ }
+
+ private void MarkChanged()
+ {
+ connection = null;
+ }
+
+ public bool Connected {
+ get {
+ return (connection != null);
+ }
+ }
+
+ public string Username {
+ get {
+ return username;
+ }
+ set {
+ if (username != value) {
+ username = value;
+ MarkChanged ();
+ }
+ }
+ }
+
+ public string Password {
+ get {
+ return password;
+ }
+ set {
+ if (password != value) {
+ password = value;
+ MarkChanged ();
+ }
+ }
+ }
+
+ public string Token {
+ get {
+ return token;
+ }
+ set {
+ token = value;
+ }
+ }
+
+ public string UnlockCaptcha {
+ get {
+ return unlock_captcha;
+ }
+ set {
+ unlock_captcha = value;
+ }
+ }
+
+ public PicasaWeb Picasa {
+ get {
+ return picasa;
+ }
+ }
+ }
+
+
+ public class GoogleAccountManager
+ {
+ private static GoogleAccountManager instance;
+ private const string keyring_item_name = "Google Account";
+ ArrayList accounts;
+
+ public delegate void AccountListChangedHandler (GoogleAccountManager manager, GoogleAccount changed_account);
+ public event AccountListChangedHandler AccountListChanged;
+
+ public static GoogleAccountManager GetInstance ()
+ {
+ if (instance == null) {
+ instance = new GoogleAccountManager ();
+ }
+
+ return instance;
+ }
+
+ private GoogleAccountManager ()
+ {
+ accounts = new ArrayList ();
+ ReadAccounts ();
+ }
+
+ public void MarkChanged ()
+ {
+ MarkChanged (true, null);
+ }
+
+ public void MarkChanged (bool write, GoogleAccount changed_account)
+ {
+ if (write)
+ WriteAccounts ();
+
+ if (AccountListChanged != null)
+ AccountListChanged (this, changed_account);
+ }
+
+ public ArrayList GetAccounts ()
+ {
+ return accounts;
+ }
+
+ public void AddAccount (GoogleAccount account)
+ {
+ AddAccount (account, true);
+ }
+
+ public void AddAccount (GoogleAccount account, bool write)
+ {
+ accounts.Add (account);
+ MarkChanged (write, account);
+ }
+
+ public void RemoveAccount (GoogleAccount account)
+ {
+ string keyring;
+ try {
+ keyring = Ring.GetDefaultKeyring();
+ } catch {
+ return;
+ }
+ Hashtable request_attributes = new Hashtable();
+ request_attributes["name"] = keyring_item_name;
+ request_attributes["username"] = account.Username;
+ try {
+ foreach(ItemData result in Ring.Find(ItemType.GenericSecret, request_attributes)) {
+ Ring.DeleteItem(keyring, result.ItemID);
+ }
+ } catch (Exception e) {
+ Console.WriteLine(e);
+ }
+ accounts.Remove (account);
+ MarkChanged ();
+ }
+
+ public void WriteAccounts ()
+ {
+ string keyring;
+ try {
+ keyring = Ring.GetDefaultKeyring();
+ } catch {
+ return;
+ }
+ foreach (GoogleAccount account in accounts) {
+ Hashtable update_request_attributes = new Hashtable();
+ update_request_attributes["name"] = keyring_item_name;
+ update_request_attributes["username"] = account.Username;
+
+ try {
+ Ring.CreateItem(keyring, ItemType.GenericSecret, keyring_item_name, update_request_attributes, account.Password, true);
+ } catch {
+ continue;
+ }
+ }
+ }
+
+ private void ReadAccounts ()
+ {
+
+ Hashtable request_attributes = new Hashtable();
+ request_attributes["name"] = keyring_item_name;
+ try {
+ foreach(ItemData result in Ring.Find(ItemType.GenericSecret, request_attributes)) {
+ if(!result.Attributes.ContainsKey("name") || !result.Attributes.ContainsKey("username") ||
+ (result.Attributes["name"] as string) != keyring_item_name)
+ continue;
+
+ string username = (string)result.Attributes["username"];
+ string password = result.Secret;
+
+ if (username == null || username == String.Empty || password == null || password == String.Empty)
+ throw new ApplicationException ("Invalid username/password in keyring");
+
+ GoogleAccount account = new GoogleAccount(username, password);
+ if (account != null)
+ AddAccount (account, false);
+
+ }
+ } catch (Exception e) {
+ Console.Error.WriteLine(e);
+ }
+
+ MarkChanged ();
+ }
+ }
+
+ public class GoogleAccountDialog {
+ public GoogleAccountDialog (Gtk.Window parent) : this (parent, null, false, null) {
+ Dialog.Response += HandleAddResponse;
+ add_button.Sensitive = false;
+ }
+
+ public GoogleAccountDialog (Gtk.Window parent, GoogleAccount account, bool show_error, CaptchaException captcha_exception)
+ {
+ xml = new Glade.XML (null, "PicasaWebExport.glade", dialog_name, "f-spot");
+ xml.Autoconnect (this);
+ Dialog.Modal = false;
+ Dialog.TransientFor = parent;
+ Dialog.DefaultResponse = Gtk.ResponseType.Ok;
+
+ this.account = account;
+
+ bool show_captcha = (captcha_exception != null);
+ status_area.Visible = show_error;
+ locked_area.Visible = show_captcha;
+ captcha_label.Visible = show_captcha;
+ captcha_entry.Visible = show_captcha;
+ captcha_image.Visible = show_captcha;
+
+ password_entry.ActivatesDefault = true;
+ username_entry.ActivatesDefault = true;
+
+ if (show_captcha) {
+ try {
+ using (ImageFile img = ImageFile.Create(new Uri(captcha_exception.CaptchaUrl))) {
+ captcha_image.Pixbuf = img.Load();
+ token = captcha_exception.Token;
+ }
+ } catch (Exception) {}
+ }
+
+ if (account != null) {
+ password_entry.Text = account.Password;
+ username_entry.Text = account.Username;
+ add_button.Label = Gtk.Stock.Ok;
+ Dialog.Response += HandleEditResponse;
+ }
+
+ if (remove_button != null)
+ remove_button.Visible = account != null;
+
+ this.Dialog.Show ();
+
+ password_entry.Changed += HandleChanged;
+ username_entry.Changed += HandleChanged;
+ HandleChanged (null, null);
+ }
+
+ private void HandleChanged (object sender, System.EventArgs args)
+ {
+ password = password_entry.Text;
+ username = username_entry.Text;
+
+ add_button.Sensitive = !(password == String.Empty || username == String.Empty);
+ }
+
+ [GLib.ConnectBefore]
+ protected void HandleAddResponse (object sender, Gtk.ResponseArgs args)
+ {
+ if (args.ResponseId == Gtk.ResponseType.Ok) {
+ GoogleAccount account = new GoogleAccount (username, password);
+ GoogleAccountManager.GetInstance ().AddAccount (account);
+ }
+ Dialog.Destroy ();
+ }
+
+ protected void HandleEditResponse (object sender, Gtk.ResponseArgs args)
+ {
+ if (args.ResponseId == Gtk.ResponseType.Ok) {
+ account.Username = username;
+ account.Password = password;
+ account.Token = token;
+ account.UnlockCaptcha = captcha_entry.Text;
+ GoogleAccountManager.GetInstance ().MarkChanged (true, account);
+ } else if (args.ResponseId == Gtk.ResponseType.Reject) {
+ // NOTE we are using Reject to signal the remove action.
+ GoogleAccountManager.GetInstance ().RemoveAccount (account);
+ }
+ Dialog.Destroy ();
+ }
+
+ private Gtk.Dialog Dialog {
+ get {
+ if (dialog == null)
+ dialog = (Gtk.Dialog) xml.GetWidget (dialog_name);
+
+ return dialog;
+ }
+ }
+
+ private GoogleAccount account;
+ private string password;
+ private string username;
+ private string token;
+
+ private Glade.XML xml;
+ private string dialog_name = "google_add_dialog";
+
+ // widgets
+ [Glade.Widget] Gtk.Dialog dialog;
+ [Glade.Widget] Gtk.Entry password_entry;
+ [Glade.Widget] Gtk.Entry username_entry;
+ [Glade.Widget] Gtk.Entry captcha_entry;
+
+ [Glade.Widget] Gtk.Button add_button;
+ [Glade.Widget] Gtk.Button remove_button;
+ [Glade.Widget] Gtk.Button cancel_button;
+
+ [Glade.Widget] Gtk.HBox status_area;
+ [Glade.Widget] Gtk.HBox locked_area;
+
+ [Glade.Widget] Gtk.Image captcha_image;
+ [Glade.Widget] Gtk.Label captcha_label;
+
+ }
+
+ public class GoogleAddAlbum {
+ [Glade.Widget] Gtk.Dialog dialog;
+ [Glade.Widget] Gtk.OptionMenu album_optionmenu;
+
+ [Glade.Widget] Gtk.Entry title_entry;
+ [Glade.Widget] Gtk.Entry description_entry;
+ [Glade.Widget] Gtk.CheckButton public_check;
+
+ [Glade.Widget] Gtk.Button add_button;
+ [Glade.Widget] Gtk.Button cancel_button;
+
+ private Glade.XML xml;
+ private string dialog_name = "google_add_album_dialog";
+
+ private GoogleExport export;
+ private PicasaWeb picasa;
+ private string description;
+ private string title;
+ private bool public_album;
+
+ public GoogleAddAlbum (GoogleExport export, PicasaWeb picasa)
+ {
+ xml = new Glade.XML (null, "PicasaWebExport.glade", dialog_name, "f-spot");
+ xml.Autoconnect (this);
+
+ this.export = export;
+ this.picasa = picasa;
+
+ Dialog.Response += HandleAddResponse;
+
+ description_entry.Changed += HandleChanged;
+ title_entry.Changed += HandleChanged;
+ HandleChanged (null, null);
+ }
+
+ private void HandleChanged (object sender, EventArgs args)
+ {
+ description = description_entry.Text;
+ title = title_entry.Text;
+ public_album = public_check.Active;
+
+ if (title == String.Empty)
+ add_button.Sensitive = false;
+ else
+ add_button.Sensitive = true;
+ }
+
+ [GLib.ConnectBefore]
+ protected void HandleAddResponse (object sender, Gtk.ResponseArgs args)
+ {
+ if (args.ResponseId == Gtk.ResponseType.Ok) {
+ public_album = public_check.Active;
+
+ try {
+ picasa.CreateAlbum (System.Web.HttpUtility.HtmlEncode (title), description, public_album ? AlbumAccess.Public : AlbumAccess.Private);
+ } catch (System.Exception e) {
+ HigMessageDialog md =
+ new HigMessageDialog (Dialog,
+ Gtk.DialogFlags.Modal |
+ Gtk.DialogFlags.DestroyWithParent,
+ Gtk.MessageType.Error, Gtk.ButtonsType.Ok,
+ Catalog.GetString ("Error while creating Album"),
+ String.Format (Catalog.GetString ("The following error was encountered while attempting to create an album: {0}"), e.Message));
+ md.Run ();
+ md.Destroy ();
+ return;
+ }
+ export.HandleAlbumAdded (title);
+ }
+ Dialog.Destroy ();
+ }
+
+ private Gtk.Dialog Dialog {
+ get {
+ if (dialog == null)
+ dialog = (Gtk.Dialog) xml.GetWidget (dialog_name);
+
+ return dialog;
+ }
+ }
+ }
+
+
+ public class GoogleExport : FSpot.Extensions.IExporter {
+ public GoogleExport ()
+ {
+ }
+
+ public void Run (IBrowsableCollection selection)
+ {
+ xml = new Glade.XML (null, "PicasaWebExport.glade", dialog_name, "f-spot");
+ xml.Autoconnect (this);
+
+ this.items = selection.Items;
+ album_button.Sensitive = false;
+ IconView view = new IconView (selection);
+ view.DisplayDates = false;
+ view.DisplayTags = false;
+
+ Dialog.Modal = false;
+ Dialog.TransientFor = null;
+
+ thumb_scrolledwindow.Add (view);
+ view.Show ();
+ Dialog.Show ();
+
+
+ GoogleAccountManager manager = GoogleAccountManager.GetInstance ();
+ manager.AccountListChanged += PopulateGoogleOptionMenu;
+ PopulateGoogleOptionMenu (manager, null);
+
+ if (edit_button != null)
+ edit_button.Clicked += HandleEditGallery;
+
+ Dialog.Response += HandleResponse;
+ connect = true;
+ HandleSizeActive (null, null);
+ Connect ();
+
+ scale_check.Toggled += HandleScaleCheckToggled;
+
+ LoadPreference (SCALE_KEY);
+ LoadPreference (SIZE_KEY);
+ LoadPreference (ROTATE_KEY);
+ LoadPreference (BROWSER_KEY);
+// LoadPreference (Preferences.EXPORT_PICASAWEB_META);
+ LoadPreference (TAG_KEY);
+ }
+
+ private bool scale;
+ private int size;
+ private bool browser;
+ private bool rotate;
+// private bool meta;
+ private bool export_tag;
+ private bool connect = false;
+
+ private long approx_size = 0;
+ private long sent_bytes = 0;
+
+ IBrowsableItem [] items;
+ int photo_index;
+ FSpot.ThreadProgressDialog progress_dialog;
+
+ ArrayList accounts;
+ private GoogleAccount account;
+ private PicasaAlbum album;
+
+ private string xml_path;
+
+ private Glade.XML xml;
+ private string dialog_name = "google_export_dialog";
+
+ public const string EXPORT_SERVICE = "picasaweb/";
+ public const string SCALE_KEY = Preferences.APP_FSPOT_EXPORT + EXPORT_SERVICE + "scale";
+ public const string SIZE_KEY = Preferences.APP_FSPOT_EXPORT + EXPORT_SERVICE + "size";
+ public const string ROTATE_KEY = Preferences.APP_FSPOT_EXPORT + EXPORT_SERVICE + "rotate";
+ public const string BROWSER_KEY = Preferences.APP_FSPOT_EXPORT + EXPORT_SERVICE + "browser";
+ public const string TAG_KEY = Preferences.APP_FSPOT_EXPORT + EXPORT_SERVICE + "tag";
+
+ // widgets
+ [Glade.Widget] Gtk.Dialog dialog;
+ [Glade.Widget] Gtk.OptionMenu gallery_optionmenu;
+ [Glade.Widget] Gtk.OptionMenu album_optionmenu;
+
+ [Glade.Widget] Gtk.Entry width_entry;
+ [Glade.Widget] Gtk.Entry height_entry;
+
+ [Glade.Widget] Gtk.Label status_label;
+
+ [Glade.Widget] Gtk.CheckButton browser_check;
+ [Glade.Widget] Gtk.CheckButton scale_check;
+ [Glade.Widget] Gtk.CheckButton rotate_check;
+// [Glade.Widget] Gtk.CheckButton meta_check;
+ [Glade.Widget] Gtk.CheckButton tag_check;
+
+ [Glade.Widget] Gtk.SpinButton size_spin;
+
+ [Glade.Widget] Gtk.Button album_button;
+ [Glade.Widget] Gtk.Button add_button;
+ [Glade.Widget] Gtk.Button edit_button;
+
+ [Glade.Widget] Gtk.Button export_button;
+ [Glade.Widget] Gtk.Button cancel_button;
+
+ [Glade.Widget] Gtk.ScrolledWindow thumb_scrolledwindow;
+
+ System.Threading.Thread command_thread;
+
+
+ private void HandleResponse (object sender, Gtk.ResponseArgs args)
+ {
+ if (args.ResponseId != Gtk.ResponseType.Ok) {
+ Dialog.Destroy ();
+ return;
+ }
+
+ if (scale_check != null) {
+ scale = scale_check.Active;
+ size = size_spin.ValueAsInt;
+ } else
+ scale = false;
+
+ browser = browser_check.Active;
+ rotate = rotate_check.Active;
+// meta = meta_check.Active;
+ export_tag = tag_check.Active;
+
+ if (account != null) {
+ //System.Console.WriteLine ("history = {0}", album_optionmenu.History);
+ album = (PicasaAlbum) account.Picasa.GetAlbums() [Math.Max (0, album_optionmenu.History)];
+ photo_index = 0;
+
+ Dialog.Destroy ();
+
+ command_thread = new System.Threading.Thread (new System.Threading.ThreadStart (this.Upload));
+ command_thread.Name = Catalog.GetString ("Uploading Pictures");
+
+ progress_dialog = new FSpot.ThreadProgressDialog (command_thread, items.Length);
+ progress_dialog.Start ();
+
+ // Save these settings for next time
+ Preferences.Set (SCALE_KEY, scale);
+ Preferences.Set (SIZE_KEY, size);
+ Preferences.Set (ROTATE_KEY, rotate);
+ Preferences.Set (BROWSER_KEY, browser);
+// Preferences.Set (Preferences.EXPORT_GALLERY_META, meta);
+ Preferences.Set (TAG_KEY, export_tag);
+ }
+ }
+
+ public void HandleSizeActive (object sender, EventArgs args)
+ {
+ size_spin.Sensitive = scale_check.Active;
+ }
+
+ private void HandleUploadProgress(object o, UploadProgressEventArgs args)
+ {
+ if (approx_size == 0)
+ progress_dialog.ProgressText = System.String.Format (Catalog.GetString ("{0} Sent"), SizeUtil.ToHumanReadable(args.BytesSent));
+ else
+ progress_dialog.ProgressText = System.String.Format (Catalog.GetString ("{0} of approx. {1}"), SizeUtil.ToHumanReadable(sent_bytes + args.BytesSent), SizeUtil.ToHumanReadable(approx_size));
+ progress_dialog.Fraction = ((photo_index - 1) / (double) items.Length) + (args.BytesSent / (args.BytesTotal * (double) items.Length));
+ }
+
+ private void Upload ()
+ {
+ album.UploadProgress += HandleUploadProgress;
+ sent_bytes = 0;
+ approx_size = 0;
+
+ System.Console.WriteLine ("Starting Upload to Picasa");
+
+ FilterSet filters = new FilterSet ();
+ filters.Add (new JpegFilter ());
+
+ if (scale)
+ filters.Add (new ResizeFilter ((uint)size));
+
+ if (rotate)
+ filters.Add (new OrientationFilter ());
+
+ Array.Sort (items as Photo[], new Photo.CompareDateName ());
+
+ while (photo_index < items.Length) {
+ try {
+ IBrowsableItem item = items[photo_index];
+
+ FileInfo file_info;
+ Console.WriteLine ("uploading {0}", photo_index);
+
+ progress_dialog.Message = String.Format (Catalog.GetString ("Uploading picture \"{0}\" ({1} of {2})"),
+ item.Name, photo_index+1, items.Length);
+ photo_index++;
+
+ FilterRequest request = new FilterRequest (item.DefaultVersionUri);
+
+ filters.Convert (request);
+
+ file_info = new FileInfo (request.Current.LocalPath);
+
+ if (approx_size == 0) //first image
+ approx_size = file_info.Length * items.Length;
+ else
+ approx_size = sent_bytes * items.Length / (photo_index - 1);
+
+ PicasaPicture picture = album.UploadPicture (request.Current.LocalPath, Path.ChangeExtension (item.Name, "jpg"), item.Description);
+ if (Core.Database != null && item is Photo)
+ Core.Database.Exports.Create ((item as Photo).Id,
+ (item as Photo).DefaultVersionId,
+ ExportStore.PicasaExportType,
+ picture.Link);
+
+ sent_bytes += file_info.Length;
+
+ request.Dispose ();
+ //tagging
+ if (item.Tags != null && export_tag)
+ foreach (Tag tag in item.Tags)
+ picture.AddTag (tag.Name);
+
+ } catch (System.Exception e) {
+ progress_dialog.Message = String.Format (Catalog.GetString ("Error Uploading To Gallery: {0}"),
+ e.Message);
+ progress_dialog.ProgressText = Catalog.GetString ("Error");
+ System.Console.WriteLine (e);
+
+ if (progress_dialog.PerformRetrySkip ())
+ photo_index--;
+ }
+ }
+
+ progress_dialog.Message = Catalog.GetString ("Done Sending Photos");
+ progress_dialog.Fraction = 1.0;
+ progress_dialog.ProgressText = Catalog.GetString ("Upload Complete");
+ progress_dialog.ButtonLabel = Gtk.Stock.Ok;
+
+ if (browser) {
+ GnomeUtil.UrlShow (null, album.Link);
+ }
+ }
+
+ private void HandleScaleCheckToggled (object o, EventArgs e)
+ {
+ rotate_check.Sensitive = !scale_check.Active;
+ }
+
+ private void PopulateGoogleOptionMenu (GoogleAccountManager manager, GoogleAccount changed_account)
+ {
+ Gtk.Menu menu = new Gtk.Menu ();
+ this.account = changed_account;
+ int pos = -1;
+
+ accounts = manager.GetAccounts ();
+ if (accounts == null || accounts.Count == 0) {
+ Gtk.MenuItem item = new Gtk.MenuItem (Catalog.GetString ("(No Gallery)"));
+ menu.Append (item);
+ gallery_optionmenu.Sensitive = false;
+ edit_button.Sensitive = false;
+ } else {
+ int i = 0;
+ foreach (GoogleAccount account in accounts) {
+ if (account == changed_account)
+ pos = i;
+
+ Gtk.MenuItem item = new Gtk.MenuItem (account.Username);
+ menu.Append (item);
+ i++;
+ }
+ gallery_optionmenu.Sensitive = true;
+ edit_button.Sensitive = true;
+ }
+
+ menu.ShowAll ();
+ gallery_optionmenu.Menu = menu;
+ gallery_optionmenu.SetHistory ((uint)pos);
+ }
+
+ private void Connect ()
+ {
+ Connect (null);
+ }
+
+ private void Connect (GoogleAccount selected)
+ {
+ Connect (selected, null, null);
+ }
+
+ private void Connect (GoogleAccount selected, string token, string text)
+ {
+ try {
+ if (accounts.Count != 0 && connect) {
+ if (selected == null)
+ account = (GoogleAccount) accounts [gallery_optionmenu.History];
+ else
+ account = selected;
+
+ if (!account.Connected)
+ account.Connect ();
+
+ PopulateAlbumOptionMenu (account.Picasa);
+
+ long qu = account.Picasa.QuotaUsed;
+ long ql = account.Picasa.QuotaLimit;
+
+ StringBuilder sb = new StringBuilder("<small>");
+ sb.Append(Catalog.GetString("Available space :"));
+ sb.Append(SizeUtil.ToHumanReadable (ql - qu));
+ sb.Append(" (");
+ sb.Append(100 * qu / ql);
+ sb.Append("% used out of ");
+ sb.Append(SizeUtil.ToHumanReadable (ql));
+ sb.Append(")");
+ sb.Append("</small>");
+
+ status_label.Text = sb.ToString();
+ status_label.UseMarkup = true;
+
+ album_button.Sensitive = true;
+ }
+ } catch (CaptchaException exc){
+ System.Console.WriteLine("Your google account is locked");
+ if (selected != null)
+ account = selected;
+
+ PopulateAlbumOptionMenu (account.Picasa);
+ album_button.Sensitive = false;
+
+ new GoogleAccountDialog (this.Dialog, account, false, exc);
+
+ System.Console.WriteLine ("Your google account is locked, you can unlock it by visiting: {0}", CaptchaException.UnlockCaptchaURL);
+
+ } catch (System.Exception) {
+ System.Console.WriteLine ("Can not connect to Picasa. Bad username ? password ? network connection ?");
+ //System.Console.WriteLine ("{0}",ex);
+ if (selected != null)
+ account = selected;
+
+ PopulateAlbumOptionMenu (account.Picasa);
+
+ status_label.Text = String.Empty;
+ album_button.Sensitive = false;
+
+ new GoogleAccountDialog (this.Dialog, account, true, null);
+ }
+ }
+
+ private void HandleAccountSelected (object sender, System.EventArgs args)
+ {
+ Connect ();
+ }
+
+ public void HandleAlbumAdded (string title) {
+ GoogleAccount account = (GoogleAccount) accounts [gallery_optionmenu.History];
+ PopulateAlbumOptionMenu (account.Picasa);
+
+ // make the newly created album selected
+ PicasaAlbumCollection albums = account.Picasa.GetAlbums();
+ for (int i=0; i < albums.Count; i++) {
+ if (((PicasaAlbum)albums[i]).Title == title) {
+ album_optionmenu.SetHistory((uint)i);
+ }
+ }
+ }
+
+ private void PopulateAlbumOptionMenu (PicasaWeb picasa)
+ {
+ PicasaAlbumCollection albums = null;
+ if (picasa != null) {
+ try {
+ albums = picasa.GetAlbums();
+ } catch {
+ Console.WriteLine("Can't get the albums");
+ picasa = null;
+ }
+ }
+
+ Gtk.Menu menu = new Gtk.Menu ();
+
+ bool disconnected = picasa == null || !account.Connected || albums == null;
+
+ if (disconnected || albums.Count == 0) {
+ string msg = disconnected ? Catalog.GetString ("(Not Connected)")
+ : Catalog.GetString ("(No Albums)");
+
+ Gtk.MenuItem item = new Gtk.MenuItem (msg);
+ menu.Append (item);
+
+ export_button.Sensitive = false;
+ album_optionmenu.Sensitive = false;
+ album_button.Sensitive = false;
+
+ if (disconnected)
+ album_button.Sensitive = false;
+ } else {
+ foreach (PicasaAlbum album in albums.AllValues) {
+ System.Text.StringBuilder label_builder = new System.Text.StringBuilder ();
+
+ label_builder.Append (album.Title);
+
+ Gtk.MenuItem item = new Gtk.MenuItem (label_builder.ToString ());
+ ((Gtk.Label)item.Child).UseUnderline = false;
+ menu.Append (item);
+ }
+
+ export_button.Sensitive = items.Length > 0;
+ album_optionmenu.Sensitive = true;
+ album_button.Sensitive = true;
+ }
+
+ menu.ShowAll ();
+ album_optionmenu.Menu = menu;
+ }
+
+ public void HandleAddGallery (object sender, System.EventArgs args)
+ {
+ new GoogleAccountDialog (this.Dialog);
+ }
+
+ public void HandleEditGallery (object sender, System.EventArgs args)
+ {
+ new GoogleAccountDialog (this.Dialog, account, false, null);
+ }
+
+ public void HandleAddAlbum (object sender, System.EventArgs args)
+ {
+ if (account == null)
+ throw new Exception (Catalog.GetString ("No account selected"));
+
+ new GoogleAddAlbum (this, account.Picasa);
+ }
+
+ void LoadPreference (string key)
+ {
+ object val = Preferences.Get (key);
+
+ if (val == null)
+ return;
+
+ //System.Console.WriteLine ("Setting {0} to {1}", key, val);
+
+ switch (key) {
+ case SCALE_KEY:
+ if (scale_check.Active != (bool) val) {
+ scale_check.Active = (bool) val;
+ rotate_check.Sensitive = !(bool) val;
+ }
+ break;
+
+ case SIZE_KEY:
+ size_spin.Value = (double) (int) val;
+ break;
+
+ case BROWSER_KEY:
+ if (browser_check.Active != (bool) val)
+ browser_check.Active = (bool) val;
+ break;
+
+ case ROTATE_KEY:
+ if (rotate_check.Active != (bool) val)
+ rotate_check.Active = (bool) val;
+ break;
+
+// case Preferences.EXPORT_GALLERY_META:
+// if (meta_check.Active != (bool) val)
+// meta_check.Active = (bool) val;
+// break;
+
+ case TAG_KEY:
+ if (tag_check.Active != (bool) val)
+ tag_check.Active = (bool) val;
+ break;
+ }
+ }
+
+ private Gtk.Dialog Dialog {
+ get {
+ if (dialog == null)
+ dialog = (Gtk.Dialog) xml.GetWidget (dialog_name);
+
+ return dialog;
+ }
+ }
+ }
+}
Added: trunk/extensions/PicasaWebExport/PicasaWebExport.glade
==============================================================================
--- (empty file)
+++ trunk/extensions/PicasaWebExport/PicasaWebExport.glade Fri Feb 8 15:37:13 2008
@@ -0,0 +1,835 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
+<!--*- mode: xml -*-->
+<glade-interface>
+ <requires lib="canvas"/>
+ <requires lib="gnome"/>
+ <widget class="GtkDialog" id="google_export_dialog">
+ <property name="title" translatable="yes">Export</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+ <property name="has_separator">False</property>
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="dialog-vbox11">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkHBox" id="hbox17">
+ <property name="visible">True</property>
+ <property name="border_width">6</property>
+ <child>
+ <widget class="GtkFrame" id="frame8">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">GTK_SHADOW_NONE</property>
+ <child>
+ <widget class="GtkAlignment" id="alignment12">
+ <property name="visible">True</property>
+ <property name="left_padding">12</property>
+ <child>
+ <widget class="GtkScrolledWindow" id="thumb_scrolledwindow">
+ <property name="width_request">180</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="photo_frame">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"><b>Photos</b></property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkVBox" id="vbox11">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <widget class="GtkFrame" id="frame9">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">GTK_SHADOW_NONE</property>
+ <child>
+ <widget class="GtkAlignment" id="alignment13">
+ <property name="visible">True</property>
+ <property name="left_padding">12</property>
+ <child>
+ <widget class="GtkVBox" id="vbox12">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <widget class="GtkHBox" id="hbox20">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <widget class="GtkLabel" id="gallery_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Gallery:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">gallery_optionmenu</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkOptionMenu" id="gallery_optionmenu">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="response_id">0</property>
+ <signal name="changed" handler="HandleAccountSelected"/>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkButton" id="gallery_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-add</property>
+ <property name="use_stock">True</property>
+ <property name="response_id">0</property>
+ <signal name="clicked" handler="HandleAddGallery"/>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkButton" id="edit_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-edit</property>
+ <property name="use_stock">True</property>
+ <property name="response_id">0</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="status_label">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label44">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"><b>PicasaWeb Export</b></property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkFrame" id="frame10">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">GTK_SHADOW_NONE</property>
+ <child>
+ <widget class="GtkAlignment" id="alignment14">
+ <property name="visible">True</property>
+ <property name="left_padding">12</property>
+ <child>
+ <widget class="GtkVBox" id="vbox13">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <widget class="GtkHBox" id="hbox18">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <widget class="GtkLabel" id="album_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Export to Album:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">album_optionmenu</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkOptionMenu" id="album_optionmenu">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="response_id">0</property>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkButton" id="album_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-add</property>
+ <property name="use_stock">True</property>
+ <property name="response_id">0</property>
+ <signal name="clicked" handler="HandleAddAlbum"/>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkCheckButton" id="browser_check">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Open _album in browser when done uploading</property>
+ <property name="use_underline">True</property>
+ <property name="response_id">0</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label45">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"><b>Album</b></property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkFrame" id="frame11">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">GTK_SHADOW_NONE</property>
+ <child>
+ <widget class="GtkAlignment" id="alignment15">
+ <property name="visible">True</property>
+ <property name="left_padding">12</property>
+ <child>
+ <widget class="GtkVBox" id="vbox14">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <widget class="GtkHBox" id="hbox58">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkCheckButton" id="scale_check">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">_Resize to: </property>
+ <property name="use_underline">True</property>
+ <property name="response_id">0</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="HandleSizeActive"/>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkSpinButton" id="size_spin">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">400 0 10000 1 10 10</property>
+ <property name="climb_rate">1</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label153">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">pixels</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkCheckButton" id="rotate_check">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">_Autorotate</property>
+ <property name="use_underline">True</property>
+ <property name="response_id">0</property>
+ <property name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkCheckButton" id="tag_check">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">_Export tags</property>
+ <property name="use_underline">True</property>
+ <property name="response_id">0</property>
+ <property name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label46">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"><b>Style</b></property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <widget class="GtkHButtonBox" id="dialog-action_area11">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+ <child>
+ <widget class="GtkButton" id="cancel_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="label">gtk-cancel</property>
+ <property name="use_stock">True</property>
+ <property name="response_id">-6</property>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkButton" id="export_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="label">_Export</property>
+ <property name="use_underline">True</property>
+ <property name="response_id">-5</property>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <widget class="GtkDialog" id="google_add_album_dialog">
+ <property name="visible">True</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+ <property name="has_separator">False</property>
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="dialog-vbox12">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkTable" id="table10">
+ <property name="visible">True</property>
+ <property name="border_width">12</property>
+ <property name="n_rows">3</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">7</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="descroption_label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Description:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">description_entry</property>
+ </widget>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkEntry" id="description_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">*</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="name_label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Album Title:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">title_entry</property>
+ </widget>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkEntry" id="title_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">*</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkCheckButton" id="public_check">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Public Album</property>
+ <property name="use_underline">True</property>
+ <property name="response_id">0</property>
+ <property name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <widget class="GtkHButtonBox" id="dialog-action_area12">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+ <child>
+ <widget class="GtkButton" id="cancel_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="label">gtk-cancel</property>
+ <property name="use_stock">True</property>
+ <property name="response_id">-6</property>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkButton" id="add_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="label">gtk-add</property>
+ <property name="use_stock">True</property>
+ <property name="response_id">-5</property>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <widget class="GtkDialog" id="google_add_dialog">
+ <property name="visible">True</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+ <property name="has_separator">False</property>
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="dialog-vbox12">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkVBox" id="vbox63">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkHBox" id="status_area">
+ <property name="border_width">12</property>
+ <child>
+ <widget class="GtkImage" id="image12">
+ <property name="visible">True</property>
+ <property name="yalign">0</property>
+ <property name="stock">gtk-dialog-question</property>
+ <property name="icon_size">6</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVBox" id="vbox64">
+ <property name="visible">True</property>
+ <property name="border_width">6</property>
+ <child>
+ <widget class="GtkLabel" id="summary_label">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes"><span weight='bold' size='larger'>Error Connecting to Gallery</span>
+</property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="description_label">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Please verify that the settings for this gallery are correct.</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="locked_area">
+ <property name="border_width">12</property>
+ <child>
+ <widget class="GtkImage" id="image45">
+ <property name="visible">True</property>
+ <property name="yalign">0</property>
+ <property name="stock">gtk-missing-image</property>
+ <property name="icon_size">6</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVBox" id="vbox84">
+ <property name="visible">True</property>
+ <property name="border_width">6</property>
+ <child>
+ <widget class="GtkLabel" id="label214">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes"><span weight='bold' size='larger'>Your Google Account is locked</span>
+</property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label215">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Please verify that the settings for this gallery are correct.
+Enter the letters as they are shown in the image in
+the 'Captcha' field. <i>Letters are not case-sensitive</i></property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkTable" id="table10">
+ <property name="visible">True</property>
+ <property name="border_width">12</property>
+ <property name="n_rows">3</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">7</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <widget class="GtkLabel" id="password_label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Password:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">password_entry</property>
+ </widget>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkEntry" id="password_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="visibility">False</property>
+ <property name="invisible_char">*</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="username_label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Username:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">username_entry</property>
+ </widget>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkEntry" id="username_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">*</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="captcha_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Captcha:</property>
+ <property name="use_underline">True</property>
+ </widget>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox88">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkEntry" id="captcha_entry">
+ <property name="can_focus">True</property>
+ <property name="invisible_char">*</property>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkImage" id="captcha_image">
+ <property name="stock">gtk-missing-image</property>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <widget class="GtkHButtonBox" id="dialog-action_area12">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+ <child>
+ <widget class="GtkButton" id="cancel_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="label">gtk-cancel</property>
+ <property name="use_stock">True</property>
+ <property name="response_id">-6</property>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkButton" id="remove_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="label">gtk-remove</property>
+ <property name="use_stock">True</property>
+ <property name="response_id">-2</property>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkButton" id="add_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="label">gtk-add</property>
+ <property name="use_stock">True</property>
+ <property name="response_id">-5</property>
+ </widget>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+</glade-interface>
Added: trunk/extensions/PicasaWebExport/google-sharp/AlbumAccess.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/PicasaWebExport/google-sharp/AlbumAccess.cs Fri Feb 8 15:37:13 2008
@@ -0,0 +1,36 @@
+//
+// Mono.Google.Picasa.AlbumAccess.cs:
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo ximian com)
+//
+// (C) Copyright 2006 Novell, Inc. (http://www.novell.com)
+//
+
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace Mono.Google.Picasa {
+ public enum AlbumAccess {
+ Public,
+ Private
+ }
+}
+
Added: trunk/extensions/PicasaWebExport/google-sharp/AssemblyInfo.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/PicasaWebExport/google-sharp/AssemblyInfo.cs Fri Feb 8 15:37:13 2008
@@ -0,0 +1,36 @@
+// AssemblyInfo.cs for Mono.Google.dll
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo ximian com)
+//
+// Copyright (c) 2006 Novell, Inc. (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyVersion("0.1.0")]
+[assembly: AssemblyTitle ("Mono.Google")]
+[assembly: AssemblyDescription ("")]
+[assembly: AssemblyCopyright ("(c) 2006 Novell, Inc.")]
+[assembly: AssemblyCompany ("Novell, Inc.")]
+
Added: trunk/extensions/PicasaWebExport/google-sharp/Authentication.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/PicasaWebExport/google-sharp/Authentication.cs Fri Feb 8 15:37:13 2008
@@ -0,0 +1,158 @@
+//
+// Mono.Google.Authentication.cs:
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo ximian com)
+// Stephane Delcroix (stephane delcroix org)
+//
+// (C) Copyright 2006 Novell, Inc. (http://www.novell.com)
+// (C) Copyright 2007 S. Delcroix
+//
+
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Check the Google Authentication Page at http://code.google.com/apis/accounts/AuthForInstalledApps.html
+//
+
+using System;
+using System.IO;
+using System.Net;
+using System.Text;
+using System.Web;
+
+namespace Mono.Google {
+ class Authentication {
+ static string client_login_url = "https://www.google.com/accounts/ClientLogin";
+
+ public static string GetAuthorization (GoogleConnection conn, string email, string password,
+ GoogleService service, string token, string captcha)
+ {
+ if (email == null || email == String.Empty || password == null || password == String.Empty)
+ return null;
+
+ email = HttpUtility.UrlEncode (email);
+ password = HttpUtility.UrlEncode (password);
+ string appname = HttpUtility.UrlEncode (conn.ApplicationName);
+ string service_code = service.ServiceCode;
+
+ StringBuilder content = new StringBuilder ();
+ content.Append ("accountType=HOSTED_OR_GOOGLE");
+ content.AppendFormat ("&Email={0}", email);
+ content.AppendFormat ("&Passwd={0}", password);
+ content.AppendFormat ("&email={0}", email);
+ content.AppendFormat ("&service={0}", service_code);
+ content.AppendFormat ("&source={0}", appname);
+
+ if (token != null) {
+ content.AppendFormat ("&logintoken={0}", token);
+ content.AppendFormat ("&logincaptcha={0}", captcha);
+ }
+ byte [] bytes = Encoding.UTF8.GetBytes (content.ToString ());
+
+ HttpWebRequest request = (HttpWebRequest) WebRequest.Create (client_login_url);
+ request.Method = "POST";
+ request.ContentType = "application/x-www-form-urlencoded";
+ request.ContentLength = bytes.Length;
+
+ Stream output = request.GetRequestStream ();
+ output.Write (bytes, 0, bytes.Length);
+ output.Close ();
+
+ HttpWebResponse response = null;
+ try {
+ response = (HttpWebResponse) request.GetResponse ();
+ } catch (WebException wexc) {
+ response = wexc.Response as HttpWebResponse;
+ if (response == null)
+ throw;
+ ThrowOnError (response);
+ throw; // if the method above does not throw, we do
+ }
+
+ //string sid = null;
+ //string lsid = null;
+ string auth = null;
+
+ using (Stream stream = response.GetResponseStream ()) {
+ StreamReader sr = new StreamReader (stream, Encoding.UTF8);
+ string s;
+ while ((s = sr.ReadLine ()) != null) {
+ if (s.StartsWith ("Auth="))
+ auth = s.Substring (5);
+ //else if (s.StartsWith ("LSID="))
+ // lsid = s.Substring (5);
+ //else if (s.StartsWith ("SID="))
+ // sid = s.Substring (4);
+ }
+ }
+ response.Close ();
+
+ return auth;
+ }
+
+ static void ThrowOnError (HttpWebResponse response)
+ {
+ if (response.StatusCode != HttpStatusCode.Forbidden)
+ return;
+
+ string url = null;
+ string token = null;
+ string captcha_url = null;
+ string code = null;
+ using (StreamReader reader = new StreamReader (response.GetResponseStream ())) {
+ string str;
+ while ((str = reader.ReadLine ()) != null) {
+ if (str.StartsWith ("Url=")) {
+ url = str.Substring (4);
+ } else if (str.StartsWith ("Error=")) {
+ /* These are the values for Error
+ None,
+ BadAuthentication,
+ NotVerified,
+ TermsNotAgreed,
+ CaptchaRequired,
+ Unknown,
+ AccountDeleted,
+ AccountDisabled,
+ ServiceUnavailable
+ */
+ code = str.Substring (6);
+ } else if (str.StartsWith ("CaptchaToken=")) {
+ token = str.Substring (13);
+ } else if (str.StartsWith ("CaptchaUrl=")) {
+ captcha_url = str.Substring (11);
+ }
+ }
+ }
+ if (code == "CaptchaRequired" && token != null && captcha_url != null) {
+ if (url != null) {
+ Uri uri = new Uri (url);
+ captcha_url = new Uri (uri, captcha_url).ToString ();
+ } else if (!captcha_url.StartsWith ("https://")) {
+ captcha_url = "https://www.google.com/accounts/" + captcha_url;
+ }
+ throw new CaptchaException (url, token, captcha_url);
+ }
+
+ throw new UnauthorizedAccessException (String.Format ("Access to '{0}' is denied ({1})", url, code));
+ }
+ }
+}
+
Added: trunk/extensions/PicasaWebExport/google-sharp/CaptchaException.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/PicasaWebExport/google-sharp/CaptchaException.cs Fri Feb 8 15:37:13 2008
@@ -0,0 +1,87 @@
+//
+// Mono.Google.CaptchaException
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo novell com)
+//
+// Copyright (c) 2006 Novell, Inc. (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Runtime.Serialization;
+
+namespace Mono.Google {
+ [Serializable]
+ public class CaptchaException : UnauthorizedAccessException, ISerializable
+ {
+ public static string UnlockCaptchaURL = "https://www.google.com/accounts/DisplayUnlockCaptcha";
+ string url;
+ string token;
+ string captcha_url;
+
+ public CaptchaException ()
+ {
+ }
+
+ public CaptchaException (string url, string token, string captcha_url)
+ {
+ this.url = url;
+ this.token = token;
+ this.captcha_url = captcha_url;
+ }
+
+ protected CaptchaException (SerializationInfo info, StreamingContext context)
+ : base (info, context)
+ {
+ if (info == null)
+ throw new ArgumentNullException ("info");
+
+ url = info.GetString ("url");
+ token = info.GetString ("token");
+ captcha_url = info.GetString ("captcha_url");
+ }
+
+ void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ throw new ArgumentNullException ("info");
+
+ base.GetObjectData (info, context);
+ info.AddValue ("url", url);
+ info.AddValue ("token", token);
+ info.AddValue ("captcha_url", captcha_url);
+ }
+
+ public string Url {
+ get { return url; }
+ }
+
+ public string Token {
+ get { return token; }
+ }
+
+ public string CaptchaUrl {
+ get { return captcha_url; }
+ }
+ }
+}
+
Added: trunk/extensions/PicasaWebExport/google-sharp/CreateAlbumException.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/PicasaWebExport/google-sharp/CreateAlbumException.cs Fri Feb 8 15:37:13 2008
@@ -0,0 +1,44 @@
+//
+// Mono.Google.Picasa.CreateAlbumException.cs:
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo ximian com)
+//
+// (C) Copyright 2006 Novell, Inc. (http://www.novell.com)
+//
+
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Runtime.Serialization;
+namespace Mono.Google.Picasa {
+ public class CreateAlbumException : Exception {
+ public CreateAlbumException (string msg) : base (msg)
+ {
+ }
+
+ protected CreateAlbumException (SerializationInfo info, StreamingContext context)
+ : base (info, context)
+ {
+ }
+ }
+}
+
Added: trunk/extensions/PicasaWebExport/google-sharp/DeleteAlbumException.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/PicasaWebExport/google-sharp/DeleteAlbumException.cs Fri Feb 8 15:37:13 2008
@@ -0,0 +1,44 @@
+//
+// Mono.Google.Picasa.DeleteAlbumException.cs:
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo ximian com)
+//
+// (C) Copyright 2006 Novell, Inc. (http://www.novell.com)
+//
+
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Runtime.Serialization;
+namespace Mono.Google.Picasa {
+ public class DeleteAlbumException : Exception {
+ public DeleteAlbumException (string msg) : base (msg)
+ {
+ }
+
+ protected DeleteAlbumException (SerializationInfo info, StreamingContext context)
+ : base (info, context)
+ {
+ }
+ }
+}
+
Added: trunk/extensions/PicasaWebExport/google-sharp/GDataApi.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/PicasaWebExport/google-sharp/GDataApi.cs Fri Feb 8 15:37:13 2008
@@ -0,0 +1,92 @@
+/*
+ * Mono.Google.Picasa.GDataApi.cs
+ *
+ * Author(s):
+ * Stephane Delcroix <stephane delcroix org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Check Picasa Web Albums Data Api at http://code.google.com/apis/picasaweb/gdata.html
+ *
+ */
+
+
+namespace Mono.Google.Picasa {
+ class GDataApi {
+ private const string feed = "http://picasaweb.google.com/data/feed/api/";
+ private const string entry = "http://picasaweb.google.com/data/entry/api/";
+ const string gallery = "user/{userid}?kind=album";
+ const string album_by_id = "user/{userid}/albumid/{aid}?kind=photo";
+ //const string album_by_name = entry + "user/{userid}/album/{aname}?kind=photo";
+ const string picture_by_id = "user/{userid}/albumid/{aid}/photoid/{pid}";
+ const string post_url = feed + "user/{userid}";
+ const string post_picture = feed + "user/{userid}/albumid/{aid}";
+ const string date_format = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.000Z'";
+
+ public static string GetGalleryFeed (string user)
+ {
+ return feed + gallery.Replace ("{userid}", user);
+ }
+
+ public static string GetGalleryEntry (string user)
+ {
+ return entry + gallery.Replace ("{userid}", user);
+ }
+
+ public static string GetAlbumFeedById (string user, string aid)
+ {
+ return feed + album_by_id.Replace ("{userid}", user).Replace ("{aid}", aid);
+ }
+
+ public static string GetAlbumEntryById (string user, string aid)
+ {
+ return entry + album_by_id.Replace ("{userid}", user).Replace ("{aid}", aid);
+ }
+
+ //public static string GetAlbumByName (string user, string aname)
+ //{
+ // return album_by_name.Replace ("{userid}", user).Replace ("{aname}", aname);
+ //}
+
+ public static string GetPictureEntry (string user, string aid, string pid)
+ {
+ return entry + picture_by_id.Replace ("{userid}", user).Replace ("{aid}", aid).Replace ("{pid}", pid);
+ }
+
+ public static string GetPictureFeed (string user, string aid, string pid)
+ {
+ return feed + picture_by_id.Replace ("{userid}", user).Replace ("{aid}", aid).Replace ("{pid}", pid);
+ }
+
+ public static string GetPostURL (string user)
+ {
+ return post_url.Replace ("{userid}", user);
+ }
+
+ public static string GetURLForUpload (string user, string aid)
+ {
+ return post_picture.Replace ("{userid}", user).Replace ("{aid}", aid);
+ }
+
+ public static string DateFormat {
+ get { return date_format; }
+ }
+ }
+}
Added: trunk/extensions/PicasaWebExport/google-sharp/GoogleConnection.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/PicasaWebExport/google-sharp/GoogleConnection.cs Fri Feb 8 15:37:13 2008
@@ -0,0 +1,212 @@
+//
+// Mono.Google.GoogleConnection.cs:
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo ximian com)
+// Stephane Delcroix (stephane delcroix org)
+//
+// (C) Copyright 2006 Novell, Inc. (http://www.novell.com)
+// (C) Copyright 2007 S. Delcroix
+//
+
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Check the Google Authentication Page at http://code.google.com/apis/accounts/AuthForInstalledApps.html
+//
+
+using System;
+using System.Globalization;
+using System.IO;
+using System.Net;
+using System.Text;
+using System.Reflection;
+
+namespace Mono.Google {
+ public class GoogleConnection {
+ string user;
+ GoogleService service;
+ string auth;
+ string appname;
+
+ public GoogleConnection (GoogleService service)
+ {
+ this.service = service;
+ }
+
+ public string ApplicationName {
+ get {
+ if (appname == null) {
+ Assembly assembly = Assembly.GetEntryAssembly ();
+ if (assembly == null)
+ throw new InvalidOperationException ("You need to set GoogleConnection.ApplicationName.");
+ AssemblyName aname = assembly.GetName ();
+ appname = String.Format ("{0}-{1}", aname.Name, aname.Version);
+ }
+
+ return appname;
+ }
+
+ set {
+ if (value == null || value == "")
+ throw new ArgumentException ("Cannot be null or empty", "value");
+
+ appname = value;
+ }
+ }
+
+ public void Authenticate (string user, string password)
+ {
+ if (user == null)
+ throw new ArgumentNullException ("user");
+
+ if (this.user != null)
+ throw new InvalidOperationException (String.Format ("Already authenticated for {0}", this.user));
+
+ this.user = user;
+ this.auth = Authentication.GetAuthorization (this, user, password, service, null, null);
+ if (this.auth == null) {
+ this.user = null;
+ throw new Exception (String.Format ("Authentication failed for user {0}", user));
+ }
+ }
+
+ public void Authenticate (string user, string password, string token, string captcha)
+ {
+ if (user == null)
+ throw new ArgumentNullException ("user");
+
+ if (token == null)
+ throw new ArgumentNullException ("token");
+
+ if (captcha == null)
+ throw new ArgumentNullException ("captcha");
+
+ if (this.user != null)
+ throw new InvalidOperationException (String.Format ("Already authenticated for {0}", this.user));
+
+ this.user = user;
+ this.auth = Authentication.GetAuthorization (this, user, password, service, token, captcha);
+ if (this.auth == null) {
+ this.user = null;
+ throw new Exception (String.Format ("Authentication failed for user {0}", user));
+ }
+ }
+
+ public HttpWebRequest AuthenticatedRequest (string url)
+ {
+ if (url == null)
+ throw new ArgumentNullException ("url");
+
+ HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
+ if (auth != null)
+ req.Headers.Add ("Authorization: GoogleLogin auth=" + auth);
+ return req;
+ }
+
+ public string DownloadString (string url)
+ {
+ if (url == null)
+ throw new ArgumentNullException ("url");
+
+ string received = null;
+ HttpWebRequest req = AuthenticatedRequest (url);
+ HttpWebResponse response = (HttpWebResponse) req.GetResponse ();
+ Encoding encoding = Encoding.UTF8;
+ if (response.ContentEncoding != "") {
+ try {
+ encoding = Encoding.GetEncoding (response.ContentEncoding);
+ } catch {}
+ }
+
+ using (Stream stream = response.GetResponseStream ()) {
+ StreamReader sr = new StreamReader (stream, encoding);
+ received = sr.ReadToEnd ();
+ }
+ response.Close ();
+ return received;
+ }
+
+ public byte [] DownloadBytes (string url)
+ {
+ if (url == null)
+ throw new ArgumentNullException ("url");
+
+ HttpWebRequest req = AuthenticatedRequest (url);
+ HttpWebResponse response = (HttpWebResponse) req.GetResponse ();
+ byte [] bytes = null;
+ using (Stream stream = response.GetResponseStream ()) {
+ if (response.ContentLength != -1) {
+ bytes = new byte [response.ContentLength];
+ stream.Read (bytes, 0, bytes.Length);
+ } else {
+ MemoryStream ms = new MemoryStream ();
+ bytes = new byte [4096];
+ int nread;
+ while ((nread = stream.Read (bytes, 0, bytes.Length)) > 0) {
+ ms.Write (bytes, 0, nread);
+ if (nread < bytes.Length)
+ break;
+ }
+ bytes = ms.ToArray ();
+ }
+ }
+ response.Close ();
+
+ return bytes;
+ }
+
+ public void DownloadToStream (string url, Stream output)
+ {
+ if (url == null)
+ throw new ArgumentNullException ("url");
+
+ if (output == null)
+ throw new ArgumentNullException ("output");
+
+ if (!output.CanWrite)
+ throw new ArgumentException ("The stream is not writeable", "output");
+
+ HttpWebRequest req = AuthenticatedRequest (url);
+ HttpWebResponse response = (HttpWebResponse) req.GetResponse ();
+ byte [] bytes = null;
+ using (Stream stream = response.GetResponseStream ()) {
+ bytes = new byte [4096];
+ int nread;
+ while ((nread = stream.Read (bytes, 0, bytes.Length)) > 0) {
+ output.Write (bytes, 0, nread);
+ }
+ }
+ response.Close ();
+ }
+
+ public string User {
+ get { return user; }
+ }
+
+ public GoogleService Service {
+ get { return service; }
+ }
+
+ internal string AuthToken {
+ get { return auth; }
+ }
+ }
+}
+
Added: trunk/extensions/PicasaWebExport/google-sharp/GoogleService.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/PicasaWebExport/google-sharp/GoogleService.cs Fri Feb 8 15:37:13 2008
@@ -0,0 +1,54 @@
+//
+// Mono.Google.GoogleService.cs:
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo ximian com)
+// Stephane Delcroix (stephane delcroix org)
+//
+// (C) Copyright 2006 Novell, Inc. (http://www.novell.com)
+// (C) Copyright 2007 S. Delcroix
+//
+
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+namespace Mono.Google {
+ public class GoogleService {
+ public static GoogleService Picasa {
+ get { return new GoogleService ("lh2"); }
+ }
+
+ public static GoogleService Calendar {
+ get { return new GoogleService ("cl"); }
+ }
+
+ string service_code;
+ public string ServiceCode {
+ get { return service_code; }
+ }
+
+ private GoogleService (string service_code)
+ {
+ this.service_code = service_code;
+ }
+ }
+}
+
Added: trunk/extensions/PicasaWebExport/google-sharp/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/extensions/PicasaWebExport/google-sharp/Makefile.am Fri Feb 8 15:37:13 2008
@@ -0,0 +1,45 @@
+include $(top_srcdir)/Makefile.include
+
+ASSEMBLY_NAME = Mono.Google
+
+ASSEMBLY_SOURCES = \
+ $(srcdir)/AlbumAccess.cs \
+ $(srcdir)/AssemblyInfo.cs \
+ $(srcdir)/Authentication.cs \
+ $(srcdir)/CaptchaException.cs \
+ $(srcdir)/CreateAlbumException.cs \
+ $(srcdir)/DeleteAlbumException.cs \
+ $(srcdir)/GDataApi.cs \
+ $(srcdir)/GoogleConnection.cs \
+ $(srcdir)/GoogleService.cs \
+ $(srcdir)/MultipartRequest.cs \
+ $(srcdir)/NoCheckCertificatePolicy.cs \
+ $(srcdir)/PicasaAlbum.cs \
+ $(srcdir)/PicasaAlbumCollection.cs \
+ $(srcdir)/PicasaPicture.cs \
+ $(srcdir)/PicasaPictureCollection.cs \
+ $(srcdir)/PicasaWeb.cs \
+ $(srcdir)/UploadPictureException.cs \
+ $(srcdir)/UploadProgressEventArgs.cs \
+ $(srcdir)/UploadProgressEventHandler.cs \
+ $(srcdir)/XmlUtil.cs
+
+REFS = -r:System.Web
+
+PKGS =
+
+ASSEMBLY = $(ASSEMBLY_NAME).dll
+
+all: $(ASSEMBLY)
+
+$(ASSEMBLY): $(ASSEMBLY_SOURCES)
+ $(CSC_LIB) -out:$@ $(PKGS) $(REFS) $(ASSEMBLY_SOURCES)
+
+assemblydir = $(pkglibdir)
+assembly_DATA = $(ASSEMBLY)
+
+EXTRA_DIST = $(ASSEMBLY_SOURCES)
+
+CLEANFILES = \
+ $(ASSEMBLY) \
+ $(ASSEMBLY).mdb
Added: trunk/extensions/PicasaWebExport/google-sharp/MultipartRequest.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/PicasaWebExport/google-sharp/MultipartRequest.cs Fri Feb 8 15:37:13 2008
@@ -0,0 +1,163 @@
+//
+// Mono.Google.MultipartRequest
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo ximian com)
+// Stephane Delcroix (stephane delcroix org)
+//
+// (C) Copyright 2006 Novell, Inc. (http://www.novell.com)
+// (C) Copyright 2007 S. Delcroix
+//
+
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections;
+using System.Globalization;
+using System.IO;
+using System.Net;
+using System.Text;
+using System.Xml;
+
+namespace Mono.Google {
+ class MultipartRequest {
+ static byte [] crlf = new byte [] { 13, 10 };
+ HttpWebRequest request;
+ Stream output_stream;
+ const string separator_string = "PART_SEPARATOR";
+ const string separator = "--" + separator_string + "\r\n";
+ const string separator_end = "--" + separator_string + "--\r\n";
+ byte [] separator_bytes = Encoding.ASCII.GetBytes (separator);
+ byte [] separator_end_bytes = Encoding.ASCII.GetBytes (separator_end);
+ bool output_set;
+
+ public MultipartRequest (GoogleConnection conn, string url)
+ {
+ request = conn.AuthenticatedRequest (url);
+ request.Method = "POST";
+ request.ContentType = "multipart/related; boundary=\"" + separator_string + "\"";
+ request.Headers.Add ("MIME-version", "1.0");
+ }
+
+ public HttpWebRequest Request {
+ get { return request; }
+ }
+
+ public Stream OutputStream {
+ get { return output_stream; }
+ set {
+ output_set = true;
+ output_stream = value;
+ }
+ }
+
+ public void BeginPart ()
+ {
+ BeginPart (false);
+ }
+
+ public void BeginPart (bool first)
+ {
+ if (!first)
+ return;
+ if (output_stream == null)
+ output_stream = request.GetRequestStream ();
+
+ string multipart = "Media multipart posting\r\n";
+ byte [] multipart_bytes = Encoding.ASCII.GetBytes (multipart);
+ output_stream.Write (multipart_bytes, 0, multipart_bytes.Length);
+ output_stream.Write (separator_bytes, 0, separator_bytes.Length);
+ }
+
+ public void AddHeader (string name, string val)
+ {
+ AddHeader (name, val, false);
+ }
+
+ public void AddHeader (string name, string val, bool last)
+ {
+ AddHeader (String.Format ("{0}: {1}"), last);
+ }
+
+ public void AddHeader (string header)
+ {
+ AddHeader (header, false);
+ }
+
+ public void AddHeader (string header, bool last)
+ {
+ bool need_crlf = !header.EndsWith ("\r\n");
+ byte [] bytes = Encoding.UTF8.GetBytes (header);
+ output_stream.Write (bytes, 0, bytes.Length);
+ if (need_crlf)
+ output_stream.Write (crlf, 0, 2);
+ if (last)
+ output_stream.Write (crlf, 0, 2);
+ }
+
+ public void WriteContent (string content)
+ {
+ WriteContent (Encoding.UTF8.GetBytes (content));
+ }
+
+ public void WriteContent (byte [] content)
+ {
+ output_stream.Write (content, 0, content.Length);
+ output_stream.Write (crlf, 0, crlf.Length);
+ }
+
+ public void WritePartialContent (byte [] content, int offset, int nbytes)
+ {
+ output_stream.Write (content, offset, nbytes);
+ }
+
+ public void EndPartialContent ()
+ {
+ output_stream.Write (crlf, 0, crlf.Length);
+ }
+
+ public void EndPart (bool last)
+ {
+ if (last) {
+ output_stream.Write (separator_end_bytes, 0, separator_end_bytes.Length);
+ if (!output_set)
+ output_stream.Close ();
+ } else {
+ output_stream.Write (separator_bytes, 0, separator_bytes.Length);
+ }
+ }
+
+ public string GetResponseAsString ()
+ {
+ HttpWebResponse response = null;
+ response = (HttpWebResponse) request.GetResponse ();
+ string received = "";
+ // FIXME: use CharacterSet?
+ using (Stream stream = response.GetResponseStream ()) {
+ StreamReader sr = new StreamReader (stream, Encoding.UTF8);
+ received = sr.ReadToEnd ();
+ }
+ response.Close ();
+ return received;
+ }
+ }
+}
+
Added: trunk/extensions/PicasaWebExport/google-sharp/NoCheckCertificatePolicy.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/PicasaWebExport/google-sharp/NoCheckCertificatePolicy.cs Fri Feb 8 15:37:13 2008
@@ -0,0 +1,41 @@
+//
+// Mono.Google.NoCheckCertificatePolicy
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo ximian com)
+//
+// (C) Copyright 2006 Novell, Inc. (http://www.novell.com)
+//
+
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System.Net;
+using System.Security.Cryptography.X509Certificates;
+
+namespace Mono.Google {
+ public class NoCheckCertificatePolicy : ICertificatePolicy {
+ public bool CheckValidationResult (ServicePoint a, X509Certificate b, WebRequest c, int d)
+ {
+ return true;
+ }
+ }
+}
+
Added: trunk/extensions/PicasaWebExport/google-sharp/PicasaAlbum.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/PicasaWebExport/google-sharp/PicasaAlbum.cs Fri Feb 8 15:37:13 2008
@@ -0,0 +1,338 @@
+//
+// Mono.Google.Picasa.PicasaAlbum.cs:
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo ximian com)
+// Stephane Delcroix (stephane delcroix org)
+//
+// (C) Copyright 2006 Novell, Inc. (http://www.novell.com)
+// (C) Copyright 2007 S. Delcroix
+//
+
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections;
+using System.IO;
+using System.Net;
+using System.Text;
+using System.Xml;
+
+namespace Mono.Google.Picasa {
+ public class PicasaAlbum {
+ GoogleConnection conn;
+ string user;
+ string title;
+ string description;
+ string id;
+ string link;
+ string authkey = null;
+ AlbumAccess access = AlbumAccess.Public;
+ int num_photos = -1;
+ int num_photos_remaining = -1;
+ long bytes_used = -1;
+
+ private PicasaAlbum (GoogleConnection conn)
+ {
+ if (conn == null)
+ throw new ArgumentNullException ("conn");
+
+ this.conn = conn;
+ }
+
+ public PicasaAlbum (GoogleConnection conn, string aid) : this (conn)
+ {
+ if (conn.User == null)
+ throw new ArgumentException ("Need authentication before being used.", "conn");
+
+ if (aid == null || aid == String.Empty)
+ throw new ArgumentNullException ("aid");
+
+ this.user = conn.User;
+ this.id = aid;
+
+ string received = conn.DownloadString (GDataApi.GetAlbumEntryById (conn.User, aid));
+ XmlDocument doc = new XmlDocument ();
+ doc.LoadXml (received);
+ XmlNamespaceManager nsmgr = new XmlNamespaceManager (doc.NameTable);
+ XmlUtil.AddDefaultNamespaces (nsmgr);
+ XmlNode entry = doc.SelectSingleNode ("atom:entry", nsmgr);
+ ParseAlbum (entry, nsmgr);
+ }
+
+ public PicasaAlbum (GoogleConnection conn, string user, string aid, string authkey) : this (conn)
+ {
+ if (user == null || user == String.Empty)
+ throw new ArgumentNullException ("user");
+
+ if (aid == null || aid == String.Empty)
+ throw new ArgumentNullException ("aid");
+
+ this.user = user;
+ this.id = aid;
+ this.authkey = authkey;
+
+ string download_link = GDataApi.GetAlbumEntryById (user, id);
+ if (authkey != null && authkey != "")
+ download_link += "&authkey=" + authkey;
+ string received = conn.DownloadString (download_link);
+
+ XmlDocument doc = new XmlDocument ();
+ doc.LoadXml (received);
+ XmlNamespaceManager nsmgr = new XmlNamespaceManager (doc.NameTable);
+ XmlUtil.AddDefaultNamespaces (nsmgr);
+ XmlNode entry = doc.SelectSingleNode ("atom:entry", nsmgr);
+ ParseAlbum (entry, nsmgr);
+ }
+
+ internal PicasaAlbum (GoogleConnection conn, string user, XmlNode nodeitem, XmlNamespaceManager nsmgr) : this (conn)
+ {
+ this.user = user ?? conn.User;
+
+ ParseAlbum (nodeitem, nsmgr);
+ }
+
+
+ private void ParseAlbum (XmlNode nodeitem, XmlNamespaceManager nsmgr)
+ {
+
+ title = nodeitem.SelectSingleNode ("atom:title", nsmgr).InnerText;
+ description = nodeitem.SelectSingleNode ("media:group/media:description", nsmgr).InnerText;
+ XmlNode node = nodeitem.SelectSingleNode ("gphoto:id", nsmgr);
+ if (node != null)
+ id = node.InnerText;
+
+ foreach (XmlNode xlink in nodeitem.SelectNodes ("atom:link", nsmgr)) {
+ if (xlink.Attributes.GetNamedItem ("rel").Value == "alternate") {
+ link = xlink.Attributes.GetNamedItem ("href").Value;
+ break;
+ }
+ }
+ node = nodeitem.SelectSingleNode ("gphoto:access", nsmgr);
+ if (node != null) {
+ string acc = node.InnerText;
+ access = (acc == "public") ? AlbumAccess.Public : AlbumAccess.Private;
+ }
+ node = nodeitem.SelectSingleNode ("gphoto:numphotos", nsmgr);
+ if (node != null)
+ num_photos = (int) UInt32.Parse (node.InnerText);
+
+ node = nodeitem.SelectSingleNode ("gphoto:numphotosremaining", nsmgr);
+ if (node != null)
+ num_photos_remaining = (int) UInt32.Parse (node.InnerText);
+ node = nodeitem.SelectSingleNode ("gphoto:bytesused", nsmgr);
+ if (node != null)
+ bytes_used = (long) UInt64.Parse (node.InnerText);
+ }
+
+ public PicasaPictureCollection GetPictures ()
+ {
+
+ string download_link = GDataApi.GetAlbumFeedById (user, id);
+ if (authkey != null && authkey != "")
+ download_link += "&authkey=" + authkey;
+ string received = conn.DownloadString (download_link);
+ XmlDocument doc = new XmlDocument ();
+ doc.LoadXml (received);
+ XmlNamespaceManager nsmgr = new XmlNamespaceManager (doc.NameTable);
+ XmlUtil.AddDefaultNamespaces (nsmgr);
+ XmlNode feed = doc.SelectSingleNode ("atom:feed", nsmgr);
+ PicasaPictureCollection coll = new PicasaPictureCollection ();
+ foreach (XmlNode item in feed.SelectNodes ("atom:entry", nsmgr)) {
+ coll.Add (new PicasaPicture (conn, this, item, nsmgr));
+ }
+ coll.SetReadOnly ();
+ return coll;
+ }
+
+ /* from http://code.google.com/apis/picasaweb/gdata.html#Add_Photo
+ <entry xmlns='http://www.w3.org/2005/Atom'>
+ <title>darcy-beach.jpg</title>
+ <summary>Darcy on the beach</summary>
+ <category scheme="http://schemas.google.com/g/2005#kind"
+ term="http://schemas.google.com/photos/2007#photo"/>
+ </entry>
+ */
+
+ static string GetXmlForUpload (string title, string description)
+ {
+ XmlUtil xml = new XmlUtil ();
+ xml.WriteElementString ("title", title);
+ xml.WriteElementString ("summary", description);
+ xml.WriteElementStringWithAttributes ("category", null,
+ "scheme", "http://schemas.google.com/g/2005#kind",
+ "term", "http://schemas.google.com/photos/2007#photo");
+ return xml.GetDocumentString ();
+ }
+
+ public PicasaPicture UploadPicture (string title, Stream input)
+ {
+ return UploadPicture (title, null, input);
+ }
+
+ public PicasaPicture UploadPicture (string title, string description, Stream input)
+ {
+ return UploadPicture (title, description, "image/jpeg", input);
+ }
+
+ public PicasaPicture UploadPicture (string title, string description, string mime_type, Stream input)
+ {
+ if (title == null)
+ throw new ArgumentNullException ("title");
+
+ if (input == null)
+ throw new ArgumentNullException ("input");
+
+ if (!input.CanRead)
+ throw new ArgumentException ("Cannot read from stream", "input");
+
+ string url = GDataApi.GetURLForUpload (conn.User, id);
+ if (url == null)
+ throw new UnauthorizedAccessException ("You are not authorized to upload to this album.");
+
+ MultipartRequest request = new MultipartRequest (conn, url);
+ MemoryStream ms = null;
+ if (UploadProgress != null) {
+ // We do 'manual' buffering
+ request.Request.AllowWriteStreamBuffering = false;
+ ms = new MemoryStream ();
+ request.OutputStream = ms;
+ }
+
+ request.BeginPart (true);
+ request.AddHeader ("Content-Type: application/atom+xml; \r\n", true);
+ string upload = GetXmlForUpload (title, description);
+ request.WriteContent (upload);
+ request.EndPart (false);
+ request.BeginPart ();
+ request.AddHeader ("Content-Type: " + mime_type + "\r\n", true);
+
+ byte [] data = new byte [8192];
+ int nread;
+ while ((nread = input.Read (data, 0, data.Length)) > 0) {
+ request.WritePartialContent (data, 0, nread);
+ }
+ request.EndPartialContent ();
+ request.EndPart (true); // It won't call Close() on the MemoryStream
+
+ if (UploadProgress != null) {
+ int req_length = (int) ms.Length;
+ request.Request.ContentLength = req_length;
+ DoUploadProgress (title, 0, req_length);
+ using (Stream req_stream = request.Request.GetRequestStream ()) {
+ byte [] buffer = ms.GetBuffer ();
+ int nwrite = 0;
+ int offset;
+ for (offset = 0; offset < req_length; offset += nwrite) {
+ nwrite = System.Math.Min (16384, req_length - offset);
+ req_stream.Write (buffer, offset, nwrite);
+ // The progress uses the actual request size, not file size.
+ DoUploadProgress (title, offset, req_length);
+ }
+ DoUploadProgress (title, offset, req_length);
+
+ }
+ }
+
+ string received = request.GetResponseAsString ();
+ XmlDocument doc = new XmlDocument ();
+ doc.LoadXml (received);
+ XmlNamespaceManager nsmgr = new XmlNamespaceManager (doc.NameTable);
+ XmlUtil.AddDefaultNamespaces (nsmgr);
+ XmlNode entry = doc.SelectSingleNode ("atom:entry", nsmgr);
+
+ return new PicasaPicture (conn, this, entry, nsmgr);
+ }
+
+ public PicasaPicture UploadPicture (string filename)
+ {
+ return UploadPicture (filename, "");
+ }
+
+ public PicasaPicture UploadPicture (string filename, string description)
+ {
+ return UploadPicture (filename, Path.GetFileName (filename), description);
+ }
+
+ public PicasaPicture UploadPicture (string filename, string title, string description)
+ {
+ if (filename == null)
+ throw new ArgumentNullException ("filename");
+
+ if (title == null)
+ throw new ArgumentNullException ("title");
+
+ using (Stream stream = File.OpenRead (filename)) {
+ return UploadPicture (title, description, stream);
+ }
+ }
+
+ public string Title {
+ get { return title; }
+ }
+
+ public string Description {
+ get { return description; }
+ }
+
+ public string Link {
+ get { return link; }
+ }
+
+ public string UniqueID {
+ get { return id; }
+ }
+
+ public AlbumAccess Access {
+ get { return access; }
+ }
+
+ public int PicturesCount {
+ get { return num_photos; }
+ }
+
+ public int PicturesRemaining {
+ get { return num_photos_remaining; }
+ }
+
+ public string User {
+ get { return user; }
+ }
+
+ public long BytesUsed {
+ get { return bytes_used; }
+ }
+
+ internal GoogleConnection Connection {
+ get { return conn; }
+ }
+
+ void DoUploadProgress (string title, long sent, long total)
+ {
+ if (UploadProgress != null) {
+ UploadProgress (this, new UploadProgressEventArgs (title, sent, total));
+ }
+ }
+
+ public event UploadProgressEventHandler UploadProgress;
+ }
+}
+
Added: trunk/extensions/PicasaWebExport/google-sharp/PicasaAlbumCollection.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/PicasaWebExport/google-sharp/PicasaAlbumCollection.cs Fri Feb 8 15:37:13 2008
@@ -0,0 +1,92 @@
+//
+// Mono.Google.Picasa.PicasaAlbumCollection
+//
+// Author:
+// Gonzalo Paniagua Javier (gonzalo novell com)
+//
+
+//
+// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections.Specialized;
+
+namespace Mono.Google.Picasa {
+ public sealed class PicasaAlbumCollection : NameObjectCollectionBase {
+ internal PicasaAlbumCollection ()
+ {
+ }
+
+ internal void Add (PicasaAlbum album)
+ {
+ if (BaseGet (album.UniqueID) != null)
+ throw new Exception ("Duplicate album?");
+
+ BaseAdd (album.UniqueID, album);
+ }
+
+ internal void SetReadOnly ()
+ {
+ IsReadOnly = true;
+ }
+
+ public PicasaAlbum GetByTitle (string title)
+ {
+ if (title == null)
+ throw new ArgumentNullException ("id");
+
+ int count = Count;
+ for (int i = 0; i < count; i++) {
+ if (this [i].Title == title)
+ return this [i];
+ }
+
+ return null;
+ }
+
+ public PicasaAlbum this [int index] {
+ get { return (PicasaAlbum) BaseGet (index); }
+ }
+
+ public PicasaAlbum this [string uniqueID] {
+ get { return (PicasaAlbum) BaseGet (uniqueID); }
+ }
+
+ public string [] AllKeys {
+ get {
+ NameObjectCollectionBase.KeysCollection keys = Keys;
+ int count = keys.Count;
+ string [] result = new string [count];
+ for (int i = 0; i < count; i++)
+ result [i] = keys [i];
+
+ return result;
+ }
+ }
+
+ public PicasaAlbum [] AllValues {
+ get { return (PicasaAlbum []) BaseGetAllValues (typeof (PicasaAlbum)); }
+ }
+ }
+}
+
Added: trunk/extensions/PicasaWebExport/google-sharp/PicasaPicture.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/PicasaWebExport/google-sharp/PicasaPicture.cs Fri Feb 8 15:37:13 2008
@@ -0,0 +1,205 @@
+//
+// Mono.Google.Picasa.PicasaPicture.cs:
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo ximian com)
+// Stephane Delcroix (stephane delcroix org)
+//
+// (C) Copyright 2006 Novell, Inc. (http://www.novell.com)
+// (C) Copyright 2007 S. Delcroix
+//
+
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.IO;
+using System.Net;
+using System.Text;
+using System.Xml;
+using System.Globalization;
+
+namespace Mono.Google.Picasa {
+ public class PicasaPicture {
+ GoogleConnection conn;
+ PicasaAlbum album;
+ string title;
+ string description;
+ DateTime pub_date;
+ string thumbnail_url;
+ string image_url;
+ int width;
+ int height;
+ int index;
+ string id;
+ string link;
+ string tags;
+
+ internal PicasaPicture (GoogleConnection conn, PicasaAlbum album, XmlNode nodeitem, XmlNamespaceManager nsmgr)
+ {
+ this.conn = conn;
+ this.album = album;
+ ParsePicture (nodeitem, nsmgr);
+ }
+
+ public PicasaPicture (GoogleConnection conn, string aid, string pid)
+ {
+ if (conn == null)
+ throw new ArgumentNullException ("conn");
+ if (conn.User == null)
+ throw new ArgumentException ("Need authentication before being used.", "conn");
+ this.conn = conn;
+
+ if (aid == null || aid == String.Empty)
+ throw new ArgumentNullException ("aid");
+ this.album = new PicasaAlbum (conn, aid);
+
+ if (pid == null || pid == String.Empty)
+ throw new ArgumentNullException ("pid");
+
+ string received = conn.DownloadString (GDataApi.GetPictureEntry (conn.User, aid, pid));
+ XmlDocument doc = new XmlDocument ();
+ doc.LoadXml (received);
+ XmlNamespaceManager nsmgr = new XmlNamespaceManager (doc.NameTable);
+ XmlUtil.AddDefaultNamespaces (nsmgr);
+ XmlNode entry = doc.SelectSingleNode ("atom:entry", nsmgr);
+ ParsePicture (entry, nsmgr);
+ }
+
+ private void ParsePicture (XmlNode nodeitem, XmlNamespaceManager nsmgr)
+ {
+ title = nodeitem.SelectSingleNode ("atom:title", nsmgr).InnerText;
+ foreach (XmlNode xlink in nodeitem.SelectNodes ("atom:link", nsmgr)) {
+ if (xlink.Attributes.GetNamedItem ("rel").Value == "alternate") {
+ link = xlink.Attributes.GetNamedItem ("href").Value;
+ break;
+ }
+ }
+ description = nodeitem.SelectSingleNode ("media:group/media:description", nsmgr).InnerText;
+ CultureInfo info = CultureInfo.InvariantCulture;
+ pub_date = DateTime.ParseExact (nodeitem.SelectSingleNode ("atom:published", nsmgr).InnerText, GDataApi.DateFormat, info);
+ thumbnail_url = nodeitem.SelectSingleNode ("media:group/media:thumbnail", nsmgr).Attributes.GetNamedItem ("url").Value;
+ image_url = nodeitem.SelectSingleNode ("media:group/media:content", nsmgr).Attributes.GetNamedItem ("url").Value;
+ width = (int) UInt32.Parse (nodeitem.SelectSingleNode ("gphoto:width", nsmgr).InnerText);
+ height = (int) UInt32.Parse (nodeitem.SelectSingleNode ("gphoto:height", nsmgr).InnerText);
+
+ XmlNode node = nodeitem.SelectSingleNode ("gphoto:index", nsmgr);
+ index = (node != null) ? (int) UInt32.Parse (node.InnerText) : -1;
+ node = nodeitem.SelectSingleNode ("gphoto:id", nsmgr);
+ id = (node != null) ? node.InnerText : "auto" + title.GetHashCode ().ToString ();
+ tags = nodeitem.SelectSingleNode ("media:group/media:keywords", nsmgr).InnerText;
+ }
+
+ static string GetXmlForTagging (string tag)
+ {
+ XmlUtil xml = new XmlUtil ();
+ xml.WriteElementString ("title", tag);
+ xml.WriteElementStringWithAttributes ("category", null,
+ "scheme", "http://schemas.google.com/g/2005#kind",
+ "term", "http://schemas.google.com/photos/2007#tag");
+ return xml.GetDocumentString ();
+
+ }
+
+ public void AddTag (string tag)
+ {
+ if (tag == null)
+ throw new ArgumentNullException ("title");
+
+ string op_string = GetXmlForTagging (tag);
+ byte [] op_bytes = Encoding.UTF8.GetBytes (op_string);
+ string url = GDataApi.GetPictureFeed (conn.User, album.UniqueID, UniqueID);
+ HttpWebRequest request = conn.AuthenticatedRequest (url);
+ request.ContentType = "application/atom+xml; charset=UTF-8";
+ request.Method = "POST";
+ Stream output_stream = request.GetRequestStream ();
+ output_stream.Write (op_bytes, 0, op_bytes.Length);
+ output_stream.Close ();
+
+ HttpWebResponse response = (HttpWebResponse) request.GetResponse ();
+ string received = "";
+ using (Stream stream = response.GetResponseStream ()) {
+ StreamReader sr = new StreamReader (stream, Encoding.UTF8);
+ received = sr.ReadToEnd ();
+ }
+ response.Close ();
+
+ }
+
+ public void DownloadToStream (Stream stream)
+ {
+ conn.DownloadToStream (image_url, stream);
+ }
+
+ public void DownloadThumbnailToStream (Stream stream)
+ {
+ conn.DownloadToStream (thumbnail_url, stream);
+ }
+
+ public PicasaAlbum Album {
+ get { return album; }
+ }
+
+ public string Title {
+ get { return title; }
+ }
+
+ public string Description {
+ get { return description; }
+ }
+
+ public DateTime Date {
+ get { return pub_date; }
+ }
+
+ public string ThumbnailURL {
+ get { return thumbnail_url; }
+ }
+
+ public string ImageURL {
+ get { return image_url; }
+ }
+
+ public int Width {
+ get { return width; }
+ }
+
+ public int Height {
+ get { return height; }
+ }
+
+ public int Index {
+ get { return index; }
+ }
+
+ public string UniqueID {
+ get { return id; }
+ }
+
+ public string Link {
+ get { return link; }
+ }
+
+ public string Tags {
+ get { return tags; }
+ }
+ }
+}
+
Added: trunk/extensions/PicasaWebExport/google-sharp/PicasaPictureCollection.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/PicasaWebExport/google-sharp/PicasaPictureCollection.cs Fri Feb 8 15:37:13 2008
@@ -0,0 +1,94 @@
+//
+// Mono.Google.Picasa.PicasaPictureCollection
+//
+// Author:
+// Gonzalo Paniagua Javier (gonzalo novell com)
+//
+
+//
+// Copyright (C) 2006 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+
+namespace Mono.Google.Picasa {
+ public sealed class PicasaPictureCollection : NameObjectCollectionBase {
+ internal PicasaPictureCollection ()
+ {
+ }
+
+ internal void Add (PicasaPicture picture)
+ {
+ if (BaseGet (picture.UniqueID) != null)
+ throw new Exception ("Duplicate picture?");
+
+ BaseAdd (picture.UniqueID, picture);
+ }
+
+ internal void SetReadOnly ()
+ {
+ IsReadOnly = true;
+ }
+
+ public PicasaPicture GetByTitle (string title)
+ {
+ if (title == null)
+ throw new ArgumentNullException ("id");
+
+ int count = Count;
+ for (int i = 0; i < count; i++) {
+ if (this [i].Title == title)
+ return this [i];
+ }
+
+ return null;
+ }
+
+ public PicasaPicture this [int index] {
+ get { return (PicasaPicture) BaseGet (index); }
+ }
+
+ public PicasaPicture this [string uniqueID] {
+ get { return (PicasaPicture) BaseGet (uniqueID); }
+ }
+
+ public string [] AllKeys {
+ get {
+ NameObjectCollectionBase.KeysCollection keys = Keys;
+ int count = keys.Count;
+ string [] result = new string [count];
+ for (int i = 0; i < count; i++)
+ result [i] = keys [i];
+
+ return result;
+ }
+ }
+
+ public PicasaPicture [] AllValues {
+ get { return (PicasaPicture []) BaseGetAllValues (typeof (PicasaPicture)); }
+ }
+
+ }
+}
+
Added: trunk/extensions/PicasaWebExport/google-sharp/PicasaWeb.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/PicasaWebExport/google-sharp/PicasaWeb.cs Fri Feb 8 15:37:13 2008
@@ -0,0 +1,291 @@
+//
+// Mono.Google.Picasa.PicasaWeb.cs:
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo ximian com)
+// Stephane Delcroix (stephane delcroix org)
+//
+// (C) Copyright 2006 Novell, Inc. (http://www.novell.com)
+// (C) Copyright 2007 S. Delcroix
+//
+
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Check Picasa Web Albums Data Api at http://code.google.com/apis/picasaweb/gdata.html
+//
+
+using System;
+using System.Collections;
+using System.Globalization;
+using System.IO;
+using System.Net;
+using System.Text;
+using System.Xml;
+
+namespace Mono.Google.Picasa {
+ public class PicasaWeb {
+ GoogleConnection conn;
+ string title;
+ string user;
+ string nickname;
+ long quota_used;
+ long quota_limit;
+
+ public PicasaWeb (GoogleConnection conn) : this (conn, null)
+ {
+ }
+
+ public PicasaWeb (GoogleConnection conn, string username)
+ {
+ if (conn == null)
+ throw new ArgumentNullException ("conn");
+
+ if (conn.User == null && username == null)
+ throw new ArgumentException ("The connection should be authenticated OR you should call this constructor with a non-null username argument");
+
+ this.conn = conn;
+ this.user = username ?? conn.User;
+
+ string received = conn.DownloadString (GDataApi.GetGalleryEntry (user));
+ XmlDocument doc = new XmlDocument ();
+ doc.LoadXml (received);
+ XmlNamespaceManager nsmgr = new XmlNamespaceManager (doc.NameTable);
+ XmlUtil.AddDefaultNamespaces (nsmgr);
+ XmlNode entry = doc.SelectSingleNode ("atom:entry", nsmgr);
+ ParseGallery (entry, nsmgr);
+ }
+
+ public string Title {
+ get { return title; }
+ }
+
+ public string User {
+ get { return user; }
+ }
+
+ public string NickName {
+ get { return nickname; }
+ }
+
+ public long QuotaUsed {
+ get { return quota_used; }
+ }
+
+ public long QuotaLimit {
+ get { return quota_limit; }
+ }
+
+ internal GoogleConnection Connection {
+ get { return conn; }
+ }
+
+ public PicasaAlbum CreateAlbum (string title)
+ {
+ return CreateAlbum (title, null);
+ }
+
+ public PicasaAlbum CreateAlbum (string title, AlbumAccess access)
+ {
+ return CreateAlbum (title, null, access, DateTime.Now);
+ }
+
+ public PicasaAlbum CreateAlbum (string title, string description)
+ {
+ return CreateAlbum (title, description, AlbumAccess.Public);
+ }
+
+ public PicasaAlbum CreateAlbum (string title, string description, AlbumAccess access)
+ {
+ return CreateAlbum (title, description, access, DateTime.Now);
+ }
+
+ public PicasaAlbum CreateAlbum (string title, string description, AlbumAccess access, DateTime pubDate)
+ {
+ if (title == null)
+ throw new ArgumentNullException ("title");
+
+ if (description == null)
+ description = "";
+
+ if (access != AlbumAccess.Public && access != AlbumAccess.Private)
+ throw new ArgumentException ("Invalid value.", "access");
+
+ // Check if pubDate can be in the past
+ string url = GDataApi.GetPostURL (conn.User);
+ if (url == null)
+ throw new UnauthorizedAccessException ("You are not authorized to create albums.");
+ string op_string = GetXmlForCreate (title, description, pubDate, access);
+ byte [] op_bytes = Encoding.UTF8.GetBytes (op_string);
+ HttpWebRequest request = conn.AuthenticatedRequest (url);
+ request.ContentType = "application/atom+xml; charset=UTF-8";
+ request.Method = "POST";
+ Stream output_stream = request.GetRequestStream ();
+ output_stream.Write (op_bytes, 0, op_bytes.Length);
+ output_stream.Close ();
+
+ HttpWebResponse response = (HttpWebResponse) request.GetResponse ();
+ string received = "";
+ using (Stream stream = response.GetResponseStream ()) {
+ StreamReader sr = new StreamReader (stream, Encoding.UTF8);
+ received = sr.ReadToEnd ();
+ }
+ response.Close ();
+
+ XmlDocument doc = new XmlDocument ();
+ doc.LoadXml (received);
+ XmlNamespaceManager nsmgr = new XmlNamespaceManager (doc.NameTable);
+ XmlUtil.AddDefaultNamespaces (nsmgr);
+ XmlNode entry = doc.SelectSingleNode ("atom:entry", nsmgr);
+ return new PicasaAlbum (conn, null, entry, nsmgr);
+ }
+
+ /* (from gdata documentation...)
+ <entry xmlns='http://www.w3.org/2005/Atom'
+ xmlns:media='http://search.yahoo.com/mrss/'
+ xmlns:gphoto='http://schemas.google.com/photos/2007'>
+ <title type='text'>Trip To Italy</title>
+ <summary type='text'>This was the recent trip I took to Italy.</summary>
+ <gphoto:location>Italy</gphoto:location>
+ <gphoto:access>public</gphoto:access>
+ <gphoto:commentingEnabled>true</gphoto:commentingEnabled>
+ <gphoto:timestamp>1152255600000</gphoto:timestamp>
+ <media:group>
+ <media:keywords>italy, vacation</media:keywords>
+ </media:group>
+ <category scheme='http://schemas.google.com/g/2005#kind'
+ term='http://schemas.google.com/photos/2007#album'></category>
+ </entry>
+ */
+
+ private static string GetXmlForCreate (string title, string desc, DateTime date, AlbumAccess access)
+ {
+ XmlUtil xml = new XmlUtil ();
+ xml.WriteElementStringWithAttributes ("title", title, "type", "text");
+ xml.WriteElementStringWithAttributes ("summary", desc, "type", "text");
+ // location ?
+ xml.WriteElementString ("access", access.ToString ().ToLower (CultureInfo.InvariantCulture), PicasaNamespaces.GPhoto);
+ // commentingEnabled ?
+ xml.WriteElementString ("timestamp", ((long)(date - new DateTime (1970, 1, 1)).TotalSeconds * 1000).ToString (), PicasaNamespaces.GPhoto);
+ //keywords ?
+ xml.WriteElementStringWithAttributes ("category", null,
+ "scheme", "http://schemas.google.com/g/2005#kind",
+ "term", "http://schemas.google.com/photos/2007#album");
+
+ return xml.GetDocumentString ();
+ }
+
+ /*
+ "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" +
+ "<rss version=\"2.0\" xmlns:gphoto=\"http://www.temp.com/\">\n" +
+ " <channel>\n" +
+ " <gphoto:user>{0}</gphoto:user>\n" +
+ " <gphoto:id>{1}</gphoto:id>\n" +
+ " <gphoto:op>deleteAlbum</gphoto:op>\n" +
+ " </channel>\n" +
+ "</rss>";
+ */
+
+// static string GetXmlForDelete (string user, string aid)
+// {
+// XmlUtil xml = new XmlUtil ();
+// xml.WriteElementString ("user", user, PicasaNamespaces.GPhoto);
+// xml.WriteElementString ("id", aid, PicasaNamespaces.GPhoto);
+// xml.WriteElementString ("op", "deleteAlbum", PicasaNamespaces.GPhoto);
+// return xml.GetDocumentString ();
+// }
+
+ public void DeleteAlbum (PicasaAlbum album)
+ {
+ if (album == null)
+ throw new ArgumentNullException ("album");
+
+ DeleteAlbum (album.UniqueID);
+ }
+
+ public void DeleteAlbum (string unique_id)
+ {
+ //FIXME: implement this
+ throw new System.NotImplementedException ("but I'll implemented if you say please...");
+// if (unique_id == null)
+// throw new ArgumentNullException ("unique_id");
+//
+// string url = GDataApi.GetPostURL (conn.User);
+// if (url == null)
+// throw new UnauthorizedAccessException ("You are not authorized to delete this album.");
+// string op_string = GetXmlForDelete (conn.User, unique_id);
+// byte [] op_bytes = Encoding.UTF8.GetBytes (op_string);
+// MultipartRequest request = new MultipartRequest (conn, url);
+//// request.Request.CookieContainer = conn.Cookies;
+// request.BeginPart ();
+// request.AddHeader ("Content-Disposition: form-data; name=\"xml\"\r\n");
+// request.AddHeader ("Content-Type: text/plain; charset=utf8\r\n", true);
+// request.WriteContent (op_bytes);
+// request.EndPart (true);
+// string received = request.GetResponseAsString ();
+//
+// XmlDocument doc = new XmlDocument ();
+// doc.LoadXml (received);
+// XmlNode node = doc.SelectSingleNode ("/response/result");
+// if (node == null)
+// throw new DeleteAlbumException ("Invalid response from server");
+//
+// if (node.InnerText != "success") {
+// node = doc.SelectSingleNode ("/response/reason");
+// if (node == null)
+// throw new DeleteAlbumException ("Unknown reason");
+//
+// throw new DeleteAlbumException (node.InnerText);
+// }
+ }
+
+ public PicasaAlbumCollection GetAlbums ()
+ {
+ string gallery_link = GDataApi.GetGalleryFeed (user);
+ string received = conn.DownloadString (gallery_link);
+
+ XmlDocument doc = new XmlDocument ();
+ doc.LoadXml (received);
+ XmlNamespaceManager nsmgr = new XmlNamespaceManager (doc.NameTable);
+ XmlUtil.AddDefaultNamespaces (nsmgr);
+ XmlNode feed = doc.SelectSingleNode ("atom:feed", nsmgr);
+ PicasaAlbumCollection coll = new PicasaAlbumCollection ();
+ foreach (XmlNode item in feed.SelectNodes ("atom:entry", nsmgr)) {
+ coll.Add (new PicasaAlbum (conn, user, item, nsmgr));
+ }
+ coll.SetReadOnly ();
+ return coll;
+ }
+
+ private void ParseGallery (XmlNode nodeitem, XmlNamespaceManager nsmgr)
+ {
+ XmlNode node = nodeitem.SelectSingleNode ("atom:title", nsmgr);
+ title = node.InnerText;
+ node = nodeitem.SelectSingleNode ("gphoto:user", nsmgr);
+ user = node.InnerText;
+ node = nodeitem.SelectSingleNode ("gphoto:nickname", nsmgr);
+ nickname = node.InnerText;
+ node = nodeitem.SelectSingleNode ("gphoto:quotacurrent", nsmgr);
+ quota_used = (node != null) ? (long) UInt64.Parse (node.InnerText) : -1;
+ node = nodeitem.SelectSingleNode ("gphoto:quotalimit", nsmgr);
+ quota_limit = (node != null) ? (long) UInt64.Parse (node.InnerText) : -1;
+ }
+ }
+}
+
Added: trunk/extensions/PicasaWebExport/google-sharp/UploadPictureException.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/PicasaWebExport/google-sharp/UploadPictureException.cs Fri Feb 8 15:37:13 2008
@@ -0,0 +1,44 @@
+//
+// Mono.Google.Picasa.UploadPictureException.cs:
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo ximian com)
+//
+// (C) Copyright 2006 Novell, Inc. (http://www.novell.com)
+//
+
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Runtime.Serialization;
+namespace Mono.Google.Picasa {
+ public class UploadPictureException : Exception {
+ public UploadPictureException (string msg) : base (msg)
+ {
+ }
+
+ protected UploadPictureException (SerializationInfo info, StreamingContext context)
+ : base (info, context)
+ {
+ }
+ }
+}
+
Added: trunk/extensions/PicasaWebExport/google-sharp/UploadProgressEventArgs.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/PicasaWebExport/google-sharp/UploadProgressEventArgs.cs Fri Feb 8 15:37:13 2008
@@ -0,0 +1,57 @@
+//
+// Mono.Google.Picasa.UploadProgressEventArgs
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo ximian com)
+//
+// (C) Copyright 2006 Novell, Inc. (http://www.novell.com)
+//
+
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+namespace Mono.Google.Picasa {
+ public sealed class UploadProgressEventArgs : EventArgs {
+ string title;
+ long bytes_sent;
+ long bytes_total;
+
+ internal UploadProgressEventArgs (string title, long bytes_sent, long bytes_total)
+ {
+ this.title = title;
+ this.bytes_sent = bytes_sent;
+ this.bytes_total = bytes_total;
+ }
+
+ public string Title {
+ get { return title; }
+ }
+
+ public long BytesSent {
+ get { return bytes_sent; }
+ }
+
+ public long BytesTotal {
+ get { return bytes_total; }
+ }
+ }
+}
+
Added: trunk/extensions/PicasaWebExport/google-sharp/UploadProgressEventHandler.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/PicasaWebExport/google-sharp/UploadProgressEventHandler.cs Fri Feb 8 15:37:13 2008
@@ -0,0 +1,33 @@
+//
+// Mono.Google.Picasa.UploadProgressEventHandler.cs:
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo ximian com)
+//
+// (C) Copyright 2006 Novell, Inc. (http://www.novell.com)
+//
+
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace Mono.Google.Picasa {
+ public delegate void UploadProgressEventHandler (object sender, UploadProgressEventArgs args);
+}
+
Added: trunk/extensions/PicasaWebExport/google-sharp/XmlUtil.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/PicasaWebExport/google-sharp/XmlUtil.cs Fri Feb 8 15:37:13 2008
@@ -0,0 +1,121 @@
+//
+// Mono.Google.Picasa.XmlUtil.cs:
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo ximian com)
+// Stephane Delcroix (stephane delcroix org)
+//
+// (C) Copyright 2006 Novell, Inc. (http://www.novell.com)
+// (C) Copyright 2007 S. Delcroix
+//
+
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Check Picasa Web Albums Data Api at http://code.google.com/apis/picasaweb/gdata.html
+//
+
+using System;
+using System.IO;
+using System.Text;
+using System.Xml;
+namespace Mono.Google.Picasa {
+ enum PicasaNamespaces {
+ None,
+ Atom,
+ GPhoto,
+ Photo,
+ Media
+ }
+
+ internal class XmlUtil {
+ static string [] URIs = new string [] {
+ null,
+ "http://www.w3.org/2005/Atom",
+ "http://schemas.google.com/photos/2007",
+ "http://www.pheed.com/pheed/",
+ "http://search.yahoo.com/mrss/"
+ };
+
+ StringWriter sr;
+ XmlTextWriter writer;
+
+ public XmlUtil ()
+ {
+ StartDocument ();
+ }
+
+ public void StartDocument ()
+ {
+ sr = new StringWriter ();
+ writer = new XmlTextWriter (sr);
+ writer.Formatting = Formatting.Indented;
+ writer.Indentation = 2;
+ writer.Namespaces = true;
+ writer.WriteStartElement (null, "entry", null);
+ writer.WriteAttributeString ("xmlns", null, URIs [(int) PicasaNamespaces.Atom]);
+ writer.WriteAttributeString ("xmlns", "media", null, URIs [(int) PicasaNamespaces.Media]);
+ writer.WriteAttributeString ("xmlns", "gphoto", null, URIs [(int) PicasaNamespaces.GPhoto]);
+ }
+
+ public void WriteElementString (string name, string val)
+ {
+ writer.WriteElementString (name, val);
+ }
+
+ public void WriteElementString (string name, string val, string uri)
+ {
+ writer.WriteElementString (name, uri, val);
+ }
+
+ public void WriteElementString (string name, string val, PicasaNamespaces ns)
+ {
+ writer.WriteElementString (name, URIs [(int) ns], val);
+ }
+
+ public void WriteStartElement (string elem)
+ {
+ writer.WriteStartElement (elem, null);
+ }
+
+ public void WriteElementStringWithAttributes (string ename, string eval, params string[] attributes)
+ {
+ writer.WriteStartElement (null, ename, null);
+ for (int i = 0; i < attributes.Length; i+=2)
+ writer.WriteAttributeString (attributes[i], attributes[i+1]);
+ writer.WriteRaw (eval);
+ writer.WriteEndElement ();
+ }
+
+ public string GetDocumentString ()
+ {
+ writer.Close ();
+ return sr.ToString ();
+ }
+
+ internal static void AddDefaultNamespaces (XmlNamespaceManager nsmgr) {
+ nsmgr.AddNamespace ("atom", "http://www.w3.org/2005/Atom");
+ nsmgr.AddNamespace ("photo", "http://www.pheed.com/pheed/");
+ nsmgr.AddNamespace ("media", "http://search.yahoo.com/mrss/");
+ nsmgr.AddNamespace ("gphoto", "http://schemas.google.com/photos/2007");
+ nsmgr.AddNamespace ("batch", "http://schemas.google.com/gdata/batch");
+ }
+ }
+}
+
Modified: trunk/po/POTFILES.in
==============================================================================
--- trunk/po/POTFILES.in (original)
+++ trunk/po/POTFILES.in Fri Feb 8 15:37:13 2008
@@ -60,7 +60,6 @@
src/PhotoVersionCommands.cs
src/PhotoVersionMenu.cs
src/PhotoView.cs
-src/PicasaWebExport.cs
src/Preferences.cs
src/ProgressDialog.cs
src/QueryWidget.cs
Modified: trunk/po/POTFILES.skip
==============================================================================
--- trunk/po/POTFILES.skip (original)
+++ trunk/po/POTFILES.skip Fri Feb 8 15:37:13 2008
@@ -22,3 +22,6 @@
extensions/GalleryExport/GalleryExport.cs
extensions/GalleryExport/GalleryExport.glade
extensions/GalleryExport/GalleryRemote.cs
+extensions/PicasaWebExport/PicasaWebExport.cs
+extensions/PicasaWebExport/PicasaWebExport.glade
+extensions/PicasaWebExport/PicasaWebRemote.cs
Modified: trunk/src/Makefile.am
==============================================================================
--- trunk/src/Makefile.am (original)
+++ trunk/src/Makefile.am Fri Feb 8 15:37:13 2008
@@ -188,7 +188,6 @@
$(srcdir)/PhotoVersionCommands.cs \
$(srcdir)/PhotoVersionMenu.cs \
$(srcdir)/PhotoView.cs \
- $(srcdir)/PicasaWebExport.cs \
$(srcdir)/PixbufLoader.cs \
$(srcdir)/PixbufUtils.cs \
$(srcdir)/PixbufCache.cs \
Modified: trunk/src/Preferences.cs
==============================================================================
--- trunk/src/Preferences.cs (original)
+++ trunk/src/Preferences.cs Fri Feb 8 15:37:13 2008
@@ -50,12 +50,6 @@
public const string EXPORT_TOKEN_23HQ = "/apps/f-spot/export/tokens/23hq";
public const string EXPORT_TOKEN_ZOOOMR = "/apps/f-spot/export/tokens/zooomr";
- public const string EXPORT_PICASAWEB_SCALE = "/apps/f-spot/export/picasaweb/scale";
- public const string EXPORT_PICASAWEB_SIZE = "/apps/f-spot/export/picasaweb/size";
- public const string EXPORT_PICASAWEB_ROTATE = "/apps/f-spot/export/picasaweb/rotate";
- public const string EXPORT_PICASAWEB_BROWSER = "/apps/f-spot/export/picasaweb/browser";
- public const string EXPORT_PICASAWEB_TAG = "/apps/f-spot/export/picasaweb/tag";
-
public const string EXPORT_SMUGMUG_SCALE = "/apps/f-spot/export/smugmug/scale";
public const string EXPORT_SMUGMUG_SIZE = "/apps/f-spot/export/smugmug/size";
public const string EXPORT_SMUGMUG_ROTATE = "/apps/f-spot/export/smugmug/rotate";
@@ -152,10 +146,6 @@
case SHOW_DATES:
case SHOW_RATINGS:
case VIEWER_SHOW_FILENAMES:
- case EXPORT_PICASAWEB_SCALE:
- case EXPORT_PICASAWEB_ROTATE:
- case EXPORT_PICASAWEB_BROWSER:
- case EXPORT_PICASAWEB_TAG:
case EXPORT_SMUGMUG_SCALE:
case EXPORT_SMUGMUG_ROTATE:
case EXPORT_SMUGMUG_BROWSER:
@@ -165,7 +155,6 @@
case DBUS_READ_ONLY:
return true;
- case EXPORT_PICASAWEB_SIZE:
case EXPORT_SMUGMUG_SIZE:
case EXPORT_FOLDER_SIZE:
return 800;
Modified: trunk/src/f-spot.glade
==============================================================================
--- trunk/src/f-spot.glade (original)
+++ trunk/src/f-spot.glade Fri Feb 8 15:37:13 2008
@@ -1915,834 +1915,6 @@
</widget>
</child>
</widget>
- <widget class="GtkDialog" id="google_export_dialog">
- <property name="title" translatable="yes">Export</property>
- <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
- <property name="has_separator">False</property>
- <child internal-child="vbox">
- <widget class="GtkVBox" id="dialog-vbox11">
- <property name="visible">True</property>
- <child>
- <widget class="GtkHBox" id="hbox17">
- <property name="visible">True</property>
- <property name="border_width">6</property>
- <child>
- <widget class="GtkFrame" id="frame8">
- <property name="visible">True</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">GTK_SHADOW_NONE</property>
- <child>
- <widget class="GtkAlignment" id="alignment12">
- <property name="visible">True</property>
- <property name="left_padding">12</property>
- <child>
- <widget class="GtkScrolledWindow" id="thumb_scrolledwindow">
- <property name="width_request">180</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
- <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
- <property name="shadow_type">GTK_SHADOW_IN</property>
- <child>
- <placeholder/>
- </child>
- </widget>
- </child>
- </widget>
- </child>
- <child>
- <widget class="GtkLabel" id="photo_frame">
- <property name="visible">True</property>
- <property name="label" translatable="yes"><b>Photos</b></property>
- <property name="use_markup">True</property>
- </widget>
- <packing>
- <property name="type">label_item</property>
- </packing>
- </child>
- </widget>
- </child>
- <child>
- <widget class="GtkVBox" id="vbox11">
- <property name="visible">True</property>
- <property name="spacing">6</property>
- <child>
- <widget class="GtkFrame" id="frame9">
- <property name="visible">True</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">GTK_SHADOW_NONE</property>
- <child>
- <widget class="GtkAlignment" id="alignment13">
- <property name="visible">True</property>
- <property name="left_padding">12</property>
- <child>
- <widget class="GtkVBox" id="vbox12">
- <property name="visible">True</property>
- <property name="spacing">6</property>
- <child>
- <widget class="GtkHBox" id="hbox20">
- <property name="visible">True</property>
- <property name="spacing">6</property>
- <child>
- <widget class="GtkLabel" id="gallery_label">
- <property name="visible">True</property>
- <property name="label" translatable="yes">_Gallery:</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">gallery_optionmenu</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="GtkOptionMenu" id="gallery_optionmenu">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="response_id">0</property>
- <signal name="changed" handler="HandleAccountSelected"/>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="gallery_button">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="label">gtk-add</property>
- <property name="use_stock">True</property>
- <property name="response_id">0</property>
- <signal name="clicked" handler="HandleAddGallery"/>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="edit_button">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="label">gtk-edit</property>
- <property name="use_stock">True</property>
- <property name="response_id">0</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">3</property>
- </packing>
- </child>
- </widget>
- </child>
- <child>
- <widget class="GtkLabel" id="status_label">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="use_markup">True</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- </child>
- <child>
- <widget class="GtkLabel" id="label44">
- <property name="visible">True</property>
- <property name="label" translatable="yes"><b>PicasaWeb Export</b></property>
- <property name="use_markup">True</property>
- </widget>
- <packing>
- <property name="type">label_item</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="GtkFrame" id="frame10">
- <property name="visible">True</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">GTK_SHADOW_NONE</property>
- <child>
- <widget class="GtkAlignment" id="alignment14">
- <property name="visible">True</property>
- <property name="left_padding">12</property>
- <child>
- <widget class="GtkVBox" id="vbox13">
- <property name="visible">True</property>
- <property name="spacing">6</property>
- <child>
- <widget class="GtkHBox" id="hbox18">
- <property name="visible">True</property>
- <property name="spacing">6</property>
- <child>
- <widget class="GtkLabel" id="album_label">
- <property name="visible">True</property>
- <property name="label" translatable="yes">_Export to Album:</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">album_optionmenu</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="GtkOptionMenu" id="album_optionmenu">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="response_id">0</property>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="album_button">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="label">gtk-add</property>
- <property name="use_stock">True</property>
- <property name="response_id">0</property>
- <signal name="clicked" handler="HandleAddAlbum"/>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- </widget>
- </child>
- <child>
- <widget class="GtkCheckButton" id="browser_check">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="label" translatable="yes">Open _album in browser when done uploading</property>
- <property name="use_underline">True</property>
- <property name="response_id">0</property>
- <property name="active">True</property>
- <property name="draw_indicator">True</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- </child>
- <child>
- <widget class="GtkLabel" id="label45">
- <property name="visible">True</property>
- <property name="label" translatable="yes"><b>Album</b></property>
- <property name="use_markup">True</property>
- </widget>
- <packing>
- <property name="type">label_item</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <widget class="GtkFrame" id="frame11">
- <property name="visible">True</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">GTK_SHADOW_NONE</property>
- <child>
- <widget class="GtkAlignment" id="alignment15">
- <property name="visible">True</property>
- <property name="left_padding">12</property>
- <child>
- <widget class="GtkVBox" id="vbox14">
- <property name="visible">True</property>
- <property name="spacing">6</property>
- <child>
- <widget class="GtkHBox" id="hbox58">
- <property name="visible">True</property>
- <child>
- <widget class="GtkCheckButton" id="scale_check">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="label" translatable="yes">_Resize to: </property>
- <property name="use_underline">True</property>
- <property name="response_id">0</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="HandleSizeActive"/>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="GtkSpinButton" id="size_spin">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="adjustment">400 0 10000 1 10 10</property>
- <property name="climb_rate">1</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label153">
- <property name="visible">True</property>
- <property name="label" translatable="yes">pixels</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <placeholder/>
- </child>
- </widget>
- </child>
- <child>
- <widget class="GtkCheckButton" id="rotate_check">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="label" translatable="yes">_Autorotate</property>
- <property name="use_underline">True</property>
- <property name="response_id">0</property>
- <property name="draw_indicator">True</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <widget class="GtkCheckButton" id="tag_check">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="label" translatable="yes">_Export tags</property>
- <property name="use_underline">True</property>
- <property name="response_id">0</property>
- <property name="draw_indicator">True</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- </child>
- <child>
- <widget class="GtkLabel" id="label46">
- <property name="visible">True</property>
- <property name="label" translatable="yes"><b>Style</b></property>
- <property name="use_markup">True</property>
- </widget>
- <packing>
- <property name="type">label_item</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child internal-child="action_area">
- <widget class="GtkHButtonBox" id="dialog-action_area11">
- <property name="visible">True</property>
- <property name="layout_style">GTK_BUTTONBOX_END</property>
- <child>
- <widget class="GtkButton" id="cancel_button">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="can_default">True</property>
- <property name="label">gtk-cancel</property>
- <property name="use_stock">True</property>
- <property name="response_id">-6</property>
- </widget>
- </child>
- <child>
- <widget class="GtkButton" id="export_button">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="can_default">True</property>
- <property name="label">_Export</property>
- <property name="use_underline">True</property>
- <property name="response_id">-5</property>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">GTK_PACK_END</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- <widget class="GtkDialog" id="google_add_album_dialog">
- <property name="visible">True</property>
- <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
- <property name="has_separator">False</property>
- <child internal-child="vbox">
- <widget class="GtkVBox" id="dialog-vbox12">
- <property name="visible">True</property>
- <child>
- <widget class="GtkTable" id="table10">
- <property name="visible">True</property>
- <property name="border_width">12</property>
- <property name="n_rows">3</property>
- <property name="n_columns">2</property>
- <property name="column_spacing">7</property>
- <property name="row_spacing">6</property>
- <child>
- <placeholder/>
- </child>
- <child>
- <widget class="GtkLabel" id="descroption_label">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">_Description:</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">description_entry</property>
- </widget>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkEntry" id="description_entry">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="invisible_char">*</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="name_label">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">_Album Title:</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">title_entry</property>
- </widget>
- <packing>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkEntry" id="title_entry">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="invisible_char">*</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkCheckButton" id="public_check">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="label" translatable="yes">Public Album</property>
- <property name="use_underline">True</property>
- <property name="response_id">0</property>
- <property name="draw_indicator">True</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">GTK_PACK_END</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child internal-child="action_area">
- <widget class="GtkHButtonBox" id="dialog-action_area12">
- <property name="visible">True</property>
- <property name="layout_style">GTK_BUTTONBOX_END</property>
- <child>
- <widget class="GtkButton" id="cancel_button">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="can_default">True</property>
- <property name="label">gtk-cancel</property>
- <property name="use_stock">True</property>
- <property name="response_id">-6</property>
- </widget>
- </child>
- <child>
- <widget class="GtkButton" id="add_button">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="can_default">True</property>
- <property name="has_default">True</property>
- <property name="label">gtk-add</property>
- <property name="use_stock">True</property>
- <property name="response_id">-5</property>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">GTK_PACK_END</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- <widget class="GtkDialog" id="google_add_dialog">
- <property name="visible">True</property>
- <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
- <property name="has_separator">False</property>
- <child internal-child="vbox">
- <widget class="GtkVBox" id="dialog-vbox12">
- <property name="visible">True</property>
- <child>
- <widget class="GtkVBox" id="vbox63">
- <property name="visible">True</property>
- <child>
- <widget class="GtkHBox" id="status_area">
- <property name="border_width">12</property>
- <child>
- <widget class="GtkImage" id="image12">
- <property name="visible">True</property>
- <property name="yalign">0</property>
- <property name="stock">gtk-dialog-question</property>
- <property name="icon_size">6</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="padding">2</property>
- </packing>
- </child>
- <child>
- <widget class="GtkVBox" id="vbox64">
- <property name="visible">True</property>
- <property name="border_width">6</property>
- <child>
- <widget class="GtkLabel" id="summary_label">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes"><span weight='bold' size='larger'>Error Connecting to Gallery</span>
-</property>
- <property name="use_markup">True</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="description_label">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Please verify that the settings for this gallery are correct.</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="GtkHBox" id="locked_area">
- <property name="border_width">12</property>
- <child>
- <widget class="GtkImage" id="image45">
- <property name="visible">True</property>
- <property name="yalign">0</property>
- <property name="stock">gtk-missing-image</property>
- <property name="icon_size">6</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="padding">2</property>
- </packing>
- </child>
- <child>
- <widget class="GtkVBox" id="vbox84">
- <property name="visible">True</property>
- <property name="border_width">6</property>
- <child>
- <widget class="GtkLabel" id="label214">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes"><span weight='bold' size='larger'>Your Google Account is locked</span>
-</property>
- <property name="use_markup">True</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label215">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Please verify that the settings for this gallery are correct.
-Enter the letters as they are shown in the image in
-the 'Captcha' field. <i>Letters are not case-sensitive</i></property>
- <property name="use_markup">True</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <widget class="GtkTable" id="table10">
- <property name="visible">True</property>
- <property name="border_width">12</property>
- <property name="n_rows">3</property>
- <property name="n_columns">2</property>
- <property name="column_spacing">7</property>
- <property name="row_spacing">6</property>
- <child>
- <widget class="GtkLabel" id="password_label">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">_Password:</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">password_entry</property>
- </widget>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkEntry" id="password_entry">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="visibility">False</property>
- <property name="invisible_char">*</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="username_label">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">_Username:</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">username_entry</property>
- </widget>
- <packing>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkEntry" id="username_entry">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="invisible_char">*</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="captcha_label">
- <property name="xalign">1</property>
- <property name="label" translatable="yes">_Captcha:</property>
- <property name="use_underline">True</property>
- </widget>
- <packing>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkHBox" id="hbox88">
- <property name="visible">True</property>
- <child>
- <widget class="GtkEntry" id="captcha_entry">
- <property name="can_focus">True</property>
- <property name="invisible_char">*</property>
- </widget>
- </child>
- <child>
- <widget class="GtkImage" id="captcha_image">
- <property name="stock">gtk-missing-image</property>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">GTK_PACK_END</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child internal-child="action_area">
- <widget class="GtkHButtonBox" id="dialog-action_area12">
- <property name="visible">True</property>
- <property name="layout_style">GTK_BUTTONBOX_END</property>
- <child>
- <widget class="GtkButton" id="cancel_button">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="can_default">True</property>
- <property name="label">gtk-cancel</property>
- <property name="use_stock">True</property>
- <property name="response_id">-6</property>
- </widget>
- </child>
- <child>
- <widget class="GtkButton" id="remove_button">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="can_default">True</property>
- <property name="label">gtk-remove</property>
- <property name="use_stock">True</property>
- <property name="response_id">-2</property>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="add_button">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="can_default">True</property>
- <property name="has_default">True</property>
- <property name="label">gtk-add</property>
- <property name="use_stock">True</property>
- <property name="response_id">-5</property>
- </widget>
- <packing>
- <property name="position">2</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">GTK_PACK_END</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
<widget class="GtkDialog" id="vfs_export_dialog">
<property name="title" translatable="yes">Export</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]