[gthumb] [facebook] added facebook exporter



commit 6c3bbf84adc0ddcdda5b114c430d060cbb426e10
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Fri Apr 9 21:01:02 2010 +0200

    [facebook] added facebook exporter

 data/icons/hicolor/16x16/actions/Makefile.am       |    1 +
 data/icons/hicolor/16x16/actions/facebook.png      |  Bin 0 -> 324 bytes
 extensions/facebook/Makefile.am                    |   12 +-
 extensions/facebook/callbacks.c                    |    2 +-
 extensions/facebook/data/ui/Makefile.am            |    3 +-
 extensions/facebook/data/ui/export-to-facebook.ui  |  220 +-----
 .../facebook/data/ui/facebook-album-properties.ui  |  163 +++++
 .../facebook/data/ui/facebook-ask-authorization.ui |    6 +-
 .../data/ui/facebook-complete-authorization.ui     |    5 +-
 .../facebook/data/ui/facebook-export-completed.ui  |    4 +-
 extensions/facebook/dlg-export-to-facebook.c       |  715 ++++++--------------
 .../facebook/facebook-account-chooser-dialog.c     |   10 +-
 .../facebook/facebook-account-chooser-dialog.h     |    6 +-
 .../facebook/facebook-account-manager-dialog.c     |    2 +-
 .../facebook/facebook-account-manager-dialog.h     |    2 +-
 extensions/facebook/facebook-account.c             |   78 ++-
 extensions/facebook/facebook-account.h             |   24 +-
 .../facebook/facebook-album-properties-dialog.c    |  202 ++++++
 .../facebook/facebook-album-properties-dialog.h    |   64 ++
 extensions/facebook/facebook-album.c               |  268 +++-----
 extensions/facebook/facebook-album.h               |   71 +--
 extensions/facebook/facebook-authentication.c      |  733 ++++++++++++++++++++
 extensions/facebook/facebook-authentication.h      |   77 ++
 extensions/facebook/facebook-connection.c          |  299 +++++----
 extensions/facebook/facebook-connection.h          |   84 ++--
 extensions/facebook/facebook-service.c             |  624 +++++++----------
 extensions/facebook/facebook-service.h             |  132 ++--
 extensions/facebook/facebook-types.h               |   28 +-
 extensions/facebook/facebook-user.c                |  112 +---
 extensions/facebook/facebook-user.h                |   37 +-
 extensions/facebook/facebook.extension.in.in       |    2 +-
 extensions/flicker/flickr-authentication.c         |   11 +-
 gthumb/gth-progress-dialog.c                       |    8 +-
 33 files changed, 2292 insertions(+), 1713 deletions(-)
---
diff --git a/data/icons/hicolor/16x16/actions/Makefile.am b/data/icons/hicolor/16x16/actions/Makefile.am
index 045c994..e435660 100644
--- a/data/icons/hicolor/16x16/actions/Makefile.am
+++ b/data/icons/hicolor/16x16/actions/Makefile.am
@@ -6,6 +6,7 @@ iconsdir = $(themedir)/$(size)/$(context)
 
 icons_DATA = 			\
 	browser-mode.png	\
+	facebook.png		\
 	file-catalog.png	\
 	file-library.png	\
 	file-search.png		\
diff --git a/data/icons/hicolor/16x16/actions/facebook.png b/data/icons/hicolor/16x16/actions/facebook.png
new file mode 100644
index 0000000..92996c7
Binary files /dev/null and b/data/icons/hicolor/16x16/actions/facebook.png differ
diff --git a/extensions/facebook/Makefile.am b/extensions/facebook/Makefile.am
index f0ec599..4d3d9bb 100644
--- a/extensions/facebook/Makefile.am
+++ b/extensions/facebook/Makefile.am
@@ -18,12 +18,16 @@ libfacebook_la_SOURCES = 			\
 	facebook-account-chooser-dialog.h	\
 	facebook-account-manager-dialog.c	\
 	facebook-account-manager-dialog.h	\
+	facebook-album.c			\
+	facebook-album.h			\
+	facebook-album-properties-dialog.c	\
+	facebook-album-properties-dialog.h	\
+	facebook-authentication.c		\
+	facebook-authentication.h		\
 	facebook-connection.c			\
 	facebook-connection.h			\
 	facebook-photo.c			\
 	facebook-photo.h			\
-	facebook-photoset.c			\
-	facebook-photoset.h			\
 	facebook-service.c			\
 	facebook-service.h			\
 	facebook-types.h			\
@@ -31,9 +35,9 @@ libfacebook_la_SOURCES = 			\
 	facebook-user.h				\
 	main.c
 
-libfacebook_la_CFLAGS = $(GTHUMB_CFLAGS) $(LIBSOUP_CFLAGS) -I$(top_srcdir) -I$(top_builddir)/gthumb 
+libfacebook_la_CFLAGS = $(GTHUMB_CFLAGS) $(LIBSOUP_CFLAGS) $(GNOME_KEYRING_CFLAGS) -I$(top_srcdir) -I$(top_builddir)/gthumb 
 libfacebook_la_LDFLAGS = $(EXTENSION_LIBTOOL_FLAGS)
-libfacebook_la_LIBADD = $(GTHUMB_LIBS) $(LIBSOUP_LIBS) 
+libfacebook_la_LIBADD = $(GTHUMB_LIBS) $(LIBSOUP_LIBS) $(GNOME_KEYRING_LIBS)
 libfacebook_la_DEPENDENCIES = $(top_builddir)/gthumb/gthumb$(EXEEXT)
 
 extensioninidir = $(extensiondir)
diff --git a/extensions/facebook/callbacks.c b/extensions/facebook/callbacks.c
index cc41b5a..5f35d14 100644
--- a/extensions/facebook/callbacks.c
+++ b/extensions/facebook/callbacks.c
@@ -66,7 +66,7 @@ browser_data_free (BrowserData *data)
 
 
 void
-fl__gth_browser_construct_cb (GthBrowser *browser)
+fb__gth_browser_construct_cb (GthBrowser *browser)
 {
 	BrowserData *data;
 	GError      *error = NULL;
diff --git a/extensions/facebook/data/ui/Makefile.am b/extensions/facebook/data/ui/Makefile.am
index 0ebaf9e..ce64791 100644
--- a/extensions/facebook/data/ui/Makefile.am
+++ b/extensions/facebook/data/ui/Makefile.am
@@ -1,8 +1,9 @@
 uidir = $(pkgdatadir)/ui
 ui_DATA = 					\
-	export-to-flickr.ui			\
+	export-to-facebook.ui			\
 	facebook-account-chooser.ui		\
 	facebook-account-manager.ui		\
+	facebook-album-properties.ui		\
 	facebook-ask-authorization.ui		\
 	facebook-complete-authorization.ui	\
 	facebook-export-completed.ui
diff --git a/extensions/facebook/data/ui/export-to-facebook.ui b/extensions/facebook/data/ui/export-to-facebook.ui
index c45d946..492d59e 100644
--- a/extensions/facebook/data/ui/export-to-facebook.ui
+++ b/extensions/facebook/data/ui/export-to-facebook.ui
@@ -1,4 +1,4 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <requires lib="gtk+" version="2.16"/>
   <!-- interface-naming-policy project-wide -->
@@ -10,20 +10,17 @@
     <child internal-child="vbox">
       <object class="GtkVBox" id="dialog-vbox7">
         <property name="visible">True</property>
-        <property name="orientation">vertical</property>
         <property name="spacing">6</property>
         <child>
           <object class="GtkVBox" id="hbox1">
             <property name="visible">True</property>
             <property name="border_width">5</property>
-            <property name="orientation">vertical</property>
             <property name="spacing">12</property>
             <child>
               <object class="GtkVBox" id="images_box">
                 <property name="width_request">460</property>
-                <property name="height_request">220</property>
+                <property name="height_request">340</property>
                 <property name="visible">True</property>
-                <property name="orientation">vertical</property>
                 <property name="spacing">3</property>
                 <child>
                   <object class="GtkLabel" id="images_info_label">
@@ -43,12 +40,11 @@
             <child>
               <object class="GtkVBox" id="vbox1">
                 <property name="visible">True</property>
-                <property name="orientation">vertical</property>
                 <property name="spacing">6</property>
                 <child>
                   <object class="GtkTable" id="table2">
                     <property name="visible">True</property>
-                    <property name="n_rows">5</property>
+                    <property name="n_rows">2</property>
                     <property name="n_columns">2</property>
                     <property name="column_spacing">6</property>
                     <property name="row_spacing">5</property>
@@ -74,7 +70,6 @@
                     <child>
                       <object class="GtkVBox" id="vbox4">
                         <property name="visible">True</property>
-                        <property name="orientation">vertical</property>
                         <property name="spacing">3</property>
                         <child>
                           <object class="GtkHBox" id="hbox4">
@@ -119,41 +114,6 @@
                             <property name="position">0</property>
                           </packing>
                         </child>
-                        <child>
-                          <object class="GtkHBox" id="hbox3">
-                            <property name="visible">True</property>
-                            <property name="spacing">6</property>
-                            <child>
-                              <object class="GtkLabel" id="label4">
-                                <property name="visible">True</property>
-                                <property name="label" translatable="yes">Free space:</property>
-                                <attributes>
-                                  <attribute name="absolute-size" value="10000"/>
-                                </attributes>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkLabel" id="free_space_label">
-                                <property name="visible">True</property>
-                                <property name="xalign">0</property>
-                                <property name="yalign">0.51999998092651367</property>
-                                <attributes>
-                                  <attribute name="absolute-size" value="10000"/>
-                                </attributes>
-                              </object>
-                              <packing>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
                       </object>
                       <packing>
                         <property name="left_attach">1</property>
@@ -164,9 +124,8 @@
                       <object class="GtkLabel" id="label1">
                         <property name="visible">True</property>
                         <property name="xalign">0</property>
-                        <property name="label" translatable="yes">Ph_otoset:</property>
+                        <property name="label" translatable="yes">A_lbum:</property>
                         <property name="use_underline">True</property>
-                        <property name="mnemonic_widget">photoset_comboboxentry</property>
                       </object>
                       <packing>
                         <property name="top_attach">1</property>
@@ -175,103 +134,44 @@
                       </packing>
                     </child>
                     <child>
-                      <object class="GtkComboBoxEntry" id="photoset_comboboxentry">
+                      <object class="GtkHBox" id="hbox2">
                         <property name="visible">True</property>
-                        <property name="model">photoset_liststore</property>
-                        <property name="text_column">2</property>
+                        <property name="spacing">6</property>
                         <child>
-                          <object class="GtkCellRendererText" id="cellrenderertext2"/>
-                          <attributes>
-                            <attribute name="text">3</attribute>
-                          </attributes>
-                        </child>
-                      </object>
-                      <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>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label5">
-                        <property name="visible">True</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">_Privacy:</property>
-                        <property name="use_underline">True</property>
-                        <property name="mnemonic_widget">privacy_combobox</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">2</property>
-                        <property name="bottom_attach">3</property>
-                        <property name="x_options">GTK_FILL</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkComboBox" id="privacy_combobox">
-                        <property name="visible">True</property>
-                        <property name="model">privacy_liststore</property>
-                        <property name="active">0</property>
-                        <child>
-                          <object class="GtkCellRendererText" id="cellrenderertext5"/>
-                          <attributes>
-                            <attribute name="text">1</attribute>
-                          </attributes>
+                          <object class="GtkComboBox" id="album_combobox">
+                            <property name="visible">True</property>
+                            <property name="model">album_liststore</property>
+                          </object>
+                          <packing>
+                            <property name="position">0</property>
+                          </packing>
                         </child>
-                      </object>
-                      <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>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkCheckButton" id="hidden_checkbutton">
-                        <property name="label" translatable="yes">Hi_de from public searches</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="use_underline">True</property>
-                        <property name="draw_indicator">True</property>
-                      </object>
-                      <packing>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">4</property>
-                        <property name="bottom_attach">5</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label2">
-                        <property name="visible">True</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">_Safety:</property>
-                        <property name="use_underline">True</property>
-                        <property name="mnemonic_widget">safety_combobox</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">3</property>
-                        <property name="bottom_attach">4</property>
-                        <property name="x_options">GTK_FILL</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkComboBox" id="safety_combobox">
-                        <property name="visible">True</property>
-                        <property name="model">safety_liststore</property>
-                        <property name="active">0</property>
                         <child>
-                          <object class="GtkCellRendererText" id="cellrenderertext3"/>
-                          <attributes>
-                            <attribute name="text">1</attribute>
-                          </attributes>
+                          <object class="GtkButton" id="add_album_button">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <property name="tooltip_text" translatable="yes">Add a new album</property>
+                            <property name="use_action_appearance">False</property>
+                            <child>
+                              <object class="GtkImage" id="image1">
+                                <property name="visible">True</property>
+                                <property name="stock">gtk-add</property>
+                              </object>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">1</property>
+                          </packing>
                         </child>
                       </object>
                       <packing>
                         <property name="left_attach">1</property>
                         <property name="right_attach">2</property>
-                        <property name="top_attach">3</property>
-                        <property name="bottom_attach">4</property>
+                        <property name="top_attach">1</property>
+                        <property name="bottom_attach">2</property>
                       </packing>
                     </child>
                   </object>
@@ -366,59 +266,7 @@
       <column type="gchararray"/>
     </columns>
   </object>
-  <object class="GtkListStore" id="safety_liststore">
-    <columns>
-      <!-- column-name value -->
-      <column type="gint"/>
-      <!-- column-name name -->
-      <column type="gchararray"/>
-    </columns>
-    <data>
-      <row>
-        <col id="0">0</col>
-        <col id="1" translatable="yes">Safe content</col>
-      </row>
-      <row>
-        <col id="0">1</col>
-        <col id="1" translatable="yes">Moderate content</col>
-      </row>
-      <row>
-        <col id="0">2</col>
-        <col id="1" translatable="yes">Restricted content</col>
-      </row>
-    </data>
-  </object>
-  <object class="GtkListStore" id="privacy_liststore">
-    <columns>
-      <!-- column-name value -->
-      <column type="gint"/>
-      <!-- column-name name -->
-      <column type="gchararray"/>
-    </columns>
-    <data>
-      <row>
-        <col id="0">0</col>
-        <col id="1" translatable="yes">Public photos</col>
-      </row>
-      <row>
-        <col id="0">1</col>
-        <col id="1" translatable="yes">Private photos, visible to family and friends</col>
-      </row>
-      <row>
-        <col id="0">2</col>
-        <col id="1" translatable="yes">Private photos, visible to friends</col>
-      </row>
-      <row>
-        <col id="0">3</col>
-        <col id="1" translatable="yes">Private photos, visible to family</col>
-      </row>
-      <row>
-        <col id="0">4</col>
-        <col id="1" translatable="yes">Private photos</col>
-      </row>
-    </data>
-  </object>
-  <object class="GtkListStore" id="photoset_liststore">
+  <object class="GtkListStore" id="album_liststore">
     <columns>
       <!-- column-name data -->
       <column type="GObject"/>
diff --git a/extensions/facebook/data/ui/facebook-album-properties.ui b/extensions/facebook/data/ui/facebook-album-properties.ui
new file mode 100644
index 0000000..410c2ac
--- /dev/null
+++ b/extensions/facebook/data/ui/facebook-album-properties.ui
@@ -0,0 +1,163 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="2.18"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkVBox" id="album_properties">
+    <property name="visible">True</property>
+    <child>
+      <object class="GtkTable" id="table1">
+        <property name="visible">True</property>
+        <property name="n_rows">4</property>
+        <property name="n_columns">2</property>
+        <property name="column_spacing">6</property>
+        <property name="row_spacing">6</property>
+        <child>
+          <object class="GtkLabel" id="label1">
+            <property name="visible">True</property>
+            <property name="xalign">0</property>
+            <property name="label" translatable="yes">_Name:</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">name_entry</property>
+          </object>
+          <packing>
+            <property name="x_options">GTK_FILL</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="name_entry">
+            <property name="width_request">300</property>
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="invisible_char">â??</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label2">
+            <property name="visible">True</property>
+            <property name="xalign">0</property>
+            <property name="label" translatable="yes">_Visibility:</property>
+            <property name="use_underline">True</property>
+          </object>
+          <packing>
+            <property name="top_attach">3</property>
+            <property name="bottom_attach">4</property>
+            <property name="x_options">GTK_FILL</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkHBox" id="hbox1">
+            <property name="visible">True</property>
+            <child>
+              <object class="GtkComboBox" id="visibility_combobox">
+                <property name="visible">True</property>
+                <property name="model">visibility_liststore</property>
+                <property name="active">0</property>
+                <child>
+                  <object class="GtkCellRendererText" id="cellrenderertext1"/>
+                  <attributes>
+                    <attribute name="text">0</attribute>
+                  </attributes>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">3</property>
+            <property name="bottom_attach">4</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="description_entry">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="invisible_char">â??</property>
+          </object>
+          <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>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label3">
+            <property name="visible">True</property>
+            <property name="xalign">0</property>
+            <property name="label" translatable="yes">D_escription:</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">description_entry</property>
+          </object>
+          <packing>
+            <property name="top_attach">2</property>
+            <property name="bottom_attach">3</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="location_entry">
+            <property name="width_request">300</property>
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="invisible_char">â??</property>
+            <property name="invisible_char_set">True</property>
+          </object>
+          <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>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label4">
+            <property name="visible">True</property>
+            <property name="xalign">0</property>
+            <property name="label" translatable="yes">_Location:</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">location_entry</property>
+          </object>
+          <packing>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="x_options">GTK_FILL</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+  </object>
+  <object class="GtkListStore" id="visibility_liststore">
+    <columns>
+      <!-- column-name name -->
+      <column type="gchararray"/>
+      <!-- column-name value -->
+      <column type="gint"/>
+    </columns>
+    <data>
+      <row>
+        <col id="0" translatable="yes">Public photos</col>
+        <col id="1">0</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Private photos, visible to friends</col>
+        <col id="1">3</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Private</col>
+        <col id="1">4</col>
+      </row>
+    </data>
+  </object>
+</interface>
diff --git a/extensions/facebook/data/ui/facebook-ask-authorization.ui b/extensions/facebook/data/ui/facebook-ask-authorization.ui
index 8cc162b..4e9c69f 100644
--- a/extensions/facebook/data/ui/facebook-ask-authorization.ui
+++ b/extensions/facebook/data/ui/facebook-ask-authorization.ui
@@ -1,22 +1,18 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <requires lib="gtk+" version="2.16"/>
   <!-- interface-naming-policy project-wide -->
   <object class="GtkMessageDialog" id="ask_authorization_messagedialog">
     <property name="border_width">5</property>
-    <property name="title" translatable="yes">Upload to Flickr</property>
     <property name="resizable">False</property>
     <property name="modal">True</property>
     <property name="type_hint">normal</property>
     <property name="skip_taskbar_hint">True</property>
     <property name="message_type">other</property>
-    <property name="text" translatable="yes">gthumb requires your authorization to upload the photos to Flickr</property>
-    <property name="secondary_text" translatable="yes">Click 'Authorize' to open your web browser and authorize gthumb to upload photos to Flickr. When you're finished, return to this window to complete the authorization.</property>
     <property name="image">icon_image</property>
     <child internal-child="vbox">
       <object class="GtkVBox" id="dialog-vbox1">
         <property name="visible">True</property>
-        <property name="orientation">vertical</property>
         <property name="spacing">2</property>
         <child internal-child="action_area">
           <object class="GtkHButtonBox" id="dialog-action_area1">
diff --git a/extensions/facebook/data/ui/facebook-complete-authorization.ui b/extensions/facebook/data/ui/facebook-complete-authorization.ui
index 4b11130..5acc5e7 100644
--- a/extensions/facebook/data/ui/facebook-complete-authorization.ui
+++ b/extensions/facebook/data/ui/facebook-complete-authorization.ui
@@ -1,22 +1,19 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <requires lib="gtk+" version="2.16"/>
   <!-- interface-naming-policy project-wide -->
   <object class="GtkMessageDialog" id="complete_authorization_messagedialog">
     <property name="border_width">5</property>
-    <property name="title" translatable="yes">Upload to Flickr</property>
     <property name="resizable">False</property>
     <property name="modal">True</property>
     <property name="type_hint">normal</property>
     <property name="skip_taskbar_hint">True</property>
     <property name="message_type">other</property>
-    <property name="text" translatable="yes">Return to this window when you have finished the authorization process on Flickr.com</property>
     <property name="secondary_text" translatable="yes">Once you're done, click the 'Continue' button below.</property>
     <property name="image">icon_image1</property>
     <child internal-child="vbox">
       <object class="GtkVBox" id="dialog-vbox4">
         <property name="visible">True</property>
-        <property name="orientation">vertical</property>
         <property name="spacing">2</property>
         <child internal-child="action_area">
           <object class="GtkHButtonBox" id="dialog-action_area4">
diff --git a/extensions/facebook/data/ui/facebook-export-completed.ui b/extensions/facebook/data/ui/facebook-export-completed.ui
index 8341986..7de41da 100644
--- a/extensions/facebook/data/ui/facebook-export-completed.ui
+++ b/extensions/facebook/data/ui/facebook-export-completed.ui
@@ -1,10 +1,9 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <requires lib="gtk+" version="2.16"/>
   <!-- interface-naming-policy project-wide -->
   <object class="GtkMessageDialog" id="completed_messagedialog">
     <property name="border_width">5</property>
-    <property name="title" translatable="yes">Upload to Flickr</property>
     <property name="resizable">False</property>
     <property name="modal">True</property>
     <property name="type_hint">normal</property>
@@ -13,7 +12,6 @@
     <child internal-child="vbox">
       <object class="GtkVBox" id="dialog-vbox1">
         <property name="visible">True</property>
-        <property name="orientation">vertical</property>
         <property name="spacing">2</property>
         <child internal-child="action_area">
           <object class="GtkHButtonBox" id="dialog-action_area1">
diff --git a/extensions/facebook/dlg-export-to-facebook.c b/extensions/facebook/dlg-export-to-facebook.c
index 9b19533..efb47b5 100644
--- a/extensions/facebook/dlg-export-to-facebook.c
+++ b/extensions/facebook/dlg-export-to-facebook.c
@@ -24,9 +24,9 @@
 #include <gtk/gtk.h>
 #include <gthumb.h>
 #include "dlg-export-to-facebook.h"
-#include "facebook-account-chooser-dialog.h"
-#include "facebook-account-manager-dialog.h"
+#include "facebook-authentication.h"
 #include "facebook-album.h"
+#include "facebook-album-properties-dialog.h"
 #include "facebook-service.h"
 #include "facebook-user.h"
 
@@ -45,26 +45,25 @@ enum {
 	ALBUM_DATA_COLUMN,
 	ALBUM_ICON_COLUMN,
 	ALBUM_TITLE_COLUMN,
-	ALBUM_N_PHOTOS_COLUMN
+	ALBUM_SIZE_COLUMN
 };
 
 
 typedef struct {
-	GthBrowser       *browser;
-	GthFileData      *location;
-	GList            *file_list;
-	GtkBuilder       *builder;
-	GtkWidget        *dialog;
-	GtkWidget        *progress_dialog;
-	GList            *accounts;
-	FacebookAccount    *account;
-	FacebookUser       *user;
-	GList            *albums;
-	FacebookPhotoset   *album;
-	FacebookConnection *conn;
-	FacebookService    *service;
-	GList            *photos_ids;
-	GCancellable     *cancellable;
+	GthBrowser             *browser;
+	GthFileData            *location;
+	GList                  *file_list;
+	GtkBuilder             *builder;
+	GtkWidget              *dialog;
+	GtkWidget              *progress_dialog;
+	FacebookConnection     *conn;
+	FacebookAuthentication *auth;
+	FacebookService        *service;
+	FacebookUser           *user;
+	GList                  *albums;
+	FacebookAlbum          *album;
+	GList                  *photos_ids;
+	GCancellable           *cancellable;
 } DialogData;
 
 
@@ -75,14 +74,13 @@ export_dialog_destroy_cb (GtkWidget  *widget,
 	if (data->conn != NULL)
 		gth_task_completed (GTH_TASK (data->conn), NULL);
 	_g_object_unref (data->cancellable);
+	_g_string_list_free (data->photos_ids);
+	_g_object_unref (data->album);
+	_g_object_list_unref (data->albums);
+	_g_object_unref (data->user);
 	_g_object_unref (data->service);
+	_g_object_unref (data->auth);
 	_g_object_unref (data->conn);
-	_g_object_list_unref (data->accounts);
-	_g_object_unref (data->account);
-	_g_object_unref (data->user);
-	_g_object_list_unref (data->albums);
-	_g_object_unref (data->album);
-	_g_string_list_free (data->photos_ids);
 	_g_object_unref (data->builder);
 	_g_object_list_unref (data->file_list);
 	_g_object_unref (data->location);
@@ -111,30 +109,15 @@ completed_messagedialog_response_cb (GtkDialog *dialog,
 
 			gtk_widget_destroy (GTK_WIDGET (dialog));
 
-			if (data->album == NULL) {
-				GString *ids;
-				GList   *scan;
-
-				ids = g_string_new ("");
-				for (scan = data->photos_ids; scan; scan = scan->next) {
-					if (scan != data->photos_ids)
-						g_string_append (ids, ",");
-					g_string_append (ids, (char *) scan->data);
-				}
-				url = g_strconcat ("http://www.facebook.com/photos/upload/edit/?ids=";, ids->str, NULL);
-
-				g_string_free (ids, TRUE);
-			}
-			else if (data->album->url != NULL)
-				url = g_strdup (data->album->url);
-			else if (data->album->id != NULL)
-				url = g_strconcat ("http://www.facebook.com/photos/";, data->user->id, "/sets/", data->album->id, NULL);
+			if ((data->album != NULL) && (data->album->link != NULL))
+				url = g_strdup (data->album->link);
 
 			if ((url != NULL) && ! gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (dialog)), url, 0, &error)) {
 				if (data->conn != NULL)
 					gth_task_dialog (GTH_TASK (data->conn), TRUE);
 				_gtk_error_dialog_from_gerror_run (GTK_WINDOW (data->browser), _("Could not connect to the server"), &error);
 			}
+
 			gtk_widget_destroy (data->dialog);
 
 			g_free (url);
@@ -155,7 +138,7 @@ export_completed_with_success (DialogData *data)
 
 	gth_task_dialog (GTH_TASK (data->conn), TRUE);
 
-	builder = _gtk_builder_new_from_file ("flicker-export-completed.ui", "flicker");
+	builder = _gtk_builder_new_from_file ("facebook-export-completed.ui", "facebook");
 	dialog = _gtk_builder_get_widget (builder, "completed_messagedialog");
 	g_object_set_data_full (G_OBJECT (dialog), "builder", builder, g_object_unref);
 	g_signal_connect (dialog,
@@ -170,103 +153,21 @@ export_completed_with_success (DialogData *data)
 
 
 static void
-add_photos_to_album_ready_cb (GObject      *source_object,
-				 GAsyncResult *result,
-				 gpointer      user_data)
-{
-	DialogData *data = user_data;
-	GError     *error = NULL;
-
-	if (! facebook_service_add_photos_to_set_finish (FACEBOOK_SERVICE (source_object), result, &error)) {
-		_gtk_error_dialog_from_gerror_show (GTK_WINDOW (data->browser), _("Could not create the album"), &error);
-		gtk_widget_destroy (data->dialog);
-		return;
-	}
-
-	export_completed_with_success (data);
-}
-
-
-static void
-add_photos_to_album (DialogData *data)
-{
-	facebook_service_add_photos_to_set (data->service,
-					  data->album,
-					  data->photos_ids,
-					  data->cancellable,
-					  add_photos_to_album_ready_cb,
-					  data);
-}
-
-
-static void
-create_album_ready_cb (GObject      *source_object,
-			  GAsyncResult *result,
-			  gpointer      user_data)
+upload_photos_ready_cb (GObject      *source_object,
+		        GAsyncResult *result,
+		        gpointer      user_data)
 {
 	DialogData *data = user_data;
 	GError     *error = NULL;
-	char       *primary;
 
-	primary = g_strdup (data->album->primary);
-	g_object_unref (data->album);
-	data->album = facebook_service_create_album_finish (FACEBOOK_SERVICE (source_object), result, &error);
-	if (error != NULL) {
-		_gtk_error_dialog_from_gerror_show (GTK_WINDOW (data->browser), _("Could not create the album"), &error);
-		gtk_widget_destroy (data->dialog);
-	}
-	else {
-		facebook_album_set_primary (data->album, primary);
-		add_photos_to_album (data);
-	}
-
-	g_free (primary);
-}
-
-
-static void
-post_photos_ready_cb (GObject      *source_object,
-		      GAsyncResult *result,
-		      gpointer      user_data)
-{
-	DialogData *data = user_data;
-	GError     *error = NULL;
-
-	data->photos_ids = facebook_service_post_photos_finish (FACEBOOK_SERVICE (source_object), result, &error);
+	data->photos_ids = facebook_service_upload_photos_finish (FACEBOOK_SERVICE (source_object), result, &error);
 	if (error != NULL) {
 		_gtk_error_dialog_from_gerror_show (GTK_WINDOW (data->browser), _("Could not upload the files"), &error);
 		gtk_widget_destroy (data->dialog);
 		return;
 	}
 
-	if (data->album == NULL) {
-		export_completed_with_success (data);
-		return;
-	}
-
-	/* create the album if it doesn't exists */
-
-	if (data->album->id == NULL) {
-		char *first_id;
-
-		first_id = data->photos_ids->data;
-		facebook_album_set_primary (data->album, first_id);
-		facebook_service_create_album (data->service,
-						data->album,
-						data->cancellable,
-						create_album_ready_cb,
-						data);
-	}
-	else
-		add_photos_to_album (data);
-}
-
-
-static int
-find_album_by_title (FacebookPhotoset *album,
-		        const char     *name)
-{
-	return g_strcmp0 (album->title, name);
+	export_completed_with_success (data);
 }
 
 
@@ -284,45 +185,34 @@ export_dialog_response_cb (GtkDialog *dialog,
 
 	case GTK_RESPONSE_DELETE_EVENT:
 	case GTK_RESPONSE_CANCEL:
-		facebook_accounts_save_to_file (data->accounts, data->account);
 		gtk_widget_destroy (data->dialog);
 		break;
 
 	case GTK_RESPONSE_OK:
 		{
-			char  *album_title;
-			GList *file_list;
+			GtkTreeIter  iter;
+			GList       *file_list;
 
 			gtk_widget_hide (data->dialog);
 			gth_task_dialog (GTH_TASK (data->conn), FALSE);
 
 			data->album = NULL;
-			album_title = gtk_combo_box_get_active_text (GTK_COMBO_BOX (GET_WIDGET ("album_comboboxentry")));
-			if ((album_title != NULL) && (g_strcmp0 (album_title, "") != 0)) {
-				GList *link;
-
-				link = g_list_find_custom (data->albums, album_title, (GCompareFunc) find_album_by_title);
-				if (link != NULL)
-					data->album = g_object_ref (link->data);
-
-				if (data->album == NULL) {
-					data->album = facebook_album_new ();
-					facebook_album_set_title (data->album, album_title);
-				}
+			if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (GET_WIDGET ("album_combobox")), &iter)) {
+				gtk_tree_model_get (gtk_combo_box_get_model (GTK_COMBO_BOX (GET_WIDGET ("album_combobox"))),
+						    &iter,
+						    ALBUM_DATA_COLUMN, &data->album,
+						    -1);
 			}
 
 			file_list = gth_file_data_list_to_file_list (data->file_list);
-			facebook_service_post_photos (data->service,
-						    gtk_combo_box_get_active (GTK_COMBO_BOX (GET_WIDGET ("privacy_combobox"))),
-						    gtk_combo_box_get_active (GTK_COMBO_BOX (GET_WIDGET ("safety_combobox"))),
-						    gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("hidden_checkbutton"))),
-						    file_list,
-						    data->cancellable,
-						    post_photos_ready_cb,
-						    data);
+			facebook_service_upload_photos (data->service,
+						        data->album,
+						        file_list,
+						        data->cancellable,
+						        upload_photos_ready_cb,
+						        data);
 
 			_g_object_list_unref (file_list);
-			g_free (album_title);
 		}
 		break;
 
@@ -335,19 +225,21 @@ export_dialog_response_cb (GtkDialog *dialog,
 static void
 update_account_list (DialogData *data)
 {
-	GtkTreeIter  iter;
-	int          current_account;
-	int          idx;
-	GList       *scan;
-	char        *free_space;
+	int              current_account_idx;
+	FacebookAccount *current_account;
+	int              idx;
+	GList           *scan;
+	GtkTreeIter      iter;
 
-	current_account = 0;
 	gtk_list_store_clear (GTK_LIST_STORE (GET_WIDGET ("account_liststore")));
-	for (scan = data->accounts, idx = 0; scan; scan = scan->next, idx++) {
+
+	current_account_idx = 0;
+	current_account = facebook_authentication_get_account (data->auth);
+	for (scan = facebook_authentication_get_accounts (data->auth), idx = 0; scan; scan = scan->next, idx++) {
 		FacebookAccount *account = scan->data;
 
-		if ((data->account != NULL) && (g_strcmp0 (data->account->username, account->username) == 0))
-			current_account = idx;
+		if ((current_account != NULL) && (g_strcmp0 (current_account->username, account->username) == 0))
+			current_account_idx = idx;
 
 		gtk_list_store_append (GTK_LIST_STORE (GET_WIDGET ("account_liststore")), &iter);
 		gtk_list_store_set (GTK_LIST_STORE (GET_WIDGET ("account_liststore")), &iter,
@@ -355,83 +247,54 @@ update_account_list (DialogData *data)
 				    ACCOUNT_NAME_COLUMN, account->username,
 				    -1);
 	}
-	gtk_combo_box_set_active (GTK_COMBO_BOX (GET_WIDGET ("account_combobox")), current_account);
-
-	free_space = g_format_size_for_display (data->user->max_bandwidth - data->user->used_bandwidth);
-	gtk_label_set_text (GTK_LABEL (GET_WIDGET ("free_space_label")), free_space);
-	g_free (free_space);
+	gtk_combo_box_set_active (GTK_COMBO_BOX (GET_WIDGET ("account_combobox")), current_account_idx);
 }
 
 
 static void
-album_list_ready_cb (GObject      *source_object,
-			GAsyncResult *res,
-			gpointer      user_data)
+authentication_accounts_changed_cb (FacebookAuthentication *auth,
+				    gpointer              user_data)
 {
-	DialogData *data = user_data;
-	GError     *error = NULL;
-	GList      *scan;
+	update_account_list ((DialogData *) user_data);
+}
 
-	_g_object_list_unref (data->albums);
-	data->albums = facebook_service_list_albums_finish (FACEBOOK_SERVICE (source_object), res, &error);
-	if (error != NULL) {
-		if (data->conn != NULL)
-			gth_task_dialog (GTH_TASK (data->conn), TRUE);
-		_gtk_error_dialog_from_gerror_run (GTK_WINDOW (data->browser), _("Could not connect to the server"), &error);
-		gtk_widget_destroy (data->dialog);
-		return;
-	}
+
+static void
+update_album_list (DialogData *data)
+{
+	GList *scan;
 
 	gtk_list_store_clear (GTK_LIST_STORE (GET_WIDGET ("album_liststore")));
 	for (scan = data->albums; scan; scan = scan->next) {
-		FacebookPhotoset *album = scan->data;
-		char           *n_photos;
-		GtkTreeIter     iter;
+		FacebookAlbum *album = scan->data;
+		char          *size;
+		GtkTreeIter    iter;
 
-		n_photos = g_strdup_printf ("(%d)", album->n_photos);
+		size = g_strdup_printf ("(%d)", album->size);
 
 		gtk_list_store_append (GTK_LIST_STORE (GET_WIDGET ("album_liststore")), &iter);
 		gtk_list_store_set (GTK_LIST_STORE (GET_WIDGET ("album_liststore")), &iter,
 				    ALBUM_DATA_COLUMN, album,
 				    ALBUM_ICON_COLUMN, "file-catalog",
-				    ALBUM_TITLE_COLUMN, album->title,
-				    ALBUM_N_PHOTOS_COLUMN, n_photos,
+				    ALBUM_TITLE_COLUMN, album->name,
+				    ALBUM_SIZE_COLUMN, size,
 				    -1);
 
-		g_free (n_photos);
+		g_free (size);
 	}
-
-	gtk_widget_set_sensitive (GET_WIDGET ("upload_button"), TRUE);
-
-	gth_task_dialog (GTH_TASK (data->conn), TRUE);
-
-	gtk_window_set_transient_for (GTK_WINDOW (data->dialog), GTK_WINDOW (data->browser));
-	gtk_window_set_modal (GTK_WINDOW (data->dialog), FALSE);
-	gtk_window_present (GTK_WINDOW (data->dialog));
 }
 
 
 static void
-get_album_list (DialogData *data)
-{
-	facebook_service_list_albums (data->service,
-				       NULL,
-				       data->cancellable,
-				       album_list_ready_cb,
-				       data);
-}
-
-
-static void
-upload_status_ready_cb (GObject      *source_object,
-			GAsyncResult *res,
-			gpointer      user_data)
+get_albums_ready_cb (GObject      *source_object,
+		     GAsyncResult *res,
+		     gpointer      user_data)
 {
 	DialogData *data = user_data;
 	GError     *error = NULL;
 
-	_g_object_unref (data->user);
-	data->user = facebook_service_get_upload_status_finish (FACEBOOK_SERVICE (source_object), res, &error);
+	_g_object_list_unref (data->albums);
+	data->albums = facebook_service_get_albums_finish (FACEBOOK_SERVICE (source_object), res, &error);
 	if (error != NULL) {
 		if (data->conn != NULL)
 			gth_task_dialog (GTH_TASK (data->conn), TRUE);
@@ -440,286 +303,90 @@ upload_status_ready_cb (GObject      *source_object,
 		return;
 	}
 
-	update_account_list (data);
-	get_album_list (data);
-}
-
+	gtk_widget_set_sensitive (GET_WIDGET ("upload_button"), TRUE);
+	update_album_list (data);
 
-static void
-connect_to_server (DialogData *data)
-{
-	g_return_if_fail (data->account != NULL);
-
-	facebook_connection_set_auth_token (data->conn, data->account->token);
-	if (data->service == NULL)
-		data->service = facebook_service_new (data->conn);
-	facebook_service_get_upload_status (data->service,
-					  data->cancellable,
-					  upload_status_ready_cb,
-					  data);
+	gth_task_dialog (GTH_TASK (data->conn), TRUE);
+	gtk_window_set_transient_for (GTK_WINDOW (data->dialog), GTK_WINDOW (data->browser));
+	gtk_window_set_modal (GTK_WINDOW (data->dialog), FALSE);
+	gtk_window_present (GTK_WINDOW (data->dialog));
 }
 
 
 static void
-connection_token_ready_cb (GObject      *source_object,
-			   GAsyncResult *res,
-			   gpointer      user_data)
+authentication_ready_cb (FacebookAuthentication *auth,
+			 FacebookUser           *user,
+			 DialogData             *data)
 {
-	DialogData *data = user_data;
-	GError     *error = NULL;
-	GList      *link;
-
-	if (! facebook_connection_get_token_finish (FACEBOOK_CONNECTION (source_object), res, &error)) {
-		if (data->conn != NULL)
-			gth_task_dialog (GTH_TASK (data->conn), TRUE);
-		_gtk_error_dialog_from_gerror_run (GTK_WINDOW (data->browser), _("Could not connect to the server"), &error);
-		gtk_widget_destroy (data->dialog);
-		return;
-	}
-
-	_g_object_unref (data->account);
-	data->account = facebook_account_new ();
-	facebook_account_set_username (data->account, facebook_connection_get_username (data->conn));
-	facebook_account_set_token (data->account, facebook_connection_get_auth_token (data->conn));
-
-	link = g_list_find_custom (data->accounts, data->account, (GCompareFunc) facebook_account_cmp);
-	if (link != NULL) {
-		data->accounts = g_list_remove_link (data->accounts, link);
-		_g_object_list_unref (link);
-	}
-	data->accounts = g_list_prepend (data->accounts, g_object_ref (data->account));
+	_g_object_unref (data->user);
+	data->user = g_object_ref (user);
+	update_account_list (data);
 
-	connect_to_server (data);
+	facebook_service_get_albums (data->service,
+				     data->user->id,
+				     data->cancellable,
+				     get_albums_ready_cb,
+				     data);
 }
 
 
 static void
-complete_authorization_messagedialog_response_cb (GtkDialog *dialog,
-						  int        response_id,
-						  gpointer   user_data)
+edit_accounts_button_clicked_cb (GtkButton  *button,
+				 DialogData *data)
 {
-	DialogData *data = user_data;
-
-	switch (response_id) {
-	case GTK_RESPONSE_HELP:
-		show_help_dialog (GTK_WINDOW (dialog), "flicker-complete-authorization");
-		break;
-
-	case GTK_RESPONSE_DELETE_EVENT:
-	case GTK_RESPONSE_CANCEL:
-		gtk_widget_destroy (GTK_WIDGET (dialog));
-		gtk_widget_destroy (data->dialog);
-		break;
-
-	case GTK_RESPONSE_OK:
-		gtk_widget_destroy (GTK_WIDGET (dialog));
-		gth_task_dialog (GTH_TASK (data->conn), FALSE);
-		facebook_connection_get_token (data->conn,
-					     data->cancellable,
-					     connection_token_ready_cb,
-					     data);
-		break;
-
-	default:
-		break;
-	}
+	facebook_authentication_edit_accounts (data->auth, GTK_WINDOW (data->dialog));
 }
 
 
 static void
-complete_authorization (DialogData *data)
-{
-	GtkBuilder *builder;
-	GtkWidget  *dialog;
-
-	gth_task_dialog (GTH_TASK (data->conn), TRUE);
-
-	builder = _gtk_builder_new_from_file ("flicker-complete-authorization.ui", "flicker");
-	dialog = _gtk_builder_get_widget (builder, "complete_authorization_messagedialog");
-	g_object_set_data_full (G_OBJECT (dialog), "builder", builder, g_object_unref);
-	g_signal_connect (dialog,
-			  "response",
-			  G_CALLBACK (complete_authorization_messagedialog_response_cb),
-			  data);
-
-	gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (data->browser));
-	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
-	gtk_window_present (GTK_WINDOW (dialog));
-}
-
-
-static void
-ask_authorization_messagedialog_response_cb (GtkDialog *dialog,
-					     int        response_id,
-					     gpointer   user_data)
+account_combobox_changed_cb (GtkComboBox *widget,
+			     gpointer     user_data)
 {
-	DialogData *data = user_data;
-
-	switch (response_id) {
-	case GTK_RESPONSE_HELP:
-		show_help_dialog (GTK_WINDOW (dialog), "flicker-ask-authorization");
-		break;
-
-	case GTK_RESPONSE_DELETE_EVENT:
-	case GTK_RESPONSE_CANCEL:
-		gtk_widget_destroy (GTK_WIDGET (dialog));
-		gtk_widget_destroy (data->dialog);
-		break;
-
-	case GTK_RESPONSE_OK:
-		{
-			char   *url;
-			GError *error = NULL;
-
-			gtk_widget_destroy (GTK_WIDGET (dialog));
-
-			url = facebook_connection_get_login_link (data->conn, FACEBOOK_ACCESS_WRITE);
-			if (gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (dialog)), url, 0, &error)) {
-				complete_authorization (data);
-			}
-			else {
-				if (data->conn != NULL)
-					gth_task_dialog (GTH_TASK (data->conn), TRUE);
-				_gtk_error_dialog_from_gerror_run (GTK_WINDOW (data->browser), _("Could not connect to the server"), &error);
-				gtk_widget_destroy (data->dialog);
-			}
-
-			g_free (url);
-		}
-		break;
-
-	default:
-		break;
-	}
-}
-
+	DialogData      *data = user_data;
+	GtkTreeIter      iter;
+	FacebookAccount *account;
 
-static void
-ask_authorization (DialogData *data)
-{
-	GtkBuilder *builder;
-	GtkWidget  *dialog;
+	if (! gtk_combo_box_get_active_iter (widget, &iter))
+		return;
 
-	gth_task_dialog (GTH_TASK (data->conn), TRUE);
+	gtk_tree_model_get (gtk_combo_box_get_model (widget),
+			    &iter,
+			    ACCOUNT_DATA_COLUMN, &account,
+			    -1);
 
-	builder = _gtk_builder_new_from_file ("flicker-ask-authorization.ui", "flicker");
-	dialog = _gtk_builder_get_widget (builder, "ask_authorization_messagedialog");
-	g_object_set_data_full (G_OBJECT (dialog), "builder", builder, g_object_unref);
-	g_signal_connect (dialog,
-			  "response",
-			  G_CALLBACK (ask_authorization_messagedialog_response_cb),
-			  data);
+	if (facebook_account_cmp (account, facebook_authentication_get_account (data->auth)) != 0)
+		facebook_authentication_connect (data->auth, account);
 
-	gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (data->browser));
-	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
-	gtk_window_present (GTK_WINDOW (dialog));
+	g_object_unref (account);
 }
 
 
 static void
-connection_frob_ready_cb (GObject      *source_object,
-			  GAsyncResult *res,
-			  gpointer      user_data)
+create_album_ready_cb (GObject      *source_object,
+		       GAsyncResult *result,
+		       gpointer      user_data)
 {
-	DialogData *data = user_data;
-	GError     *error = NULL;
+	DialogData    *data = user_data;
+	FacebookAlbum *album;
+	GError        *error = NULL;
 
-	if (! facebook_connection_get_frob_finish (FACEBOOK_CONNECTION (source_object), res, &error)) {
+	album = facebook_service_create_album_finish (data->service, result, &error);
+	if (error != NULL) {
 		if (data->conn != NULL)
 			gth_task_dialog (GTH_TASK (data->conn), TRUE);
-		_gtk_error_dialog_from_gerror_run (GTK_WINDOW (data->browser), _("Could not connect to the server"), &error);
-		gtk_widget_destroy (data->dialog);
+		_gtk_error_dialog_from_gerror_show (GTK_WINDOW (data->browser), _("Could not create the album"), &error);
 		return;
 	}
 
-	ask_authorization (data);
+	data->albums = g_list_append (data->albums, album);
+	update_album_list (data);
 }
 
 
 static void
-start_authorization_process (DialogData *data)
-{
-	facebook_connection_get_frob (data->conn,
-				    data->cancellable,
-				    connection_frob_ready_cb,
-				    data);
-}
-
-
-static void
-account_chooser_dialog_response_cb (GtkDialog *dialog,
-				    int        response_id,
-				    gpointer   user_data)
-{
-	DialogData *data = user_data;
-
-	switch (response_id) {
-	case GTK_RESPONSE_DELETE_EVENT:
-	case GTK_RESPONSE_CANCEL:
-		gtk_widget_destroy (GTK_WIDGET (dialog));
-		gtk_widget_destroy (data->dialog);
-		break;
-
-	case GTK_RESPONSE_OK:
-		_g_object_unref (data->account);
-		data->account = facebook_account_chooser_dialog_get_active (FACEBOOK_ACCOUNT_CHOOSER_DIALOG (dialog));
-		if (data->account != NULL) {
-			gtk_widget_destroy (GTK_WIDGET (dialog));
-			connect_to_server (data);
-		}
-
-		break;
-
-	case FACEBOOK_ACCOUNT_CHOOSER_RESPONSE_NEW:
-		gtk_widget_destroy (GTK_WIDGET (dialog));
-		start_authorization_process (data);
-		break;
-
-	default:
-		break;
-	}
-}
-
-
-static void
-auto_select_account (DialogData *data)
-{
-	gtk_widget_hide (data->dialog);
-	gth_task_dialog (GTH_TASK (data->conn), FALSE);
-
-	if (data->accounts != NULL) {
-		if (data->account != NULL) {
-			connect_to_server (data);
-		}
-		else if (data->accounts->next == NULL) {
-			data->account = g_object_ref (data->accounts->data);
-			connect_to_server (data);
-		}
-		else {
-			GtkWidget *dialog;
-
-			gth_task_dialog (GTH_TASK (data->conn), TRUE);
-			dialog = facebook_account_chooser_dialog_new (data->accounts, data->account);
-			g_signal_connect (dialog,
-					  "response",
-					  G_CALLBACK (account_chooser_dialog_response_cb),
-					  data);
-
-			gtk_window_set_title (GTK_WINDOW (dialog), _("Choose Account"));
-			gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (data->browser));
-			gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
-			gtk_window_present (GTK_WINDOW (dialog));
-		}
-	}
-	else
-		start_authorization_process (data);
-}
-
-
-static void
-account_manager_dialog_response_cb (GtkDialog *dialog,
-			            int        response_id,
-			            gpointer   user_data)
+new_album_dialog_response_cb (GtkDialog *dialog,
+			      int        response_id,
+			      gpointer   user_data)
 {
 	DialogData *data = user_data;
 
@@ -730,16 +397,22 @@ account_manager_dialog_response_cb (GtkDialog *dialog,
 		break;
 
 	case GTK_RESPONSE_OK:
-		_g_object_list_unref (data->accounts);
-		data->accounts = facebook_account_manager_dialog_get_accounts (FACEBOOK_ACCOUNT_MANAGER_DIALOG (dialog));
-		if (! g_list_find_custom (data->accounts, data->account, (GCompareFunc) facebook_account_cmp)) {
-			_g_object_unref (data->account);
-			data->account = NULL;
-			auto_select_account (data);
+		{
+			FacebookAlbum *album;
+
+			album = facebook_album_new ();
+			facebook_album_set_name (album, facebook_album_properties_dialog_get_name (FACEBOOK_ALBUM_PROPERTIES_DIALOG (dialog)));
+			facebook_album_set_location (album, facebook_album_properties_dialog_get_location (FACEBOOK_ALBUM_PROPERTIES_DIALOG (dialog)));
+			facebook_album_set_description (album, facebook_album_properties_dialog_get_description (FACEBOOK_ALBUM_PROPERTIES_DIALOG (dialog)));
+			album->visibility = facebook_album_properties_dialog_get_visibility (FACEBOOK_ALBUM_PROPERTIES_DIALOG (dialog));
+			facebook_service_create_album (data->service,
+						       album,
+						       data->cancellable,
+						       create_album_ready_cb,
+						       data);
+
+			g_object_unref (album);
 		}
-		else
-			update_account_list (data);
-		facebook_accounts_save_to_file (data->accounts, data->account);
 		gtk_widget_destroy (GTK_WIDGET (dialog));
 		break;
 
@@ -750,54 +423,31 @@ account_manager_dialog_response_cb (GtkDialog *dialog,
 
 
 static void
-edit_accounts_button_clicked_cb (GtkButton *button,
-			         gpointer   user_data)
+add_album_button_clicked_cb (GtkButton *button,
+			     gpointer   user_data)
 {
 	DialogData *data = user_data;
 	GtkWidget  *dialog;
 
-	dialog = facebook_account_manager_dialog_new (data->accounts);
+	dialog = facebook_album_properties_dialog_new (g_file_info_get_edit_name (data->location->info),
+						       NULL,
+						       NULL,
+						       FACEBOOK_VISIBILITY_SELF);
 	g_signal_connect (dialog,
 			  "response",
-			  G_CALLBACK (account_manager_dialog_response_cb),
+			  G_CALLBACK (new_album_dialog_response_cb),
 			  data);
 
-	gtk_window_set_title (GTK_WINDOW (dialog), _("Edit Accounts"));
+	gtk_window_set_title (GTK_WINDOW (dialog), _("New Album"));
 	gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (data->dialog));
 	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
 	gtk_window_present (GTK_WINDOW (dialog));
 }
 
 
-static void
-account_combobox_changed_cb (GtkComboBox *widget,
-			     gpointer     user_data)
-{
-	DialogData    *data = user_data;
-	GtkTreeIter    iter;
-	FacebookAccount *account;
-
-	if (! gtk_combo_box_get_active_iter (widget, &iter))
-		return;
-
-	gtk_tree_model_get (gtk_combo_box_get_model (widget),
-			    &iter,
-			    ACCOUNT_DATA_COLUMN, &account,
-			    -1);
-
-	if (facebook_account_cmp (account, data->account) != 0) {
-		_g_object_unref (data->account);
-		data->account = account;
-		auto_select_account (data);
-	}
-	else
-		g_object_unref (account);
-}
-
-
 void
 dlg_export_to_facebook (GthBrowser *browser,
-		      GList      *file_list)
+		        GList      *file_list)
 {
 	DialogData *data;
 	GList      *scan;
@@ -806,14 +456,40 @@ dlg_export_to_facebook (GthBrowser *browser,
 	char       *total_size_formatted;
 	char       *text;
 	GtkWidget  *list_view;
+	char       *title;
 
 	data = g_new0 (DialogData, 1);
 	data->browser = browser;
 	data->location = gth_file_data_dup (gth_browser_get_location_data (browser));
-	data->builder = _gtk_builder_new_from_file ("export-to-facebook.ui", "flicker");
+	data->builder = _gtk_builder_new_from_file ("export-to-facebook.ui", "facebook");
 	data->dialog = _gtk_builder_get_widget (data->builder, "export_dialog");
 	data->cancellable = g_cancellable_new ();
 
+	{
+		GtkCellLayout   *cell_layout;
+		GtkCellRenderer *renderer;
+
+		cell_layout = GTK_CELL_LAYOUT (GET_WIDGET ("album_combobox"));
+
+		renderer = gtk_cell_renderer_pixbuf_new ();
+		gtk_cell_layout_pack_start (cell_layout, renderer, FALSE);
+		gtk_cell_layout_set_attributes (cell_layout, renderer,
+						"icon-name", ALBUM_ICON_COLUMN,
+						NULL);
+
+		renderer = gtk_cell_renderer_text_new ();
+		gtk_cell_layout_pack_start (cell_layout, renderer, TRUE);
+		gtk_cell_layout_set_attributes (cell_layout, renderer,
+						"text", ALBUM_TITLE_COLUMN,
+						NULL);
+
+		renderer = gtk_cell_renderer_text_new ();
+		gtk_cell_layout_pack_end (cell_layout, renderer, FALSE);
+		gtk_cell_layout_set_attributes (cell_layout, renderer,
+						"text", ALBUM_SIZE_COLUMN,
+						NULL);
+	}
+
 	data->file_list = NULL;
 	n_total = 0;
 	total_size = 0;
@@ -822,10 +498,15 @@ dlg_export_to_facebook (GthBrowser *browser,
 		const char  *mime_type;
 
 		mime_type = gth_file_data_get_mime_type (file_data);
-		if (g_content_type_equals (mime_type, "image/bmp")
-		    || g_content_type_equals (mime_type, "image/gif")
+		if (g_content_type_equals (mime_type, "image/gif") /* FIXME: check if the mime types are correct */
 		    || g_content_type_equals (mime_type, "image/jpeg")
-		    || g_content_type_equals (mime_type, "image/png"))
+		    || g_content_type_equals (mime_type, "image/png")
+		    || g_content_type_equals (mime_type, "image/psd")
+		    || g_content_type_equals (mime_type, "image/tiff")
+		    || g_content_type_equals (mime_type, "image/jp2")
+		    || g_content_type_equals (mime_type, "image/iff")
+		    || g_content_type_equals (mime_type, "image/bmp")
+		    || g_content_type_equals (mime_type, "image/xbm"))
 		{
 			total_size += g_file_info_get_size (file_data->info);
 			n_total++;
@@ -862,9 +543,12 @@ dlg_export_to_facebook (GthBrowser *browser,
 	gtk_box_pack_start (GTK_BOX (GET_WIDGET ("images_box")), list_view, TRUE, TRUE, 0);
 	gth_file_list_set_files (GTH_FILE_LIST (list_view), data->file_list);
 
-	gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (GET_WIDGET ("album_comboboxentry")))), g_file_info_get_edit_name (data->location->info));
 	gtk_widget_set_sensitive (GET_WIDGET ("upload_button"), FALSE);
 
+	title = g_strdup_printf (_("Export to %s"), "Facebook");
+	gtk_window_set_title (GTK_WINDOW (data->dialog), title);
+	g_free (title);
+
 	/* Set the signals handlers. */
 
 	g_signal_connect (G_OBJECT (data->dialog),
@@ -883,12 +567,29 @@ dlg_export_to_facebook (GthBrowser *browser,
 			  "changed",
 			  G_CALLBACK (account_combobox_changed_cb),
 			  data);
+	g_signal_connect (GET_WIDGET ("add_album_button"),
+			  "clicked",
+			  G_CALLBACK (add_album_button_clicked_cb),
+			  data);
 
 	data->conn = facebook_connection_new ();
+	data->service = facebook_service_new (data->conn);
+	data->auth = facebook_authentication_new (data->conn,
+						  data->service,
+						  data->cancellable,
+						  GTK_WIDGET (data->browser),
+						  data->dialog);
+	g_signal_connect (data->auth,
+			  "ready",
+			  G_CALLBACK (authentication_ready_cb),
+			  data);
+	g_signal_connect (data->auth,
+			  "accounts_changed",
+			  G_CALLBACK (authentication_accounts_changed_cb),
+			  data);
+
 	data->progress_dialog = gth_progress_dialog_new (GTK_WINDOW (data->browser));
 	gth_progress_dialog_add_task (GTH_PROGRESS_DIALOG (data->progress_dialog), GTH_TASK (data->conn));
 
-	data->accounts = facebook_accounts_load_from_file ();
-	data->account = facebook_accounts_find_default (data->accounts);
-	auto_select_account (data);
+	facebook_authentication_auto_connect (data->auth);
 }
diff --git a/extensions/facebook/facebook-account-chooser-dialog.c b/extensions/facebook/facebook-account-chooser-dialog.c
index 9bdf5ff..9597a7c 100644
--- a/extensions/facebook/facebook-account-chooser-dialog.c
+++ b/extensions/facebook/facebook-account-chooser-dialog.c
@@ -127,8 +127,8 @@ facebook_account_chooser_dialog_get_type (void)
 
 static void
 facebook_account_chooser_dialog_construct (FacebookAccountChooserDialog *self,
-				         GList                      *accounts,
-				         FacebookAccount              *default_account)
+				           GList                        *accounts,
+				           FacebookAccount              *default_account)
 {
 	GtkTreeIter  iter;
 	GList       *scan;
@@ -155,8 +155,8 @@ facebook_account_chooser_dialog_construct (FacebookAccountChooserDialog *self,
 
 
 GtkWidget *
-facebook_account_chooser_dialog_new (GList         *accounts,
-				   FacebookAccount *default_account)
+facebook_account_chooser_dialog_new (GList           *accounts,
+				     FacebookAccount *default_account)
 {
 	FacebookAccountChooserDialog *self;
 
@@ -170,7 +170,7 @@ facebook_account_chooser_dialog_new (GList         *accounts,
 FacebookAccount *
 facebook_account_chooser_dialog_get_active (FacebookAccountChooserDialog *self)
 {
-	GtkTreeIter    iter;
+	GtkTreeIter      iter;
 	FacebookAccount *account;
 
 	if (! gtk_combo_box_get_active_iter (GTK_COMBO_BOX (GET_WIDGET ("account_combobox")), &iter))
diff --git a/extensions/facebook/facebook-account-chooser-dialog.h b/extensions/facebook/facebook-account-chooser-dialog.h
index a71ba35..14f92fc 100644
--- a/extensions/facebook/facebook-account-chooser-dialog.h
+++ b/extensions/facebook/facebook-account-chooser-dialog.h
@@ -51,9 +51,9 @@ struct _FacebookAccountChooserDialogClass {
 	GtkDialogClass parent_class;
 };
 
-GType           facebook_account_chooser_dialog_get_type    (void);
-GtkWidget *     facebook_account_chooser_dialog_new         (GList                      *accounts,
-							   FacebookAccount              *default_account);
+GType             facebook_account_chooser_dialog_get_type    (void);
+GtkWidget *       facebook_account_chooser_dialog_new         (GList                        *accounts,
+							       FacebookAccount              *default_account);
 FacebookAccount * facebook_account_chooser_dialog_get_active  (FacebookAccountChooserDialog *self);
 
 G_END_DECLS
diff --git a/extensions/facebook/facebook-account-manager-dialog.c b/extensions/facebook/facebook-account-manager-dialog.c
index 40845c1..3afd680 100644
--- a/extensions/facebook/facebook-account-manager-dialog.c
+++ b/extensions/facebook/facebook-account-manager-dialog.c
@@ -189,7 +189,7 @@ facebook_account_manager_dialog_get_type (void)
 
 static void
 facebook_account_manager_dialog_construct (FacebookAccountManagerDialog *self,
-				         GList                      *accounts)
+				           GList                        *accounts)
 {
 	GtkListStore *list_store;
 	GtkTreeIter   iter;
diff --git a/extensions/facebook/facebook-account-manager-dialog.h b/extensions/facebook/facebook-account-manager-dialog.h
index 02f56ea..2d6b87b 100644
--- a/extensions/facebook/facebook-account-manager-dialog.h
+++ b/extensions/facebook/facebook-account-manager-dialog.h
@@ -51,7 +51,7 @@ struct _FacebookAccountManagerDialogClass {
 };
 
 GType          facebook_account_manager_dialog_get_type     (void);
-GtkWidget *    facebook_account_manager_dialog_new          (GList                      *accounts);
+GtkWidget *    facebook_account_manager_dialog_new          (GList                        *accounts);
 GList *        facebook_account_manager_dialog_get_accounts (FacebookAccountManagerDialog *dialog);
 
 G_END_DECLS
diff --git a/extensions/facebook/facebook-account.c b/extensions/facebook/facebook-account.c
index 0abf778..d0b2300 100644
--- a/extensions/facebook/facebook-account.c
+++ b/extensions/facebook/facebook-account.c
@@ -23,6 +23,9 @@
 #include <config.h>
 #include <stdlib.h>
 #include <string.h>
+#ifdef HAVE_GNOME_KEYRING
+#include <gnome-keyring.h>
+#endif /* HAVE_GNOME_KEYRING */
 #include <gthumb.h>
 #include "facebook-account.h"
 
@@ -37,8 +40,10 @@ facebook_account_finalize (GObject *obj)
 
 	self = FACEBOOK_ACCOUNT (obj);
 
+	g_free (self->user_id);
 	g_free (self->username);
-	g_free (self->token);
+	g_free (self->session_key);
+	g_free (self->secret);
 
 	G_OBJECT_CLASS (facebook_account_parent_class)->finalize (obj);
 }
@@ -57,15 +62,31 @@ facebook_account_create_element (DomDomizable *base,
 			       DomDocument  *doc)
 {
 	FacebookAccount *self;
-	DomElement *element;
+	DomElement      *element;
+	gboolean         set_secret;
 
 	self = FACEBOOK_ACCOUNT (base);
 
 	element = dom_document_create_element (doc, "account", NULL);
+	if (self->user_id != NULL)
+		dom_element_set_attribute (element, "uid", self->user_id);
 	if (self->username != NULL)
 		dom_element_set_attribute (element, "username", self->username);
-	if (self->token != NULL)
-		dom_element_set_attribute (element, "token", self->token);
+
+	/* Don't save the secret in the configuration file if gnome-keyring is
+	 * available. */
+
+	set_secret = TRUE;
+#ifdef HAVE_GNOME_KEYRING
+	if (gnome_keyring_is_available ())
+		set_secret = FALSE;
+#endif
+	if (set_secret) {
+		if (self->session_key != NULL)
+			dom_element_set_attribute (element, "session_key", self->session_key);
+		if (self->secret != NULL)
+			dom_element_set_attribute (element, "secret", self->secret);
+	}
 	if (self->is_default)
 		dom_element_set_attribute (element, "default", "1");
 
@@ -81,8 +102,10 @@ facebook_account_load_from_element (DomDomizable *base,
 
 	self = FACEBOOK_ACCOUNT (base);
 
-	facebook_account_set_username (self, dom_element_get_attribute (element, "username"));
-	facebook_account_set_token (self, dom_element_get_attribute (element, "token"));
+	_g_strset (&self->user_id, dom_element_get_attribute (element, "uid"));
+	_g_strset (&self->username, dom_element_get_attribute (element, "username"));
+	_g_strset (&self->session_key, dom_element_get_attribute (element, "session_key"));
+	_g_strset (&self->secret, dom_element_get_attribute (element, "secret"));
 	self->is_default = (g_strcmp0 (dom_element_get_attribute (element, "default"), "1") == 0);
 }
 
@@ -98,6 +121,11 @@ facebook_account_dom_domizable_interface_init (DomDomizableIface *iface)
 static void
 facebook_account_instance_init (FacebookAccount *self)
 {
+	self->user_id = NULL;
+	self->username = NULL;
+	self->session_key = NULL;
+	self->secret = NULL;
+	self->is_default = FALSE;
 }
 
 
@@ -144,30 +172,40 @@ facebook_account_new (void)
 
 
 void
-facebook_account_set_username (FacebookAccount *self,
-			     const char    *value)
+facebook_account_set_session_key (FacebookAccount *self,
+				  const char      *value)
 {
-	g_free (self->username);
-	self->username = NULL;
-	if (value != NULL)
-		self->username = g_strdup (value);
+	_g_strset (&self->session_key, value);
 }
 
 
 void
-facebook_account_set_token (FacebookAccount *self,
-			  const char    *value)
+facebook_account_set_secret (FacebookAccount *self,
+			     const char      *value)
+{
+	_g_strset (&self->secret, value);
+}
+
+
+void
+facebook_account_set_user_id (FacebookAccount *self,
+			      const char      *value)
+{
+	_g_strset (&self->user_id, value);
+}
+
+
+void
+facebook_account_set_username (FacebookAccount *self,
+			       const char      *value)
 {
-	g_free (self->token);
-	self->token = NULL;
-	if (value != NULL)
-		self->token = g_strdup (value);
+	_g_strset (&self->username, value);
 }
 
 
 int
 facebook_account_cmp (FacebookAccount *a,
-		    FacebookAccount *b)
+		      FacebookAccount *b)
 {
 	if ((a == NULL) && (b == NULL))
 		return 0;
@@ -176,5 +214,5 @@ facebook_account_cmp (FacebookAccount *a,
 	else if (b == NULL)
 		return -1;
 	else
-		return g_strcmp0 (a->username, b->username);
+		return g_strcmp0 (a->user_id, b->user_id);
 }
diff --git a/extensions/facebook/facebook-account.h b/extensions/facebook/facebook-account.h
index 20e7dcd..52ac633 100644
--- a/extensions/facebook/facebook-account.h
+++ b/extensions/facebook/facebook-account.h
@@ -43,8 +43,10 @@ struct _FacebookAccount {
 	GObject parent_instance;
 	FacebookAccountPrivate *priv;
 
+	char     *user_id;
 	char     *username;
-	char     *token;
+	char     *session_key;
+	char     *secret;
 	gboolean  is_default;
 };
 
@@ -52,14 +54,18 @@ struct _FacebookAccountClass {
 	GObjectClass parent_class;
 };
 
-GType             facebook_account_get_type       (void);
-FacebookAccount *   facebook_account_new            (void);
-void              facebook_account_set_username   (FacebookAccount *self,
-						 const char    *value);
-void              facebook_account_set_token      (FacebookAccount *self,
-						 const char    *value);
-int               facebook_account_cmp            (FacebookAccount *a,
-						 FacebookAccount *b);
+GType             facebook_account_get_type         (void);
+FacebookAccount * facebook_account_new              (void);
+void              facebook_account_set_session_key  (FacebookAccount *self,
+						     const char      *value);
+void              facebook_account_set_secret       (FacebookAccount *self,
+						     const char      *value);
+void              facebook_account_set_user_id      (FacebookAccount *self,
+						     const char      *value);
+void              facebook_account_set_username     (FacebookAccount *self,
+						     const char      *value);
+int               facebook_account_cmp              (FacebookAccount *a,
+						     FacebookAccount *b);
 
 G_END_DECLS
 
diff --git a/extensions/facebook/facebook-album-properties-dialog.c b/extensions/facebook/facebook-album-properties-dialog.c
new file mode 100644
index 0000000..fe88d2d
--- /dev/null
+++ b/extensions/facebook/facebook-album-properties-dialog.c
@@ -0,0 +1,202 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2010 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include "facebook-album-properties-dialog.h"
+
+
+#define GET_WIDGET(x) (_gtk_builder_get_widget (self->priv->builder, (x)))
+
+
+static gpointer parent_class = NULL;
+
+
+struct _FacebookAlbumPropertiesDialogPrivate {
+	GtkBuilder *builder;
+};
+
+
+static void
+facebook_album_properties_dialog_finalize (GObject *object)
+{
+	FacebookAlbumPropertiesDialog *self;
+
+	self = FACEBOOK_ALBUM_PROPERTIES_DIALOG (object);
+	_g_object_unref (self->priv->builder);
+
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+static void
+facebook_album_properties_dialog_class_init (FacebookAlbumPropertiesDialogClass *klass)
+{
+	GObjectClass *object_class;
+
+	parent_class = g_type_class_peek_parent (klass);
+	g_type_class_add_private (klass, sizeof (FacebookAlbumPropertiesDialogPrivate));
+
+	object_class = (GObjectClass*) klass;
+	object_class->finalize = facebook_album_properties_dialog_finalize;
+}
+
+
+static void
+facebook_album_properties_dialog_init (FacebookAlbumPropertiesDialog *self)
+{
+	GtkWidget *content;
+
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, FACEBOOK_TYPE_ALBUM_PROPERTIES_DIALOG, FacebookAlbumPropertiesDialogPrivate);
+	self->priv->builder = _gtk_builder_new_from_file ("facebook-album-properties.ui", "facebook");
+
+	gtk_window_set_resizable (GTK_WINDOW (self), FALSE);
+	gtk_dialog_set_has_separator (GTK_DIALOG (self), FALSE);
+	gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (self))), 5);
+	gtk_container_set_border_width (GTK_CONTAINER (self), 5);
+
+	content = _gtk_builder_get_widget (self->priv->builder, "album_properties");
+	gtk_container_set_border_width (GTK_CONTAINER (content), 5);
+  	gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (self))), content, TRUE, TRUE, 0);
+
+	gtk_dialog_add_buttons (GTK_DIALOG (self),
+				GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+				GTK_STOCK_OK, GTK_RESPONSE_OK,
+				NULL);
+	gtk_dialog_set_default_response (GTK_DIALOG (self), GTK_RESPONSE_OK);
+}
+
+
+GType
+facebook_album_properties_dialog_get_type (void)
+{
+	static GType type = 0;
+
+	if (type == 0) {
+		static const GTypeInfo g_define_type_info = {
+			sizeof (FacebookAlbumPropertiesDialogClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) facebook_album_properties_dialog_class_init,
+			(GClassFinalizeFunc) NULL,
+			NULL,
+			sizeof (FacebookAlbumPropertiesDialog),
+			0,
+			(GInstanceInitFunc) facebook_album_properties_dialog_init,
+			NULL
+		};
+		type = g_type_register_static (GTK_TYPE_DIALOG,
+					       "FacebookAlbumPropertiesDialog",
+					       &g_define_type_info,
+					       0);
+	}
+
+	return type;
+}
+
+
+static void
+facebook_album_properties_dialog_construct (FacebookAlbumPropertiesDialog *self,
+				            const char                    *name,
+				            const char                    *location,
+				            const char                    *description,
+				            FacebookVisibility             visibility)
+{
+	int idx;
+
+	if (name != NULL)
+		gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("name_entry")), name);
+	if (location != NULL)
+		gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("location_entry")), location);
+	if (description != NULL)
+		gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("description_entry")), description);
+
+	switch (visibility) {
+	case FACEBOOK_VISIBILITY_EVERYONE:
+		idx = 0;
+		break;
+	case FACEBOOK_VISIBILITY_ALL_FRIENDS:
+		idx = 1;
+		break;
+	case FACEBOOK_VISIBILITY_SELF:
+		idx = 2;
+		break;
+	default:
+		idx = 0;
+		break;
+	}
+	gtk_combo_box_set_active (GTK_COMBO_BOX (GET_WIDGET ("visibility_combobox")), idx);
+}
+
+
+GtkWidget *
+facebook_album_properties_dialog_new (const char         *name,
+				      const char         *location,
+				      const char         *description,
+				      FacebookVisibility  visibility)
+{
+	FacebookAlbumPropertiesDialog *self;
+
+	self = g_object_new (FACEBOOK_TYPE_ALBUM_PROPERTIES_DIALOG, NULL);
+	facebook_album_properties_dialog_construct (self, name, location, description, visibility);
+
+	return (GtkWidget *) self;
+}
+
+
+const char *
+facebook_album_properties_dialog_get_name (FacebookAlbumPropertiesDialog *self)
+{
+	return gtk_entry_get_text (GTK_ENTRY (GET_WIDGET ("name_entry")));
+}
+
+
+const char *
+facebook_album_properties_dialog_get_location (FacebookAlbumPropertiesDialog *self)
+{
+	return gtk_entry_get_text (GTK_ENTRY (GET_WIDGET ("location_entry")));
+}
+
+
+const char *
+facebook_album_properties_dialog_get_description (FacebookAlbumPropertiesDialog *self)
+{
+	return gtk_entry_get_text (GTK_ENTRY (GET_WIDGET ("description_entry")));
+}
+
+
+FacebookVisibility
+facebook_album_properties_dialog_get_visibility (FacebookAlbumPropertiesDialog *self)
+{
+	GtkTreeIter        iter;
+	FacebookVisibility value;
+
+	if (! gtk_combo_box_get_active_iter (GTK_COMBO_BOX (GET_WIDGET ("visibility_combobox")), &iter))
+		return FACEBOOK_VISIBILITY_SELF;
+
+	gtk_tree_model_get (gtk_combo_box_get_model (GTK_COMBO_BOX (GET_WIDGET ("visibility_combobox"))),
+			    &iter,
+			    1, &value,
+			    -1);
+
+	return value;
+}
diff --git a/extensions/facebook/facebook-album-properties-dialog.h b/extensions/facebook/facebook-album-properties-dialog.h
new file mode 100644
index 0000000..bc9d337
--- /dev/null
+++ b/extensions/facebook/facebook-album-properties-dialog.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2010 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef FACEBOOK_ALBUM_PROPERTIES_DIALOG_H
+#define FACEBOOK_ALBUM_PROPERTIES_DIALOG_H
+
+#include <gtk/gtk.h>
+#include <gthumb.h>
+#include "facebook-album.h"
+
+G_BEGIN_DECLS
+
+#define FACEBOOK_TYPE_ALBUM_PROPERTIES_DIALOG            (facebook_album_properties_dialog_get_type ())
+#define FACEBOOK_ALBUM_PROPERTIES_DIALOG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), FACEBOOK_TYPE_ALBUM_PROPERTIES_DIALOG, FacebookAlbumPropertiesDialog))
+#define FACEBOOK_ALBUM_PROPERTIES_DIALOG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), FACEBOOK_TYPE_ALBUM_PROPERTIES_DIALOG, FacebookAlbumPropertiesDialogClass))
+#define FACEBOOK_IS_ALBUM_PROPERTIES_DIALOG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FACEBOOK_TYPE_ALBUM_PROPERTIES_DIALOG))
+#define FACEBOOK_IS_ALBUM_PROPERTIES_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FACEBOOK_TYPE_ALBUM_PROPERTIES_DIALOG))
+#define FACEBOOK_ALBUM_PROPERTIES_DIALOG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), FACEBOOK_TYPE_ALBUM_PROPERTIES_DIALOG, FacebookAlbumPropertiesDialogClass))
+
+typedef struct _FacebookAlbumPropertiesDialog FacebookAlbumPropertiesDialog;
+typedef struct _FacebookAlbumPropertiesDialogClass FacebookAlbumPropertiesDialogClass;
+typedef struct _FacebookAlbumPropertiesDialogPrivate FacebookAlbumPropertiesDialogPrivate;
+
+struct _FacebookAlbumPropertiesDialog {
+	GtkDialog parent_instance;
+	FacebookAlbumPropertiesDialogPrivate *priv;
+};
+
+struct _FacebookAlbumPropertiesDialogClass {
+	GtkDialogClass parent_class;
+};
+
+GType               facebook_album_properties_dialog_get_type        (void);
+GtkWidget *         facebook_album_properties_dialog_new             (const char                    *name,
+								      const char                    *location,
+								      const char                    *description,
+								      FacebookVisibility             visibility);
+const char *        facebook_album_properties_dialog_get_name        (FacebookAlbumPropertiesDialog *self);
+const char *        facebook_album_properties_dialog_get_location    (FacebookAlbumPropertiesDialog *self);
+const char *        facebook_album_properties_dialog_get_description (FacebookAlbumPropertiesDialog *self);
+FacebookVisibility  facebook_album_properties_dialog_get_visibility  (FacebookAlbumPropertiesDialog *self);
+
+G_END_DECLS
+
+#endif /* FACEBOOK_ALBUM_PROPERTIES_DIALOG_H */
diff --git a/extensions/facebook/facebook-album.c b/extensions/facebook/facebook-album.c
index 0573fe5..6e810bd 100644
--- a/extensions/facebook/facebook-album.c
+++ b/extensions/facebook/facebook-album.c
@@ -24,68 +24,51 @@
 #include <stdlib.h>
 #include <string.h>
 #include <gthumb.h>
-#include "facebook-photoset.h"
+#include "facebook-album.h"
 
 
-static gpointer facebook_photoset_parent_class = NULL;
+static gpointer facebook_album_parent_class = NULL;
 
 
 static void
-facebook_photoset_finalize (GObject *obj)
+facebook_album_finalize (GObject *obj)
 {
-	FacebookPhotoset *self;
+	FacebookAlbum *self;
 
-	self = FACEBOOK_PHOTOSET (obj);
+	self = FACEBOOK_ALBUM (obj);
 
 	g_free (self->id);
-	g_free (self->title);
+	g_free (self->name);
 	g_free (self->description);
-	g_free (self->primary);
-	g_free (self->secret);
-	g_free (self->server);
-	g_free (self->farm);
+	g_free (self->location);
+	g_free (self->link);
 
-	G_OBJECT_CLASS (facebook_photoset_parent_class)->finalize (obj);
+	G_OBJECT_CLASS (facebook_album_parent_class)->finalize (obj);
 }
 
 
 static void
-facebook_photoset_class_init (FacebookPhotosetClass *klass)
+facebook_album_class_init (FacebookAlbumClass *klass)
 {
-	facebook_photoset_parent_class = g_type_class_peek_parent (klass);
-	G_OBJECT_CLASS (klass)->finalize = facebook_photoset_finalize;
+	facebook_album_parent_class = g_type_class_peek_parent (klass);
+	G_OBJECT_CLASS (klass)->finalize = facebook_album_finalize;
 }
 
 
 static DomElement*
-facebook_photoset_create_element (DomDomizable *base,
-				DomDocument  *doc)
+facebook_album_create_element (DomDomizable *base,
+			       DomDocument  *doc)
 {
-	FacebookPhotoset *self;
-	DomElement     *element;
-	char           *value;
+	FacebookAlbum *self;
+	DomElement    *element;
 
-	self = FACEBOOK_PHOTOSET (base);
+	self = FACEBOOK_ALBUM (base);
 
 	element = dom_document_create_element (doc, "photoset", NULL);
 	if (self->id != NULL)
-		dom_element_set_attribute (element, "id", self->id);
-	if (self->primary != NULL)
-		dom_element_set_attribute (element, "primary", self->primary);
-	if (self->secret != NULL)
-		dom_element_set_attribute (element, "secret", self->secret);
-	if (self->server != NULL)
-		dom_element_set_attribute (element, "server", self->server);
-	if (self->n_photos >= 0) {
-		value = g_strdup_printf ("%d", self->n_photos);
-		dom_element_set_attribute (element, "photos", value);
-		g_free (value);
-	}
-	if (self->farm != NULL)
-		dom_element_set_attribute (element, "farm", self->farm);
-
-	if (self->title != NULL)
-		dom_element_append_child (element, dom_document_create_element_with_text (doc, self->title, "title", NULL));
+		dom_element_set_attribute (element, "aid", self->id);
+	if (self->name != NULL)
+		dom_element_append_child (element, dom_document_create_element_with_text (doc, self->name, "name", NULL));
 	if (self->description != NULL)
 		dom_element_append_child (element, dom_document_create_element_with_text (doc, self->description, "description", NULL));
 
@@ -93,194 +76,153 @@ facebook_photoset_create_element (DomDomizable *base,
 }
 
 
+static FacebookVisibility
+get_visibility_by_name (const char *name)
+{
+	if (name == NULL)
+		return FACEBOOK_VISIBILITY_EVERYONE;
+	if (g_strcmp0 (name, "everyone") == 0)
+		return FACEBOOK_VISIBILITY_EVERYONE;
+	if (g_strcmp0 (name, "networks_friends") == 0)
+		return FACEBOOK_VISIBILITY_NETWORKS_FRIENDS;
+	if (g_strcmp0 (name, "friends_of_friends") == 0)
+		return FACEBOOK_VISIBILITY_FRIENDS_OF_FRIENDS;
+	if (g_strcmp0 (name, "all_friends") == 0)
+		return FACEBOOK_VISIBILITY_ALL_FRIENDS;
+	if (g_strcmp0 (name, "self") == 0)
+		return FACEBOOK_VISIBILITY_SELF;
+	if (g_strcmp0 (name, "custom") == 0)
+		return FACEBOOK_VISIBILITY_CUSTOM;
+
+	return FACEBOOK_VISIBILITY_EVERYONE;
+}
+
+
 static void
-facebook_photoset_load_from_element (DomDomizable *base,
+facebook_album_load_from_element (DomDomizable *base,
 				   DomElement   *element)
 {
-	FacebookPhotoset *self;
+	FacebookAlbum *self;
 	DomElement     *node;
 
-	self = FACEBOOK_PHOTOSET (base);
+	self = FACEBOOK_ALBUM (base);
 
-	facebook_photoset_set_id (self, dom_element_get_attribute (element, "id"));
-	facebook_photoset_set_title (self, NULL);
-	facebook_photoset_set_description (self, NULL);
-	facebook_photoset_set_n_photos (self, dom_element_get_attribute (element, "photos"));
-	facebook_photoset_set_primary (self, dom_element_get_attribute (element, "primary"));
-	facebook_photoset_set_secret (self, dom_element_get_attribute (element, "secret"));
-	facebook_photoset_set_server (self, dom_element_get_attribute (element, "server"));
-	facebook_photoset_set_farm (self, dom_element_get_attribute (element, "farm"));
-	facebook_photoset_set_url (self, dom_element_get_attribute (element, "url"));
+	_g_strset (&self->id, NULL);
+	_g_strset (&self->name, NULL);
+	_g_strset (&self->description, NULL);
+	_g_strset (&self->location, NULL);
+	_g_strset (&self->link, NULL);
+	self->size = 0;
+	self->visibility = FACEBOOK_VISIBILITY_SELF;
 
 	for (node = element->first_child; node; node = node->next_sibling) {
-		if (g_strcmp0 (node->tag_name, "title") == 0) {
-			facebook_photoset_set_title (self, dom_element_get_inner_text (node));
+		if (g_strcmp0 (node->tag_name, "aid") == 0) {
+			_g_strset (&self->id, dom_element_get_inner_text (node));
+		}
+		else if (g_strcmp0 (node->tag_name, "name") == 0) {
+			_g_strset (&self->name, dom_element_get_inner_text (node));
 		}
 		else if (g_strcmp0 (node->tag_name, "description") == 0) {
-			facebook_photoset_set_description (self, dom_element_get_inner_text (node));
+			_g_strset (&self->description, dom_element_get_inner_text (node));
+		}
+		else if (g_strcmp0 (node->tag_name, "location") == 0) {
+			_g_strset (&self->location, dom_element_get_inner_text (node));
+		}
+		else if (g_strcmp0 (node->tag_name, "link") == 0) {
+			_g_strset (&self->link, dom_element_get_inner_text (node));
+		}
+		else if (g_strcmp0 (node->tag_name, "size") == 0) {
+			self->size = atoi (dom_element_get_inner_text (node));
+		}
+		else if (g_strcmp0 (node->tag_name, "visible") == 0) {
+			self->visibility = get_visibility_by_name (dom_element_get_inner_text (node));
 		}
 	}
 }
 
 
 static void
-facebook_photoset_dom_domizable_interface_init (DomDomizableIface *iface)
+facebook_album_dom_domizable_interface_init (DomDomizableIface *iface)
 {
-	iface->create_element = facebook_photoset_create_element;
-	iface->load_from_element = facebook_photoset_load_from_element;
+	iface->create_element = facebook_album_create_element;
+	iface->load_from_element = facebook_album_load_from_element;
 }
 
 
 static void
-facebook_photoset_instance_init (FacebookPhotoset *self)
+facebook_album_instance_init (FacebookAlbum *self)
 {
 	self->id = NULL;
-	self->title = NULL;
+	self->name = NULL;
 	self->description = NULL;
-	self->primary = NULL;
-	self->secret = NULL;
-	self->server = NULL;
-	self->farm = NULL;
-	self->url = NULL;
+	self->location = NULL;
+	self->link = NULL;
+	self->size = 0;
+	self->visibility = FACEBOOK_VISIBILITY_SELF;
 }
 
 
 GType
-facebook_photoset_get_type (void)
+facebook_album_get_type (void)
 {
-	static GType facebook_photoset_type_id = 0;
+	static GType facebook_album_type_id = 0;
 
-	if (facebook_photoset_type_id == 0) {
+	if (facebook_album_type_id == 0) {
 		static const GTypeInfo g_define_type_info = {
-			sizeof (FacebookPhotosetClass),
+			sizeof (FacebookAlbumClass),
 			(GBaseInitFunc) NULL,
 			(GBaseFinalizeFunc) NULL,
-			(GClassInitFunc) facebook_photoset_class_init,
+			(GClassInitFunc) facebook_album_class_init,
 			(GClassFinalizeFunc) NULL,
 			NULL,
-			sizeof (FacebookPhotoset),
+			sizeof (FacebookAlbum),
 			0,
-			(GInstanceInitFunc) facebook_photoset_instance_init,
+			(GInstanceInitFunc) facebook_album_instance_init,
 			NULL
 		};
 		static const GInterfaceInfo dom_domizable_info = {
-			(GInterfaceInitFunc) facebook_photoset_dom_domizable_interface_init,
+			(GInterfaceInitFunc) facebook_album_dom_domizable_interface_init,
 			(GInterfaceFinalizeFunc) NULL,
 			NULL
 		};
 
-		facebook_photoset_type_id = g_type_register_static (G_TYPE_OBJECT,
-								   "FacebookPhotoset",
-								   &g_define_type_info,
-								   0);
-		g_type_add_interface_static (facebook_photoset_type_id, DOM_TYPE_DOMIZABLE, &dom_domizable_info);
+		facebook_album_type_id = g_type_register_static (G_TYPE_OBJECT,
+								 "FacebookAlbum",
+								 &g_define_type_info,
+								 0);
+		g_type_add_interface_static (facebook_album_type_id, DOM_TYPE_DOMIZABLE, &dom_domizable_info);
 	}
 
-	return facebook_photoset_type_id;
-}
-
-
-FacebookPhotoset *
-facebook_photoset_new (void)
-{
-	return g_object_new (FACEBOOK_TYPE_PHOTOSET, NULL);
-}
-
-
-void
-facebook_photoset_set_id (FacebookPhotoset *self,
-			const char     *value)
-{
-	g_free (self->id);
-	self->id = NULL;
-	if (value != NULL)
-		self->id = g_strdup (value);
-}
-
-
-void
-facebook_photoset_set_title (FacebookPhotoset *self,
-			   const char     *value)
-{
-	g_free (self->title);
-	self->title = NULL;
-	if (value != NULL)
-		self->title = g_strdup (value);
-}
-
-
-void
-facebook_photoset_set_description (FacebookPhotoset *self,
-			         const char     *value)
-{
-	g_free (self->description);
-	self->description = NULL;
-	if (value != NULL)
-		self->description = g_strdup (value);
+	return facebook_album_type_id;
 }
 
 
-void
-facebook_photoset_set_n_photos (FacebookPhotoset *self,
-			      const char     *value)
-{
-	if (value != NULL)
-		self->n_photos = atoi (value);
-	else
-		self->n_photos = 0;
-}
-
-
-void
-facebook_photoset_set_primary (FacebookPhotoset *self,
-			     const char     *value)
-{
-	g_free (self->primary);
-	self->primary = NULL;
-	if (value != NULL)
-		self->primary = g_strdup (value);
-}
-
-
-void
-facebook_photoset_set_secret (FacebookPhotoset *self,
-			    const char     *value)
+FacebookAlbum *
+facebook_album_new (void)
 {
-	g_free (self->secret);
-	self->secret = NULL;
-	if (value != NULL)
-		self->secret = g_strdup (value);
+	return g_object_new (FACEBOOK_TYPE_ALBUM, NULL);
 }
 
 
 void
-facebook_photoset_set_server (FacebookPhotoset *self,
-			    const char     *value)
+facebook_album_set_name (FacebookAlbum *self,
+			 const char    *value)
 {
-	g_free (self->server);
-	self->server = NULL;
-	if (value != NULL)
-		self->server = g_strdup (value);
+	_g_strset (&self->name, value);
 }
 
 
 void
-facebook_photoset_set_farm (FacebookPhotoset *self,
-			  const char     *value)
+facebook_album_set_location (FacebookAlbum *self,
+			     const char    *value)
 {
-	g_free (self->farm);
-	self->farm = NULL;
-	if (value != NULL)
-		self->farm = g_strdup (value);
+	_g_strset (&self->location, value);
 }
 
 
 void
-facebook_photoset_set_url (FacebookPhotoset *self,
-			 const char     *value)
+facebook_album_set_description (FacebookAlbum *self,
+				const char    *value)
 {
-	g_free (self->url);
-	self->url = NULL;
-	if (value != NULL)
-		self->url = g_strdup (value);
+	_g_strset (&self->description, value);
 }
diff --git a/extensions/facebook/facebook-album.h b/extensions/facebook/facebook-album.h
index 7aabea8..a3e3c58 100644
--- a/extensions/facebook/facebook-album.h
+++ b/extensions/facebook/facebook-album.h
@@ -20,63 +20,50 @@
  *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
  */
 
-#ifndef FACEBOOK_PHOTOSET_H
-#define FACEBOOK_PHOTOSET_H
+#ifndef FACEBOOK_ALBUM_H
+#define FACEBOOK_ALBUM_H
 
 #include <glib.h>
 #include <glib-object.h>
+#include "facebook-types.h"
 
 G_BEGIN_DECLS
 
-#define FACEBOOK_TYPE_PHOTOSET            (facebook_photoset_get_type ())
-#define FACEBOOK_PHOTOSET(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), FACEBOOK_TYPE_PHOTOSET, FacebookPhotoset))
-#define FACEBOOK_PHOTOSET_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), FACEBOOK_TYPE_PHOTOSET, FacebookPhotosetClass))
-#define FACEBOOK_IS_PHOTOSET(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FACEBOOK_TYPE_PHOTOSET))
-#define FACEBOOK_IS_PHOTOSET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FACEBOOK_TYPE_PHOTOSET))
-#define FACEBOOK_PHOTOSET_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), FACEBOOK_TYPE_PHOTOSET, FacebookPhotosetClass))
+#define FACEBOOK_TYPE_ALBUM            (facebook_album_get_type ())
+#define FACEBOOK_ALBUM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), FACEBOOK_TYPE_ALBUM, FacebookAlbum))
+#define FACEBOOK_ALBUM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), FACEBOOK_TYPE_ALBUM, FacebookAlbumClass))
+#define FACEBOOK_IS_ALBUM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FACEBOOK_TYPE_ALBUM))
+#define FACEBOOK_IS_ALBUM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FACEBOOK_TYPE_ALBUM))
+#define FACEBOOK_ALBUM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), FACEBOOK_TYPE_ALBUM, FacebookAlbumClass))
 
-typedef struct _FacebookPhotoset FacebookPhotoset;
-typedef struct _FacebookPhotosetClass FacebookPhotosetClass;
+typedef struct _FacebookAlbum FacebookAlbum;
+typedef struct _FacebookAlbumClass FacebookAlbumClass;
 
-struct _FacebookPhotoset {
+struct _FacebookAlbum {
 	GObject parent_instance;
 
-	char *id;
-	char *title;
-	char *description;
-	int   n_photos;
-	char *primary;
-	char *secret;
-	char *server;
-	char *farm;
-	char *url;
+	char               *id;
+	char               *name;
+	char               *location;
+	char               *description;
+	char               *link;
+	int                 size;
+	FacebookVisibility  visibility;
 };
 
-struct _FacebookPhotosetClass {
+struct _FacebookAlbumClass {
 	GObjectClass parent_class;
 };
 
-GType             facebook_photoset_get_type          (void);
-FacebookPhotoset *  facebook_photoset_new               (void);
-void              facebook_photoset_set_id            (FacebookPhotoset *self,
-						     const char     *value);
-void              facebook_photoset_set_title         (FacebookPhotoset *self,
-						     const char     *value);
-void              facebook_photoset_set_description   (FacebookPhotoset *self,
-						     const char     *value);
-void              facebook_photoset_set_n_photos      (FacebookPhotoset *self,
-						     const char     *value);
-void              facebook_photoset_set_primary       (FacebookPhotoset *self,
-						     const char     *value);
-void              facebook_photoset_set_secret        (FacebookPhotoset *self,
-						     const char     *value);
-void              facebook_photoset_set_server        (FacebookPhotoset *self,
-						     const char     *value);
-void              facebook_photoset_set_farm          (FacebookPhotoset *self,
-						     const char     *value);
-void              facebook_photoset_set_url           (FacebookPhotoset *self,
-						     const char     *value);
+GType           facebook_album_get_type        (void);
+FacebookAlbum * facebook_album_new             (void);
+void            facebook_album_set_name        (FacebookAlbum *self,
+					        const char    *value);
+void            facebook_album_set_location    (FacebookAlbum *self,
+					        const char    *value);
+void            facebook_album_set_description (FacebookAlbum *self,
+						const char    *value);
 
 G_END_DECLS
 
-#endif /* FACEBOOK_PHOTOSET_H */
+#endif /* FACEBOOK_ALBUM_H */
diff --git a/extensions/facebook/facebook-authentication.c b/extensions/facebook/facebook-authentication.c
new file mode 100644
index 0000000..d8a11a3
--- /dev/null
+++ b/extensions/facebook/facebook-authentication.c
@@ -0,0 +1,733 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2010 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <glib.h>
+#ifdef HAVE_GNOME_KEYRING
+#include <gnome-keyring.h>
+#endif /* HAVE_GNOME_KEYRING */
+#include "facebook-account-chooser-dialog.h"
+#include "facebook-account-manager-dialog.h"
+#include "facebook-authentication.h"
+#include "facebook-user.h"
+#include "facebook-service.h"
+
+
+#define SECRET_SEPARATOR ("::")
+
+
+/* Signals */
+enum {
+	READY,
+	ACCOUNTS_CHANGED,
+	LAST_SIGNAL
+};
+
+struct _FacebookAuthenticationPrivate
+{
+	FacebookConnection *conn;
+	FacebookService    *service;
+	GCancellable       *cancellable;
+	GList              *accounts;
+	FacebookAccount    *account;
+	GtkWidget          *browser;
+	GtkWidget          *dialog;
+};
+
+
+static GObjectClass *parent_class = NULL;
+static guint facebook_authentication_signals[LAST_SIGNAL] = { 0 };
+
+
+GQuark
+facebook_authentication_error_quark (void)
+{
+	return g_quark_from_static_string ("facebook-authentication-error-quark");
+}
+
+
+static void
+facebook_authentication_finalize (GObject *object)
+{
+	FacebookAuthentication *self;
+
+	self = FACEBOOK_AUTHENTICATION (object);
+	_g_object_unref (self->priv->conn);
+	_g_object_unref (self->priv->service);
+	_g_object_unref (self->priv->cancellable);
+	_g_object_list_unref (self->priv->accounts);
+	_g_object_unref (self->priv->account);
+
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+static void
+facebook_authentication_class_init (FacebookAuthenticationClass *class)
+{
+	GObjectClass *object_class;
+
+	parent_class = g_type_class_peek_parent (class);
+	g_type_class_add_private (class, sizeof (FacebookAuthenticationPrivate));
+
+	object_class = (GObjectClass*) class;
+	object_class->finalize = facebook_authentication_finalize;
+
+	/* signals */
+
+	facebook_authentication_signals[READY] =
+		g_signal_new ("ready",
+			      G_TYPE_FROM_CLASS (class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (FacebookAuthenticationClass, ready),
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__OBJECT,
+			      G_TYPE_NONE,
+			      1,
+			      G_TYPE_OBJECT);
+	facebook_authentication_signals[ACCOUNTS_CHANGED] =
+		g_signal_new ("accounts_changed",
+			      G_TYPE_FROM_CLASS (class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (FacebookAuthenticationClass, accounts_changed),
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__VOID,
+			      G_TYPE_NONE,
+			      0);
+}
+
+
+static void
+facebook_authentication_init (FacebookAuthentication *self)
+{
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, FACEBOOK_TYPE_AUTHENTICATION, FacebookAuthenticationPrivate);
+	self->priv->conn = NULL;
+	self->priv->accounts = NULL;
+	self->priv->account = NULL;
+}
+
+
+GType
+facebook_authentication_get_type (void)
+{
+	static GType type = 0;
+
+	if (! type) {
+		GTypeInfo type_info = {
+			sizeof (GthTaskClass),
+			NULL,
+			NULL,
+			(GClassInitFunc) facebook_authentication_class_init,
+			NULL,
+			NULL,
+			sizeof (GthTask),
+			0,
+			(GInstanceInitFunc) facebook_authentication_init
+		};
+
+		type = g_type_register_static (G_TYPE_OBJECT,
+					       "FacebookAuthentication",
+					       &type_info,
+					       0);
+	}
+
+	return type;
+}
+
+
+FacebookAuthentication *
+facebook_authentication_new (FacebookConnection *conn,
+			     FacebookService    *service,
+			     GCancellable       *cancellable,
+			     GtkWidget          *browser,
+			     GtkWidget          *dialog)
+{
+	FacebookAuthentication *self;
+
+	g_return_val_if_fail (conn != NULL, NULL);
+
+	self = (FacebookAuthentication *) g_object_new (FACEBOOK_TYPE_AUTHENTICATION, NULL);
+	self->priv->conn = g_object_ref (conn);
+	self->priv->service = g_object_ref (service);
+	self->priv->cancellable = _g_object_ref (cancellable);
+	self->priv->accounts = facebook_accounts_load_from_file ();
+	self->priv->account = facebook_accounts_find_default (self->priv->accounts);
+	self->priv->browser = browser;
+	self->priv->dialog = dialog;
+
+	return self;
+}
+
+
+/* -- facebook_authentication_auto_connect -- */
+
+
+static void
+get_user_info_ready_cb (GObject      *source_object,
+			GAsyncResult *res,
+			gpointer      user_data)
+{
+	FacebookAuthentication *self = user_data;
+	FacebookUser           *user;
+	GError                 *error = NULL;
+
+	user = facebook_service_get_user_info_finish (FACEBOOK_SERVICE (source_object), res, &error);
+	if (error != NULL) {
+		if (self->priv->conn != NULL)
+			gth_task_dialog (GTH_TASK (self->priv->conn), TRUE);
+		_gtk_error_dialog_from_gerror_run (GTK_WINDOW (self->priv->browser), _("Could not connect to the server"), &error);
+		gtk_widget_destroy (self->priv->dialog);
+		return;
+	}
+
+	facebook_account_set_username (self->priv->account, user->username);
+	facebook_accounts_save_to_file (self->priv->accounts, self->priv->account);
+
+	g_signal_emit (self, facebook_authentication_signals[READY], 0, user);
+
+	g_object_unref (user);
+}
+
+
+static void start_authorization_process (FacebookAuthentication *self);
+
+
+static void
+get_logged_in_user_ready_cb (GObject      *source_object,
+			     GAsyncResult *res,
+			     gpointer      user_data)
+{
+	FacebookAuthentication *self = user_data;
+	char                   *uid;
+	GError                 *error = NULL;
+
+	uid = facebook_service_get_logged_in_user_finish (FACEBOOK_SERVICE (source_object), res, &error);
+	if (error != NULL) {
+		if (self->priv->conn != NULL)
+			gth_task_dialog (GTH_TASK (self->priv->conn), TRUE);
+		_gtk_error_dialog_from_gerror_run (GTK_WINDOW (self->priv->browser), _("Could not connect to the server"), &error);
+		gtk_widget_destroy (self->priv->dialog);
+		return;
+	}
+
+	if (g_strcmp0 (uid, self->priv->account->user_id) == 0) {
+		FacebookUser *user;
+
+		user = facebook_user_new ();
+		facebook_user_set_id (user, uid);
+		facebook_user_set_username (user, self->priv->account->username);
+		g_signal_emit (self, facebook_authentication_signals[READY], 0, user);
+
+		g_object_unref (user);
+	}
+	else {
+		/* Authorization required */
+		start_authorization_process (self);
+	}
+
+	g_free (uid);
+}
+
+
+static void
+connect_to_server_step2 (FacebookAuthentication *self)
+{
+	if ((self->priv->account->session_key == NULL) || (self->priv->account->secret == NULL)) {
+		start_authorization_process (self);
+		return;
+	}
+	facebook_connection_set_session (self->priv->conn,
+					 self->priv->account->session_key,
+					 self->priv->account->secret);
+	if (self->priv->account->username == NULL)
+		facebook_service_get_user_info (self->priv->service,
+						"first_name,middle_name,last_name,name",
+						self->priv->cancellable,
+						get_user_info_ready_cb,
+						self);
+	else
+		facebook_service_get_logged_in_user (self->priv->service,
+						     self->priv->cancellable,
+						     get_logged_in_user_ready_cb,
+						     self);
+}
+
+
+#ifdef HAVE_GNOME_KEYRING
+static void
+find_password_cb (GnomeKeyringResult  result,
+                  const char         *string,
+                  gpointer            user_data)
+{
+	FacebookAuthentication *self = user_data;
+
+	if (string != NULL) {
+		char **values;
+
+		values = g_strsplit (string, SECRET_SEPARATOR, 2);
+		if ((values[0] != NULL) && (values[1] != NULL)) {
+			self->priv->account->session_key = g_strdup (values[0]);
+			self->priv->account->secret = g_strdup (values[1]);
+		}
+
+		g_strfreev (values);
+	}
+
+	connect_to_server_step2 (self);
+}
+#endif
+
+
+static void
+connect_to_server (FacebookAuthentication *self)
+{
+	g_return_if_fail (self->priv->account != NULL);
+
+#ifdef HAVE_GNOME_KEYRING
+	if (((self->priv->account->session_key == NULL) || (self->priv->account->secret == NULL)) && gnome_keyring_is_available ()) {
+		gnome_keyring_find_password (GNOME_KEYRING_NETWORK_PASSWORD,
+					     find_password_cb,
+					     self,
+					     NULL,
+					     "user", self->priv->account->user_id,
+					     "server", FACEBOOK_HTTPS_REST_SERVER,
+					     "protocol", "https",
+					     NULL);
+		return;
+	}
+#endif
+
+	connect_to_server_step2 (self);
+}
+
+
+static void
+set_account (FacebookAuthentication *self,
+	     FacebookAccount        *account)
+{
+	GList *link;
+
+	link = g_list_find_custom (self->priv->accounts, self->priv->account, (GCompareFunc) facebook_account_cmp);
+	if (link != NULL) {
+		self->priv->accounts = g_list_remove_link (self->priv->accounts, link);
+		_g_object_list_unref (link);
+	}
+
+	_g_object_unref (self->priv->account);
+	self->priv->account = NULL;
+
+	if (account != NULL) {
+		self->priv->account = g_object_ref (account);
+		self->priv->accounts = g_list_prepend (self->priv->accounts, g_object_ref (self->priv->account));
+	}
+}
+
+
+#ifdef HAVE_GNOME_KEYRING
+static void
+store_password_done_cb (GnomeKeyringResult result,
+			gpointer           user_data)
+{
+	FacebookAuthentication *self = user_data;
+	connect_to_server (self);
+}
+#endif
+
+
+static void
+get_session_ready_cb (GObject      *source_object,
+		      GAsyncResult *res,
+		      gpointer      user_data)
+{
+	FacebookAuthentication *self = user_data;
+	GError                 *error = NULL;
+	FacebookAccount        *account;
+
+	if (! facebook_connection_get_session_finish (FACEBOOK_CONNECTION (source_object), res, &error)) {
+		if (self->priv->conn != NULL)
+			gth_task_dialog (GTH_TASK (self->priv->conn), TRUE);
+		_gtk_error_dialog_from_gerror_run (GTK_WINDOW (self->priv->browser), _("Could not connect to the server"), &error);
+		gtk_widget_destroy (self->priv->dialog);
+		return;
+	}
+
+	account = facebook_account_new ();
+	facebook_account_set_session_key (account, facebook_connection_get_session_key (self->priv->conn));
+	facebook_account_set_secret (account, facebook_connection_get_secret (self->priv->conn));
+	facebook_account_set_user_id (account, facebook_connection_get_user_id (self->priv->conn));
+	set_account (self, account);
+	g_object_unref (account);
+
+#ifdef HAVE_GNOME_KEYRING
+	if (gnome_keyring_is_available ()) {
+		char *secret;
+
+		secret = g_strconcat (facebook_connection_get_session_key (self->priv->conn),
+				      SECRET_SEPARATOR,
+				      facebook_connection_get_secret (self->priv->conn),
+				      NULL);
+		gnome_keyring_store_password (GNOME_KEYRING_NETWORK_PASSWORD,
+					      GNOME_KEYRING_SESSION,
+					      "Facebook",
+					      secret,
+					      store_password_done_cb,
+					      self,
+					      NULL,
+					      "user", facebook_connection_get_user_id (self->priv->conn),
+					      "server", FACEBOOK_HTTPS_REST_SERVER,
+					      "protocol", "https",
+					      NULL);
+		g_free (secret);
+		return;
+	}
+#endif
+
+	connect_to_server (self);
+}
+
+
+static void
+complete_authorization_messagedialog_response_cb (GtkDialog *dialog,
+						  int        response_id,
+						  gpointer   user_data)
+{
+	FacebookAuthentication *self = user_data;
+
+	switch (response_id) {
+	case GTK_RESPONSE_HELP:
+		show_help_dialog (GTK_WINDOW (dialog), "facebook-complete-authorization");
+		break;
+
+	case GTK_RESPONSE_DELETE_EVENT:
+	case GTK_RESPONSE_CANCEL:
+		gtk_widget_destroy (GTK_WIDGET (dialog));
+		gtk_widget_destroy (self->priv->dialog);
+		break;
+
+	case GTK_RESPONSE_OK:
+		gtk_widget_destroy (GTK_WIDGET (dialog));
+		gth_task_dialog (GTH_TASK (self->priv->conn), FALSE);
+		facebook_connection_get_session (self->priv->conn,
+						 self->priv->cancellable,
+						 get_session_ready_cb,
+						 self);
+		break;
+
+	default:
+		break;
+	}
+}
+
+
+static void
+complete_authorization (FacebookAuthentication *self)
+{
+	GtkBuilder *builder;
+	GtkWidget  *dialog;
+	char       *text;
+	char       *secondary_text;
+
+	gth_task_dialog (GTH_TASK (self->priv->conn), TRUE);
+
+	builder = _gtk_builder_new_from_file ("facebook-complete-authorization.ui", "facebook");
+	dialog = _gtk_builder_get_widget (builder, "complete_authorization_messagedialog");
+	text = g_strdup_printf (_("Return to this window when you have finished the authorization process on %s"), "Facebook");
+	secondary_text = g_strdup (_("Once you're done, click the 'Continue' button below."));
+	g_object_set (dialog, "text", text, "secondary-text", secondary_text, NULL);
+	g_object_set_data_full (G_OBJECT (dialog), "builder", builder, g_object_unref);
+	g_signal_connect (dialog,
+			  "response",
+			  G_CALLBACK (complete_authorization_messagedialog_response_cb),
+			  self);
+
+	if (GTK_WIDGET_VISIBLE (self->priv->dialog))
+		gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (self->priv->dialog));
+	else
+		gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (self->priv->browser));
+	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+	gtk_window_present (GTK_WINDOW (dialog));
+
+	g_free (secondary_text);
+	g_free (text);
+}
+
+
+static void
+ask_authorization_messagedialog_response_cb (GtkDialog *dialog,
+					     int        response_id,
+					     gpointer   user_data)
+{
+	FacebookAuthentication *self = user_data;
+
+	switch (response_id) {
+	case GTK_RESPONSE_HELP:
+		show_help_dialog (GTK_WINDOW (dialog), "facebook-ask-authorization");
+		break;
+
+	case GTK_RESPONSE_DELETE_EVENT:
+	case GTK_RESPONSE_CANCEL:
+		gtk_widget_destroy (GTK_WIDGET (dialog));
+		gtk_widget_destroy (self->priv->dialog);
+		break;
+
+	case GTK_RESPONSE_OK:
+		{
+			char   *url;
+			GError *error = NULL;
+
+			gtk_widget_destroy (GTK_WIDGET (dialog));
+
+			url = facebook_connection_get_login_link (self->priv->conn, FACEBOOK_ACCESS_WRITE);
+			if (gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (dialog)), url, 0, &error)) {
+				complete_authorization (self);
+			}
+			else {
+				if (self->priv->conn != NULL)
+					gth_task_dialog (GTH_TASK (self->priv->conn), TRUE);
+				_gtk_error_dialog_from_gerror_run (GTK_WINDOW (self->priv->browser), _("Could not connect to the server"), &error);
+				gtk_widget_destroy (self->priv->dialog);
+			}
+
+			g_free (url);
+		}
+		break;
+
+	default:
+		break;
+	}
+}
+
+
+static void
+ask_authorization (FacebookAuthentication *self)
+{
+	GtkBuilder *builder;
+	GtkWidget  *dialog;
+	char       *text;
+	char       *secondary_text;
+
+	gth_task_dialog (GTH_TASK (self->priv->conn), TRUE);
+
+	builder = _gtk_builder_new_from_file ("facebook-ask-authorization.ui", "facebook");
+	dialog = _gtk_builder_get_widget (builder, "ask_authorization_messagedialog");
+	if (GTK_WIDGET_VISIBLE (self->priv->dialog))
+		gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (self->priv->dialog));
+	else
+		gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (self->priv->browser));
+
+	text = g_strdup_printf (_("gthumb requires your authorization to upload the photos to %s"), "Facebook");
+	secondary_text = g_strdup_printf (_("Click 'Authorize' to open your web browser and authorize gthumb to upload photos to %s. When you're finished, return to this window to complete the authorization."), "Facebook");
+	g_object_set (dialog, "text", text, "secondary-text", secondary_text, NULL);
+	g_object_set_data_full (G_OBJECT (dialog), "builder", builder, g_object_unref);
+	g_signal_connect (dialog,
+			  "response",
+			  G_CALLBACK (ask_authorization_messagedialog_response_cb),
+			  self);
+
+	gtk_widget_show (dialog);
+
+	g_free (secondary_text);
+	g_free (text);
+}
+
+
+static void
+create_token_ready_cb (GObject      *source_object,
+		       GAsyncResult *res,
+		       gpointer      user_data)
+{
+	FacebookAuthentication *self = user_data;
+	GError               *error = NULL;
+
+	if (! facebook_connection_create_token_finish (FACEBOOK_CONNECTION (source_object), res, &error)) {
+		if (self->priv->conn != NULL)
+			gth_task_dialog (GTH_TASK (self->priv->conn), TRUE);
+		_gtk_error_dialog_from_gerror_run (GTK_WINDOW (self->priv->browser), _("Could not connect to the server"), &error);
+		gtk_widget_destroy (self->priv->dialog);
+		return;
+	}
+
+	ask_authorization (self);
+}
+
+
+static void
+start_authorization_process (FacebookAuthentication *self)
+{
+	facebook_connection_create_token (self->priv->conn,
+					  self->priv->cancellable,
+					  create_token_ready_cb,
+					  self);
+}
+
+
+static void
+account_chooser_dialog_response_cb (GtkDialog *dialog,
+				    int        response_id,
+				    gpointer   user_data)
+{
+	FacebookAuthentication *self = user_data;
+
+	switch (response_id) {
+	case GTK_RESPONSE_DELETE_EVENT:
+	case GTK_RESPONSE_CANCEL:
+		gtk_widget_destroy (GTK_WIDGET (dialog));
+		gtk_widget_destroy (self->priv->dialog);
+		break;
+
+	case GTK_RESPONSE_OK:
+		_g_object_unref (self->priv->account);
+		self->priv->account = facebook_account_chooser_dialog_get_active (FACEBOOK_ACCOUNT_CHOOSER_DIALOG (dialog));
+		if (self->priv->account != NULL) {
+			gtk_widget_destroy (GTK_WIDGET (dialog));
+			connect_to_server (self);
+		}
+
+		break;
+
+	case FACEBOOK_ACCOUNT_CHOOSER_RESPONSE_NEW:
+		gtk_widget_destroy (GTK_WIDGET (dialog));
+		start_authorization_process (self);
+		break;
+
+	default:
+		break;
+	}
+}
+
+
+void
+facebook_authentication_auto_connect (FacebookAuthentication *self)
+{
+	gtk_widget_hide (self->priv->dialog);
+	gth_task_dialog (GTH_TASK (self->priv->conn), FALSE);
+
+	if (self->priv->accounts != NULL) {
+		if (self->priv->account != NULL) {
+			connect_to_server (self);
+		}
+		else if (self->priv->accounts->next == NULL) {
+			self->priv->account = g_object_ref (self->priv->accounts->data);
+			connect_to_server (self);
+		}
+		else {
+			GtkWidget *dialog;
+
+			gth_task_dialog (GTH_TASK (self->priv->conn), TRUE);
+			dialog = facebook_account_chooser_dialog_new (self->priv->accounts, self->priv->account);
+			g_signal_connect (dialog,
+					  "response",
+					  G_CALLBACK (account_chooser_dialog_response_cb),
+					  self);
+
+			gtk_window_set_title (GTK_WINDOW (dialog), _("Choose Account"));
+			gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (self->priv->browser));
+			gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+			gtk_window_present (GTK_WINDOW (dialog));
+		}
+	}
+	else
+		start_authorization_process (self);
+}
+
+
+void
+facebook_authentication_connect (FacebookAuthentication *self,
+			         FacebookAccount        *account)
+{
+	set_account (self, account);
+	facebook_authentication_auto_connect (self);
+}
+
+
+FacebookAccount *
+facebook_authentication_get_account (FacebookAuthentication *self)
+{
+	return self->priv->account;
+}
+
+
+GList *
+facebook_authentication_get_accounts (FacebookAuthentication *self)
+{
+	return self->priv->accounts;
+}
+
+
+/* -- facebook_authentication_edit_accounts -- */
+
+
+static void
+account_manager_dialog_response_cb (GtkDialog *dialog,
+			            int        response_id,
+			            gpointer   user_data)
+{
+	FacebookAuthentication *self = user_data;
+
+	switch (response_id) {
+	case GTK_RESPONSE_DELETE_EVENT:
+	case GTK_RESPONSE_CANCEL:
+		gtk_widget_destroy (GTK_WIDGET (dialog));
+		break;
+
+	case GTK_RESPONSE_OK:
+		_g_object_list_unref (self->priv->accounts);
+		self->priv->accounts = facebook_account_manager_dialog_get_accounts (FACEBOOK_ACCOUNT_MANAGER_DIALOG (dialog));
+		if (! g_list_find_custom (self->priv->accounts, self->priv->account, (GCompareFunc) facebook_account_cmp)) {
+			_g_object_unref (self->priv->account);
+			self->priv->account = NULL;
+			facebook_authentication_auto_connect (self);
+		}
+		else
+			g_signal_emit (self, facebook_authentication_signals[ACCOUNTS_CHANGED], 0);
+		facebook_accounts_save_to_file (self->priv->accounts, self->priv->account);
+		gtk_widget_destroy (GTK_WIDGET (dialog));
+		break;
+
+	case FACEBOOK_ACCOUNT_MANAGER_RESPONSE_NEW:
+		gtk_widget_destroy (GTK_WIDGET (dialog));
+		start_authorization_process (self);
+		break;
+
+	default:
+		break;
+	}
+}
+
+
+void
+facebook_authentication_edit_accounts (FacebookAuthentication *self,
+				       GtkWindow              *parent)
+{
+	GtkWidget  *dialog;
+
+	dialog = facebook_account_manager_dialog_new (self->priv->accounts);
+	g_signal_connect (dialog,
+			  "response",
+			  G_CALLBACK (account_manager_dialog_response_cb),
+			  self);
+
+	gtk_window_set_title (GTK_WINDOW (dialog), _("Edit Accounts"));
+	gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (self->priv->dialog));
+	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+	gtk_window_present (GTK_WINDOW (dialog));
+}
diff --git a/extensions/facebook/facebook-authentication.h b/extensions/facebook/facebook-authentication.h
new file mode 100644
index 0000000..499066c
--- /dev/null
+++ b/extensions/facebook/facebook-authentication.h
@@ -0,0 +1,77 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2010 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef FACEBOOK_AUTHENTICATION_H
+#define FACEBOOK_AUTHENTICATION_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include "facebook-account.h"
+#include "facebook-connection.h"
+#include "facebook-service.h"
+#include "facebook-user.h"
+
+G_BEGIN_DECLS
+
+#define FACEBOOK_TYPE_AUTHENTICATION            (facebook_authentication_get_type ())
+#define FACEBOOK_AUTHENTICATION(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), FACEBOOK_TYPE_AUTHENTICATION, FacebookAuthentication))
+#define FACEBOOK_AUTHENTICATION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), FACEBOOK_TYPE_AUTHENTICATION, FacebookAuthenticationClass))
+#define FACEBOOK_IS_AUTHENTICATION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FACEBOOK_TYPE_AUTHENTICATION))
+#define FACEBOOK_IS_AUTHENTICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FACEBOOK_TYPE_AUTHENTICATION))
+#define FACEBOOK_AUTHENTICATION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), FACEBOOK_TYPE_AUTHENTICATION, FacebookAuthenticationClass))
+
+typedef struct _FacebookAuthentication FacebookAuthentication;
+typedef struct _FacebookAuthenticationClass FacebookAuthenticationClass;
+typedef struct _FacebookAuthenticationPrivate FacebookAuthenticationPrivate;
+
+struct _FacebookAuthentication {
+	GObject parent_instance;
+	FacebookAuthenticationPrivate *priv;
+};
+
+struct _FacebookAuthenticationClass {
+	GObjectClass parent_class;
+
+	/*< signals >*/
+
+	void  (*ready)             (FacebookAuthentication *auth,
+				    FacebookUser           *user);
+	void  (*accounts_changed)  (FacebookAuthentication *auth);
+};
+
+GType                     facebook_authentication_get_type       (void);
+FacebookAuthentication *  facebook_authentication_new            (FacebookConnection     *conn,
+								  FacebookService        *service,
+								  GCancellable           *cancellable,
+								  GtkWidget              *browser,
+								  GtkWidget              *dialog);
+void                      facebook_authentication_auto_connect   (FacebookAuthentication *auth);
+void                      facebook_authentication_connect        (FacebookAuthentication *auth,
+								  FacebookAccount        *account);
+FacebookAccount *         facebook_authentication_get_account    (FacebookAuthentication *auth);
+GList *                   facebook_authentication_get_accounts   (FacebookAuthentication *auth);
+void                      facebook_authentication_edit_accounts  (FacebookAuthentication *auth,
+								  GtkWindow              *parent);
+
+G_END_DECLS
+
+#endif /* FACEBOOK_AUTHENTICATION_H */
diff --git a/extensions/facebook/facebook-connection.c b/extensions/facebook/facebook-connection.c
index a5b54b9..1f57ec9 100644
--- a/extensions/facebook/facebook-connection.c
+++ b/extensions/facebook/facebook-connection.c
@@ -28,9 +28,10 @@
 #include "facebook-user.h"
 
 
-#undef DEBUG_FACEBOOK_CONNECTION
-#define GTHUMB_FACEBOOK_API_KEY "8960706ee7f4151e893b11837e9c24ce"
-#define GTHUMB_FACEBOOK_SHARED_SECRET "1ff8d1e45c873423"
+#define DEBUG_FACEBOOK_CONNECTION 1
+#define GTHUMB_FACEBOOK_API_KEY "1536ca726857c69843423d0312b9b356"
+#define GTHUMB_FACEBOOK_SHARED_SECRET "8c0b99672a9bbc159ebec3c9a8240679"
+#define FACEBOOK_API_VERSION "1.0"
 
 
 GQuark
@@ -39,7 +40,7 @@ facebook_connection_error_quark (void)
 	static GQuark quark;
 
         if (!quark)
-                quark = g_quark_from_static_string ("facebook_connection");
+                quark = g_quark_from_static_string ("facebook-connection-error");
 
         return quark;
 }
@@ -51,13 +52,14 @@ facebook_connection_error_quark (void)
 struct _FacebookConnectionPrivate
 {
 	SoupSession        *session;
-	char               *frob;
 	char               *token;
-	char               *username;
+	char               *secret;
+	char               *session_key;
 	char               *user_id;
 	GCancellable       *cancellable;
 	GSimpleAsyncResult *result;
 	GChecksum          *checksum;
+	char               *call_id;
 };
 
 
@@ -71,13 +73,14 @@ facebook_connection_finalize (GObject *object)
 
 	self = FACEBOOK_CONNECTION (object);
 
+	g_free (self->priv->call_id);
 	g_checksum_free (self->priv->checksum);
 	_g_object_unref (self->priv->result);
 	_g_object_unref (self->priv->cancellable);
 	g_free (self->priv->user_id);
-	g_free (self->priv->username);
+	g_free (self->priv->session_key);
+	g_free (self->priv->secret);
 	g_free (self->priv->token);
-	g_free (self->priv->frob);
 	_g_object_unref (self->priv->session);
 
 	G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -121,13 +124,14 @@ facebook_connection_init (FacebookConnection *self)
 {
 	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, FACEBOOK_TYPE_CONNECTION, FacebookConnectionPrivate);
 	self->priv->session = NULL;
-	self->priv->username = NULL;
-	self->priv->user_id = NULL;
 	self->priv->token = NULL;
-	self->priv->frob = NULL;
+	self->priv->secret = NULL;
+	self->priv->session_key = NULL;
+	self->priv->user_id = NULL;
 	self->priv->cancellable = NULL;
 	self->priv->result = NULL;
 	self->priv->checksum = g_checksum_new (G_CHECKSUM_MD5);
+	self->priv->call_id = NULL;
 }
 
 
@@ -167,14 +171,14 @@ facebook_connection_new (void)
 
 
 void
-facebook_connection_send_message (FacebookConnection    *self,
-				SoupMessage         *msg,
-				GCancellable        *cancellable,
-				GAsyncReadyCallback  callback,
-				gpointer             user_data,
-				gpointer             source_tag,
-				SoupSessionCallback  soup_session_cb,
-				gpointer             soup_session_cb_data)
+facebook_connection_send_message (FacebookConnection  *self,
+				  SoupMessage         *msg,
+				  GCancellable        *cancellable,
+				  GAsyncReadyCallback  callback,
+				  gpointer             user_data,
+				  gpointer             source_tag,
+				  SoupSessionCallback  soup_session_cb,
+				  gpointer             soup_session_cb_data)
 {
 	if (self->priv->session == NULL) {
 		self->priv->session = soup_session_async_new_with_options (
@@ -228,56 +232,75 @@ facebook_connection_reset_result (FacebookConnection *self)
 
 void
 facebook_connection_add_api_sig (FacebookConnection *self,
-			       GHashTable       *data_set)
+			         GHashTable         *data_set)
 {
 	GList *keys;
 	GList *scan;
 
 	g_hash_table_insert (data_set, "api_key", GTHUMB_FACEBOOK_API_KEY);
-	if (self->priv->token != NULL)
-		g_hash_table_insert (data_set, "auth_token", self->priv->token);
+	g_hash_table_insert (data_set, "v", FACEBOOK_API_VERSION);
+	g_hash_table_insert (data_set, "format", "XML");
 
-	g_checksum_reset (self->priv->checksum);
-	g_checksum_update (self->priv->checksum, (guchar *) GTHUMB_FACEBOOK_SHARED_SECRET, -1);
+	if (self->priv->session_key != NULL) {
+		GTimeVal current_time;
 
+		g_hash_table_insert (data_set, "session_key", self->priv->session_key);
+		g_hash_table_insert (data_set, "ss", "true");
+
+		g_free (self->priv->call_id);
+		g_get_current_time (&current_time);
+		self->priv->call_id = g_strdup_printf ("%ld.%ld", current_time.tv_sec, current_time.tv_usec);
+		g_hash_table_insert (data_set, "call_id", self->priv->call_id);
+	}
+
+	g_checksum_reset (self->priv->checksum);
 	keys = g_hash_table_get_keys (data_set);
 	keys = g_list_sort (keys, (GCompareFunc) strcmp);
 	for (scan = keys; scan; scan = scan->next) {
 		char *key = scan->data;
 
 		g_checksum_update (self->priv->checksum, (guchar *) key, -1);
+		g_checksum_update (self->priv->checksum, (guchar *) "=", -1);
 		g_checksum_update (self->priv->checksum, g_hash_table_lookup (data_set, key), -1);
 	}
-	g_hash_table_insert (data_set, "api_sig", (gpointer) g_checksum_get_string (self->priv->checksum));
+	if (self->priv->session_key != NULL)
+		g_checksum_update (self->priv->checksum, (guchar *) self->priv->secret, -1);
+	else
+		g_checksum_update (self->priv->checksum, (guchar *) GTHUMB_FACEBOOK_SHARED_SECRET, -1);
+	g_hash_table_insert (data_set, "sig", (gpointer) g_checksum_get_string (self->priv->checksum));
 
 	g_list_free (keys);
 }
 
 
 static void
-connection_frob_ready_cb (SoupSession *session,
-			  SoupMessage *msg,
-			  gpointer     user_data)
+create_token_ready_cb (SoupSession *session,
+		       SoupMessage *msg,
+		       gpointer     user_data)
 {
 	FacebookConnection *self = user_data;
-	SoupBuffer       *body;
-	DomDocument      *doc = NULL;
-	GError           *error = NULL;
+	SoupBuffer         *body;
+	DomDocument        *doc = NULL;
+	GError             *error = NULL;
 
-	g_free (self->priv->frob);
-	self->priv->frob = NULL;
+	g_free (self->priv->token);
+	g_free (self->priv->session_key);
+	g_free (self->priv->secret);
+	g_free (self->priv->user_id);
+	self->priv->token = NULL;
+	self->priv->session_key = NULL;
+	self->priv->secret = NULL;
+	self->priv->user_id = NULL;
 
 	body = soup_message_body_flatten (msg->response_body);
 	if (facebook_utils_parse_response (body, &doc, &error)) {
 		DomElement *root;
-		DomElement *child;
 
 		root = DOM_ELEMENT (doc)->first_child;
-		for (child = root->first_child; child; child = child->next_sibling)
-			if (g_strcmp0 (child->tag_name, "frob") == 0)
-				self->priv->frob = g_strdup (dom_element_get_inner_text (child));
+		if (g_strcmp0 (root->tag_name, "auth_createToken_response") == 0)
+			self->priv->token = g_strdup (dom_element_get_inner_text (root));
 
-		if (self->priv->frob == NULL) {
+		if (self->priv->token == NULL) {
 			error = g_error_new_literal (FACEBOOK_CONNECTION_ERROR, 0, _("Unknown error"));
 			g_simple_async_result_set_from_error (self->priv->result, error);
 		}
@@ -296,10 +319,10 @@ connection_frob_ready_cb (SoupSession *session,
 
 
 void
-facebook_connection_get_frob (FacebookConnection    *self,
-			    GCancellable        *cancellable,
-			    GAsyncReadyCallback  callback,
-			    gpointer             user_data)
+facebook_connection_create_token (FacebookConnection  *self,
+				  GCancellable        *cancellable,
+				  GAsyncReadyCallback  callback,
+				  gpointer             user_data)
 {
 	GHashTable  *data_set;
 	SoupMessage *msg;
@@ -307,26 +330,26 @@ facebook_connection_get_frob (FacebookConnection    *self,
 	gth_task_progress (GTH_TASK (self), _("Connecting to the server"), NULL, TRUE, 0.0);
 
 	data_set = g_hash_table_new (g_str_hash, g_str_equal);
-	g_hash_table_insert (data_set, "method", "facebook.auth.getFrob");
+	g_hash_table_insert (data_set, "method", "facebook.auth.createToken");
 	facebook_connection_add_api_sig (self, data_set);
-	msg = soup_form_request_new_from_hash ("GET", "http://api.facebook.com/services/rest";, data_set);
+	msg = soup_form_request_new_from_hash ("POST", FACEBOOK_HTTPS_REST_SERVER, data_set);
 	facebook_connection_send_message (self,
-					msg,
-					cancellable,
-					callback,
-					user_data,
-					facebook_connection_get_frob,
-					connection_frob_ready_cb,
-					self);
+					  msg,
+					  cancellable,
+					  callback,
+					  user_data,
+					  facebook_connection_create_token,
+					  create_token_ready_cb,
+					  self);
 
 	g_hash_table_destroy (data_set);
 }
 
 
 gboolean
-facebook_connection_get_frob_finish (FacebookConnection  *self,
-				   GAsyncResult      *result,
-				   GError           **error)
+facebook_connection_create_token_finish (FacebookConnection  *self,
+					 GAsyncResult        *result,
+				         GError             **error)
 {
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
 		return FALSE;
@@ -342,47 +365,48 @@ get_access_type_name (FacebookAccessType access_type)
 
 	switch (access_type) {
 	case FACEBOOK_ACCESS_READ:
-		name = "read";
+		name = "read_stream,offline_access";
 		break;
 
 	case FACEBOOK_ACCESS_WRITE:
-		name = "write";
-		break;
-
-	case FACEBOOK_ACCESS_DELETE:
-		name = "delete";
+		name = "photo_upload,offline_access";
 		break;
 	}
 
 	return name;
 }
 
+
 char *
 facebook_connection_get_login_link (FacebookConnection *self,
-				  FacebookAccessType  access_type)
+				    FacebookAccessType  access_type)
 {
 	GHashTable *data_set;
 	GString    *link;
 	GList      *keys;
 	GList      *scan;
 
-	g_return_val_if_fail (self->priv->frob != NULL, NULL);
+	g_return_val_if_fail (self->priv->token != NULL, NULL);
 
 	data_set = g_hash_table_new (g_str_hash, g_str_equal);
-	g_hash_table_insert (data_set, "frob", self->priv->frob);
-	g_hash_table_insert (data_set, "perms", get_access_type_name (access_type));
-	facebook_connection_add_api_sig (self, data_set);
+	g_hash_table_insert (data_set, "api_key", GTHUMB_FACEBOOK_API_KEY);
+	g_hash_table_insert (data_set, "auth_token", self->priv->token);
+	g_hash_table_insert (data_set, "req_perms", get_access_type_name (access_type));
 
-	link = g_string_new ("http://www.facebook.com/services/auth/?";);
+	link = g_string_new ("http://www.facebook.com/login.php?";);
 	keys = g_hash_table_get_keys (data_set);
 	for (scan = keys; scan; scan = scan->next) {
 		char *key = scan->data;
+		char *encoded;
 
 		if (scan != keys)
 			g_string_append (link, "&");
 		g_string_append (link, key);
 		g_string_append (link, "=");
-		g_string_append (link, g_hash_table_lookup (data_set, key));
+		encoded = soup_uri_encode (g_hash_table_lookup (data_set, key), NULL);
+		g_string_append (link, encoded);
+
+		g_free (encoded);
 	}
 
 	g_list_free (keys);
@@ -393,38 +417,37 @@ facebook_connection_get_login_link (FacebookConnection *self,
 
 
 static void
-connection_token_ready_cb (SoupSession *session,
-			   SoupMessage *msg,
-			   gpointer     user_data)
+get_session_ready_cb (SoupSession *session,
+		      SoupMessage *msg,
+		      gpointer     user_data)
 {
 	FacebookConnection *self = user_data;
-	SoupBuffer       *body;
-	DomDocument      *doc = NULL;
-	GError           *error = NULL;
+	SoupBuffer         *body;
+	DomDocument        *doc = NULL;
+	GError             *error = NULL;
 
 	body = soup_message_body_flatten (msg->response_body);
 	if (facebook_utils_parse_response (body, &doc, &error)) {
-		DomElement *response;
-		DomElement *auth;
-
-		response = DOM_ELEMENT (doc)->first_child;
-		for (auth = response->first_child; auth; auth = auth->next_sibling) {
-			if (g_strcmp0 (auth->tag_name, "auth") == 0) {
-				DomElement *node;
-
-				for (node = auth->first_child; node; node = node->next_sibling) {
-					if (g_strcmp0 (node->tag_name, "token") == 0) {
-						self->priv->token = g_strdup (dom_element_get_inner_text (node));
-					}
-					else if (g_strcmp0 (node->tag_name, "user") == 0) {
-						self->priv->username = g_strdup (dom_element_get_attribute (node, "username"));
-						self->priv->user_id = g_strdup (dom_element_get_attribute (node, "nsid"));
-					}
+		DomElement *root;
+
+		root = DOM_ELEMENT (doc)->first_child;
+		if (g_strcmp0 (root->tag_name, "auth_getSession_response") == 0) {
+			DomElement *node;
+
+			for (node = root->first_child; node; node = node->next_sibling) {
+				if (g_strcmp0 (node->tag_name, "session_key") == 0) {
+					self->priv->session_key = g_strdup (dom_element_get_inner_text (node));
+				}
+				else if (g_strcmp0 (node->tag_name, "secret") == 0) {
+					self->priv->secret = g_strdup (dom_element_get_inner_text (node));
+				}
+				else if (g_strcmp0 (node->tag_name, "uid") == 0) {
+					self->priv->user_id = g_strdup (dom_element_get_inner_text (node));
 				}
 			}
 		}
 
-		if (self->priv->token == NULL) {
+		if ((self->priv->session_key == NULL) || (self->priv->secret == NULL)) {
 			error = g_error_new_literal (FACEBOOK_CONNECTION_ERROR, 0, _("Unknown error"));
 			g_simple_async_result_set_from_error (self->priv->result, error);
 		}
@@ -443,41 +466,45 @@ connection_token_ready_cb (SoupSession *session,
 
 
 void
-facebook_connection_get_token (FacebookConnection    *self,
-			     GCancellable        *cancellable,
-			     GAsyncReadyCallback  callback,
-			     gpointer             user_data)
+facebook_connection_get_session (FacebookConnection  *self,
+				 GCancellable        *cancellable,
+				 GAsyncReadyCallback  callback,
+				 gpointer             user_data)
 {
 	GHashTable  *data_set;
 	SoupMessage *msg;
 
 	gth_task_progress (GTH_TASK (self), _("Connecting to the server"), NULL, TRUE, 0.0);
 
-	g_free (self->priv->token);
-	self->priv->token = NULL;
+	g_free (self->priv->session_key);
+	g_free (self->priv->secret);
+	g_free (self->priv->user_id);
+	self->priv->session_key = NULL;
+	self->priv->secret = NULL;
+	self->priv->user_id = NULL;
 
 	data_set = g_hash_table_new (g_str_hash, g_str_equal);
-	g_hash_table_insert (data_set, "method", "facebook.auth.getToken");
-	g_hash_table_insert (data_set, "frob", self->priv->frob);
+	g_hash_table_insert (data_set, "method", "facebook.auth.getSession");
+	g_hash_table_insert (data_set, "auth_token", self->priv->token);
 	facebook_connection_add_api_sig (self, data_set);
-	msg = soup_form_request_new_from_hash ("GET", "http://api.facebook.com/services/rest";, data_set);
+	msg = soup_form_request_new_from_hash ("POST", FACEBOOK_HTTPS_REST_SERVER, data_set);
 	facebook_connection_send_message (self,
-					msg,
-					cancellable,
-					callback,
-					user_data,
-					facebook_connection_get_token,
-					connection_token_ready_cb,
-					self);
+					  msg,
+					  cancellable,
+					  callback,
+					  user_data,
+					  facebook_connection_get_session,
+					  get_session_ready_cb,
+					  self);
 
 	g_hash_table_destroy (data_set);
 }
 
 
 gboolean
-facebook_connection_get_token_finish (FacebookConnection  *self,
-				    GAsyncResult      *result,
-				    GError           **error)
+facebook_connection_get_session_finish (FacebookConnection  *self,
+					GAsyncResult        *result,
+					GError             **error)
 {
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
 		return FALSE;
@@ -487,27 +514,26 @@ facebook_connection_get_token_finish (FacebookConnection  *self,
 
 
 void
-facebook_connection_set_auth_token (FacebookConnection *self,
-				  const char       *value)
+facebook_connection_set_session (FacebookConnection *self,
+				 const char         *session_key,
+				 const char         *secret)
 {
-	g_free (self->priv->token);
-	self->priv->token = NULL;
-	if (value != NULL)
-		self->priv->token = g_strdup (value);
+	_g_strset (&self->priv->session_key, session_key);
+	_g_strset (&self->priv->secret, secret);
 }
 
 
 const char *
-facebook_connection_get_auth_token (FacebookConnection *self)
+facebook_connection_get_session_key (FacebookConnection *self)
 {
-	return self->priv->token;
+	return self->priv->session_key;
 }
 
 
 const char *
-facebook_connection_get_username (FacebookConnection *self)
+facebook_connection_get_secret (FacebookConnection *self)
 {
-	return self->priv->username;
+	return self->priv->secret;
 }
 
 
@@ -523,8 +549,8 @@ facebook_connection_get_user_id (FacebookConnection *self)
 
 gboolean
 facebook_utils_parse_response (SoupBuffer   *body,
-			     DomDocument **doc_p,
-			     GError      **error)
+			       DomDocument **doc_p,
+			       GError      **error)
 {
 	DomDocument *doc;
 	DomElement  *node;
@@ -536,21 +562,26 @@ facebook_utils_parse_response (SoupBuffer   *body,
 	}
 
 	for (node = DOM_ELEMENT (doc)->first_child; node; node = node->next_sibling) {
-		if (g_strcmp0 (node->tag_name, "rsp") == 0) {
-			if (g_strcmp0 (dom_element_get_attribute (node, "stat"), "ok") != 0) {
-				DomElement *child;
-
-				for (child = node->first_child; child; child = child->next_sibling) {
-					if (g_strcmp0 (child->tag_name, "err") == 0) {
-						*error = g_error_new_literal (FACEBOOK_CONNECTION_ERROR,
-									      atoi (dom_element_get_attribute (child, "code")),
-									      dom_element_get_attribute (child, "msg"));
-					}
+		if (g_strcmp0 (node->tag_name, "error_response") == 0) {
+			DomElement *child;
+			int         code = 0;
+			const char *message = NULL;
+
+			for (child = node->first_child; child; child = child->next_sibling) {
+				if (g_strcmp0 (child->tag_name, "error_code") == 0) {
+					code = atoi (dom_element_get_inner_text (child));
+				}
+				else if (g_strcmp0 (child->tag_name, "error_msg") == 0) {
+					message = dom_element_get_inner_text (child);
 				}
-
-				g_object_unref (doc);
-				return FALSE;
 			}
+
+			*error = g_error_new_literal (FACEBOOK_CONNECTION_ERROR,
+						      code,
+						      message);
+
+			g_object_unref (doc);
+			return FALSE;
 		}
 	}
 
diff --git a/extensions/facebook/facebook-connection.h b/extensions/facebook/facebook-connection.h
index c2ae844..405de55 100644
--- a/extensions/facebook/facebook-connection.h
+++ b/extensions/facebook/facebook-connection.h
@@ -33,10 +33,13 @@
 
 typedef enum {
 	FACEBOOK_ACCESS_READ,
-	FACEBOOK_ACCESS_WRITE,
-	FACEBOOK_ACCESS_DELETE
+	FACEBOOK_ACCESS_WRITE
 } FacebookAccessType;
 
+#define FACEBOOK_REST_SERVER "api.facebook.com/restserver.php"
+#define FACEBOOK_HTTP_REST_SERVER "http://"; FACEBOOK_REST_SERVER
+#define FACEBOOK_HTTPS_REST_SERVER "https://"; FACEBOOK_REST_SERVER
+
 #define FACEBOOK_CONNECTION_ERROR facebook_connection_error_quark ()
 GQuark facebook_connection_error_quark (void);
 
@@ -62,46 +65,47 @@ struct _FacebookConnectionClass
 	GthTaskClass __parent_class;
 };
 
-GType                facebook_connection_get_type           (void) G_GNUC_CONST;
-FacebookConnection *   facebook_connection_new                (void);
-void		     facebook_connection_send_message       (FacebookConnection      *self,
-						           SoupMessage           *msg,
-						           GCancellable          *cancellable,
-						           GAsyncReadyCallback    callback,
-						           gpointer               user_data,
-						           gpointer               source_tag,
-						           SoupSessionCallback    soup_session_cb,
-						           gpointer               soup_session_cb_data);
-GSimpleAsyncResult * facebook_connection_get_result         (FacebookConnection      *self);
-void                 facebook_connection_reset_result       (FacebookConnection      *self);
-void                 facebook_connection_add_api_sig        (FacebookConnection      *self,
-						           GHashTable            *data_set);
-void                 facebook_connection_get_frob           (FacebookConnection      *self,
-						           GCancellable          *cancellable,
-						           GAsyncReadyCallback    callback,
-						           gpointer               user_data);
-gboolean             facebook_connection_get_frob_finish    (FacebookConnection      *self,
-							   GAsyncResult          *result,
-							   GError               **error);
-char *               facebook_connection_get_login_link     (FacebookConnection      *self,
-							   FacebookAccessType       access_type);
-void                 facebook_connection_get_token          (FacebookConnection      *self,
-						           GCancellable          *cancellable,
-						           GAsyncReadyCallback    callback,
-						           gpointer               user_data);
-gboolean             facebook_connection_get_token_finish   (FacebookConnection      *self,
-							   GAsyncResult          *result,
-							   GError               **error);
-void                 facebook_connection_set_auth_token     (FacebookConnection      *self,
-							   const char            *value);
-const char *         facebook_connection_get_auth_token     (FacebookConnection      *self);
-const char *         facebook_connection_get_username       (FacebookConnection      *self);
-const char *         facebook_connection_get_user_id        (FacebookConnection      *self);
+GType                facebook_connection_get_type             (void) G_GNUC_CONST;
+FacebookConnection * facebook_connection_new                  (void);
+void		     facebook_connection_send_message         (FacebookConnection    *self,
+						               SoupMessage           *msg,
+						               GCancellable          *cancellable,
+						               GAsyncReadyCallback    callback,
+						               gpointer               user_data,
+						               gpointer               source_tag,
+						               SoupSessionCallback    soup_session_cb,
+						               gpointer               soup_session_cb_data);
+GSimpleAsyncResult * facebook_connection_get_result           (FacebookConnection    *self);
+void                 facebook_connection_reset_result         (FacebookConnection    *self);
+void                 facebook_connection_add_api_sig          (FacebookConnection    *self,
+						               GHashTable            *data_set);
+void                 facebook_connection_create_token         (FacebookConnection    *self,
+						               GCancellable          *cancellable,
+						               GAsyncReadyCallback    callback,
+						               gpointer               user_data);
+gboolean             facebook_connection_create_token_finish  (FacebookConnection    *self,
+							       GAsyncResult          *result,
+							       GError               **error);
+char *               facebook_connection_get_login_link       (FacebookConnection    *self,
+							       FacebookAccessType     access_type);
+void                 facebook_connection_get_session          (FacebookConnection    *self,
+						               GCancellable          *cancellable,
+						               GAsyncReadyCallback    callback,
+						               gpointer               user_data);
+gboolean             facebook_connection_get_session_finish   (FacebookConnection    *self,
+							       GAsyncResult          *result,
+							       GError               **error);
+void                 facebook_connection_set_session          (FacebookConnection    *self,
+							       const char            *session_key,
+							       const char            *secret);
+const char *         facebook_connection_get_session_key      (FacebookConnection    *self);
+const char *         facebook_connection_get_secret           (FacebookConnection    *self);
+const char *         facebook_connection_get_user_id          (FacebookConnection    *self);
 
 /* utilities */
 
-gboolean             facebook_utils_parse_response          (SoupBuffer            *body,
-							   DomDocument          **doc_p,
-							   GError               **error);
+gboolean             facebook_utils_parse_response            (SoupBuffer            *body,
+							       DomDocument          **doc_p,
+							       GError               **error);
 
 #endif /* FACEBOOK_CONNECTION_H */
diff --git a/extensions/facebook/facebook-service.c b/extensions/facebook/facebook-service.c
index 6c5d1fc..aa97081 100644
--- a/extensions/facebook/facebook-service.c
+++ b/extensions/facebook/facebook-service.c
@@ -25,18 +25,17 @@
 #include <glib/gi18n.h>
 #include <gthumb.h>
 #include "facebook-account.h"
+#include "facebook-album.h"
 #include "facebook-connection.h"
 #include "facebook-photo.h"
-#include "facebook-photoset.h"
 #include "facebook-service.h"
 #include "facebook-user.h"
 
 
 typedef struct {
-	FacebookPrivacyType    privacy_level;
-	FacebookSafetyType     safety_level;
-	gboolean             hidden;
+	FacebookAlbum       *album;
 	GList               *file_list;
+	FacebookVisibility   visibility_level;
 	GCancellable        *cancellable;
         GAsyncReadyCallback  callback;
         gpointer             user_data;
@@ -61,36 +60,11 @@ post_photos_data_free (PostPhotosData *post_photos)
 }
 
 
-typedef struct {
-	FacebookPhotoset      *photoset;
-	GList               *photo_ids;
-	GCancellable        *cancellable;
-        GAsyncReadyCallback  callback;
-        gpointer             user_data;
-        int                  n_files;
-        GList               *current;
-        int                  n_current;
-} AddPhotosData;
-
-
-static void
-add_photos_data_free (AddPhotosData *add_photos)
-{
-	if (add_photos == NULL)
-		return;
-	_g_object_unref (add_photos->photoset);
-	_g_string_list_free (add_photos->photo_ids);
-	_g_object_unref (add_photos->cancellable);
-	g_free (add_photos);
-}
-
-
 struct _FacebookServicePrivate
 {
 	FacebookConnection *conn;
 	FacebookUser       *user;
-	PostPhotosData   *post_photos;
-	AddPhotosData    *add_photos;
+	PostPhotosData     *post_photos;
 };
 
 
@@ -107,7 +81,6 @@ facebook_service_finalize (GObject *object)
 	_g_object_unref (self->priv->conn);
 	_g_object_unref (self->priv->user);
 	post_photos_data_free (self->priv->post_photos);
-	add_photos_data_free (self->priv->add_photos);
 
 	G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -176,15 +149,15 @@ facebook_service_new (FacebookConnection *conn)
 }
 
 
-/* -- facebook_service_get_upload_status -- */
+/* -- facebook_service_get_user_info -- */
 
 
 static void
-get_upload_status_ready_cb (SoupSession *session,
-			    SoupMessage *msg,
-			    gpointer     user_data)
+get_logged_in_user_ready_cb (SoupSession *session,
+			     SoupMessage *msg,
+			     gpointer     user_data)
 {
-	FacebookService      *self = user_data;
+	FacebookService    *self = user_data;
 	GSimpleAsyncResult *result;
 	SoupBuffer         *body;
 	DomDocument        *doc = NULL;
@@ -204,23 +177,19 @@ get_upload_status_ready_cb (SoupSession *session,
 
 	body = soup_message_body_flatten (msg->response_body);
 	if (facebook_utils_parse_response (body, &doc, &error)) {
-		DomElement *response;
-		DomElement *node;
-		FacebookUser *user = NULL;
+		DomElement *root;
+		char       *uid = NULL;
 
-		response = DOM_ELEMENT (doc)->first_child;
-		for (node = response->first_child; node; node = node->next_sibling) {
-			if (g_strcmp0 (node->tag_name, "user") == 0) {
-				user = facebook_user_new ();
-				dom_domizable_load_from_element (DOM_DOMIZABLE (user), node);
-				g_simple_async_result_set_op_res_gpointer (result, user, (GDestroyNotify) g_object_unref);
-			}
-		}
+		root = DOM_ELEMENT (doc)->first_child;
+		if (g_strcmp0 (root->tag_name, "users_getLoggedInUser_response") == 0)
+			uid = g_strdup (dom_element_get_inner_text (root));
 
-		if (user == NULL) {
+		if (uid == NULL) {
 			error = g_error_new_literal (FACEBOOK_CONNECTION_ERROR, 0, _("Unknown error"));
 			g_simple_async_result_set_from_error (result, error);
 		}
+		else
+			g_simple_async_result_set_op_res_gpointer (result, uid, g_free);
 
 		g_object_unref (doc);
 	}
@@ -234,10 +203,10 @@ get_upload_status_ready_cb (SoupSession *session,
 
 
 void
-facebook_service_get_upload_status (FacebookService       *self,
-				  GCancellable        *cancellable,
-				  GAsyncReadyCallback  callback,
-				  gpointer             user_data)
+facebook_service_get_logged_in_user (FacebookService     *self,
+				     GCancellable        *cancellable,
+				     GAsyncReadyCallback  callback,
+				     gpointer             user_data)
 {
 	GHashTable  *data_set;
 	SoupMessage *msg;
@@ -245,41 +214,41 @@ facebook_service_get_upload_status (FacebookService       *self,
 	gth_task_progress (GTH_TASK (self->priv->conn), _("Connecting to the server"), _("Getting account information"), TRUE, 0.0);
 
 	data_set = g_hash_table_new (g_str_hash, g_str_equal);
-	g_hash_table_insert (data_set, "method", "facebook.people.getUploadStatus");
+	g_hash_table_insert (data_set, "method", "facebook.users.getLoggedInUser");
 	facebook_connection_add_api_sig (self->priv->conn, data_set);
-	msg = soup_form_request_new_from_hash ("GET", "http://api.facebook.com/services/rest";, data_set);
+	msg = soup_form_request_new_from_hash ("POST", FACEBOOK_HTTPS_REST_SERVER, data_set);
 	facebook_connection_send_message (self->priv->conn,
-					msg,
-					cancellable,
-					callback,
-					user_data,
-					facebook_service_get_upload_status,
-					get_upload_status_ready_cb,
-					self);
+					  msg,
+					  cancellable,
+					  callback,
+					  user_data,
+					  facebook_service_get_logged_in_user,
+					  get_logged_in_user_ready_cb,
+					  self);
 
 	g_hash_table_destroy (data_set);
 }
 
 
-FacebookUser *
-facebook_service_get_upload_status_finish (FacebookService  *self,
-					 GAsyncResult   *result,
-					 GError        **error)
+char *
+facebook_service_get_logged_in_user_finish (FacebookService  *self,
+					    GAsyncResult     *result,
+					    GError          **error)
 {
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
 		return NULL;
 	else
-		return g_object_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result)));
+		return g_strdup (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result)));
 }
 
 
-/* -- facebook_service_list_photosets -- */
+/* -- facebook_service_get_user_info -- */
 
 
 static void
-list_photosets_ready_cb (SoupSession *session,
-			 SoupMessage *msg,
-			 gpointer     user_data)
+get_user_info_ready_cb (SoupSession *session,
+			SoupMessage *msg,
+			gpointer     user_data)
 {
 	FacebookService      *self = user_data;
 	GSimpleAsyncResult *result;
@@ -301,29 +270,27 @@ list_photosets_ready_cb (SoupSession *session,
 
 	body = soup_message_body_flatten (msg->response_body);
 	if (facebook_utils_parse_response (body, &doc, &error)) {
-		DomElement *response;
-		DomElement *node;
-		GList      *photosets = NULL;
+		DomElement   *node;
+		FacebookUser *user = NULL;
 
-		response = DOM_ELEMENT (doc)->first_child;
-		for (node = response->first_child; node; node = node->next_sibling) {
-			if (g_strcmp0 (node->tag_name, "photosets") == 0) {
+		for (node = DOM_ELEMENT (doc)->first_child; node; node = node->next_sibling) {
+			if (g_strcmp0 (node->tag_name, "users_getInfo_response") == 0) {
 				DomElement *child;
 
 				for (child = node->first_child; child; child = child->next_sibling) {
-					if (g_strcmp0 (child->tag_name, "photoset") == 0) {
-						FacebookPhotoset *photoset;
-
-						photoset = facebook_photoset_new ();
-						dom_domizable_load_from_element (DOM_DOMIZABLE (photoset), child);
-						photosets = g_list_prepend (photosets, photoset);
+					if (g_strcmp0 (child->tag_name, "user") == 0) {
+						user = facebook_user_new ();
+						dom_domizable_load_from_element (DOM_DOMIZABLE (user), child);
+						g_simple_async_result_set_op_res_gpointer (result, user, (GDestroyNotify) g_object_unref);
 					}
 				}
 			}
 		}
 
-		photosets = g_list_reverse (photosets);
-		g_simple_async_result_set_op_res_gpointer (result, photosets, (GDestroyNotify) _g_object_list_unref);
+		if (user == NULL) {
+			error = g_error_new_literal (FACEBOOK_CONNECTION_ERROR, 0, _("Unknown error"));
+			g_simple_async_result_set_from_error (result, error);
+		}
 
 		g_object_unref (doc);
 	}
@@ -337,57 +304,57 @@ list_photosets_ready_cb (SoupSession *session,
 
 
 void
-facebook_service_list_photosets (FacebookService       *self,
-			       const char          *user_id,
-			       GCancellable        *cancellable,
-			       GAsyncReadyCallback  callback,
-			       gpointer             user_data)
+facebook_service_get_user_info (FacebookService     *self,
+				const char          *fields,
+				GCancellable        *cancellable,
+				GAsyncReadyCallback  callback,
+				gpointer             user_data)
 {
 	GHashTable  *data_set;
 	SoupMessage *msg;
 
-	gth_task_progress (GTH_TASK (self->priv->conn), _("Getting the album list"), NULL, TRUE, 0.0);
+	gth_task_progress (GTH_TASK (self->priv->conn), _("Connecting to the server"), _("Getting account information"), TRUE, 0.0);
 
 	data_set = g_hash_table_new (g_str_hash, g_str_equal);
-	g_hash_table_insert (data_set, "method", "facebook.photosets.getList");
-	if (user_id != NULL)
-		g_hash_table_insert (data_set, "user_id", (char *) user_id);
+	g_hash_table_insert (data_set, "method", "facebook.users.getInfo");
+	g_hash_table_insert (data_set, "uids", (char *) facebook_connection_get_user_id (self->priv->conn));
+	g_hash_table_insert (data_set, "fields", (char *) fields);
 	facebook_connection_add_api_sig (self->priv->conn, data_set);
-	msg = soup_form_request_new_from_hash ("GET", "http://api.facebook.com/services/rest";, data_set);
+	msg = soup_form_request_new_from_hash ("POST", FACEBOOK_HTTPS_REST_SERVER, data_set);
 	facebook_connection_send_message (self->priv->conn,
-					msg,
-					cancellable,
-					callback,
-					user_data,
-					facebook_service_list_photosets,
-					list_photosets_ready_cb,
-					self);
+					  msg,
+					  cancellable,
+					  callback,
+					  user_data,
+					  facebook_service_get_user_info,
+					  get_user_info_ready_cb,
+					  self);
 
 	g_hash_table_destroy (data_set);
 }
 
 
-GList *
-facebook_service_list_photosets_finish (FacebookService  *service,
-				      GAsyncResult   *result,
-				      GError        **error)
+FacebookUser *
+facebook_service_get_user_info_finish (FacebookService  *self,
+				       GAsyncResult     *result,
+				       GError          **error)
 {
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
 		return NULL;
 	else
-		return _g_object_list_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result)));
+		return g_object_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result)));
 }
 
 
-/* -- facebook_service_create_photoset_finish -- */
+/* -- facebook_service_get_albums -- */
 
 
 static void
-create_photoset_ready_cb (SoupSession *session,
-			  SoupMessage *msg,
-			  gpointer     user_data)
+get_albums_ready_cb (SoupSession *session,
+		     SoupMessage *msg,
+		     gpointer     user_data)
 {
-	FacebookService      *self = user_data;
+	FacebookService    *self = user_data;
 	GSimpleAsyncResult *result;
 	SoupBuffer         *body;
 	DomDocument        *doc = NULL;
@@ -407,23 +374,27 @@ create_photoset_ready_cb (SoupSession *session,
 
 	body = soup_message_body_flatten (msg->response_body);
 	if (facebook_utils_parse_response (body, &doc, &error)) {
-		DomElement     *response;
-		DomElement     *node;
-		FacebookPhotoset *photoset = NULL;
+		DomElement *node;
+		GList      *albums = NULL;
 
-		response = DOM_ELEMENT (doc)->first_child;
-		for (node = response->first_child; node; node = node->next_sibling) {
-			if (g_strcmp0 (node->tag_name, "photoset") == 0) {
-				photoset = facebook_photoset_new ();
-				dom_domizable_load_from_element (DOM_DOMIZABLE (photoset), node);
-				g_simple_async_result_set_op_res_gpointer (result, photoset, (GDestroyNotify) g_object_unref);
+		for (node = DOM_ELEMENT (doc)->first_child; node; node = node->next_sibling) {
+			if (g_strcmp0 (node->tag_name, "photos_getAlbums_response") == 0) {
+				DomElement *child;
+
+				for (child = node->first_child; child; child = child->next_sibling) {
+					if (g_strcmp0 (child->tag_name, "album") == 0) {
+						FacebookAlbum *album;
+
+						album = facebook_album_new ();
+						dom_domizable_load_from_element (DOM_DOMIZABLE (album), child);
+						albums = g_list_prepend (albums, album);
+					}
+				}
 			}
 		}
 
-		if (photoset == NULL) {
-			error = g_error_new_literal (FACEBOOK_CONNECTION_ERROR, 0, _("Unknown error"));
-			g_simple_async_result_set_from_error (result, error);
-		}
+		albums = g_list_reverse (albums);
+		g_simple_async_result_set_op_res_gpointer (result, albums, (GDestroyNotify) _g_object_list_unref);
 
 		g_object_unref (doc);
 	}
@@ -437,94 +408,58 @@ create_photoset_ready_cb (SoupSession *session,
 
 
 void
-facebook_service_create_photoset (FacebookService       *self,
-				FacebookPhotoset      *photoset,
-				GCancellable        *cancellable,
-				GAsyncReadyCallback  callback,
-				gpointer             user_data)
+facebook_service_get_albums (FacebookService     *self,
+			     const char          *user_id,
+			     GCancellable        *cancellable,
+			     GAsyncReadyCallback  callback,
+			     gpointer             user_data)
 {
 	GHashTable  *data_set;
 	SoupMessage *msg;
 
-	g_return_if_fail (photoset != NULL);
-	g_return_if_fail (photoset->primary != NULL);
+	g_return_if_fail (user_id != NULL);
 
-	gth_task_progress (GTH_TASK (self->priv->conn), _("Creating the new album"), NULL, TRUE, 0.0);
+	gth_task_progress (GTH_TASK (self->priv->conn), _("Getting the album list"), NULL, TRUE, 0.0);
 
 	data_set = g_hash_table_new (g_str_hash, g_str_equal);
-	g_hash_table_insert (data_set, "method", "facebook.photosets.create");
-	g_hash_table_insert (data_set, "title", photoset->title);
-	g_hash_table_insert (data_set, "primary_photo_id", photoset->primary);
+	g_hash_table_insert (data_set, "method", "facebook.photos.getAlbums");
+	g_hash_table_insert (data_set, "uid", (char *) user_id);
 	facebook_connection_add_api_sig (self->priv->conn, data_set);
-	msg = soup_form_request_new_from_hash ("GET", "http://api.facebook.com/services/rest";, data_set);
+	msg = soup_form_request_new_from_hash ("GET", FACEBOOK_HTTPS_REST_SERVER, data_set);
 	facebook_connection_send_message (self->priv->conn,
-					msg,
-					cancellable,
-					callback,
-					user_data,
-					facebook_service_create_photoset,
-					create_photoset_ready_cb,
-					self);
+					  msg,
+					  cancellable,
+					  callback,
+					  user_data,
+					  facebook_service_get_albums,
+					  get_albums_ready_cb,
+					  self);
 
 	g_hash_table_destroy (data_set);
 }
 
 
-FacebookPhotoset *
-facebook_service_create_photoset_finish (FacebookService  *self,
-				       GAsyncResult   *result,
-				       GError        **error)
+GList *
+facebook_service_get_albums_finish (FacebookService  *service,
+				    GAsyncResult     *result,
+				    GError          **error)
 {
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
 		return NULL;
 	else
-		return g_object_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result)));
-}
-
-
-/* -- facebook_service_add_photos_to_set -- */
-
-
-static void
-add_photos_to_set_done (FacebookService *self,
-			GError        *error)
-{
-	GSimpleAsyncResult *result;
-
-	result = facebook_connection_get_result (self->priv->conn);
-	if (result == NULL)
-		result = g_simple_async_result_new (G_OBJECT (self),
-						    self->priv->add_photos->callback,
-						    self->priv->add_photos->user_data,
-						    facebook_service_add_photos_to_set);
-
-	if (error == NULL)
-		g_simple_async_result_set_op_res_gboolean (result, TRUE);
-	else
-		g_simple_async_result_set_from_error (result, error);
-
-	g_simple_async_result_complete_in_idle (result);
+		return _g_object_list_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result)));
 }
 
 
-static void add_current_photo_to_set (FacebookService *self);
+/* -- facebook_service_create_album -- */
 
 
 static void
-add_next_photo_to_set (FacebookService *self)
+create_album_ready_cb (SoupSession *session,
+		       SoupMessage *msg,
+		       gpointer     user_data)
 {
-	self->priv->add_photos->current = self->priv->add_photos->current->next;
-	self->priv->add_photos->n_current += 1;
-	add_current_photo_to_set (self);
-}
-
-
-static void
-add_current_photo_to_set_ready_cb (SoupSession *session,
-				   SoupMessage *msg,
-				   gpointer     user_data)
-{
-	FacebookService      *self = user_data;
+	FacebookService    *self = user_data;
 	GSimpleAsyncResult *result;
 	SoupBuffer         *body;
 	DomDocument        *doc = NULL;
@@ -543,106 +478,121 @@ add_current_photo_to_set_ready_cb (SoupSession *session,
 	}
 
 	body = soup_message_body_flatten (msg->response_body);
-	if (! facebook_utils_parse_response (body, &doc, &error)) {
-		soup_buffer_free (body);
-		add_photos_to_set_done (self, error);
-		return;
+	if (facebook_utils_parse_response (body, &doc, &error)) {
+		DomElement    *node;
+		FacebookAlbum *album = NULL;
+
+		for (node = DOM_ELEMENT (doc)->first_child; node; node = node->next_sibling) {
+			if (g_strcmp0 (node->tag_name, "photos_createAlbum_response") == 0) {
+				album = facebook_album_new ();
+				dom_domizable_load_from_element (DOM_DOMIZABLE (album), node);
+				break;
+			}
+		}
+
+		if (album == NULL) {
+			error = g_error_new_literal (FACEBOOK_CONNECTION_ERROR, 0, _("Unknown error"));
+			g_simple_async_result_set_from_error (result, error);
+		}
+		else
+			g_simple_async_result_set_op_res_gpointer (result, album, (GDestroyNotify) _g_object_unref);
+
+		g_object_unref (doc);
 	}
+	else
+		g_simple_async_result_set_from_error (result, error);
 
-	g_object_unref (doc);
-	soup_buffer_free (body);
+	g_simple_async_result_complete_in_idle (result);
 
-	add_next_photo_to_set (self);
+	soup_buffer_free (body);
 }
 
 
-static void
-add_current_photo_to_set (FacebookService *self)
+static const char *
+get_privacy_from_visibility (FacebookVisibility visibility)
 {
-	char        *photo_id;
-	GHashTable  *data_set;
-	SoupMessage *msg;
+	char *value = NULL;
 
-	if (self->priv->add_photos->current == NULL) {
-		add_photos_to_set_done (self, NULL);
-		return;
-	}
+	switch (visibility) {
+	case FACEBOOK_VISIBILITY_EVERYONE:
+		value = "{ value: \"EVERYONE\" }";
+		break;
 
-	gth_task_progress (GTH_TASK (self->priv->conn),
-			   _("Creating the new album"),
-			   "",
-			   FALSE,
-			   (double) self->priv->add_photos->n_current / (self->priv->add_photos->n_files + 1));
+	case FACEBOOK_VISIBILITY_ALL_FRIENDS:
+		value = "{ value: \"ALL_FRIENDS\" }";
+		break;
 
-	photo_id = self->priv->add_photos->current->data;
-	if (g_strcmp0 (photo_id, self->priv->add_photos->photoset->primary) == 0) {
-		add_next_photo_to_set (self);
-		return;
-	}
+	case FACEBOOK_VISIBILITY_SELF:
+		value = "{ value: \"SELF\" }";
+		break;
 
-	data_set = g_hash_table_new (g_str_hash, g_str_equal);
-	g_hash_table_insert (data_set, "method", "facebook.photosets.addPhoto");
-	g_hash_table_insert (data_set, "photoset_id", self->priv->add_photos->photoset->id);
-	g_hash_table_insert (data_set, "photo_id", photo_id);
-	facebook_connection_add_api_sig (self->priv->conn, data_set);
-	msg = soup_form_request_new_from_hash ("POST", "http://api.facebook.com/services/rest";, data_set);
-	facebook_connection_send_message (self->priv->conn,
-					msg,
-					self->priv->add_photos->cancellable,
-					self->priv->add_photos->callback,
-					self->priv->add_photos->user_data,
-					facebook_service_add_photos_to_set,
-					add_current_photo_to_set_ready_cb,
-					self);
+	default:
+		break;
+	}
 
-	g_hash_table_destroy (data_set);
+	return value;
 }
 
 
 void
-facebook_service_add_photos_to_set (FacebookService        *self,
-				  FacebookPhotoset       *photoset,
-				  GList                *photo_ids,
-				  GCancellable         *cancellable,
-				  GAsyncReadyCallback   callback,
-				  gpointer              user_data)
+facebook_service_create_album (FacebookService     *self,
+			       FacebookAlbum       *album,
+			       GCancellable        *cancellable,
+			       GAsyncReadyCallback  callback,
+			       gpointer             user_data)
 {
+	GHashTable  *data_set;
+	const char  *privacy;
+	SoupMessage *msg;
+
+	g_return_if_fail (album != NULL);
+	g_return_if_fail (album->name != NULL);
+
 	gth_task_progress (GTH_TASK (self->priv->conn), _("Creating the new album"), NULL, TRUE, 0.0);
 
-	add_photos_data_free (self->priv->add_photos);
-	self->priv->add_photos = g_new0 (AddPhotosData, 1);
-	self->priv->add_photos->photoset = _g_object_ref (photoset);
-	self->priv->add_photos->photo_ids = _g_string_list_dup (photo_ids);
-	self->priv->add_photos->cancellable = _g_object_ref (cancellable);
-	self->priv->add_photos->callback = callback;
-	self->priv->add_photos->user_data = user_data;
-	self->priv->add_photos->n_files = g_list_length (self->priv->add_photos->photo_ids);
-	self->priv->add_photos->current = self->priv->add_photos->photo_ids;
-	self->priv->add_photos->n_current = 1;
-
-	facebook_connection_reset_result (self->priv->conn);
-	add_current_photo_to_set (self);
+	data_set = g_hash_table_new (g_str_hash, g_str_equal);
+	g_hash_table_insert (data_set, "method", "facebook.photos.createAlbum");
+	g_hash_table_insert (data_set, "name", album->name);
+	if (album->description != NULL)
+		g_hash_table_insert (data_set, "description", album->description);
+	if (album->location != NULL)
+		g_hash_table_insert (data_set, "location", album->location);
+	privacy = get_privacy_from_visibility (album->visibility);
+	if (privacy != NULL)
+		g_hash_table_insert (data_set, "privacy", (char *) privacy);
+	facebook_connection_add_api_sig (self->priv->conn, data_set);
+	msg = soup_form_request_new_from_hash ("POST", FACEBOOK_HTTPS_REST_SERVER, data_set);
+	facebook_connection_send_message (self->priv->conn,
+					  msg,
+					  cancellable,
+					  callback,
+					  user_data,
+					  facebook_service_create_album,
+					  create_album_ready_cb,
+					  self);
+
+	g_hash_table_destroy (data_set);
 }
 
 
-gboolean
-facebook_service_add_photos_to_set_finish (FacebookService  *self,
-					 GAsyncResult   *result,
-					 GError        **error)
+FacebookAlbum *
+facebook_service_create_album_finish (FacebookService  *self,
+				      GAsyncResult     *result,
+				      GError          **error)
 {
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
-		return FALSE;
+		return NULL;
 	else
-		return TRUE;
+		return g_object_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result)));
 }
 
 
-/* -- facebook_service_post_photos -- */
+/* -- facebook_service_upload_photos -- */
 
 
 static void
-post_photos_done (FacebookService *self,
-		  GError        *error)
+upload_photos_done (FacebookService *self,
+		    GError          *error)
 {
 	GSimpleAsyncResult *result;
 
@@ -659,13 +609,13 @@ post_photos_done (FacebookService *self,
 }
 
 
-static void facebook_service_post_current_file (FacebookService *self);
+static void facebook_service_upload_current_file (FacebookService *self);
 
 
 static void
-post_photo_ready_cb (SoupSession *session,
-		     SoupMessage *msg,
-		     gpointer     user_data)
+upload_photo_ready_cb (SoupSession *session,
+		       SoupMessage *msg,
+		       gpointer     user_data)
 {
 	FacebookService *self = user_data;
 	SoupBuffer    *body;
@@ -677,7 +627,7 @@ post_photo_ready_cb (SoupSession *session,
 		GError *error;
 
 		error = g_error_new (SOUP_HTTP_ERROR, msg->status_code, "%s", soup_status_get_phrase (msg->status_code));
-		post_photos_done (self, error);
+		upload_photos_done (self, error);
 		g_error_free (error);
 
 		return;
@@ -685,14 +635,12 @@ post_photo_ready_cb (SoupSession *session,
 
 	body = soup_message_body_flatten (msg->response_body);
 	if (facebook_utils_parse_response (body, &doc, &error)) {
-		DomElement *response;
 		DomElement *node;
 
-		/* save the file id */
+		/* save the photo id */
 
-		response = DOM_ELEMENT (doc)->first_child;
-		for (node = response->first_child; node; node = node->next_sibling) {
-			if (g_strcmp0 (node->tag_name, "photoid") == 0) {
+		for (node = DOM_ELEMENT (doc)->first_child; node; node = node->next_sibling) {
+			if (g_strcmp0 (node->tag_name, "pid") == 0) {
 				const char *id;
 
 				id = dom_element_get_inner_text (node);
@@ -704,7 +652,7 @@ post_photo_ready_cb (SoupSession *session,
 	}
 	else {
 		soup_buffer_free (body);
-		post_photos_done (self, error);
+		upload_photos_done (self, error);
 		return;
 	}
 
@@ -713,48 +661,25 @@ post_photo_ready_cb (SoupSession *session,
 	file_data = self->priv->post_photos->current->data;
 	self->priv->post_photos->uploaded_size += g_file_info_get_size (file_data->info);
 	self->priv->post_photos->current = self->priv->post_photos->current->next;
-	facebook_service_post_current_file (self);
-}
-
-
-static char *
-get_safety_value (FacebookSafetyType safety_level)
-{
-	char *value = NULL;
-
-	switch (safety_level) {
-	case FACEBOOK_SAFETY_SAFE:
-		value = "1";
-		break;
-
-	case FACEBOOK_SAFETY_MODERATE:
-		value = "2";
-		break;
-
-	case FACEBOOK_SAFETY_RESTRICTED:
-		value = "3";
-		break;
-	}
-
-	return value;
+	facebook_service_upload_current_file (self);
 }
 
 
 static void
-post_photo_file_buffer_ready_cb (void     **buffer,
-				 gsize      count,
-				 GError    *error,
-				 gpointer   user_data)
+upload_photo_file_buffer_ready_cb (void     **buffer,
+				   gsize      count,
+				   GError    *error,
+				   gpointer   user_data)
 {
 	FacebookService *self = user_data;
-	GthFileData   *file_data;
-	SoupMultipart *multipart;
-	char          *uri;
-	SoupBuffer    *body;
-	SoupMessage   *msg;
+	GthFileData     *file_data;
+	SoupMultipart   *multipart;
+	char            *uri;
+	SoupBuffer      *body;
+	SoupMessage     *msg;
 
 	if (error != NULL) {
-		post_photos_done (self, error);
+		upload_photos_done (self, error);
 		return;
 	}
 
@@ -767,33 +692,23 @@ post_photo_file_buffer_ready_cb (void     **buffer,
 		GHashTable *data_set;
 		char       *title;
 		char       *description;
-		char       *tags;
-		GObject    *metadata;
 		GList      *keys;
 		GList      *scan;
 
 		data_set = g_hash_table_new (g_str_hash, g_str_equal);
 
-		title = gth_file_data_get_attribute_as_string (file_data, "general::title");
-		if (title != NULL)
-			g_hash_table_insert (data_set, "title", title);
+		g_hash_table_insert (data_set, "method", "facebook.photos.upload");
 
+		title = gth_file_data_get_attribute_as_string (file_data, "general::title");
 		description = gth_file_data_get_attribute_as_string (file_data, "general::description");
 		if (description != NULL)
-			g_hash_table_insert (data_set, "description", description);
-
-		tags = NULL;
-		metadata = g_file_info_get_attribute_object (file_data->info, "general::tags");
-		if ((metadata != NULL) && GTH_IS_STRING_LIST (metadata))
-			tags = gth_string_list_join (GTH_STRING_LIST (metadata), " ");
-		if (tags != NULL)
-			g_hash_table_insert (data_set, "tags", tags);
-
-		g_hash_table_insert (data_set, "is_public", (self->priv->post_photos->privacy_level == FACEBOOK_PRIVACY_PUBLIC) ? "1" : "0");
-		g_hash_table_insert (data_set, "is_friend", ((self->priv->post_photos->privacy_level == FACEBOOK_PRIVACY_FRIENDS) || (self->priv->post_photos->privacy_level == FACEBOOK_PRIVACY_FRIENDS_FAMILY)) ? "1" : "0");
-		g_hash_table_insert (data_set, "is_family", ((self->priv->post_photos->privacy_level == FACEBOOK_PRIVACY_FAMILY) || (self->priv->post_photos->privacy_level == FACEBOOK_PRIVACY_FRIENDS_FAMILY)) ? "1" : "0");
-		g_hash_table_insert (data_set, "safety_level", get_safety_value (self->priv->post_photos->safety_level));
-		g_hash_table_insert (data_set, "hidden", self->priv->post_photos->hidden ? "2" : "1");
+			g_hash_table_insert (data_set, "caption", description);
+		else if (title != NULL)
+			g_hash_table_insert (data_set, "caption", title);
+
+		if (self->priv->post_photos->album != NULL)
+			g_hash_table_insert (data_set, "aid", self->priv->post_photos->album->id);
+
 		facebook_connection_add_api_sig (self->priv->conn, data_set);
 
 		keys = g_hash_table_get_keys (data_set);
@@ -802,7 +717,6 @@ post_photo_file_buffer_ready_cb (void     **buffer,
 			soup_multipart_append_form_string (multipart, key, g_hash_table_lookup (data_set, key));
 		}
 
-		g_free (tags);
 		g_list_free (keys);
 		g_hash_table_unref (data_set);
 	}
@@ -812,8 +726,8 @@ post_photo_file_buffer_ready_cb (void     **buffer,
 	uri = g_file_get_uri (file_data->file);
 	body = soup_buffer_new (SOUP_MEMORY_TEMPORARY, *buffer, count);
 	soup_multipart_append_form_file (multipart,
-					 "photo",
-					 uri,
+					 NULL,
+					 _g_uri_get_basename (uri),
 					 gth_file_data_get_mime_type (file_data),
 					 body);
 
@@ -835,27 +749,27 @@ post_photo_file_buffer_ready_cb (void     **buffer,
 		g_free (details);
 	}
 
-	msg = soup_form_request_new_from_multipart ("http://api.facebook.com/services/upload/";, multipart);
+	msg = soup_form_request_new_from_multipart (FACEBOOK_HTTPS_REST_SERVER, multipart);
 	facebook_connection_send_message (self->priv->conn,
-					msg,
-					self->priv->post_photos->cancellable,
-					self->priv->post_photos->callback,
-					self->priv->post_photos->user_data,
-					facebook_service_post_photos,
-					post_photo_ready_cb,
-					self);
+					  msg,
+					  self->priv->post_photos->cancellable,
+					  self->priv->post_photos->callback,
+					  self->priv->post_photos->user_data,
+					  facebook_service_upload_photos,
+					  upload_photo_ready_cb,
+					  self);
 
 	soup_multipart_free (multipart);
 }
 
 
 static void
-facebook_service_post_current_file (FacebookService *self)
+facebook_service_upload_current_file (FacebookService *self)
 {
 	GthFileData *file_data;
 
 	if (self->priv->post_photos->current == NULL) {
-		post_photos_done (self, NULL);
+		upload_photos_done (self, NULL);
 		return;
 	}
 
@@ -863,21 +777,21 @@ facebook_service_post_current_file (FacebookService *self)
 	g_load_file_async (file_data->file,
 			   G_PRIORITY_DEFAULT,
 			   self->priv->post_photos->cancellable,
-			   post_photo_file_buffer_ready_cb,
+			   upload_photo_file_buffer_ready_cb,
 			   self);
 }
 
 
 static void
-post_photos_info_ready_cb (GList    *files,
-		           GError   *error,
-		           gpointer  user_data)
+upload_photos_info_ready_cb (GList    *files,
+		             GError   *error,
+		             gpointer  user_data)
 {
 	FacebookService *self = user_data;
-	GList         *scan;
+	GList           *scan;
 
 	if (error != NULL) {
-		post_photos_done (self, error);
+		upload_photos_done (self, error);
 		return;
 	}
 
@@ -890,27 +804,23 @@ post_photos_info_ready_cb (GList    *files,
 	}
 
 	self->priv->post_photos->current = self->priv->post_photos->file_list;
-	facebook_service_post_current_file (self);
+	facebook_service_upload_current_file (self);
 }
 
 
 void
-facebook_service_post_photos (FacebookService       *self,
-			    FacebookPrivacyType    privacy_level,
-			    FacebookSafetyType     safety_level,
-			    gboolean             hidden,
-			    GList               *file_list, /* GFile list */
-			    GCancellable        *cancellable,
-			    GAsyncReadyCallback  callback,
-			    gpointer             user_data)
+facebook_service_upload_photos (FacebookService     *self,
+				FacebookAlbum       *album,
+				GList               *file_list, /* GFile list */
+				GCancellable        *cancellable,
+				GAsyncReadyCallback  callback,
+				gpointer             user_data)
 {
 	gth_task_progress (GTH_TASK (self->priv->conn), _("Uploading the files to the server"), NULL, TRUE, 0.0);
 
 	post_photos_data_free (self->priv->post_photos);
 	self->priv->post_photos = g_new0 (PostPhotosData, 1);
-	self->priv->post_photos->privacy_level = privacy_level;
-	self->priv->post_photos->safety_level = safety_level;
-	self->priv->post_photos->hidden = hidden;
+	self->priv->post_photos->album = _g_object_ref (album);
 	self->priv->post_photos->cancellable = _g_object_ref (cancellable);
 	self->priv->post_photos->callback = callback;
 	self->priv->post_photos->user_data = user_data;
@@ -922,15 +832,15 @@ facebook_service_post_photos (FacebookService       *self,
 				     TRUE,
 				     "*",
 				     self->priv->post_photos->cancellable,
-				     post_photos_info_ready_cb,
+				     upload_photos_info_ready_cb,
 				     self);
 }
 
 
 GList *
-facebook_service_post_photos_finish (FacebookService  *self,
-				   GAsyncResult   *result,
-				   GError        **error)
+facebook_service_upload_photos_finish (FacebookService  *self,
+				       GAsyncResult     *result,
+				       GError          **error)
 {
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
 		return NULL;
@@ -939,6 +849,8 @@ facebook_service_post_photos_finish (FacebookService  *self,
 }
 
 
+#if 0
+
 /* -- facebook_service_list_photos -- */
 
 
@@ -1064,6 +976,8 @@ facebook_service_list_photos_finish (FacebookService  *self,
 		return _g_object_list_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result)));
 }
 
+#endif
+
 
 /* utilities */
 
diff --git a/extensions/facebook/facebook-service.h b/extensions/facebook/facebook-service.h
index 88747b3..c356f7e 100644
--- a/extensions/facebook/facebook-service.h
+++ b/extensions/facebook/facebook-service.h
@@ -26,23 +26,10 @@
 #include <glib-object.h>
 #include "facebook-account.h"
 #include "facebook-connection.h"
-#include "facebook-photoset.h"
+#include "facebook-album.h"
+#include "facebook-types.h"
 #include "facebook-user.h"
 
-typedef enum {
-	FACEBOOK_PRIVACY_PUBLIC,
-	FACEBOOK_PRIVACY_FRIENDS_FAMILY,
-	FACEBOOK_PRIVACY_FRIENDS,
-	FACEBOOK_PRIVACY_FAMILY,
-	FACEBOOK_PRIVACY_PRIVATE
-} FacebookPrivacyType;
-
-typedef enum {
-	FACEBOOK_SAFETY_SAFE,
-	FACEBOOK_SAFETY_MODERATE,
-	FACEBOOK_SAFETY_RESTRICTED
-} FacebookSafetyType;
-
 #define FACEBOOK_TYPE_SERVICE         (facebook_service_get_type ())
 #define FACEBOOK_SERVICE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), FACEBOOK_TYPE_SERVICE, FacebookService))
 #define FACEBOOK_SERVICE_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), FACEBOOK_TYPE_SERVICE, FacebookServiceClass))
@@ -65,68 +52,63 @@ struct _FacebookServiceClass
 	GObjectClass __parent_class;
 };
 
-GType             facebook_service_get_type                 (void) G_GNUC_CONST;
-FacebookService *   facebook_service_new                      (FacebookConnection     *conn);
-void              facebook_service_get_upload_status        (FacebookService        *self,
-							   GCancellable         *cancellable,
-							   GAsyncReadyCallback   callback,
-							   gpointer              user_data);
-FacebookUser *      facebook_service_get_upload_status_finish (FacebookService        *self,
-						           GAsyncResult         *result,
-						           GError              **error);
-void              facebook_service_list_photosets           (FacebookService        *self,
-							   const char           *user_id,
-						           GCancellable         *cancellable,
-						           GAsyncReadyCallback   callback,
-						           gpointer              user_data);
-GList *           facebook_service_list_photosets_finish    (FacebookService        *self,
-						           GAsyncResult         *result,
-						           GError              **error);
-void              facebook_service_create_photoset          (FacebookService        *self,
-						           FacebookPhotoset       *photoset,
-						           GCancellable         *cancellable,
-						           GAsyncReadyCallback   callback,
-						           gpointer              user_data);
-FacebookPhotoset *  facebook_service_create_photoset_finish   (FacebookService        *self,
-						           GAsyncResult         *result,
-						           GError              **error);
-void              facebook_service_add_photos_to_set        (FacebookService        *self,
-						           FacebookPhotoset       *photoset,
-						           GList                *photo_ids,
-						           GCancellable         *cancellable,
-						           GAsyncReadyCallback   callback,
-						           gpointer              user_data);
-gboolean          facebook_service_add_photos_to_set_finish (FacebookService        *self,
-						           GAsyncResult         *result,
-						           GError              **error);
-void              facebook_service_post_photos              (FacebookService        *self,
-							   FacebookPrivacyType     privacy_level,
-							   FacebookSafetyType      safety_level,
-							   gboolean              hidden,
-						           GList                *file_list, /* GFile list */
-						           GCancellable         *cancellable,
-						           GAsyncReadyCallback   callback,
-						           gpointer              user_data);
-GList *           facebook_service_post_photos_finish       (FacebookService        *self,
-						           GAsyncResult         *result,
-						           GError              **error);
-void              facebook_service_list_photos              (FacebookService        *self,
-							   FacebookPhotoset       *photoset,
-							   const char           *extras,
-							   int                   per_page,
-							   int                   page,
-						           GCancellable         *cancellable,
-						           GAsyncReadyCallback   callback,
-						           gpointer              user_data);
-GList *           facebook_service_list_photos_finish       (FacebookService        *self,
-						           GAsyncResult         *result,
-						           GError              **error);
+GType             facebook_service_get_type                   (void) G_GNUC_CONST;
+FacebookService * facebook_service_new                        (FacebookConnection   *conn);
+void              facebook_service_get_logged_in_user         (FacebookService      *self,
+							       GCancellable         *cancellable,
+							       GAsyncReadyCallback   callback,
+							       gpointer              user_data);
+char *            facebook_service_get_logged_in_user_finish  (FacebookService      *self,
+						               GAsyncResult         *result,
+						               GError              **error);
+void              facebook_service_get_user_info              (FacebookService      *self,
+							       const char           *fields,
+							       GCancellable         *cancellable,
+							       GAsyncReadyCallback   callback,
+							       gpointer              user_data);
+FacebookUser *    facebook_service_get_user_info_finish       (FacebookService      *self,
+						               GAsyncResult         *result,
+						               GError              **error);
+void              facebook_service_get_albums                 (FacebookService      *self,
+							       const char           *user_id,
+							       GCancellable         *cancellable,
+							       GAsyncReadyCallback   callback,
+							       gpointer              user_data);
+GList *           facebook_service_get_albums_finish          (FacebookService      *self,
+							       GAsyncResult         *result,
+							       GError              **error);
+void              facebook_service_create_album               (FacebookService      *self,
+						               FacebookAlbum        *album,
+						               GCancellable         *cancellable,
+						               GAsyncReadyCallback   callback,
+						               gpointer              user_data);
+FacebookAlbum *   facebook_service_create_album_finish        (FacebookService      *self,
+						               GAsyncResult         *result,
+						               GError              **error);
+void              facebook_service_upload_photos              (FacebookService      *self,
+							       FacebookAlbum        *album,
+							       GList                *file_list, /* GFile list */
+							       GCancellable         *cancellable,
+							       GAsyncReadyCallback   callback,
+							       gpointer              user_data);
+GList *           facebook_service_upload_photos_finish       (FacebookService      *self,
+						               GAsyncResult         *result,
+						               GError              **error);
+#if 0
+void              facebook_service_list_photos                (FacebookService      *self,
+							       FacebookAlbum        *album,
+							       GAsyncReadyCallback   callback,
+							       gpointer              user_data);
+GList *           facebook_service_list_photos_finish         (FacebookService      *self,
+							       GAsyncResult         *result,
+							       GError              **error);
+#endif
 
 /* utilities */
 
-GList *          facebook_accounts_load_from_file  (void);
-FacebookAccount *  facebook_accounts_find_default    (GList         *accounts);
-void             facebook_accounts_save_to_file    (GList         *accounts,
-						  FacebookAccount *default_account);
+GList *            facebook_accounts_load_from_file  (void);
+FacebookAccount *  facebook_accounts_find_default    (GList           *accounts);
+void               facebook_accounts_save_to_file    (GList           *accounts,
+						      FacebookAccount *default_account);
 
 #endif /* FACEBOOK_SERVICE_H */
diff --git a/extensions/facebook/facebook-types.h b/extensions/facebook/facebook-types.h
index 949bdd5..a6c4ad3 100644
--- a/extensions/facebook/facebook-types.h
+++ b/extensions/facebook/facebook-types.h
@@ -23,29 +23,15 @@
 #ifndef FACEBOOK_TYPES_H
 #define FACEBOOK_TYPES_H
 
-typedef enum  {
-	FACEBOOK_SAFETY_LEVEL_SAFE = 1,
-	FACEBOOK_SAFETY_LEVEL_MODERATE = 2,
-	FACEBOOK_SAFETY_LEVEL_RESTRICTED = 3
-} FacebookSafetyLevel;
-
-typedef enum  {
-	FACEBOOK_CONTENT_TYPE_PHOTO = 1,
-	FACEBOOK_CONTENT_TYPE_SCREENSHOT = 2,
-	FACEBOOK_CONTENT_TYPE_OTHER = 3
-} FacebookContentType;
 
 typedef enum  {
-	FACEBOOK_HIDDEN_PUBLIC = 1,
-	FACEBOOK_HIDDEN_HIDDEN = 2,
-} FacebookHiddenType;
+	FACEBOOK_VISIBILITY_EVERYONE,
+	FACEBOOK_VISIBILITY_NETWORKS_FRIENDS,
+	FACEBOOK_VISIBILITY_FRIENDS_OF_FRIENDS,
+	FACEBOOK_VISIBILITY_ALL_FRIENDS,
+	FACEBOOK_VISIBILITY_SELF,
+	FACEBOOK_VISIBILITY_CUSTOM
+} FacebookVisibility;
 
-typedef enum {
-	FACEBOOK_SIZE_SMALL_SQUARE = 75,
-	FACEBOOK_SIZE_THUMBNAIL = 100,
-	FACEBOOK_SIZE_SMALL = 240,
-	FACEBOOK_SIZE_MEDIUM = 500,
-	FACEBOOK_SIZE_LARGE = 1024
-} FacebookSize;
 
 #endif /* FACEBOOK_TYPES_H */
diff --git a/extensions/facebook/facebook-user.c b/extensions/facebook/facebook-user.c
index e5697fd..91c9ee6 100644
--- a/extensions/facebook/facebook-user.c
+++ b/extensions/facebook/facebook-user.c
@@ -54,7 +54,7 @@ facebook_user_class_init (FacebookUserClass *klass)
 
 static DomElement*
 facebook_user_create_element (DomDomizable *base,
-			    DomDocument  *doc)
+			      DomDocument  *doc)
 {
 	FacebookUser *self;
 	DomElement *element;
@@ -64,6 +64,8 @@ facebook_user_create_element (DomDomizable *base,
 	element = dom_document_create_element (doc, "user", NULL);
 	if (self->id != NULL)
 		dom_element_set_attribute (element, "id", self->id);
+	if (self->username != NULL)
+		dom_element_set_attribute (element, "name", self->username);
 
 	return element;
 }
@@ -71,35 +73,19 @@ facebook_user_create_element (DomDomizable *base,
 
 static void
 facebook_user_load_from_element (DomDomizable *base,
-			       DomElement   *element)
+			         DomElement   *element)
 {
 	FacebookUser *self;
 	DomElement *node;
 
 	self = FACEBOOK_USER (base);
 
-	facebook_user_set_id (self, dom_element_get_attribute (element, "id"));
-	facebook_user_set_is_pro (self, dom_element_get_attribute (element, "ispro"));
-
 	for (node = element->first_child; node; node = node->next_sibling) {
-		if (g_strcmp0 (node->tag_name, "username") == 0) {
-			facebook_user_set_username (self, dom_element_get_inner_text (node));
-		}
-		else if (g_strcmp0 (node->tag_name, "bandwidth") == 0) {
-			facebook_user_set_max_bandwidth (self, dom_element_get_attribute (node, "maxbytes"));
-			facebook_user_set_used_bandwidth (self, dom_element_get_attribute (node, "usedbytes"));
-		}
-		else if (g_strcmp0 (node->tag_name, "filesize") == 0) {
-			facebook_user_set_max_filesize (self, dom_element_get_attribute (node, "maxbytes"));
+		if (g_strcmp0 (node->tag_name, "uid") == 0) {
+			_g_strset (&self->id, dom_element_get_inner_text (node));
 		}
-		else if (g_strcmp0 (node->tag_name, "videosize") == 0) {
-			facebook_user_set_max_videosize (self, dom_element_get_attribute (node, "maxbytes"));
-		}
-		else if (g_strcmp0 (node->tag_name, "sets") == 0) {
-			facebook_user_set_n_sets (self, dom_element_get_attribute (node, "created"));
-		}
-		else if (g_strcmp0 (node->tag_name, "videos") == 0) {
-			facebook_user_set_n_videos (self, dom_element_get_attribute (node, "uploaded"));
+		else if (g_strcmp0 (node->tag_name, "name") == 0) {
+			_g_strset (&self->username, dom_element_get_inner_text (node));
 		}
 	}
 }
@@ -146,9 +132,9 @@ facebook_user_get_type (void)
 		};
 
 		facebook_user_type_id = g_type_register_static (G_TYPE_OBJECT,
-								   "FacebookUser",
-								   &g_define_type_info,
-								   0);
+								"FacebookUser",
+								&g_define_type_info,
+								0);
 		g_type_add_interface_static (facebook_user_type_id, DOM_TYPE_DOMIZABLE, &dom_domizable_info);
 	}
 
@@ -165,83 +151,17 @@ facebook_user_new (void)
 
 void
 facebook_user_set_id (FacebookUser *self,
-		    const char *value)
-{
-	g_free (self->id);
-	self->id = NULL;
-	if (value != NULL)
-		self->id = g_strdup (value);
-}
-
-
-void
-facebook_user_set_is_pro (FacebookUser *self,
-			const char *value)
-{
-	self->is_pro = (g_strcmp0 (value, "1") == 0);
-}
-
-
-void
-facebook_user_set_username(FacebookUser *self,
-			 const char *value)
-{
-	g_free (self->username);
-	self->username = NULL;
-	if (value != NULL)
-		self->username = g_strdup (value);
-}
-
-
-void
-facebook_user_set_max_bandwidth (FacebookUser *self,
-			       const char *value)
+		      const char   *value)
 {
-	self->max_bandwidth = g_ascii_strtoull (value, NULL, 10);
+	_g_strset (&self->id, value);
 }
 
 
 void
-facebook_user_set_used_bandwidth (FacebookUser *self,
-				const char *value)
+facebook_user_set_username (FacebookUser *self,
+			    const char   *value)
 {
-	self->used_bandwidth = g_ascii_strtoull (value, NULL, 10);
+	_g_strset (&self->username, value);
 }
 
 
-void
-facebook_user_set_max_filesize (FacebookUser *self,
-			      const char *value)
-{
-	self->max_filesize = g_ascii_strtoull (value, NULL, 10);
-}
-
-
-void
-facebook_user_set_max_videosize (FacebookUser *self,
-			       const char *value)
-{
-	self->max_videosize = g_ascii_strtoull (value, NULL, 10);
-}
-
-
-void
-facebook_user_set_n_sets (FacebookUser *self,
-			const char *value)
-{
-	if (value != NULL)
-		self->n_sets = atoi (value);
-	else
-		self->n_sets = 0;
-}
-
-
-void
-facebook_user_set_n_videos (FacebookUser *self,
-			  const char *value)
-{
-	if (value != NULL)
-		self->n_videos = atoi (value);
-	else
-		self->n_videos = 0;
-}
diff --git a/extensions/facebook/facebook-user.h b/extensions/facebook/facebook-user.h
index f4c6b8a..b6c0a9a 100644
--- a/extensions/facebook/facebook-user.h
+++ b/extensions/facebook/facebook-user.h
@@ -41,41 +41,20 @@ typedef struct _FacebookUserClass FacebookUserClass;
 struct _FacebookUser {
 	GObject parent_instance;
 
-	char     *id;
-	gboolean  is_pro;
-	char     *username;
-	goffset   max_bandwidth;
-	goffset   used_bandwidth;
-	goffset   max_filesize;
-	goffset   max_videosize;
-	int       n_sets;
-	int       n_videos;
+	char *id;
+	char *username;
 };
 
 struct _FacebookUserClass {
 	GObjectClass parent_class;
 };
 
-GType             facebook_user_get_type             (void);
-FacebookUser *    facebook_user_new                  (void);
-void              facebook_user_set_id               (FacebookUser *self,
-						      const char   *value);
-void              facebook_user_set_is_pro           (FacebookUser *self,
-						      const char   *value);
-void              facebook_user_set_username         (FacebookUser *self,
-						      const char   *value);
-void              facebook_user_set_max_bandwidth    (FacebookUser *self,
-						      const char   *value);
-void              facebook_user_set_used_bandwidth   (FacebookUser *self,
-						      const char   *value);
-void              facebook_user_set_max_filesize     (FacebookUser *self,
-						      const char   *value);
-void              facebook_user_set_max_videosize    (FacebookUser *self,
-						      const char   *value);
-void              facebook_user_set_n_sets           (FacebookUser *self,
-						      const char   *value);
-void              facebook_user_set_n_videos         (FacebookUser *self,
-						      const char   *value);
+GType          facebook_user_get_type     (void);
+FacebookUser * facebook_user_new          (void);
+void           facebook_user_set_id       (FacebookUser *self,
+				           const char   *value);
+void           facebook_user_set_username (FacebookUser *self,
+				           const char   *value);
 
 G_END_DECLS
 
diff --git a/extensions/facebook/facebook.extension.in.in b/extensions/facebook/facebook.extension.in.in
index 3edd9de..ad73f88 100644
--- a/extensions/facebook/facebook.extension.in.in
+++ b/extensions/facebook/facebook.extension.in.in
@@ -1,5 +1,5 @@
 [Extension]
-_Name=Flicker
+_Name=Facebook
 _Description=Upload images to Facebook
 Authors=gthumb development team
 Copyright=Copyright © 2010 The Free Software Foundation, Inc.
diff --git a/extensions/flicker/flickr-authentication.c b/extensions/flicker/flickr-authentication.c
index c4ea164..83037b4 100644
--- a/extensions/flicker/flickr-authentication.c
+++ b/extensions/flicker/flickr-authentication.c
@@ -58,7 +58,7 @@ static guint flickr_authentication_signals[LAST_SIGNAL] = { 0 };
 GQuark
 flickr_authentication_error_quark (void)
 {
-	return g_quark_from_static_string ("gth-task-error-quark");
+	return g_quark_from_static_string ("flickr-authentication-error-quark");
 }
 
 
@@ -168,6 +168,7 @@ flickr_authentication_new (FlickrConnection *conn,
 	self->priv->cancellable = _g_object_ref (cancellable);
 	self->priv->accounts = flickr_accounts_load_from_file ();
 	self->priv->account = flickr_accounts_find_default (self->priv->accounts);
+	self->priv->browser = browser;
 	self->priv->dialog = dialog;
 
 	return self;
@@ -380,8 +381,8 @@ complete_authorization (FlickrAuthentication *self)
 
 	builder = _gtk_builder_new_from_file ("flicker-complete-authorization.ui", "flicker");
 	dialog = _gtk_builder_get_widget (builder, "complete_authorization_messagedialog");
-	text = g_strdup_printf ("Return to this window when you have finished the authorization process on %s", self->priv->conn->server->name);
-	secondary_text = g_strdup ("Once you're done, click the 'Continue' button below.");
+	text = g_strdup_printf (_("Return to this window when you have finished the authorization process on %s"), self->priv->conn->server->name);
+	secondary_text = g_strdup (_("Once you're done, click the 'Continue' button below."));
 	g_object_set (dialog, "text", text, "secondary-text", secondary_text, NULL);
 	g_object_set_data_full (G_OBJECT (dialog), "builder", builder, g_object_unref);
 	g_signal_connect (dialog,
@@ -459,8 +460,8 @@ ask_authorization (FlickrAuthentication *self)
 
 	builder = _gtk_builder_new_from_file ("flicker-ask-authorization.ui", "flicker");
 	dialog = _gtk_builder_get_widget (builder, "ask_authorization_messagedialog");
-	text = g_strdup_printf ("gthumb requires your authorization to upload the photos to %s", self->priv->conn->server->name);
-	secondary_text = g_strdup_printf ("Click 'Authorize' to open your web browser and authorize gthumb to upload photos to %s. When you're finished, return to this window to complete the authorization.", self->priv->conn->server->name);
+	text = g_strdup_printf (_("gthumb requires your authorization to upload the photos to %s"), self->priv->conn->server->name);
+	secondary_text = g_strdup_printf (_("Click 'Authorize' to open your web browser and authorize gthumb to upload photos to %s. When you're finished, return to this window to complete the authorization."), self->priv->conn->server->name);
 	g_object_set (dialog, "text", text, "secondary-text", secondary_text, NULL);
 	g_object_set_data_full (G_OBJECT (dialog), "builder", builder, g_object_unref);
 	g_signal_connect (dialog,
diff --git a/gthumb/gth-progress-dialog.c b/gthumb/gth-progress-dialog.c
index 919e57e..e5b3cdd 100644
--- a/gthumb/gth-progress-dialog.c
+++ b/gthumb/gth-progress-dialog.c
@@ -258,6 +258,7 @@ static gpointer gth_progress_dialog_parent_class = NULL;
 
 
 struct _GthProgressDialogPrivate {
+	GtkWindow *parent;
 	GtkWidget *task_box;
 	gulong     show_event;
 	gboolean   custom_dialog_opened;
@@ -357,7 +358,7 @@ gth_progress_dialog_new (GtkWindow *parent)
 	GthProgressDialog *self;
 
 	self = g_object_new (GTH_TYPE_PROGRESS_DIALOG, NULL);
-	gtk_window_set_transient_for (GTK_WINDOW (self), parent);
+	self->priv->parent = parent;
 
 	return (GtkWidget *) self;
 }
@@ -373,8 +374,10 @@ _show_dialog_cb (gpointer data)
 		self->priv->show_event = 0;
 	}
 
-	if (! self->priv->custom_dialog_opened && (_gtk_container_get_n_children (GTK_CONTAINER (self->priv->task_box)) > 0))
+	if (! self->priv->custom_dialog_opened && (_gtk_container_get_n_children (GTK_CONTAINER (self->priv->task_box)) > 0)) {
+		gtk_window_set_transient_for (GTK_WINDOW (self), self->priv->parent);
 		gtk_window_present (GTK_WINDOW (self));
+	}
 
 	return FALSE;
 }
@@ -394,6 +397,7 @@ task_dialog_cb (GthTask  *task,
 			self->priv->show_event = 0;
 		}
 		gtk_widget_hide (GTK_WIDGET (self));
+		gtk_window_set_transient_for (GTK_WINDOW (self), NULL);
 	}
 	else if (self->priv->show_event == 0)
 		self->priv->show_event = g_timeout_add (SHOW_DELAY, _show_dialog_cb, self);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]