diff -Nru gdata-sharp-1.4.0.2/debian/changelog gdata-sharp-1.7.0.1/debian/changelog --- gdata-sharp-1.4.0.2/debian/changelog 2011-02-23 18:24:36.000000000 +0000 +++ gdata-sharp-1.7.0.1/debian/changelog 2011-02-23 18:04:58.000000000 +0000 @@ -1,3 +1,78 @@ +gdata-sharp (1.7.0.1-1~lucid1) lucid; urgency=low + + * Merge from Maverick, remaining changes: + + [e80a685] Drop monodoc support (doesn't build) + + -- Chow Loong Jin Thu, 24 Feb 2011 02:02:05 +0800 + +gdata-sharp (1.7.0.1-1~maverick1) maverick; urgency=low + + * Backport to maverick + + -- Chow Loong Jin Thu, 24 Feb 2011 02:01:26 +0800 + +gdata-sharp (1.7.0.1-1~natty1) natty; urgency=low + + * Backport to natty + + -- Chow Loong Jin Thu, 24 Feb 2011 02:01:01 +0800 + +gdata-sharp (1.7.0.1-1) unstable; urgency=low + + * [862be2e] New upstream release + * [ab5b875] Update remove-system-web-dep.patch from upstream + * [b7c7a7d] Refresh pkgconfig-paths patch + * [b68b4b5] Drop 02_cli-2.0-port.patch (no longer needed) + * [0cc6766] Add Google.GData.Analytics to control file + * [b9dec4f] Bump ABI and API versions + * [eacb398] Use 3.0 (quilt) format + * [6f77271] Refresh 00_build-system.patch + * [85ca24a] Update my email in Uploaders + + -- Chow Loong Jin Thu, 10 Feb 2011 10:34:31 +0800 + +gdata-sharp (1.4.0.2-5~lucid1) lucid; urgency=low + + * Backport to lucid + + [e80a685] Drop monodoc support (doesn't build) + + -- Chow Loong Jin Sun, 16 Jan 2011 02:31:57 +0800 + +gdata-sharp (1.4.0.2-5~maverick1) maverick; urgency=low + + * Backport to maverick + + -- Chow Loong Jin Sun, 16 Jan 2011 01:42:02 +0800 + +gdata-sharp (1.4.0.2-5~natty1) natty; urgency=low + + * Backport to natty + + -- Chow Loong Jin Sun, 16 Jan 2011 01:42:01 +0800 + +gdata-sharp (1.4.0.2-5) experimental; urgency=low + + * [257ae00] Set Debian source format to 1.0 + * [3ba66e6] Update Debian Policy to 3.9.1 (no changes) + * [e326188] Add a patch from upstream bug #429, which removes the + dependency on System.Web. gdata-sharp already bundles a chunk of + Mono's System.Web source code, for use on Windows CE (which lacks re + required methods). This patch simply adds the rest of the System.Web + pieces used by gdata-sharp, and makes the file part of the build on + all platforms, not just Windows CE. Thanks to Gabriel Burt + + + -- Jo Shields Sat, 13 Nov 2010 11:30:56 +0000 + +gdata-sharp (1.4.0.2-4) unstable; urgency=low + + * [2237ad3] Fix build-dependencies to use mono-devel 2.4.3's + monolithic mono-devel, and use NUnit's -cil-dev package + * [3a91407] Fix calls to mdoc to not only fix FTBFS, but actually + generate documentation (Closes #598175) + + -- Jo Shields Mon, 27 Sep 2010 09:44:50 +0100 + gdata-sharp (1.4.0.2-3) unstable; urgency=low [ Jo Shields ] diff -Nru gdata-sharp-1.4.0.2/debian/control gdata-sharp-1.7.0.1/debian/control --- gdata-sharp-1.4.0.2/debian/control 2011-02-23 18:24:36.000000000 +0000 +++ gdata-sharp-1.7.0.1/debian/control 2011-02-23 18:04:58.000000000 +0000 @@ -2,19 +2,17 @@ Section: cli-mono Priority: optional Maintainer: Debian CLI Libraries Team -Uploaders: Chow Loong Jin +Uploaders: Chow Loong Jin Build-Depends: debhelper (>= 7.0.50), - quilt (>= 0.46-7~), cli-common-dev (>= 0.5.7), mono-devel (>= 2.4.3), -Build-Depends-Indep: libnunit-cil-dev, - monodoc-base (>= 2.4+dfsg) -Standards-Version: 3.8.3 +Build-Depends-Indep: libnunit-cil-dev +Standards-Version: 3.9.1 Vcs-Git: git://git.debian.org/git/pkg-cli-libs/packages/gdata-sharp.git Vcs-Browser: http://git.debian.org/?p=pkg-cli-libs/packages/gdata-sharp.git Homepage: http://code.google.com/p/google-gdata/ -Package: libgdata1.4-cil +Package: libgdata1.7-cil Architecture: all Depends: ${misc:Depends}, ${cli:Depends} Description: Google GData CLI client library @@ -42,8 +40,7 @@ Package: libgdata-cil-dev Architecture: all -Depends: libgdata1.4-cil (= ${binary:Version}), ${misc:Depends} -Replaces: libgdata1.4-cil (<< 1.4.0.2-3) +Depends: libgdata1.7-cil (= ${binary:Version}), ${misc:Depends} Description: Google GData CLI client library GData (Google data) is a set of Application Programming Interfaces (APIs) for the Common Language Infrastructure (CLI) which provide a simple protocol for @@ -67,27 +64,3 @@ . This package contains development files for the GData library, and should be used for compilation - -Package: monodoc-gdata-manual -Section: doc -Architecture: all -Depends: monodoc-manual, ${misc:Depends} -Description: compiled XML documentation for GData - GData (Google data) is a set of Application Programming Interfaces (APIs) for - the Common Language Infrastructure (CLI) which provide a simple protocol for - reading and writing data on the web. - . - Each of the following Google services provides a Google data API: - * Base - * Blogger - * Calendar - * Code Search - * Contacts - * Document List - * Google Apps Provisioning - * Notebook - * Picasa Web Albums - * Spreadsheets - * YouTube - . - This package contains the compiled XML documentation for GData diff -Nru gdata-sharp-1.4.0.2/debian/gbp.conf gdata-sharp-1.7.0.1/debian/gbp.conf --- gdata-sharp-1.4.0.2/debian/gbp.conf 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/debian/gbp.conf 2011-02-23 18:04:58.000000000 +0000 @@ -0,0 +1,2 @@ +[DEFAULT] +debian-branch = ppa/lucid diff -Nru gdata-sharp-1.4.0.2/debian/libgdata1.4-cil.install gdata-sharp-1.7.0.1/debian/libgdata1.4-cil.install --- gdata-sharp-1.4.0.2/debian/libgdata1.4-cil.install 2011-02-23 18:24:36.000000000 +0000 +++ gdata-sharp-1.7.0.1/debian/libgdata1.4-cil.install 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -debian/tmp/usr/lib/mono/gac/Google.GData.AccessControl/*/* /usr/lib/cli/Google.GData.AccessControl-1.4/ -debian/tmp/usr/lib/mono/gac/Google.GData.Apps/*/* /usr/lib/cli/Google.GData.Apps-1.4/ -debian/tmp/usr/lib/mono/gac/Google.GData.Blogger/*/* /usr/lib/cli/Google.GData.Blogger-1.4/ -debian/tmp/usr/lib/mono/gac/Google.GData.Calendar/*/* /usr/lib/cli/Google.GData.Calendar-1.4/ -debian/tmp/usr/lib/mono/gac/Google.GData.Client/*/* /usr/lib/cli/Google.GData.Client-1.4/ -debian/tmp/usr/lib/mono/gac/Google.GData.CodeSearch/*/* /usr/lib/cli/Google.GData.CodeSearch-1.4/ -debian/tmp/usr/lib/mono/gac/Google.GData.Contacts/*/* /usr/lib/cli/Google.GData.Contacts-1.4/ -debian/tmp/usr/lib/mono/gac/Google.GData.Documents/*/* /usr/lib/cli/Google.GData.Documents-1.4/ -debian/tmp/usr/lib/mono/gac/Google.GData.Extensions/*/* /usr/lib/cli/Google.GData.Extensions-1.4/ -debian/tmp/usr/lib/mono/gac/Google.GData.GoogleBase/*/* /usr/lib/cli/Google.GData.GoogleBase-1.4/ -debian/tmp/usr/lib/mono/gac/Google.GData.Health/*/* /usr/lib/cli/Google.GData.Health-1.4/ -debian/tmp/usr/lib/mono/gac/Google.GData.Photos/*/* /usr/lib/cli/Google.GData.Photos-1.4/ -debian/tmp/usr/lib/mono/gac/Google.GData.Spreadsheets/*/* /usr/lib/cli/Google.GData.Spreadsheets-1.4/ -debian/tmp/usr/lib/mono/gac/Google.GData.YouTube/*/* /usr/lib/cli/Google.GData.YouTube-1.4/ diff -Nru gdata-sharp-1.4.0.2/debian/libgdata1.4-cil.installcligac gdata-sharp-1.7.0.1/debian/libgdata1.4-cil.installcligac --- gdata-sharp-1.4.0.2/debian/libgdata1.4-cil.installcligac 2011-02-23 18:24:36.000000000 +0000 +++ gdata-sharp-1.7.0.1/debian/libgdata1.4-cil.installcligac 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -/usr/lib/cli/Google.GData.AccessControl-1.4/Google.GData.AccessControl.dll -/usr/lib/cli/Google.GData.Apps-1.4/Google.GData.Apps.dll -/usr/lib/cli/Google.GData.Blogger-1.4/Google.GData.Blogger.dll -/usr/lib/cli/Google.GData.Calendar-1.4/Google.GData.Calendar.dll -/usr/lib/cli/Google.GData.Client-1.4/Google.GData.Client.dll -/usr/lib/cli/Google.GData.CodeSearch-1.4/Google.GData.CodeSearch.dll -/usr/lib/cli/Google.GData.Contacts-1.4/Google.GData.Contacts.dll -/usr/lib/cli/Google.GData.Documents-1.4/Google.GData.Documents.dll -/usr/lib/cli/Google.GData.Extensions-1.4/Google.GData.Extensions.dll -/usr/lib/cli/Google.GData.GoogleBase-1.4/Google.GData.GoogleBase.dll -/usr/lib/cli/Google.GData.Health-1.4/Google.GData.Health.dll -/usr/lib/cli/Google.GData.Photos-1.4/Google.GData.Photos.dll -/usr/lib/cli/Google.GData.Spreadsheets-1.4/Google.GData.Spreadsheets.dll -/usr/lib/cli/Google.GData.YouTube-1.4/Google.GData.YouTube.dll diff -Nru gdata-sharp-1.4.0.2/debian/libgdata1.7-cil.install gdata-sharp-1.7.0.1/debian/libgdata1.7-cil.install --- gdata-sharp-1.4.0.2/debian/libgdata1.7-cil.install 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/debian/libgdata1.7-cil.install 2011-02-23 18:04:58.000000000 +0000 @@ -0,0 +1,15 @@ +debian/tmp/usr/lib/mono/gac/Google.GData.AccessControl/*/* /usr/lib/cli/Google.GData.AccessControl-1.7/ +debian/tmp/usr/lib/mono/gac/Google.GData.Analytics/*/* /usr/lib/cli/Google.GData.Analytics-1.7/ +debian/tmp/usr/lib/mono/gac/Google.GData.Apps/*/* /usr/lib/cli/Google.GData.Apps-1.7/ +debian/tmp/usr/lib/mono/gac/Google.GData.Blogger/*/* /usr/lib/cli/Google.GData.Blogger-1.7/ +debian/tmp/usr/lib/mono/gac/Google.GData.Calendar/*/* /usr/lib/cli/Google.GData.Calendar-1.7/ +debian/tmp/usr/lib/mono/gac/Google.GData.Client/*/* /usr/lib/cli/Google.GData.Client-1.7/ +debian/tmp/usr/lib/mono/gac/Google.GData.CodeSearch/*/* /usr/lib/cli/Google.GData.CodeSearch-1.7/ +debian/tmp/usr/lib/mono/gac/Google.GData.Contacts/*/* /usr/lib/cli/Google.GData.Contacts-1.7/ +debian/tmp/usr/lib/mono/gac/Google.GData.Documents/*/* /usr/lib/cli/Google.GData.Documents-1.7/ +debian/tmp/usr/lib/mono/gac/Google.GData.Extensions/*/* /usr/lib/cli/Google.GData.Extensions-1.7/ +debian/tmp/usr/lib/mono/gac/Google.GData.GoogleBase/*/* /usr/lib/cli/Google.GData.GoogleBase-1.7/ +debian/tmp/usr/lib/mono/gac/Google.GData.Health/*/* /usr/lib/cli/Google.GData.Health-1.7/ +debian/tmp/usr/lib/mono/gac/Google.GData.Photos/*/* /usr/lib/cli/Google.GData.Photos-1.7/ +debian/tmp/usr/lib/mono/gac/Google.GData.Spreadsheets/*/* /usr/lib/cli/Google.GData.Spreadsheets-1.7/ +debian/tmp/usr/lib/mono/gac/Google.GData.YouTube/*/* /usr/lib/cli/Google.GData.YouTube-1.7/ diff -Nru gdata-sharp-1.4.0.2/debian/libgdata1.7-cil.installcligac gdata-sharp-1.7.0.1/debian/libgdata1.7-cil.installcligac --- gdata-sharp-1.4.0.2/debian/libgdata1.7-cil.installcligac 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/debian/libgdata1.7-cil.installcligac 2011-02-23 18:04:58.000000000 +0000 @@ -0,0 +1,14 @@ +/usr/lib/cli/Google.GData.AccessControl-1.7/Google.GData.AccessControl.dll +/usr/lib/cli/Google.GData.Apps-1.7/Google.GData.Apps.dll +/usr/lib/cli/Google.GData.Blogger-1.7/Google.GData.Blogger.dll +/usr/lib/cli/Google.GData.Calendar-1.7/Google.GData.Calendar.dll +/usr/lib/cli/Google.GData.Client-1.7/Google.GData.Client.dll +/usr/lib/cli/Google.GData.CodeSearch-1.7/Google.GData.CodeSearch.dll +/usr/lib/cli/Google.GData.Contacts-1.7/Google.GData.Contacts.dll +/usr/lib/cli/Google.GData.Documents-1.7/Google.GData.Documents.dll +/usr/lib/cli/Google.GData.Extensions-1.7/Google.GData.Extensions.dll +/usr/lib/cli/Google.GData.GoogleBase-1.7/Google.GData.GoogleBase.dll +/usr/lib/cli/Google.GData.Health-1.7/Google.GData.Health.dll +/usr/lib/cli/Google.GData.Photos-1.7/Google.GData.Photos.dll +/usr/lib/cli/Google.GData.Spreadsheets-1.7/Google.GData.Spreadsheets.dll +/usr/lib/cli/Google.GData.YouTube-1.7/Google.GData.YouTube.dll diff -Nru gdata-sharp-1.4.0.2/debian/monodoc-gdata-manual.install gdata-sharp-1.7.0.1/debian/monodoc-gdata-manual.install --- gdata-sharp-1.4.0.2/debian/monodoc-gdata-manual.install 2011-02-23 18:24:36.000000000 +0000 +++ gdata-sharp-1.7.0.1/debian/monodoc-gdata-manual.install 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -debian/GData.source /usr/lib/monodoc/sources -GData.tree /usr/lib/monodoc/sources -GData.zip /usr/lib/monodoc/sources diff -Nru gdata-sharp-1.4.0.2/debian/patches/00_build-system.patch gdata-sharp-1.7.0.1/debian/patches/00_build-system.patch --- gdata-sharp-1.4.0.2/debian/patches/00_build-system.patch 2011-02-23 18:24:36.000000000 +0000 +++ gdata-sharp-1.7.0.1/debian/patches/00_build-system.patch 2011-02-23 18:04:58.000000000 +0000 @@ -1,9 +1,9 @@ Index: gdata-sharp/Makefile =================================================================== ---- gdata-sharp.orig/Makefile 2009-03-16 19:47:02.000000000 +0800 -+++ gdata-sharp/Makefile 2009-03-16 19:47:24.000000000 +0800 -@@ -128,7 +128,7 @@ - for i in $(PKGCONFIG_FILES) ; do rm "$(DESTDIR)$(PREFIX)/lib/pkgconfig/$$i" ; done +--- gdata-sharp.orig/Makefile 2011-02-10 10:31:46.295372901 +0800 ++++ gdata-sharp/Makefile 2011-02-10 10:31:47.572670311 +0800 +@@ -137,7 +137,7 @@ + for i in $(PKGCONFIG_FILES) ; do rm "$(DESTDIR)$(PKGCONFIGDIR)/$$i" ; done tests: $(ALLLIBS) - $(CSC) $(DEFINES) -target:library -out:unittests.dll $(ALLREFS) -r:nunit.framework.dll $(test_sources) diff -Nru gdata-sharp-1.4.0.2/debian/patches/01_pkgconfig-paths.patch gdata-sharp-1.7.0.1/debian/patches/01_pkgconfig-paths.patch --- gdata-sharp-1.4.0.2/debian/patches/01_pkgconfig-paths.patch 2011-02-23 18:24:36.000000000 +0000 +++ gdata-sharp-1.7.0.1/debian/patches/01_pkgconfig-paths.patch 2011-02-23 18:04:58.000000000 +0000 @@ -1,117 +1,140 @@ -diff -urNad gdata-sharp-1.4.0.2~/misc/gdata-sharp-acl.pc.in gdata-sharp-1.4.0.2/misc/gdata-sharp-acl.pc.in ---- gdata-sharp-1.4.0.2~/misc/gdata-sharp-acl.pc.in 2009-11-23 12:59:43.403604753 +0000 -+++ gdata-sharp-1.4.0.2/misc/gdata-sharp-acl.pc.in 2009-11-23 12:59:51.001113164 +0000 +Index: gdata-sharp/misc/gdata-sharp-acl.pc.in +=================================================================== +--- gdata-sharp.orig/misc/gdata-sharp-acl.pc.in 2011-02-10 10:32:08.446311299 +0800 ++++ gdata-sharp/misc/gdata-sharp-acl.pc.in 2011-02-11 02:19:49.650791230 +0800 @@ -6,4 +6,4 @@ Version: @VERSION@ Requires: gdata-sharp-core -Libs: -r:${libdir}/mono/GData-Sharp/Google.GData.AccessControl.dll -+Libs: -r:${libdir}/cli/Google.GData.AccessControl-1.4/Google.GData.AccessControl.dll -diff -urNad gdata-sharp-1.4.0.2~/misc/gdata-sharp-apps.pc.in gdata-sharp-1.4.0.2/misc/gdata-sharp-apps.pc.in ---- gdata-sharp-1.4.0.2~/misc/gdata-sharp-apps.pc.in 2009-11-23 12:59:43.403604753 +0000 -+++ gdata-sharp-1.4.0.2/misc/gdata-sharp-apps.pc.in 2009-11-23 12:59:51.001113164 +0000 ++Libs: -r:${libdir}/cli/Google.GData.AccessControl-1.7/Google.GData.AccessControl.dll +Index: gdata-sharp/misc/gdata-sharp-apps.pc.in +=================================================================== +--- gdata-sharp.orig/misc/gdata-sharp-apps.pc.in 2011-02-10 10:32:08.506340944 +0800 ++++ gdata-sharp/misc/gdata-sharp-apps.pc.in 2011-02-11 02:19:49.650791230 +0800 @@ -6,4 +6,4 @@ Version: @VERSION@ Requires: gdata-sharp-core -Libs: -r:${libdir}/mono/GData-Sharp/Google.GData.Apps.dll -+Libs: -r:${libdir}/cli/Google.GData.Apps-1.4/Google.GData.Apps.dll -diff -urNad gdata-sharp-1.4.0.2~/misc/gdata-sharp-base.pc.in gdata-sharp-1.4.0.2/misc/gdata-sharp-base.pc.in ---- gdata-sharp-1.4.0.2~/misc/gdata-sharp-base.pc.in 2009-11-23 12:59:43.403604753 +0000 -+++ gdata-sharp-1.4.0.2/misc/gdata-sharp-base.pc.in 2009-11-23 12:59:51.001113164 +0000 ++Libs: -r:${libdir}/cli/Google.GData.Apps-1.7/Google.GData.Apps.dll +Index: gdata-sharp/misc/gdata-sharp-base.pc.in +=================================================================== +--- gdata-sharp.orig/misc/gdata-sharp-base.pc.in 2011-02-10 10:32:08.482996082 +0800 ++++ gdata-sharp/misc/gdata-sharp-base.pc.in 2011-02-11 02:19:49.650791230 +0800 @@ -6,4 +6,4 @@ Version: @VERSION@ Requires: gdata-sharp-core -Libs: -r:${libdir}/mono/GData-Sharp/Google.GData.GoogleBase.dll -+Libs: -r:${libdir}/cli/Google.GData.GoogleBase-1.4/Google.GData.GoogleBase.dll -diff -urNad gdata-sharp-1.4.0.2~/misc/gdata-sharp-blogger.pc.in gdata-sharp-1.4.0.2/misc/gdata-sharp-blogger.pc.in ---- gdata-sharp-1.4.0.2~/misc/gdata-sharp-blogger.pc.in 2009-11-23 12:59:43.403604753 +0000 -+++ gdata-sharp-1.4.0.2/misc/gdata-sharp-blogger.pc.in 2009-11-23 12:59:51.001113164 +0000 ++Libs: -r:${libdir}/cli/Google.GData.GoogleBase-1.7/Google.GData.GoogleBase.dll +Index: gdata-sharp/misc/gdata-sharp-blogger.pc.in +=================================================================== +--- gdata-sharp.orig/misc/gdata-sharp-blogger.pc.in 2011-02-10 10:32:08.513010905 +0800 ++++ gdata-sharp/misc/gdata-sharp-blogger.pc.in 2011-02-11 02:19:49.650791230 +0800 @@ -6,4 +6,4 @@ Version: @VERSION@ Requires: gdata-sharp-core -Libs: -r:${libdir}/mono/GData-Sharp/Google.GData.Blogger.dll -+Libs: -r:${libdir}/cli/Google.GData.Blogger-1.4/Google.GData.Blogger.dll -diff -urNad gdata-sharp-1.4.0.2~/misc/gdata-sharp-calendar.pc.in gdata-sharp-1.4.0.2/misc/gdata-sharp-calendar.pc.in ---- gdata-sharp-1.4.0.2~/misc/gdata-sharp-calendar.pc.in 2009-11-23 12:59:43.393613331 +0000 -+++ gdata-sharp-1.4.0.2/misc/gdata-sharp-calendar.pc.in 2009-11-23 12:59:51.001113164 +0000 ++Libs: -r:${libdir}/cli/Google.GData.Blogger-1.7/Google.GData.Blogger.dll +Index: gdata-sharp/misc/gdata-sharp-calendar.pc.in +=================================================================== +--- gdata-sharp.orig/misc/gdata-sharp-calendar.pc.in 2011-02-10 10:32:08.452981261 +0800 ++++ gdata-sharp/misc/gdata-sharp-calendar.pc.in 2011-02-11 02:19:49.650791230 +0800 @@ -6,4 +6,4 @@ Version: @VERSION@ Requires: gdata-sharp-core gdata-sharp-acl -Libs: -r:${libdir}/mono/GData-Sharp/Google.GData.Calendar.dll -+Libs: -r:${libdir}/cli/Google.GData.Calendar-1.4/Google.GData.Calendar.dll -diff -urNad gdata-sharp-1.4.0.2~/misc/gdata-sharp-codesearch.pc.in gdata-sharp-1.4.0.2/misc/gdata-sharp-codesearch.pc.in ---- gdata-sharp-1.4.0.2~/misc/gdata-sharp-codesearch.pc.in 2009-11-23 12:59:43.403604753 +0000 -+++ gdata-sharp-1.4.0.2/misc/gdata-sharp-codesearch.pc.in 2009-11-23 12:59:51.001113164 +0000 ++Libs: -r:${libdir}/cli/Google.GData.Calendar-1.7/Google.GData.Calendar.dll +Index: gdata-sharp/misc/gdata-sharp-codesearch.pc.in +=================================================================== +--- gdata-sharp.orig/misc/gdata-sharp-codesearch.pc.in 2011-02-10 10:32:08.526350825 +0800 ++++ gdata-sharp/misc/gdata-sharp-codesearch.pc.in 2011-02-11 02:19:49.650791230 +0800 @@ -6,4 +6,4 @@ Version: @VERSION@ Requires: gdata-sharp-core -Libs: -r:${libdir}/mono/GData-Sharp/Google.GData.CodeSearch.dll -+Libs: -r:${libdir}/cli/Google.GData.CodeSearch-1.4/Google.GData.CodeSearch.dll -diff -urNad gdata-sharp-1.4.0.2~/misc/gdata-sharp-contacts.pc.in gdata-sharp-1.4.0.2/misc/gdata-sharp-contacts.pc.in ---- gdata-sharp-1.4.0.2~/misc/gdata-sharp-contacts.pc.in 2009-11-23 12:59:43.403604753 +0000 -+++ gdata-sharp-1.4.0.2/misc/gdata-sharp-contacts.pc.in 2009-11-23 12:59:51.001113164 +0000 ++Libs: -r:${libdir}/cli/Google.GData.CodeSearch-1.7/Google.GData.CodeSearch.dll +Index: gdata-sharp/misc/gdata-sharp-contacts.pc.in +=================================================================== +--- gdata-sharp.orig/misc/gdata-sharp-contacts.pc.in 2011-02-10 10:32:08.466321182 +0800 ++++ gdata-sharp/misc/gdata-sharp-contacts.pc.in 2011-02-11 02:19:49.650791230 +0800 @@ -6,4 +6,4 @@ Version: @VERSION@ Requires: gdata-sharp-core -Libs: -r:${libdir}/mono/GData-Sharp/Google.GData.Contacts.dll -+Libs: -r:${libdir}/cli/Google.GData.Contacts-1.4/Google.GData.Contacts.dll -diff -urNad gdata-sharp-1.4.0.2~/misc/gdata-sharp-core.pc.in gdata-sharp-1.4.0.2/misc/gdata-sharp-core.pc.in ---- gdata-sharp-1.4.0.2~/misc/gdata-sharp-core.pc.in 2009-11-23 12:59:43.393613331 +0000 -+++ gdata-sharp-1.4.0.2/misc/gdata-sharp-core.pc.in 2009-11-23 13:00:08.411113739 +0000 ++Libs: -r:${libdir}/cli/Google.GData.Contacts-1.7/Google.GData.Contacts.dll +Index: gdata-sharp/misc/gdata-sharp-core.pc.in +=================================================================== +--- gdata-sharp.orig/misc/gdata-sharp-core.pc.in 2011-02-10 10:32:08.496336002 +0800 ++++ gdata-sharp/misc/gdata-sharp-core.pc.in 2011-02-11 02:22:37.516571682 +0800 @@ -5,4 +5,4 @@ Description: CLI bindings to Google's online services (Core libraries) Version: @VERSION@ --Libs: -r:${libdir}/mono/GData-Sharp/Google.GData.Client.dll -r${libdir}/mono/GData-Sharp/Google.GData.Extensions.dll -+Libs: -r:${libdir}/cli/Google.GData.Client-1.4/Google.GData.Client.dll -r:${libdir}/cli/Google.GData.Extensions-1.4/Google.GData.Extensions.dll -diff -urNad gdata-sharp-1.4.0.2~/misc/gdata-sharp-documents.pc.in gdata-sharp-1.4.0.2/misc/gdata-sharp-documents.pc.in ---- gdata-sharp-1.4.0.2~/misc/gdata-sharp-documents.pc.in 2009-11-23 12:59:43.393613331 +0000 -+++ gdata-sharp-1.4.0.2/misc/gdata-sharp-documents.pc.in 2009-11-23 12:59:51.001113164 +0000 +-Libs: -r:${libdir}/mono/GData-Sharp/Google.GData.Client.dll -r:${libdir}/mono/GData-Sharp/Google.GData.Extensions.dll ++Libs: -r:${libdir}/cli/Google.GData.Client-1.7/Google.GData.Client.dll -r:${libdir}/cli/Google.GData.Extensions-1.7/Google.GData.Extensions.dll +Index: gdata-sharp/misc/gdata-sharp-documents.pc.in +=================================================================== +--- gdata-sharp.orig/misc/gdata-sharp-documents.pc.in 2011-02-10 10:32:08.406291539 +0800 ++++ gdata-sharp/misc/gdata-sharp-documents.pc.in 2011-02-11 02:19:49.654124543 +0800 @@ -6,4 +6,4 @@ Version: @VERSION@ Requires: gdata-sharp-core -Libs: -r:${libdir}/mono/GData-Sharp/Google.GData.Documents.dll -+Libs: -r:${libdir}/cli/Google.GData.Documents-1.4/Google.GData.Documents.dll -diff -urNad gdata-sharp-1.4.0.2~/misc/gdata-sharp-health.pc.in gdata-sharp-1.4.0.2/misc/gdata-sharp-health.pc.in ---- gdata-sharp-1.4.0.2~/misc/gdata-sharp-health.pc.in 2009-11-23 12:59:43.393613331 +0000 -+++ gdata-sharp-1.4.0.2/misc/gdata-sharp-health.pc.in 2009-11-23 12:59:51.001113164 +0000 ++Libs: -r:${libdir}/cli/Google.GData.Documents-1.7/Google.GData.Documents.dll +Index: gdata-sharp/misc/gdata-sharp-health.pc.in +=================================================================== +--- gdata-sharp.orig/misc/gdata-sharp-health.pc.in 2011-02-10 10:32:08.436306359 +0800 ++++ gdata-sharp/misc/gdata-sharp-health.pc.in 2011-02-11 02:19:49.654124543 +0800 @@ -6,4 +6,4 @@ Version: @VERSION@ Requires: gdata-sharp-core -Libs: -r:${libdir}/mono/GData-Sharp/Google.GData.Health.dll -+Libs: -r:${libdir}/cli/Google.GData.Health-1.4/Google.GData.Health.dll -diff -urNad gdata-sharp-1.4.0.2~/misc/gdata-sharp-photos.pc.in gdata-sharp-1.4.0.2/misc/gdata-sharp-photos.pc.in ---- gdata-sharp-1.4.0.2~/misc/gdata-sharp-photos.pc.in 2009-11-23 12:59:43.393613331 +0000 -+++ gdata-sharp-1.4.0.2/misc/gdata-sharp-photos.pc.in 2009-11-23 12:59:51.001113164 +0000 ++Libs: -r:${libdir}/cli/Google.GData.Health-1.7/Google.GData.Health.dll +Index: gdata-sharp/misc/gdata-sharp-photos.pc.in +=================================================================== +--- gdata-sharp.orig/misc/gdata-sharp-photos.pc.in 2011-02-10 10:32:08.422966439 +0800 ++++ gdata-sharp/misc/gdata-sharp-photos.pc.in 2011-02-11 02:19:49.654124543 +0800 @@ -6,4 +6,4 @@ Version: @VERSION@ Requires: gdata-sharp-core -Libs: -r:${libdir}/mono/GData-Sharp/Google.GData.Photos.dll -+Libs: -r:${libdir}/cli/Google.GData.Photos-1.4/Google.GData.Photos.dll -diff -urNad gdata-sharp-1.4.0.2~/misc/gdata-sharp-spreadsheets.pc.in gdata-sharp-1.4.0.2/misc/gdata-sharp-spreadsheets.pc.in ---- gdata-sharp-1.4.0.2~/misc/gdata-sharp-spreadsheets.pc.in 2009-11-23 12:59:43.393613331 +0000 -+++ gdata-sharp-1.4.0.2/misc/gdata-sharp-spreadsheets.pc.in 2009-11-23 12:59:51.001113164 +0000 ++Libs: -r:${libdir}/cli/Google.GData.Photos-1.7/Google.GData.Photos.dll +Index: gdata-sharp/misc/gdata-sharp-spreadsheets.pc.in +=================================================================== +--- gdata-sharp.orig/misc/gdata-sharp-spreadsheets.pc.in 2011-02-10 10:32:08.476326122 +0800 ++++ gdata-sharp/misc/gdata-sharp-spreadsheets.pc.in 2011-02-11 02:19:49.654124543 +0800 @@ -6,4 +6,4 @@ Version: @VERSION@ Requires: gdata-sharp-core -Libs: -r:${libdir}/mono/GData-Sharp/Google.GData.Spreadsheets.dll -+Libs: -r:${libdir}/cli/Google.GData.Spreadsheets-1.4/Google.GData.Spreadsheets.dll -diff -urNad gdata-sharp-1.4.0.2~/misc/gdata-sharp-youtube.pc.in gdata-sharp-1.4.0.2/misc/gdata-sharp-youtube.pc.in ---- gdata-sharp-1.4.0.2~/misc/gdata-sharp-youtube.pc.in 2009-11-23 12:59:43.393613331 +0000 -+++ gdata-sharp-1.4.0.2/misc/gdata-sharp-youtube.pc.in 2009-11-23 12:59:51.001113164 +0000 ++Libs: -r:${libdir}/cli/Google.GData.Spreadsheets-1.7/Google.GData.Spreadsheets.dll +Index: gdata-sharp/misc/gdata-sharp-youtube.pc.in +=================================================================== +--- gdata-sharp.orig/misc/gdata-sharp-youtube.pc.in 2011-02-10 10:32:08.416296479 +0800 ++++ gdata-sharp/misc/gdata-sharp-youtube.pc.in 2011-02-11 02:19:49.654124543 +0800 @@ -6,4 +6,4 @@ Version: @VERSION@ Requires: gdata-sharp-core -Libs: -r:${libdir}/mono/GData-Sharp/Google.GData.YouTube.dll -+Libs: -r:${libdir}/cli/Google.GData.YouTube-1.4/Google.GData.YouTube.dll ++Libs: -r:${libdir}/cli/Google.GData.YouTube-1.7/Google.GData.YouTube.dll +Index: gdata-sharp/misc/gdata-sharp-analytics.pc.in +=================================================================== +--- gdata-sharp.orig/misc/gdata-sharp-analytics.pc.in 2011-02-11 02:21:44.810105798 +0800 ++++ gdata-sharp/misc/gdata-sharp-analytics.pc.in 2011-02-11 02:22:01.066711564 +0800 +@@ -6,4 +6,4 @@ + Version: @VERSION@ + + Requires: gdata-sharp-core +-Libs: -r:${libdir}/mono/GData-Sharp/Google.GData.Analytics.dll ++Libs: -r:${libdir}/cli/Google.GData.Analytics.dll diff -Nru gdata-sharp-1.4.0.2/debian/patches/02_cli-2.0-port.patch gdata-sharp-1.7.0.1/debian/patches/02_cli-2.0-port.patch --- gdata-sharp-1.4.0.2/debian/patches/02_cli-2.0-port.patch 2011-02-23 18:24:36.000000000 +0000 +++ gdata-sharp-1.7.0.1/debian/patches/02_cli-2.0-port.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,368 +0,0 @@ -Index: gdata-sharp/src/core/gzipstream.cs -=================================================================== ---- gdata-sharp.orig/src/core/gzipstream.cs 2009-03-19 05:04:46.000000000 +0800 -+++ gdata-sharp/src/core/gzipstream.cs 2009-03-19 05:12:28.000000000 +0800 -@@ -4,308 +4,4 @@ - - namespace Google.GData.Client - { -- /// Type of compression to use for the GZipStream. Currently only Decompress is supported. -- public enum CompressionMode -- { -- /// Compresses the underlying stream. -- Compress, -- /// Decompresses the underlying stream. -- Decompress, -- } -- -- /// Provides methods and properties used to compress and decompress streams. -- public class GZipStream : Stream -- { -- #region Native const, structs, and defs -- private const string ZLibVersion = "1.2.3"; -- -- private enum ZLibReturnCode -- { -- Ok = 0, -- StreamEnd = 1, -- NeedDictionary = 2, -- Errno = -1, -- StreamError = -2, -- DataError = -3, -- MemoryError = -4, -- BufferError = -5, -- VersionError = -6 -- } -- -- private enum ZLibFlush -- { -- NoFlush = 0, -- PartialFlush = 1, -- SyncFlush = 2, -- FullFlush = 3, -- Finish = 4 -- } -- -- private enum ZLibCompressionLevel -- { -- NoCompression = 0, -- BestSpeed = 1, -- BestCompression = 2, -- DefaultCompression = 3 -- } -- -- private enum ZLibCompressionStrategy -- { -- Filtered = 1, -- HuffmanOnly = 2, -- DefaultStrategy = 0 -- } -- -- private enum ZLibCompressionMethod -- { -- Delated = 8 -- } -- -- private enum ZLibDataType -- { -- Binary = 0, -- Ascii = 1, -- Unknown = 2, -- } -- -- private enum ZLibOpenType -- { -- ZLib = 15, -- GZip = 15 + 16, -- Both = 15 + 32, -- } -- -- -- [StructLayoutAttribute(LayoutKind.Sequential)] -- private struct z_stream -- { -- public IntPtr next_in; /* next input byte */ -- public uint avail_in; /* number of bytes available at next_in */ -- public uint total_in; /* total nb of input bytes read so far */ -- -- public IntPtr next_out; /* next output byte should be put there */ -- public uint avail_out; /* remaining free space at next_out */ -- public uint total_out; /* total nb of bytes output so far */ -- -- public IntPtr msg; /* last error message, NULL if no error */ -- public IntPtr state; /* not visible by applications */ -- -- public IntPtr zalloc; /* used to allocate the internal state */ -- public IntPtr zfree; /* used to free the internal state */ -- public IntPtr opaque; /* private data object passed to zalloc and zfree */ -- -- public ZLibDataType data_type; /* best guess about the data type: ascii or binary */ -- public uint adler; /* adler32 value of the uncompressed data */ -- public uint reserved; /* reserved for future use */ -- }; -- #endregion -- -- #region P/Invoke --#if WindowsCE || PocketPC -- [DllImport("zlib.arm.dll", EntryPoint = "inflateInit2_", CharSet = CharSet.Auto)] --#else -- [DllImport("zlib.x86.dll", EntryPoint = "inflateInit2_", CharSet = CharSet.Ansi)] --#endif -- private static extern ZLibReturnCode inflateInit2(ref z_stream strm, ZLibOpenType windowBits, string version, int stream_size); -- --#if WindowsCE || PocketPC -- [DllImport("zlib.arm.dll", CharSet = CharSet.Auto)] --#else -- [DllImport("zlib.x86.dll", CharSet = CharSet.Ansi)] --#endif -- private static extern ZLibReturnCode inflate(ref z_stream strm, ZLibFlush flush); -- --#if WindowsCE || PocketPC -- [DllImport("zlib.arm.dll", CharSet = CharSet.Auto)] --#else -- [DllImport("zlib.x86.dll", CharSet = CharSet.Ansi)] --#endif -- private static extern ZLibReturnCode inflateEnd(ref z_stream strm); -- #endregion -- -- private const int BufferSize = 16384; -- -- private Stream compressedStream; -- private CompressionMode mode; -- -- private z_stream zstream = new z_stream(); -- -- private byte[] inputBuffer = new byte[BufferSize]; -- private GCHandle inputBufferHandle; -- -- /// Initializes a new instance of the GZipStream class using the specified stream and CompressionMode value. -- /// The stream to compress or decompress. -- /// One of the CompressionMode values that indicates the action to take. -- public GZipStream(Stream stream, CompressionMode mode) -- { -- if (mode != CompressionMode.Decompress) -- throw new NotImplementedException("Compression is not implemented."); -- -- this.compressedStream = stream; -- this.mode = mode; -- -- this.zstream.zalloc = IntPtr.Zero; -- this.zstream.zfree = IntPtr.Zero; -- this.zstream.opaque = IntPtr.Zero; -- -- ZLibReturnCode ret = inflateInit2(ref this.zstream, ZLibOpenType.Both, ZLibVersion, Marshal.SizeOf(typeof(z_stream))); -- -- if (ret != ZLibReturnCode.Ok) -- throw new ArgumentException("Unable to init ZLib. Return code: " + ret.ToString()); -- -- this.inputBufferHandle = GCHandle.Alloc(inputBuffer, GCHandleType.Pinned); -- } -- -- /// GZipStream destructor. Cleans all allocated resources. -- ~GZipStream() -- { -- Dispose(false); -- } -- -- ////////////////////////////////////////////////////////////////////// -- /// Handle Dispose since Stream implements IDisposable -- /// indicates if dispose called it or finalize -- ////////////////////////////////////////////////////////////////////// -- protected override void Dispose(bool disposing) -- { -- base.Dispose(disposing); -- -- if (inputBufferHandle.IsAllocated) -- { -- inputBufferHandle.Free(); -- inflateEnd(ref this.zstream); -- } -- } -- -- -- /// Reads a number of decompressed bytes into the specified byte array. -- /// The array used to store decompressed bytes. -- /// The location in the array to begin reading. -- /// The number of bytes decompressed. -- /// The number of bytes that were decompressed into the byte array. If the end of the stream has been reached, zero or the number of bytes read is returned. -- public override int Read(byte[] buffer, int offset, int count) -- { -- if (this.mode == CompressionMode.Compress) -- throw new NotSupportedException("Can't read on a compress stream!"); -- -- bool exitLoop = false; -- -- byte[] tmpOutputBuffer = new byte[count]; -- GCHandle tmpOutpuBufferHandle = GCHandle.Alloc(tmpOutputBuffer, GCHandleType.Pinned); -- -- this.zstream.next_out = tmpOutpuBufferHandle.AddrOfPinnedObject(); -- this.zstream.avail_out = (uint)tmpOutputBuffer.Length; -- -- try -- { -- while (this.zstream.avail_out > 0 && exitLoop == false) -- { -- if (this.zstream.avail_in == 0) -- { -- int readLength = this.compressedStream.Read(inputBuffer, 0, inputBuffer.Length); -- this.zstream.avail_in = (uint)readLength; -- this.zstream.next_in = this.inputBufferHandle.AddrOfPinnedObject(); -- } -- ZLibReturnCode result = inflate(ref zstream, ZLibFlush.NoFlush); -- switch (result) -- { -- case ZLibReturnCode.StreamEnd: -- exitLoop = true; -- Array.Copy(tmpOutputBuffer, 0, buffer, offset, count - (int)this.zstream.avail_out); -- break; -- case ZLibReturnCode.Ok: -- Array.Copy(tmpOutputBuffer, 0, buffer, offset, count - (int)this.zstream.avail_out); -- break; -- case ZLibReturnCode.MemoryError: -- throw new OutOfMemoryException("ZLib return code: " + result.ToString()); -- default: -- throw new Exception("ZLib return code: " + result.ToString()); -- } -- } -- -- return (count - (int)this.zstream.avail_out); -- } -- finally -- { -- tmpOutpuBufferHandle.Free(); -- } -- } -- -- /// Closes the current stream and releases any resources (such as sockets and file handles) associated with the current stream. -- public override void Close() -- { -- this.compressedStream.Close(); -- base.Close(); -- } -- -- /// Gets a value indicating whether the stream supports reading while decompressing a file. -- public override bool CanRead -- { -- get { return (this.mode == CompressionMode.Decompress ? true : false); } -- } -- -- /// Gets a value indicating whether the stream supports writing. -- public override bool CanWrite -- { -- get { return (this.mode == CompressionMode.Compress ? true : false); } -- } -- -- /// Gets a value indicating whether the stream supports seeking. -- public override bool CanSeek -- { -- get { return (false); } -- } -- -- /// Gets a reference to the underlying stream. -- public Stream BaseStream -- { -- get { return (this.compressedStream); } -- } -- -- #region Not yet supported -- /// Flushes the contents of the internal buffer of the current GZipStream object to the underlying stream. -- public override void Flush() -- { -- throw new NotSupportedException("The method or operation is not implemented."); -- } -- -- /// This property is not supported and always throws a NotSupportedException. -- /// The location in the stream. -- /// One of the SeekOrigin values. -- /// A long value. -- public override long Seek(long offset, SeekOrigin origin) -- { -- throw new NotSupportedException(); -- } -- -- /// This property is not supported and always throws a NotSupportedException. -- /// The length of the stream. -- public override void SetLength(long value) -- { -- throw new NotSupportedException(); -- } -- -- /// This property is not supported and always throws a NotSupportedException. -- /// The array used to store compressed bytes. -- /// The location in the array to begin reading. -- /// The number of bytes compressed. -- public override void Write(byte[] buffer, int offset, int count) -- { -- throw new NotSupportedException("Not yet supported!"); -- } -- -- /// This property is not supported and always throws a NotSupportedException. -- public override long Length -- { -- get { throw new NotSupportedException(); } -- } -- -- /// This property is not supported and always throws a NotSupportedException. -- public override long Position -- { -- get { throw new NotSupportedException(); } -- set { throw new NotSupportedException(); } -- } -- #endregion -- } - } -Index: gdata-sharp/src/core/request.cs -=================================================================== ---- gdata-sharp.orig/src/core/request.cs 2009-03-19 05:04:46.000000000 +0800 -+++ gdata-sharp/src/core/request.cs 2009-03-19 05:12:28.000000000 +0800 -@@ -22,6 +22,7 @@ - using System.Collections.Generic; - using System.Globalization; - using System.ComponentModel; -+using System.IO.Compression; - - #endregion - -Index: gdata-sharp/src/unittests/gziplivetest.cs -=================================================================== ---- gdata-sharp.orig/src/unittests/gziplivetest.cs 2009-03-19 05:04:46.000000000 +0800 -+++ gdata-sharp/src/unittests/gziplivetest.cs 2009-03-19 05:13:05.000000000 +0800 -@@ -10,6 +10,7 @@ - using Google.GData.Extensions; - using Google.GData.Calendar; - using Google.GData.AccessControl; -+using System.IO.Compression; - - namespace Google.GData.Client.LiveTests - { -@@ -54,7 +55,7 @@ - - Stream responseStream = request.GetResponseStream(); - Assert.IsTrue(responseStream != null, "Response stream should not be null."); -- Assert.IsTrue(responseStream is Google.GData.Client.GZipStream, "Response stream is not Google.GData.Client.GZipStream."); -+ Assert.IsTrue(responseStream is GZipStream, "Response stream is not System.IO.Compression.GZipStream."); - - AtomFeed feed = new AtomFeed(new Uri(calendarUri), this.calendarService); - feed.Parse(request.GetResponseStream(), AlternativeFormat.Atom); -Index: gdata-sharp/src/unittests/gzipstreamtest.cs -=================================================================== ---- gdata-sharp.orig/src/unittests/gzipstreamtest.cs 2009-03-19 05:13:25.000000000 +0800 -+++ gdata-sharp/src/unittests/gzipstreamtest.cs 2009-03-19 05:14:23.000000000 +0800 -@@ -3,7 +3,7 @@ - using System.Xml; - using System.IO; - --using Google.GData.Client; -+using System.IO.Compression; - - using NUnit.Framework; - -@@ -15,7 +15,7 @@ - [TestFixture] - public class GZipStreamTest : BaseTestClass - { -- private const string Data = "Google.GData.Client.GZipStream"; -+ private const string Data = "System.IO.Compression..GZipStream"; - private const string Base64GZipData = "H4sIAEDbsEYAA3PPz0/PSdVzd0ksSdRzzslMzSvRc4/KLAguKUpNzAUAg1++Bx4AAAA="; - - private byte[] compressedData; diff -Nru gdata-sharp-1.4.0.2/debian/patches/remove-system-web-dep.patch gdata-sharp-1.7.0.1/debian/patches/remove-system-web-dep.patch --- gdata-sharp-1.4.0.2/debian/patches/remove-system-web-dep.patch 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/debian/patches/remove-system-web-dep.patch 2011-02-23 18:04:58.000000000 +0000 @@ -0,0 +1,1664 @@ +Index: gdata-sharp/src/core/HttpUtility.cs +=================================================================== +--- gdata-sharp.orig/src/core/HttpUtility.cs 2011-02-09 01:07:07.780963167 +0800 ++++ gdata-sharp/src/core/HttpUtility.cs 2011-02-09 01:10:36.859808030 +0800 +@@ -1,7 +1,6 @@ +-#if WindowsCE || PocketPC +- + // + // System.Web.HttpUtility ++// http://github.com/mono/mono/tree/master/mcs/class/System.Web/System.Web.Util/ + // + // Authors: + // Patrik Torstensson (Patrik.Torstensson@labs2.com) +@@ -37,409 +36,436 @@ + using System.IO; + using System.Security.Permissions; + using System.Text; ++using System.Web.Util; ++ ++#if NET_2_0 ++using System.Collections.Generic; ++#endif ++ ++namespace System.Web.Util { ++ class Helpers { ++ public static readonly CultureInfo InvariantCulture = CultureInfo.InvariantCulture; ++ } ++} + + namespace System.Web { + ++#if !MONOTOUCH ++ // CAS - no InheritanceDemand here as the class is sealed ++ [AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)] ++#endif ++ + public sealed class HttpUtility { + + #region Fields +- ++ + static Hashtable entities; +- static object lock_ = new object (); +- ++ static object lock_ = new object(); ++ + #endregion // Fields +- ++ + static Hashtable Entities { + get { + lock (lock_) { + if (entities == null) +- InitEntities (); ++ InitEntities(); + + return entities; + } + } + } +- ++ + #region Constructors + +- static void InitEntities () +- { ++ static void InitEntities() { + // Build the hash table of HTML entity references. This list comes + // from the HTML 4.01 W3C recommendation. +- entities = new Hashtable (); +- entities.Add ("nbsp", '\u00A0'); +- entities.Add ("iexcl", '\u00A1'); +- entities.Add ("cent", '\u00A2'); +- entities.Add ("pound", '\u00A3'); +- entities.Add ("curren", '\u00A4'); +- entities.Add ("yen", '\u00A5'); +- entities.Add ("brvbar", '\u00A6'); +- entities.Add ("sect", '\u00A7'); +- entities.Add ("uml", '\u00A8'); +- entities.Add ("copy", '\u00A9'); +- entities.Add ("ordf", '\u00AA'); +- entities.Add ("laquo", '\u00AB'); +- entities.Add ("not", '\u00AC'); +- entities.Add ("shy", '\u00AD'); +- entities.Add ("reg", '\u00AE'); +- entities.Add ("macr", '\u00AF'); +- entities.Add ("deg", '\u00B0'); +- entities.Add ("plusmn", '\u00B1'); +- entities.Add ("sup2", '\u00B2'); +- entities.Add ("sup3", '\u00B3'); +- entities.Add ("acute", '\u00B4'); +- entities.Add ("micro", '\u00B5'); +- entities.Add ("para", '\u00B6'); +- entities.Add ("middot", '\u00B7'); +- entities.Add ("cedil", '\u00B8'); +- entities.Add ("sup1", '\u00B9'); +- entities.Add ("ordm", '\u00BA'); +- entities.Add ("raquo", '\u00BB'); +- entities.Add ("frac14", '\u00BC'); +- entities.Add ("frac12", '\u00BD'); +- entities.Add ("frac34", '\u00BE'); +- entities.Add ("iquest", '\u00BF'); +- entities.Add ("Agrave", '\u00C0'); +- entities.Add ("Aacute", '\u00C1'); +- entities.Add ("Acirc", '\u00C2'); +- entities.Add ("Atilde", '\u00C3'); +- entities.Add ("Auml", '\u00C4'); +- entities.Add ("Aring", '\u00C5'); +- entities.Add ("AElig", '\u00C6'); +- entities.Add ("Ccedil", '\u00C7'); +- entities.Add ("Egrave", '\u00C8'); +- entities.Add ("Eacute", '\u00C9'); +- entities.Add ("Ecirc", '\u00CA'); +- entities.Add ("Euml", '\u00CB'); +- entities.Add ("Igrave", '\u00CC'); +- entities.Add ("Iacute", '\u00CD'); +- entities.Add ("Icirc", '\u00CE'); +- entities.Add ("Iuml", '\u00CF'); +- entities.Add ("ETH", '\u00D0'); +- entities.Add ("Ntilde", '\u00D1'); +- entities.Add ("Ograve", '\u00D2'); +- entities.Add ("Oacute", '\u00D3'); +- entities.Add ("Ocirc", '\u00D4'); +- entities.Add ("Otilde", '\u00D5'); +- entities.Add ("Ouml", '\u00D6'); +- entities.Add ("times", '\u00D7'); +- entities.Add ("Oslash", '\u00D8'); +- entities.Add ("Ugrave", '\u00D9'); +- entities.Add ("Uacute", '\u00DA'); +- entities.Add ("Ucirc", '\u00DB'); +- entities.Add ("Uuml", '\u00DC'); +- entities.Add ("Yacute", '\u00DD'); +- entities.Add ("THORN", '\u00DE'); +- entities.Add ("szlig", '\u00DF'); +- entities.Add ("agrave", '\u00E0'); +- entities.Add ("aacute", '\u00E1'); +- entities.Add ("acirc", '\u00E2'); +- entities.Add ("atilde", '\u00E3'); +- entities.Add ("auml", '\u00E4'); +- entities.Add ("aring", '\u00E5'); +- entities.Add ("aelig", '\u00E6'); +- entities.Add ("ccedil", '\u00E7'); +- entities.Add ("egrave", '\u00E8'); +- entities.Add ("eacute", '\u00E9'); +- entities.Add ("ecirc", '\u00EA'); +- entities.Add ("euml", '\u00EB'); +- entities.Add ("igrave", '\u00EC'); +- entities.Add ("iacute", '\u00ED'); +- entities.Add ("icirc", '\u00EE'); +- entities.Add ("iuml", '\u00EF'); +- entities.Add ("eth", '\u00F0'); +- entities.Add ("ntilde", '\u00F1'); +- entities.Add ("ograve", '\u00F2'); +- entities.Add ("oacute", '\u00F3'); +- entities.Add ("ocirc", '\u00F4'); +- entities.Add ("otilde", '\u00F5'); +- entities.Add ("ouml", '\u00F6'); +- entities.Add ("divide", '\u00F7'); +- entities.Add ("oslash", '\u00F8'); +- entities.Add ("ugrave", '\u00F9'); +- entities.Add ("uacute", '\u00FA'); +- entities.Add ("ucirc", '\u00FB'); +- entities.Add ("uuml", '\u00FC'); +- entities.Add ("yacute", '\u00FD'); +- entities.Add ("thorn", '\u00FE'); +- entities.Add ("yuml", '\u00FF'); +- entities.Add ("fnof", '\u0192'); +- entities.Add ("Alpha", '\u0391'); +- entities.Add ("Beta", '\u0392'); +- entities.Add ("Gamma", '\u0393'); +- entities.Add ("Delta", '\u0394'); +- entities.Add ("Epsilon", '\u0395'); +- entities.Add ("Zeta", '\u0396'); +- entities.Add ("Eta", '\u0397'); +- entities.Add ("Theta", '\u0398'); +- entities.Add ("Iota", '\u0399'); +- entities.Add ("Kappa", '\u039A'); +- entities.Add ("Lambda", '\u039B'); +- entities.Add ("Mu", '\u039C'); +- entities.Add ("Nu", '\u039D'); +- entities.Add ("Xi", '\u039E'); +- entities.Add ("Omicron", '\u039F'); +- entities.Add ("Pi", '\u03A0'); +- entities.Add ("Rho", '\u03A1'); +- entities.Add ("Sigma", '\u03A3'); +- entities.Add ("Tau", '\u03A4'); +- entities.Add ("Upsilon", '\u03A5'); +- entities.Add ("Phi", '\u03A6'); +- entities.Add ("Chi", '\u03A7'); +- entities.Add ("Psi", '\u03A8'); +- entities.Add ("Omega", '\u03A9'); +- entities.Add ("alpha", '\u03B1'); +- entities.Add ("beta", '\u03B2'); +- entities.Add ("gamma", '\u03B3'); +- entities.Add ("delta", '\u03B4'); +- entities.Add ("epsilon", '\u03B5'); +- entities.Add ("zeta", '\u03B6'); +- entities.Add ("eta", '\u03B7'); +- entities.Add ("theta", '\u03B8'); +- entities.Add ("iota", '\u03B9'); +- entities.Add ("kappa", '\u03BA'); +- entities.Add ("lambda", '\u03BB'); +- entities.Add ("mu", '\u03BC'); +- entities.Add ("nu", '\u03BD'); +- entities.Add ("xi", '\u03BE'); +- entities.Add ("omicron", '\u03BF'); +- entities.Add ("pi", '\u03C0'); +- entities.Add ("rho", '\u03C1'); +- entities.Add ("sigmaf", '\u03C2'); +- entities.Add ("sigma", '\u03C3'); +- entities.Add ("tau", '\u03C4'); +- entities.Add ("upsilon", '\u03C5'); +- entities.Add ("phi", '\u03C6'); +- entities.Add ("chi", '\u03C7'); +- entities.Add ("psi", '\u03C8'); +- entities.Add ("omega", '\u03C9'); +- entities.Add ("thetasym", '\u03D1'); +- entities.Add ("upsih", '\u03D2'); +- entities.Add ("piv", '\u03D6'); +- entities.Add ("bull", '\u2022'); +- entities.Add ("hellip", '\u2026'); +- entities.Add ("prime", '\u2032'); +- entities.Add ("Prime", '\u2033'); +- entities.Add ("oline", '\u203E'); +- entities.Add ("frasl", '\u2044'); +- entities.Add ("weierp", '\u2118'); +- entities.Add ("image", '\u2111'); +- entities.Add ("real", '\u211C'); +- entities.Add ("trade", '\u2122'); +- entities.Add ("alefsym", '\u2135'); +- entities.Add ("larr", '\u2190'); +- entities.Add ("uarr", '\u2191'); +- entities.Add ("rarr", '\u2192'); +- entities.Add ("darr", '\u2193'); +- entities.Add ("harr", '\u2194'); +- entities.Add ("crarr", '\u21B5'); +- entities.Add ("lArr", '\u21D0'); +- entities.Add ("uArr", '\u21D1'); +- entities.Add ("rArr", '\u21D2'); +- entities.Add ("dArr", '\u21D3'); +- entities.Add ("hArr", '\u21D4'); +- entities.Add ("forall", '\u2200'); +- entities.Add ("part", '\u2202'); +- entities.Add ("exist", '\u2203'); +- entities.Add ("empty", '\u2205'); +- entities.Add ("nabla", '\u2207'); +- entities.Add ("isin", '\u2208'); +- entities.Add ("notin", '\u2209'); +- entities.Add ("ni", '\u220B'); +- entities.Add ("prod", '\u220F'); +- entities.Add ("sum", '\u2211'); +- entities.Add ("minus", '\u2212'); +- entities.Add ("lowast", '\u2217'); +- entities.Add ("radic", '\u221A'); +- entities.Add ("prop", '\u221D'); +- entities.Add ("infin", '\u221E'); +- entities.Add ("ang", '\u2220'); +- entities.Add ("and", '\u2227'); +- entities.Add ("or", '\u2228'); +- entities.Add ("cap", '\u2229'); +- entities.Add ("cup", '\u222A'); +- entities.Add ("int", '\u222B'); +- entities.Add ("there4", '\u2234'); +- entities.Add ("sim", '\u223C'); +- entities.Add ("cong", '\u2245'); +- entities.Add ("asymp", '\u2248'); +- entities.Add ("ne", '\u2260'); +- entities.Add ("equiv", '\u2261'); +- entities.Add ("le", '\u2264'); +- entities.Add ("ge", '\u2265'); +- entities.Add ("sub", '\u2282'); +- entities.Add ("sup", '\u2283'); +- entities.Add ("nsub", '\u2284'); +- entities.Add ("sube", '\u2286'); +- entities.Add ("supe", '\u2287'); +- entities.Add ("oplus", '\u2295'); +- entities.Add ("otimes", '\u2297'); +- entities.Add ("perp", '\u22A5'); +- entities.Add ("sdot", '\u22C5'); +- entities.Add ("lceil", '\u2308'); +- entities.Add ("rceil", '\u2309'); +- entities.Add ("lfloor", '\u230A'); +- entities.Add ("rfloor", '\u230B'); +- entities.Add ("lang", '\u2329'); +- entities.Add ("rang", '\u232A'); +- entities.Add ("loz", '\u25CA'); +- entities.Add ("spades", '\u2660'); +- entities.Add ("clubs", '\u2663'); +- entities.Add ("hearts", '\u2665'); +- entities.Add ("diams", '\u2666'); +- entities.Add ("quot", '\u0022'); +- entities.Add ("amp", '\u0026'); +- entities.Add ("lt", '\u003C'); +- entities.Add ("gt", '\u003E'); +- entities.Add ("OElig", '\u0152'); +- entities.Add ("oelig", '\u0153'); +- entities.Add ("Scaron", '\u0160'); +- entities.Add ("scaron", '\u0161'); +- entities.Add ("Yuml", '\u0178'); +- entities.Add ("circ", '\u02C6'); +- entities.Add ("tilde", '\u02DC'); +- entities.Add ("ensp", '\u2002'); +- entities.Add ("emsp", '\u2003'); +- entities.Add ("thinsp", '\u2009'); +- entities.Add ("zwnj", '\u200C'); +- entities.Add ("zwj", '\u200D'); +- entities.Add ("lrm", '\u200E'); +- entities.Add ("rlm", '\u200F'); +- entities.Add ("ndash", '\u2013'); +- entities.Add ("mdash", '\u2014'); +- entities.Add ("lsquo", '\u2018'); +- entities.Add ("rsquo", '\u2019'); +- entities.Add ("sbquo", '\u201A'); +- entities.Add ("ldquo", '\u201C'); +- entities.Add ("rdquo", '\u201D'); +- entities.Add ("bdquo", '\u201E'); +- entities.Add ("dagger", '\u2020'); +- entities.Add ("Dagger", '\u2021'); +- entities.Add ("permil", '\u2030'); +- entities.Add ("lsaquo", '\u2039'); +- entities.Add ("rsaquo", '\u203A'); +- entities.Add ("euro", '\u20AC'); ++ entities = new Hashtable(); ++ entities.Add("nbsp", '\u00A0'); ++ entities.Add("iexcl", '\u00A1'); ++ entities.Add("cent", '\u00A2'); ++ entities.Add("pound", '\u00A3'); ++ entities.Add("curren", '\u00A4'); ++ entities.Add("yen", '\u00A5'); ++ entities.Add("brvbar", '\u00A6'); ++ entities.Add("sect", '\u00A7'); ++ entities.Add("uml", '\u00A8'); ++ entities.Add("copy", '\u00A9'); ++ entities.Add("ordf", '\u00AA'); ++ entities.Add("laquo", '\u00AB'); ++ entities.Add("not", '\u00AC'); ++ entities.Add("shy", '\u00AD'); ++ entities.Add("reg", '\u00AE'); ++ entities.Add("macr", '\u00AF'); ++ entities.Add("deg", '\u00B0'); ++ entities.Add("plusmn", '\u00B1'); ++ entities.Add("sup2", '\u00B2'); ++ entities.Add("sup3", '\u00B3'); ++ entities.Add("acute", '\u00B4'); ++ entities.Add("micro", '\u00B5'); ++ entities.Add("para", '\u00B6'); ++ entities.Add("middot", '\u00B7'); ++ entities.Add("cedil", '\u00B8'); ++ entities.Add("sup1", '\u00B9'); ++ entities.Add("ordm", '\u00BA'); ++ entities.Add("raquo", '\u00BB'); ++ entities.Add("frac14", '\u00BC'); ++ entities.Add("frac12", '\u00BD'); ++ entities.Add("frac34", '\u00BE'); ++ entities.Add("iquest", '\u00BF'); ++ entities.Add("Agrave", '\u00C0'); ++ entities.Add("Aacute", '\u00C1'); ++ entities.Add("Acirc", '\u00C2'); ++ entities.Add("Atilde", '\u00C3'); ++ entities.Add("Auml", '\u00C4'); ++ entities.Add("Aring", '\u00C5'); ++ entities.Add("AElig", '\u00C6'); ++ entities.Add("Ccedil", '\u00C7'); ++ entities.Add("Egrave", '\u00C8'); ++ entities.Add("Eacute", '\u00C9'); ++ entities.Add("Ecirc", '\u00CA'); ++ entities.Add("Euml", '\u00CB'); ++ entities.Add("Igrave", '\u00CC'); ++ entities.Add("Iacute", '\u00CD'); ++ entities.Add("Icirc", '\u00CE'); ++ entities.Add("Iuml", '\u00CF'); ++ entities.Add("ETH", '\u00D0'); ++ entities.Add("Ntilde", '\u00D1'); ++ entities.Add("Ograve", '\u00D2'); ++ entities.Add("Oacute", '\u00D3'); ++ entities.Add("Ocirc", '\u00D4'); ++ entities.Add("Otilde", '\u00D5'); ++ entities.Add("Ouml", '\u00D6'); ++ entities.Add("times", '\u00D7'); ++ entities.Add("Oslash", '\u00D8'); ++ entities.Add("Ugrave", '\u00D9'); ++ entities.Add("Uacute", '\u00DA'); ++ entities.Add("Ucirc", '\u00DB'); ++ entities.Add("Uuml", '\u00DC'); ++ entities.Add("Yacute", '\u00DD'); ++ entities.Add("THORN", '\u00DE'); ++ entities.Add("szlig", '\u00DF'); ++ entities.Add("agrave", '\u00E0'); ++ entities.Add("aacute", '\u00E1'); ++ entities.Add("acirc", '\u00E2'); ++ entities.Add("atilde", '\u00E3'); ++ entities.Add("auml", '\u00E4'); ++ entities.Add("aring", '\u00E5'); ++ entities.Add("aelig", '\u00E6'); ++ entities.Add("ccedil", '\u00E7'); ++ entities.Add("egrave", '\u00E8'); ++ entities.Add("eacute", '\u00E9'); ++ entities.Add("ecirc", '\u00EA'); ++ entities.Add("euml", '\u00EB'); ++ entities.Add("igrave", '\u00EC'); ++ entities.Add("iacute", '\u00ED'); ++ entities.Add("icirc", '\u00EE'); ++ entities.Add("iuml", '\u00EF'); ++ entities.Add("eth", '\u00F0'); ++ entities.Add("ntilde", '\u00F1'); ++ entities.Add("ograve", '\u00F2'); ++ entities.Add("oacute", '\u00F3'); ++ entities.Add("ocirc", '\u00F4'); ++ entities.Add("otilde", '\u00F5'); ++ entities.Add("ouml", '\u00F6'); ++ entities.Add("divide", '\u00F7'); ++ entities.Add("oslash", '\u00F8'); ++ entities.Add("ugrave", '\u00F9'); ++ entities.Add("uacute", '\u00FA'); ++ entities.Add("ucirc", '\u00FB'); ++ entities.Add("uuml", '\u00FC'); ++ entities.Add("yacute", '\u00FD'); ++ entities.Add("thorn", '\u00FE'); ++ entities.Add("yuml", '\u00FF'); ++ entities.Add("fnof", '\u0192'); ++ entities.Add("Alpha", '\u0391'); ++ entities.Add("Beta", '\u0392'); ++ entities.Add("Gamma", '\u0393'); ++ entities.Add("Delta", '\u0394'); ++ entities.Add("Epsilon", '\u0395'); ++ entities.Add("Zeta", '\u0396'); ++ entities.Add("Eta", '\u0397'); ++ entities.Add("Theta", '\u0398'); ++ entities.Add("Iota", '\u0399'); ++ entities.Add("Kappa", '\u039A'); ++ entities.Add("Lambda", '\u039B'); ++ entities.Add("Mu", '\u039C'); ++ entities.Add("Nu", '\u039D'); ++ entities.Add("Xi", '\u039E'); ++ entities.Add("Omicron", '\u039F'); ++ entities.Add("Pi", '\u03A0'); ++ entities.Add("Rho", '\u03A1'); ++ entities.Add("Sigma", '\u03A3'); ++ entities.Add("Tau", '\u03A4'); ++ entities.Add("Upsilon", '\u03A5'); ++ entities.Add("Phi", '\u03A6'); ++ entities.Add("Chi", '\u03A7'); ++ entities.Add("Psi", '\u03A8'); ++ entities.Add("Omega", '\u03A9'); ++ entities.Add("alpha", '\u03B1'); ++ entities.Add("beta", '\u03B2'); ++ entities.Add("gamma", '\u03B3'); ++ entities.Add("delta", '\u03B4'); ++ entities.Add("epsilon", '\u03B5'); ++ entities.Add("zeta", '\u03B6'); ++ entities.Add("eta", '\u03B7'); ++ entities.Add("theta", '\u03B8'); ++ entities.Add("iota", '\u03B9'); ++ entities.Add("kappa", '\u03BA'); ++ entities.Add("lambda", '\u03BB'); ++ entities.Add("mu", '\u03BC'); ++ entities.Add("nu", '\u03BD'); ++ entities.Add("xi", '\u03BE'); ++ entities.Add("omicron", '\u03BF'); ++ entities.Add("pi", '\u03C0'); ++ entities.Add("rho", '\u03C1'); ++ entities.Add("sigmaf", '\u03C2'); ++ entities.Add("sigma", '\u03C3'); ++ entities.Add("tau", '\u03C4'); ++ entities.Add("upsilon", '\u03C5'); ++ entities.Add("phi", '\u03C6'); ++ entities.Add("chi", '\u03C7'); ++ entities.Add("psi", '\u03C8'); ++ entities.Add("omega", '\u03C9'); ++ entities.Add("thetasym", '\u03D1'); ++ entities.Add("upsih", '\u03D2'); ++ entities.Add("piv", '\u03D6'); ++ entities.Add("bull", '\u2022'); ++ entities.Add("hellip", '\u2026'); ++ entities.Add("prime", '\u2032'); ++ entities.Add("Prime", '\u2033'); ++ entities.Add("oline", '\u203E'); ++ entities.Add("frasl", '\u2044'); ++ entities.Add("weierp", '\u2118'); ++ entities.Add("image", '\u2111'); ++ entities.Add("real", '\u211C'); ++ entities.Add("trade", '\u2122'); ++ entities.Add("alefsym", '\u2135'); ++ entities.Add("larr", '\u2190'); ++ entities.Add("uarr", '\u2191'); ++ entities.Add("rarr", '\u2192'); ++ entities.Add("darr", '\u2193'); ++ entities.Add("harr", '\u2194'); ++ entities.Add("crarr", '\u21B5'); ++ entities.Add("lArr", '\u21D0'); ++ entities.Add("uArr", '\u21D1'); ++ entities.Add("rArr", '\u21D2'); ++ entities.Add("dArr", '\u21D3'); ++ entities.Add("hArr", '\u21D4'); ++ entities.Add("forall", '\u2200'); ++ entities.Add("part", '\u2202'); ++ entities.Add("exist", '\u2203'); ++ entities.Add("empty", '\u2205'); ++ entities.Add("nabla", '\u2207'); ++ entities.Add("isin", '\u2208'); ++ entities.Add("notin", '\u2209'); ++ entities.Add("ni", '\u220B'); ++ entities.Add("prod", '\u220F'); ++ entities.Add("sum", '\u2211'); ++ entities.Add("minus", '\u2212'); ++ entities.Add("lowast", '\u2217'); ++ entities.Add("radic", '\u221A'); ++ entities.Add("prop", '\u221D'); ++ entities.Add("infin", '\u221E'); ++ entities.Add("ang", '\u2220'); ++ entities.Add("and", '\u2227'); ++ entities.Add("or", '\u2228'); ++ entities.Add("cap", '\u2229'); ++ entities.Add("cup", '\u222A'); ++ entities.Add("int", '\u222B'); ++ entities.Add("there4", '\u2234'); ++ entities.Add("sim", '\u223C'); ++ entities.Add("cong", '\u2245'); ++ entities.Add("asymp", '\u2248'); ++ entities.Add("ne", '\u2260'); ++ entities.Add("equiv", '\u2261'); ++ entities.Add("le", '\u2264'); ++ entities.Add("ge", '\u2265'); ++ entities.Add("sub", '\u2282'); ++ entities.Add("sup", '\u2283'); ++ entities.Add("nsub", '\u2284'); ++ entities.Add("sube", '\u2286'); ++ entities.Add("supe", '\u2287'); ++ entities.Add("oplus", '\u2295'); ++ entities.Add("otimes", '\u2297'); ++ entities.Add("perp", '\u22A5'); ++ entities.Add("sdot", '\u22C5'); ++ entities.Add("lceil", '\u2308'); ++ entities.Add("rceil", '\u2309'); ++ entities.Add("lfloor", '\u230A'); ++ entities.Add("rfloor", '\u230B'); ++ entities.Add("lang", '\u2329'); ++ entities.Add("rang", '\u232A'); ++ entities.Add("loz", '\u25CA'); ++ entities.Add("spades", '\u2660'); ++ entities.Add("clubs", '\u2663'); ++ entities.Add("hearts", '\u2665'); ++ entities.Add("diams", '\u2666'); ++ entities.Add("quot", '\u0022'); ++ entities.Add("amp", '\u0026'); ++ entities.Add("lt", '\u003C'); ++ entities.Add("gt", '\u003E'); ++ entities.Add("OElig", '\u0152'); ++ entities.Add("oelig", '\u0153'); ++ entities.Add("Scaron", '\u0160'); ++ entities.Add("scaron", '\u0161'); ++ entities.Add("Yuml", '\u0178'); ++ entities.Add("circ", '\u02C6'); ++ entities.Add("tilde", '\u02DC'); ++ entities.Add("ensp", '\u2002'); ++ entities.Add("emsp", '\u2003'); ++ entities.Add("thinsp", '\u2009'); ++ entities.Add("zwnj", '\u200C'); ++ entities.Add("zwj", '\u200D'); ++ entities.Add("lrm", '\u200E'); ++ entities.Add("rlm", '\u200F'); ++ entities.Add("ndash", '\u2013'); ++ entities.Add("mdash", '\u2014'); ++ entities.Add("lsquo", '\u2018'); ++ entities.Add("rsquo", '\u2019'); ++ entities.Add("sbquo", '\u201A'); ++ entities.Add("ldquo", '\u201C'); ++ entities.Add("rdquo", '\u201D'); ++ entities.Add("bdquo", '\u201E'); ++ entities.Add("dagger", '\u2020'); ++ entities.Add("Dagger", '\u2021'); ++ entities.Add("permil", '\u2030'); ++ entities.Add("lsaquo", '\u2039'); ++ entities.Add("rsaquo", '\u203A'); ++ entities.Add("euro", '\u20AC'); + } + +- public HttpUtility () +- { ++ public HttpUtility() { + } +- ++ + #endregion // Constructors +- ++ + #region Methods +- +- public static void HtmlAttributeEncode (string s, TextWriter output) +- { ++ ++ public static void HtmlAttributeEncode(string s, TextWriter output) { + output.Write(HtmlAttributeEncode(s)); + } +- +- public static string HtmlAttributeEncode (string s) +- { +- if (null == s) ++ ++ public static string HtmlAttributeEncode(string s) { ++ if (null == s) { + return null; +- +- if (s.IndexOf ('&') == -1 && s.IndexOf ('"') == -1) +- return s; ++ } + +- StringBuilder output = new StringBuilder (); +- foreach (char c in s) +- switch (c) { +- case '&' : +- output.Append ("&"); +- break; +- case '"' : +- output.Append ("""); +- break; +- default: +- output.Append (c); ++ bool needEncode = false; ++ for (int i = 0; i < s.Length; i++) { ++ if (s[i] == '&' || s[i] == '"' || s[i] == '<') { ++ needEncode = true; + break; + } +- ++ } ++ ++ if (!needEncode) { ++ return s; ++ } ++ ++ StringBuilder output = new StringBuilder(); ++ int len = s.Length; ++ for (int i = 0; i < len; i++) { ++ switch (s[i]) { ++ case '&': ++ output.Append("&"); ++ break; ++ case '"': ++ output.Append("""); ++ break; ++ case '<': ++ output.Append("<"); ++ break; ++ default: ++ output.Append(s[i]); ++ break; ++ } ++ } ++ + return output.ToString(); + } +- +- public static string UrlDecode (string str) +- { ++ ++ public static string UrlDecode(string str) { + return UrlDecode(str, Encoding.UTF8); + } +- +- private static char [] GetChars (MemoryStream b, Encoding e) +- { +- return e.GetChars (b.GetBuffer (), 0, (int) b.Length); ++ ++ static char[] GetChars(MemoryStream b, Encoding e) { ++ return e.GetChars(b.GetBuffer(), 0, (int)b.Length); + } + +- public static string UrlDecode (string s, Encoding e) +- { +- if (null == s) ++ static void WriteCharBytes(IList buf, char ch, Encoding e) { ++ if (ch > 255) { ++ foreach (byte b in e.GetBytes(new char[] { ch })) ++ buf.Add(b); ++ } else ++ buf.Add((byte)ch); ++ } ++ ++ public static string UrlDecode(string s, Encoding e) { ++ if (null == s) + return null; + +- if (s.IndexOf ('%') == -1 && s.IndexOf ('+') == -1) ++ if (s.IndexOf('%') == -1 && s.IndexOf('+') == -1) + return s; + + if (e == null) + e = Encoding.UTF8; +- +- StringBuilder output = new StringBuilder (); ++ + long len = s.Length; +- MemoryStream bytes = new MemoryStream (); ++#if NET_2_0 ++ var bytes = new List (); ++#else ++ ArrayList bytes = new ArrayList(); ++#endif + int xchar; +- +- for (int i = 0; i < len; i++) { +- if (s [i] == '%' && i + 2 < len && s [i + 1] != '%') { +- if (s [i + 1] == 'u' && i + 5 < len) { +- if (bytes.Length > 0) { +- output.Append (GetChars (bytes, e)); +- bytes.SetLength (0); +- } ++ char ch; + +- xchar = GetChar (s, i + 2, 4); ++ for (int i = 0; i < len; i++) { ++ ch = s[i]; ++ if (ch == '%' && i + 2 < len && s[i + 1] != '%') { ++ if (s[i + 1] == 'u' && i + 5 < len) { ++ // unicode hex sequence ++ xchar = GetChar(s, i + 2, 4); + if (xchar != -1) { +- output.Append ((char) xchar); ++ WriteCharBytes(bytes, (char)xchar, e); + i += 5; + } else { +- output.Append ('%'); ++ WriteCharBytes(bytes, '%', e); + } +- } else if ((xchar = GetChar (s, i + 1, 2)) != -1) { +- bytes.WriteByte ((byte) xchar); ++ } else if ((xchar = GetChar(s, i + 1, 2)) != -1) { ++ WriteCharBytes(bytes, (char)xchar, e); + i += 2; + } else { +- output.Append ('%'); ++ WriteCharBytes(bytes, '%', e); + } + continue; + } + +- if (bytes.Length > 0) { +- output.Append (GetChars (bytes, e)); +- bytes.SetLength (0); +- } +- +- if (s [i] == '+') { +- output.Append (' '); +- } else { +- output.Append (s [i]); +- } +- } +- +- if (bytes.Length > 0) { +- output.Append (GetChars (bytes, e)); ++ if (ch == '+') ++ WriteCharBytes(bytes, ' ', e); ++ else ++ WriteCharBytes(bytes, ch, e); + } + ++#if NET_2_0 ++ byte[] buf = bytes.ToArray (); ++#else ++ byte[] buf = (byte[])bytes.ToArray(typeof(byte)); ++#endif ++ + bytes = null; +- return output.ToString (); ++ return e.GetString(buf); + } +- +- public static string UrlDecode (byte [] bytes, Encoding e) +- { ++ ++ public static string UrlDecode(byte[] bytes, Encoding e) { + if (bytes == null) + return null; + +- return UrlDecode (bytes, 0, bytes.Length, e); ++ return UrlDecode(bytes, 0, bytes.Length, e); + } + +- private static int GetInt (byte b) +- { +- char c = (char) b; ++ static int GetInt(byte b) { ++ char c = (char)b; + if (c >= '0' && c <= '9') + return c - '0'; + +@@ -452,12 +478,11 @@ + return -1; + } + +- private static int GetChar (byte [] bytes, int offset, int length) +- { ++ static int GetChar(byte[] bytes, int offset, int length) { + int value = 0; + int end = length + offset; + for (int i = offset; i < end; i++) { +- int current = GetInt (bytes [i]); ++ int current = GetInt(bytes[i]); + if (current == -1) + return -1; + value = (value << 4) + current; +@@ -466,16 +491,15 @@ + return value; + } + +- private static int GetChar (string str, int offset, int length) +- { ++ static int GetChar(string str, int offset, int length) { + int val = 0; + int end = length + offset; + for (int i = offset; i < end; i++) { +- char c = str [i]; ++ char c = str[i]; + if (c > 127) + return -1; + +- int current = GetInt ((byte) c); ++ int current = GetInt((byte)c); + if (current == -1) + return -1; + val = (val << 4) + current; +@@ -483,98 +507,93 @@ + + return val; + } +- +- public static string UrlDecode (byte [] bytes, int offset, int count, Encoding e) +- { ++ ++ public static string UrlDecode(byte[] bytes, int offset, int count, Encoding e) { + if (bytes == null) + return null; + if (count == 0) + return String.Empty; + + if (bytes == null) +- throw new ArgumentNullException ("bytes"); ++ throw new ArgumentNullException("bytes"); + + if (offset < 0 || offset > bytes.Length) +- throw new ArgumentOutOfRangeException ("offset"); ++ throw new ArgumentOutOfRangeException("offset"); + + if (count < 0 || offset + count > bytes.Length) +- throw new ArgumentOutOfRangeException ("count"); ++ throw new ArgumentOutOfRangeException("count"); + +- StringBuilder output = new StringBuilder (); +- MemoryStream acc = new MemoryStream (); ++ StringBuilder output = new StringBuilder(); ++ MemoryStream acc = new MemoryStream(); + + int end = count + offset; + int xchar; + for (int i = offset; i < end; i++) { +- if (bytes [i] == '%' && i + 2 < count && bytes [i + 1] != '%') { +- if (bytes [i + 1] == (byte) 'u' && i + 5 < end) { ++ if (bytes[i] == '%' && i + 2 < count && bytes[i + 1] != '%') { ++ if (bytes[i + 1] == (byte)'u' && i + 5 < end) { + if (acc.Length > 0) { +- output.Append (GetChars (acc, e)); +- acc.SetLength (0); ++ output.Append(GetChars(acc, e)); ++ acc.SetLength(0); + } +- xchar = GetChar (bytes, i + 2, 4); ++ xchar = GetChar(bytes, i + 2, 4); + if (xchar != -1) { +- output.Append ((char) xchar); ++ output.Append((char)xchar); + i += 5; + continue; + } +- } else if ((xchar = GetChar (bytes, i + 1, 2)) != -1) { +- acc.WriteByte ((byte) xchar); ++ } else if ((xchar = GetChar(bytes, i + 1, 2)) != -1) { ++ acc.WriteByte((byte)xchar); + i += 2; + continue; + } + } + + if (acc.Length > 0) { +- output.Append (GetChars (acc, e)); +- acc.SetLength (0); ++ output.Append(GetChars(acc, e)); ++ acc.SetLength(0); + } + +- if (bytes [i] == '+') { +- output.Append (' '); ++ if (bytes[i] == '+') { ++ output.Append(' '); + } else { +- output.Append ((char) bytes [i]); ++ output.Append((char)bytes[i]); + } + } + + if (acc.Length > 0) { +- output.Append (GetChars (acc, e)); ++ output.Append(GetChars(acc, e)); + } +- ++ + acc = null; +- return output.ToString (); ++ return output.ToString(); + } +- +- public static byte [] UrlDecodeToBytes (byte [] bytes) +- { ++ ++ public static byte[] UrlDecodeToBytes(byte[] bytes) { + if (bytes == null) + return null; + +- return UrlDecodeToBytes (bytes, 0, bytes.Length); ++ return UrlDecodeToBytes(bytes, 0, bytes.Length); + } + +- public static byte [] UrlDecodeToBytes (string str) +- { +- return UrlDecodeToBytes (str, Encoding.UTF8); ++ public static byte[] UrlDecodeToBytes(string str) { ++ return UrlDecodeToBytes(str, Encoding.UTF8); + } + +- public static byte [] UrlDecodeToBytes (string str, Encoding e) +- { ++ public static byte[] UrlDecodeToBytes(string str, Encoding e) { + if (str == null) + return null; + + if (e == null) +- throw new ArgumentNullException ("e"); ++ throw new ArgumentNullException("e"); + +- return UrlDecodeToBytes (e.GetBytes (str)); ++ return UrlDecodeToBytes(e.GetBytes(str)); + } + +- public static byte [] UrlDecodeToBytes (byte [] bytes, int offset, int count) +- { ++ public static byte[] UrlDecodeToBytes(byte[] bytes, int offset, int count) { + if (bytes == null) + return null; + if (count == 0) +- return new byte [0]; ++ return new byte[0]; + + int len = bytes.Length; + if (offset < 0 || offset >= len) +@@ -583,87 +602,165 @@ + if (count < 0 || offset > len - count) + throw new ArgumentOutOfRangeException("count"); + +- MemoryStream result = new MemoryStream (); ++ MemoryStream result = new MemoryStream(); + int end = offset + count; +- for (int i = offset; i < end; i++){ +- char c = (char) bytes [i]; ++ for (int i = offset; i < end; i++) { ++ char c = (char)bytes[i]; + if (c == '+') { + c = ' '; + } else if (c == '%' && i < end - 2) { +- int xchar = GetChar (bytes, i + 1, 2); ++ int xchar = GetChar(bytes, i + 1, 2); + if (xchar != -1) { +- c = (char) xchar; ++ c = (char)xchar; + i += 2; + } + } +- result.WriteByte ((byte) c); ++ result.WriteByte((byte)c); ++ } ++ ++ return result.ToArray(); ++ } ++ ++ public static string UrlEncode(string str) { ++ return UrlEncode(str, Encoding.UTF8); ++ } ++ ++ public static string UrlEncode(string s, Encoding Enc) { ++ if (s == null) ++ return null; ++ ++ if (s == "") ++ return ""; ++ ++ bool needEncode = false; ++ int len = s.Length; ++ for (int i = 0; i < len; i++) { ++ char c = s[i]; ++ if ((c < '0') || (c < 'A' && c > '9') || (c > 'Z' && c < 'a') || (c > 'z')) { ++ if (NotEncoded(c)) ++ continue; ++ ++ needEncode = true; ++ break; ++ } + } + +- return result.ToArray (); ++ if (!needEncode) ++ return s; ++ ++ // avoided GetByteCount call ++ byte[] bytes = new byte[Enc.GetMaxByteCount(s.Length)]; ++ int realLen = Enc.GetBytes(s, 0, s.Length, bytes, 0); ++ return Encoding.ASCII.GetString(UrlEncodeToBytes(bytes, 0, realLen)); ++ } ++ ++ public static string UrlEncode(byte[] bytes) { ++ if (bytes == null) ++ return null; ++ ++ if (bytes.Length == 0) ++ return ""; ++ ++ return Encoding.ASCII.GetString(UrlEncodeToBytes(bytes, 0, bytes.Length)); ++ } ++ ++ public static string UrlEncode(byte[] bytes, int offset, int count) { ++ if (bytes == null) ++ return null; ++ ++ if (bytes.Length == 0) ++ return ""; ++ ++ return Encoding.ASCII.GetString(UrlEncodeToBytes(bytes, offset, count)); ++ } ++ ++ public static byte[] UrlEncodeToBytes(string str) { ++ return UrlEncodeToBytes(str, Encoding.UTF8); ++ } ++ ++ public static byte[] UrlEncodeToBytes(string str, Encoding e) { ++ if (str == null) ++ return null; ++ ++ if (str == "") ++ return new byte[0]; ++ ++ byte[] bytes = e.GetBytes(str); ++ return UrlEncodeToBytes(bytes, 0, bytes.Length); ++ } ++ ++ public static byte[] UrlEncodeToBytes(byte[] bytes) { ++ if (bytes == null) ++ return null; ++ ++ if (bytes.Length == 0) ++ return new byte[0]; ++ ++ return UrlEncodeToBytes(bytes, 0, bytes.Length); + } + +- static char [] hexChars = "0123456789abcdef".ToCharArray (); +- const string notEncoded = "!'()*-._"; ++ static char[] hexChars = "0123456789abcdef".ToCharArray(); + +- static void UrlEncodeChar (char c, Stream result, bool isUnicode) { ++ static bool NotEncoded(char c) { ++ return (c == '!' || c == '\'' || c == '(' || c == ')' || c == '*' || c == '-' || c == '.' || c == '_'); ++ } ++ ++ static void UrlEncodeChar(char c, Stream result, bool isUnicode) { + if (c > 255) { + //FIXME: what happens when there is an internal error? + //if (!isUnicode) + // throw new ArgumentOutOfRangeException ("c", c, "c must be less than 256"); + int idx; +- int i = (int) c; ++ int i = (int)c; + +- result.WriteByte ((byte)'%'); +- result.WriteByte ((byte)'u'); ++ result.WriteByte((byte)'%'); ++ result.WriteByte((byte)'u'); + idx = i >> 12; +- result.WriteByte ((byte)hexChars [idx]); ++ result.WriteByte((byte)hexChars[idx]); + idx = (i >> 8) & 0x0F; +- result.WriteByte ((byte)hexChars [idx]); ++ result.WriteByte((byte)hexChars[idx]); + idx = (i >> 4) & 0x0F; +- result.WriteByte ((byte)hexChars [idx]); ++ result.WriteByte((byte)hexChars[idx]); + idx = i & 0x0F; +- result.WriteByte ((byte)hexChars [idx]); ++ result.WriteByte((byte)hexChars[idx]); + return; + } +- +- if (c>' ' && notEncoded.IndexOf (c)!=-1) { +- result.WriteByte ((byte)c); ++ ++ if (c > ' ' && NotEncoded(c)) { ++ result.WriteByte((byte)c); + return; + } +- if (c==' ') { +- result.WriteByte ((byte)'+'); ++ if (c == ' ') { ++ result.WriteByte((byte)'+'); + return; + } +- if ( (c < '0') || ++ if ((c < '0') || + (c < 'A' && c > '9') || + (c > 'Z' && c < 'a') || + (c > 'z')) { + if (isUnicode && c > 127) { +- result.WriteByte ((byte)'%'); +- result.WriteByte ((byte)'u'); +- result.WriteByte ((byte)'0'); +- result.WriteByte ((byte)'0'); +- } +- else +- result.WriteByte ((byte)'%'); +- +- int idx = ((int) c) >> 4; +- result.WriteByte ((byte)hexChars [idx]); +- idx = ((int) c) & 0x0F; +- result.WriteByte ((byte)hexChars [idx]); +- } +- else +- result.WriteByte ((byte)c); ++ result.WriteByte((byte)'%'); ++ result.WriteByte((byte)'u'); ++ result.WriteByte((byte)'0'); ++ result.WriteByte((byte)'0'); ++ } else ++ result.WriteByte((byte)'%'); ++ ++ int idx = ((int)c) >> 4; ++ result.WriteByte((byte)hexChars[idx]); ++ idx = ((int)c) & 0x0F; ++ result.WriteByte((byte)hexChars[idx]); ++ } else ++ result.WriteByte((byte)c); + } + +- public static byte [] UrlEncodeToBytes (byte [] bytes, int offset, int count) +- { ++ public static byte[] UrlEncodeToBytes(byte[] bytes, int offset, int count) { + if (bytes == null) + return null; + + int len = bytes.Length; + if (len == 0) +- return new byte [0]; ++ return new byte[0]; + + if (offset < 0 || offset >= len) + throw new ArgumentOutOfRangeException("offset"); +@@ -671,28 +768,33 @@ + if (count < 0 || count > len - offset) + throw new ArgumentOutOfRangeException("count"); + +- MemoryStream result = new MemoryStream (count); ++ MemoryStream result = new MemoryStream(count); + int end = offset + count; + for (int i = offset; i < end; i++) +- UrlEncodeChar ((char)bytes [i], result, false); ++ UrlEncodeChar((char)bytes[i], result, false); + + return result.ToArray(); + } + ++ public static string UrlEncodeUnicode(string str) { ++ if (str == null) ++ return null; + +- public static byte [] UrlEncodeUnicodeToBytes (string str) +- { ++ return Encoding.ASCII.GetString(UrlEncodeUnicodeToBytes(str)); ++ } ++ ++ public static byte[] UrlEncodeUnicodeToBytes(string str) { + if (str == null) + return null; + + if (str == "") +- return new byte [0]; ++ return new byte[0]; + +- MemoryStream result = new MemoryStream (str.Length); +- foreach (char c in str){ +- UrlEncodeChar (c, result, true); ++ MemoryStream result = new MemoryStream(str.Length); ++ foreach (char c in str) { ++ UrlEncodeChar(c, result, true); + } +- return result.ToArray (); ++ return result.ToArray(); + } + + /// +@@ -700,16 +802,15 @@ + /// + /// The HTML string to decode. + /// The decoded text. +- public static string HtmlDecode (string s) +- { ++ public static string HtmlDecode(string s) { + if (s == null) +- throw new ArgumentNullException ("s"); ++ throw new ArgumentNullException("s"); + +- if (s.IndexOf ('&') == -1) ++ if (s.IndexOf('&') == -1) + return s; + +- StringBuilder entity = new StringBuilder (); +- StringBuilder output = new StringBuilder (); ++ StringBuilder entity = new StringBuilder(); ++ StringBuilder output = new StringBuilder(); + int len = s.Length; + // 0 -> nothing, + // 1 -> right after '&' +@@ -718,15 +819,15 @@ + int state = 0; + int number = 0; + bool have_trailing_digits = false; +- ++ + for (int i = 0; i < len; i++) { +- char c = s [i]; ++ char c = s[i]; + if (state == 0) { + if (c == '&') { +- entity.Append (c); ++ entity.Append(c); + state = 1; + } else { +- output.Append (c); ++ output.Append(c); + } + continue; + } +@@ -734,21 +835,21 @@ + if (c == '&') { + state = 1; + if (have_trailing_digits) { +- entity.Append (number.ToString (CultureInfo.InvariantCulture)); ++ entity.Append(number.ToString(Helpers.InvariantCulture)); + have_trailing_digits = false; + } + +- output.Append (entity.ToString ()); ++ output.Append(entity.ToString()); + entity.Length = 0; +- entity.Append ('&'); ++ entity.Append('&'); + continue; + } + + if (state == 1) { + if (c == ';') { + state = 0; +- output.Append (entity.ToString ()); +- output.Append (c); ++ output.Append(entity.ToString()); ++ output.Append(c); + entity.Length = 0; + } else { + number = 0; +@@ -757,119 +858,133 @@ + } else { + state = 3; + } +- entity.Append (c); ++ entity.Append(c); + } + } else if (state == 2) { +- entity.Append (c); ++ entity.Append(c); + if (c == ';') { +- string key = entity.ToString (); +- if (key.Length > 1 && Entities.ContainsKey (key.Substring (1, key.Length - 2))) +- key = Entities [key.Substring (1, key.Length - 2)].ToString (); ++ string key = entity.ToString(); ++ if (key.Length > 1 && Entities.ContainsKey(key.Substring(1, key.Length - 2))) ++ key = Entities[key.Substring(1, key.Length - 2)].ToString(); + +- output.Append (key); ++ output.Append(key); + state = 0; + entity.Length = 0; + } + } else if (state == 3) { + if (c == ';') { + if (number > 65535) { +- output.Append ("&#"); +- output.Append (number.ToString (CultureInfo.InvariantCulture)); +- output.Append (";"); ++ output.Append("&#"); ++ output.Append(number.ToString(Helpers.InvariantCulture)); ++ output.Append(";"); + } else { +- output.Append ((char) number); ++ output.Append((char)number); + } + state = 0; + entity.Length = 0; + have_trailing_digits = false; +- } else if (Char.IsDigit (c)) { +- number = number * 10 + ((int) c - '0'); ++ } else if (Char.IsDigit(c)) { ++ number = number * 10 + ((int)c - '0'); + have_trailing_digits = true; + } else { + state = 2; + if (have_trailing_digits) { +- entity.Append (number.ToString (CultureInfo.InvariantCulture)); ++ entity.Append(number.ToString(Helpers.InvariantCulture)); + have_trailing_digits = false; + } +- entity.Append (c); ++ entity.Append(c); + } + } + } + + if (entity.Length > 0) { +- output.Append (entity.ToString ()); ++ output.Append(entity.ToString()); + } else if (have_trailing_digits) { +- output.Append (number.ToString (CultureInfo.InvariantCulture)); ++ output.Append(number.ToString(Helpers.InvariantCulture)); + } +- return output.ToString (); ++ return output.ToString(); + } +- ++ + /// + /// Decodes an HTML-encoded string and sends the resulting output to a TextWriter output stream. + /// + /// The HTML string to decode + /// The TextWriter output stream containing the decoded string. +- public static void HtmlDecode(string s, TextWriter output) +- { ++ public static void HtmlDecode(string s, TextWriter output) { + if (s != null) +- output.Write (HtmlDecode (s)); ++ output.Write(HtmlDecode(s)); + } +- ++ + /// + /// HTML-encodes a string and returns the encoded string. + /// + /// The text string to encode. + /// The HTML-encoded text. +- public static string HtmlEncode (string s) +- { ++ public static string HtmlEncode(string s) { + if (s == null) + return null; + +- StringBuilder output = new StringBuilder (); +- +- foreach (char c in s) +- switch (c) { +- case '&' : +- output.Append ("&"); +- break; +- case '>' : +- output.Append (">"); +- break; +- case '<' : +- output.Append ("<"); +- break; +- case '"' : +- output.Append ("""); +- break; +- default: +- // MS starts encoding with &# from 160 and stops at 255. +- // We don't do that. One reason is the 65308/65310 unicode +- // characters that look like '<' and '>'. +- if (c > 159) { +- output.Append ("&#"); +- output.Append (((int) c).ToString (CultureInfo.InvariantCulture)); +- output.Append (";"); +- } else { +- output.Append (c); +- } ++ bool needEncode = false; ++ for (int i = 0; i < s.Length; i++) { ++ char c = s[i]; ++ if (c == '&' || c == '"' || c == '<' || c == '>' || c > 159) { ++ needEncode = true; + break; + } +- return output.ToString (); ++ } ++ ++ if (!needEncode) ++ return s; ++ ++ StringBuilder output = new StringBuilder(); ++ ++ int len = s.Length; ++ for (int i = 0; i < len; i++) ++ switch (s[i]) { ++ case '&': ++ output.Append("&"); ++ break; ++ case '>': ++ output.Append(">"); ++ break; ++ case '<': ++ output.Append("<"); ++ break; ++ case '"': ++ output.Append("""); ++ break; ++ default: ++ // MS starts encoding with &# from 160 and stops at 255. ++ // We don't do that. One reason is the 65308/65310 unicode ++ // characters that look like '<' and '>'. ++#if TARGET_JVM ++ if (s [i] > 159 && s [i] < 256) { ++#else ++ if (s[i] > 159) { ++#endif ++ output.Append("&#"); ++ output.Append(((int)s[i]).ToString(Helpers.InvariantCulture)); ++ output.Append(";"); ++ } else { ++ output.Append(s[i]); ++ } ++ break; ++ } ++ return output.ToString(); + } +- ++ + /// + /// HTML-encodes a string and sends the resulting output to a TextWriter output stream. + /// + /// The string to encode. + /// The TextWriter output stream containing the encoded string. +- public static void HtmlEncode(string s, TextWriter output) +- { ++ public static void HtmlEncode(string s, TextWriter output) { + if (s != null) +- output.Write (HtmlEncode (s)); ++ output.Write(HtmlEncode(s)); + } + + #if NET_1_1 +- public static string UrlPathEncode (string s) ++ public static string UrlPathEncode(string s) + { + if (s == null || s.Length == 0) + return s; +@@ -877,93 +992,122 @@ + MemoryStream result = new MemoryStream (); + int length = s.Length; + for (int i = 0; i < length; i++) { +- UrlPathEncodeChar (s [i], result); ++ UrlPathEncodeChar(s [i], result); + } +- return Encoding.ASCII.GetString (result.ToArray ()); ++ return Encoding.ASCII.GetString(result.ToArray ()); + } + +- static void UrlPathEncodeChar (char c, Stream result) { ++ static void UrlPathEncodeChar(char c, Stream result) { ++#if NET_2_0 ++ if (c < 33 || c > 126) { ++#else + if (c > 127) { +- byte [] bIn = Encoding.UTF8.GetBytes (c.ToString ()); ++#endif ++ byte [] bIn = Encoding.UTF8.GetBytes(c.ToString()); + for (int i = 0; i < bIn.Length; i++) { +- result.WriteByte ((byte) '%'); ++ result.WriteByte((byte) '%'); + int idx = ((int) bIn [i]) >> 4; +- result.WriteByte ((byte) hexChars [idx]); ++ result.WriteByte((byte) hexChars [idx]); + idx = ((int) bIn [i]) & 0x0F; +- result.WriteByte ((byte) hexChars [idx]); ++ result.WriteByte((byte) hexChars [idx]); + } + } + else if (c == ' ') { +- result.WriteByte ((byte) '%'); +- result.WriteByte ((byte) '2'); +- result.WriteByte ((byte) '0'); ++ result.WriteByte((byte) '%'); ++ result.WriteByte((byte) '2'); ++ result.WriteByte((byte) '0'); + } + else +- result.WriteByte ((byte) c); ++ result.WriteByte((byte) c); + } + #endif + + #if NET_2_0 +- public static NameValueCollection ParseQueryString (string query) ++ class HttpQSCollection : NameValueCollection { ++ public override string ToString () ++ { ++ int count = Count; ++ if (count == 0) ++ return ""; ++ ++ StringBuilder sb = new StringBuilder (); ++ string [] keys = AllKeys; ++ for (int i = 0; i < count; i++) { ++ sb.AppendFormat ("{0}={1}&", keys [i], this [keys [i]]); ++ } ++ if (sb.Length > 0) ++ sb.Length--; ++ return sb.ToString (); ++ } ++ } ++ ++ public static NameValueCollection ParseQueryString(string query) + { +- return ParseQueryString (query, Encoding.UTF8); ++ return ParseQueryString(query, Encoding.UTF8); + } + +- public static NameValueCollection ParseQueryString (string query, Encoding encoding) ++ public static NameValueCollection ParseQueryString(string query, Encoding encoding) + { + if (query == null) +- throw new ArgumentNullException ("query"); ++ throw new ArgumentNullException("query"); + if (encoding == null) +- throw new ArgumentNullException ("encoding"); ++ throw new ArgumentNullException("encoding"); + if (query.Length == 0 || (query.Length == 1 && query[0] == '?')) +- return new NameValueCollection (); ++ return new NameValueCollection(); + if (query[0] == '?') +- query = query.Substring (1); ++ query = query.Substring(1); + +- NameValueCollection result = new NameValueCollection (); +- ParseQueryString (query, encoding, result); ++ NameValueCollection result = new HttpQSCollection(); ++ ParseQueryString(query, encoding, result); + return result; + } + #endif + +- internal static void ParseQueryString (string query, Encoding encoding, NameValueCollection result) +- { ++ internal static void ParseQueryString(string query, Encoding encoding, NameValueCollection result) { + if (query.Length == 0) + return; + ++ string decoded = HtmlDecode(query); ++ int decodedLength = decoded.Length; + int namePos = 0; +- while (namePos <= query.Length) { ++ bool first = true; ++ while (namePos <= decodedLength) { + int valuePos = -1, valueEnd = -1; +- for (int q = namePos; q < query.Length; q++) { +- if (valuePos == -1 && query[q] == '=') { ++ for (int q = namePos; q < decodedLength; q++) { ++ if (valuePos == -1 && decoded[q] == '=') { + valuePos = q + 1; +- } else if (query[q] == '&') { ++ } else if (decoded[q] == '&') { + valueEnd = q; + break; + } + } + ++ if (first) { ++ first = false; ++ if (decoded[namePos] == '?') ++ namePos++; ++ } ++ + string name, value; + if (valuePos == -1) { + name = null; + valuePos = namePos; + } else { +- name = UrlDecode (query.Substring (namePos, valuePos - namePos - 1), encoding); ++ name = UrlDecode(decoded.Substring(namePos, valuePos - namePos - 1), encoding); + } + if (valueEnd < 0) { + namePos = -1; +- valueEnd = query.Length; ++ valueEnd = decoded.Length; + } else { + namePos = valueEnd + 1; + } +- value = UrlDecode (query.Substring (valuePos, valueEnd - valuePos), encoding); ++ value = UrlDecode(decoded.Substring(valuePos, valueEnd - valuePos), encoding); + +- result.Add (name, value); +- if (namePos == -1) break; ++ result.Add(name, value); ++ if (namePos == -1) ++ break; + } + } + #endregion // Methods + } + } +- +-#endif +Index: gdata-sharp/src/gapps/orgmanagementservice.cs +=================================================================== +--- gdata-sharp.orig/src/gapps/orgmanagementservice.cs 2011-02-09 01:07:07.797629742 +0800 ++++ gdata-sharp/src/gapps/orgmanagementservice.cs 2011-02-09 01:07:09.454287263 +0800 +@@ -98,7 +98,7 @@ + { + String uri = String.Format("{0}/{1}?get=children&orgUnitPath={2}", + AppsOrganizationNameTable.AppsOrgUnitBaseFeedUri, customerId, +- HttpUtility.UrlPathEncode(orgUnitPath)); ++ HttpUtility.UrlEncode(orgUnitPath)); + return QueryExtendedFeed(new Uri(uri), true); + } + +@@ -271,7 +271,7 @@ + { + String uri = String.Format("{0}/{1}?get=children&orgUnitPath={2}", + AppsOrganizationNameTable.AppsOrgUserBaseFeedUri, customerId, +- HttpUtility.UrlPathEncode(orgUnitPath)); ++ HttpUtility.UrlEncode(orgUnitPath)); + return QueryExtendedFeed(new Uri(uri), true); + } + +@@ -286,7 +286,7 @@ + { + String uri = String.Format("{0}/{1}?get=children&orgUnitPath={2}", + AppsOrganizationNameTable.AppsOrgUserBaseFeedUri, customerId, +- HttpUtility.UrlPathEncode(orgUnitPath)); ++ HttpUtility.UrlEncode(orgUnitPath)); + return QueryExtendedFeed(new Uri(uri), false); + } + } +Index: gdata-sharp/Makefile +=================================================================== +--- gdata-sharp.orig/Makefile 2011-02-09 01:07:07.767629907 +0800 ++++ gdata-sharp/Makefile 2011-02-09 01:09:33.846823071 +0800 +@@ -36,7 +36,7 @@ + + UNINSTALLLIBS = $(basename $(ALLLIBS)) + +-FRAMEWORK_REFS = -r:System.dll -r:System.Xml.dll -r:System.Web.dll -r:System.Configuration.dll ++FRAMEWORK_REFS = -r:System.dll -r:System.Xml.dll -r:System.Configuration.dll + + PKGCONFIG_FILES = $(patsubst %.pc.in,%.pc,$(wildcard misc/*.pc.in)) + diff -Nru gdata-sharp-1.4.0.2/debian/patches/series gdata-sharp-1.7.0.1/debian/patches/series --- gdata-sharp-1.4.0.2/debian/patches/series 2011-02-23 18:24:36.000000000 +0000 +++ gdata-sharp-1.7.0.1/debian/patches/series 2011-02-23 18:04:58.000000000 +0000 @@ -1,3 +1,3 @@ +remove-system-web-dep.patch 00_build-system.patch 01_pkgconfig-paths.patch -02_cli-2.0-port.patch diff -Nru gdata-sharp-1.4.0.2/debian/rules gdata-sharp-1.7.0.1/debian/rules --- gdata-sharp-1.4.0.2/debian/rules 2011-02-23 18:24:36.000000000 +0000 +++ gdata-sharp-1.7.0.1/debian/rules 2011-02-23 18:04:58.000000000 +0000 @@ -2,10 +2,9 @@ export DH_VERBOSE=1 include /usr/share/cli-common/cli.make -include /usr/share/quilt/quilt.make -DEB_CLI_API_VERSION = 1.4.0.2 -DEB_CLI_ABI_VERSION = 1.4 +DEB_CLI_API_VERSION = 1.7.0.1 +DEB_CLI_ABI_VERSION = 1.7 override_dh_makeclilibs: dh_makeclilibs -m$(DEB_CLI_API_VERSION) @@ -17,14 +16,6 @@ # we have to pass PREFIX has as there is no configure script which # covers that :( dh_auto_build -- PREFIX=/usr CSC=/usr/bin/mono-csc - mkdir -p monodoc - mdoc update \ - -fno-assembly-versions \ - -L$(CURDIR)/bin \ - --out=monodoc - mdoc assemble \ - --format ecma \ - --out $(CURDIR)/GData override_dh_auto_clean: dh_auto_clean @@ -39,5 +30,5 @@ override_dh_auto_test: %: - dh --with=quilt $@ + dh $@ diff -Nru gdata-sharp-1.4.0.2/debian/source/format gdata-sharp-1.7.0.1/debian/source/format --- gdata-sharp-1.4.0.2/debian/source/format 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/debian/source/format 2011-02-23 18:24:37.000000000 +0000 @@ -0,0 +1 @@ +3.0 (quilt) diff -Nru gdata-sharp-1.4.0.2/gzip-mono-howto.txt gdata-sharp-1.7.0.1/gzip-mono-howto.txt --- gdata-sharp-1.4.0.2/gzip-mono-howto.txt 2007-08-08 23:48:51.000000000 +0000 +++ gdata-sharp-1.7.0.1/gzip-mono-howto.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ - *** How to use GZip with Mono *** - - Because the Google.GData.Client.GZipStream implementation relies on zlib, -we decided to ship our own compiled version with the library, for both Windows -and Windows Mobile. However, we can't possibly ship binaries for each platform -supported by Mono. Here are the instructions to use GZip with Mono. - - You first need to obtain zlib v1.2.3 (version 1.2.3 is *VERY* important, -it simply WON'T work if you try to use another version) at http://www.zlib.net, -or http://www.zlib.net/zlib-1.2.3.tar.gz. Then, issue the following commands: - - $ make clean - $ ./configure -s - $ make - - This will build libz.so.1.2.3 that will be needed by the library. If you -want you can issue a "make install" to install the library to your library -path. If you don't want to install, just put the libz.so.1.2.3 file in the -same directory as Google.GData.Client.dll. - - That done, you only need to do one last thing, drop the -Google.GData.Client.dll.config file found in clients/cs/misc in the same -directory as Google.GData.Client.dll file. - - Finally, to check everything is alright, run the following: - - $ nunit-console2 /fixture=Google.GData.Client.UnitTests.GZipStreamTest\ - unittests.dll - - You can also run the tests against the live server (careful to configure -unittests.dll.config before!) using: - - $ nunit-console2 /fixture=Google.GData.Client.LiveTests.GZipTestSuite\ - unittests.dll - - And there you are :) - -NB: - zlib-1.2.3.tar.gz: 485K, MD5 checksum debc62758716a169df9f62e6ab2bc634 \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/Makefile gdata-sharp-1.7.0.1/Makefile --- gdata-sharp-1.4.0.2/Makefile 2009-02-11 09:34:10.000000000 +0000 +++ gdata-sharp-1.7.0.1/Makefile 2010-03-18 19:54:24.000000000 +0000 @@ -5,6 +5,7 @@ VERSION=$(shell egrep AssemblyVersion version/AssemblyVersion.cs | egrep -o \([[:digit:]]\.\)+[[:digit:]]+) PREFIX=/usr/local +PKGCONFIGDIR = $(PREFIX)/lib/pkgconfig CORELIBS=\ Google.GData.Client.dll \ @@ -31,6 +32,9 @@ Google.GData.YouTube.dll \ Google.GData.Health.dll \ Google.GData.Blogger.dll \ + Google.GData.Analytics.dll \ + +UNINSTALLLIBS = $(basename $(ALLLIBS)) FRAMEWORK_REFS = -r:System.dll -r:System.Xml.dll -r:System.Web.dll -r:System.Configuration.dll @@ -64,11 +68,12 @@ gacl_sources = $(wildcard src/gacl/*.cs) $(wildcard version/*.cs) gapps_sources = $(wildcard src/gapps/*.cs) $(wildcard version/*.cs) gphotos_sources = $(wildcard src/gphotos/*.cs) $(wildcard version/*.cs) -gdocuments_sources = $(wildcard src/gdocuments/*.cs) $(wildcard version/*.cs) +gdocuments_sources = $(wildcard src/documents3/*.cs) $(wildcard version/*.cs) gcontact_sources = $(wildcard src/gcontacts/*.cs) $(wildcard version/*.cs) youtube_sources = $(wildcard src/youtube/*.cs) $(wildcard version/*.cs) health_sources = $(wildcard src/ghealth/*.cs) $(wildcard version/*.cs) blogger_sources = $(wildcard src/blogger/*.cs) $(wildcard version/*.cs) +analytics_sources = $(wildcard src/analytics/*.cs) $(wildcard version/*.cs) test_sources = $(wildcard src/unittests/*.cs) $(wildcard src/unittests/gbase/*.cs) $(wildcard src/unittests/gapps/*.cs)\ $(wildcard src/unittests/spreadsheets/*.cs) $(wildcard src/unittests/youtube/*.cs) $(wildcard src/version/*cs)\ $(wildcard src/unittests/core/*.cs) $(wildcard src/unittests/picasa/*.cs) @@ -100,8 +105,8 @@ Google.GData.Photos.dll: $(CORELIBS) $(gphotos_sources) src/gphotos/picasa.sn $(CSC) $(DEFINES) -target:library -out:$@ $(COREREFS) $(gphotos_sources) -keyfile:src/gphotos/picasa.sn -Google.GData.Documents.dll: $(ACLLIBS) $(gdocuments_sources) src/gdocuments/documents.sn - $(CSC) $(DEFINES) -target:library -out:$@ $(ACLREFS) $(gdocuments_sources) -keyfile:src/gdocuments/documents.sn +Google.GData.Documents.dll: $(ACLLIBS) $(gdocuments_sources) src/documents3/documents.sn + $(CSC) $(DEFINES) -target:library -out:$@ $(ACLREFS) $(gdocuments_sources) -keyfile:src/documents3/documents.sn Google.GData.Contacts.dll: $(CORELIBS) $(gcontact_sources) src/gcontacts/contacts.sn $(CSC) $(DEFINES) -target:library -out:$@ $(COREREFS) $(gcontact_sources) -keyfile:src/gcontacts/contacts.sn @@ -115,17 +120,21 @@ Google.GData.Blogger.dll: $(CORELIBS) $(blogger_sources) src/blogger/blogger.sn $(CSC) $(DEFINES) -target:library -out:$@ $(COREREFS) $(blogger_sources) -keyfile:src/blogger/blogger.sn +Google.GData.Analytics.dll: $(CORELIBS) $(analytics_sources) src/analytics/analytics.sn + $(CSC) $(DEFINES) -target:library -out:$@ $(COREREFS) $(analytics_sources) -keyfile:src/analytics/analytics.sn + + clean: - -rm *.sn *.dll *exe $(PKGCONFIG_FILES) + -rm -f *.sn *.dll *exe $(PKGCONFIG_FILES) install: all for i in $(ALLLIBS); do gacutil -i $$i -package GData-Sharp -root "$(DESTDIR)$(PREFIX)/lib"; done - install -d "$(DESTDIR)$(PREFIX)/lib/pkgconfig" - install -m 644 -t "$(DESTDIR)$(PREFIX)/lib/pkgconfig" $(PKGCONFIG_FILES) + install -d "$(DESTDIR)$(PKGCONFIGDIR)" + install -m 644 -t "$(DESTDIR)$(PKGCONFIGDIR)" $(PKGCONFIG_FILES) uninstall: - for i in $(ALLLIBS); do gacutil -u $$i -package GData-Sharp -root "$(DESTDIR)$(PREFIX)/lib"; done - for i in $(PKGCONFIG_FILES) ; do rm "$(DESTDIR)$(PREFIX)/lib/pkgconfig/$$i" ; done + for i in $(UNINSTALLLIBS); do gacutil -u $$i -package GData-Sharp -root "$(DESTDIR)$(PREFIX)/lib"; done + for i in $(PKGCONFIG_FILES) ; do rm "$(DESTDIR)$(PKGCONFIGDIR)/$$i" ; done tests: $(ALLLIBS) $(CSC) $(DEFINES) -target:library -out:unittests.dll $(ALLREFS) -r:nunit.framework.dll $(test_sources) @@ -173,8 +182,6 @@ HealthTool.exe: $(ALLLIBS) $(healthtool_sources) $(CSC) -out:$@ $(ALLREFS) $(healthtool_sources) - - test: nunit-console2 unittests.dll diff -Nru gdata-sharp-1.4.0.2/misc/buildandsetup.txt gdata-sharp-1.7.0.1/misc/buildandsetup.txt --- gdata-sharp-1.4.0.2/misc/buildandsetup.txt 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/misc/buildandsetup.txt 2010-08-25 11:02:26.000000000 +0000 @@ -0,0 +1,90 @@ +Building the SDK + +Building the .NET SDK for Google Data APIs is pretty straightforward. After you get the whole repository, you +only need to open the the solution file "Google Data API SDK.sln" in the trunk/clients/cs/src/ directory. + +Building this for debug and release results in the appropriate targets. They are in the default output +directories setup by Visual Studio though, and not in the distribution directories. + +Note, that the over 250K lines of source code in this project were developed over 5 years. Yes, if you redo +everything it's going to be much prettier, but redoing 250K lines of code is quiet a task. + +Requirements + +To use everything available to you, you need: + +ILMerge +SandCastle +SandCastleHelpFileBuilder +Python + +Versioning: + +In trunk/clients/cs/version you find AssemblyVersion.cs. This is the version masterfile that is included from +all other places. Change this to 1.8.0.0 etc to make a build with a stable version number, after you released this, +change it to 1.8.0.* again, so that subsequent builds create higher version numbers. + + +Building the MOBILE version of the SDK + +Another solution file, for windows mobile, exists in trunk/clients/cs/src/VS2005.mobile/GDataMobile.sln". +This file will only build the subset of DLLs for the Windows Mobile release. + +Building the Samples + +Open the "Google Data APIs Samples.sln" solution file in trunk/clients/cs/samples and you will +build all related samples, beside one, the "YouTubeSample.sln" in the same directory. YouTubeSample is a +webservice application, as such it deserved a seperate solution. + +Batch jobs to help + +In the trunk/clients/cs/misc directory you will find some batch jobs to help building. + +pushdlls.cmd + +This batch builds release, mobile and debug DLLs, as well as all samples, and place them in the appropriate +directories. It will also run ILMerge on 3 of the samples to make them simple .exe files with no dependencies. + +Assuming pushdlls is successful, you have a lot of updated DLLs in /trunk/clients/cs/lib and the subdirectories. +Normally you run this command to update all the DLLs at the location they are supposed to be in the repository, then +you submit them from this place. + + +Documentation + +TO BUILD DOCS YOU NEED TO ENLIST NOT JUST IN TRUNK, BUT IN DOCS on the same level. + +The documentation is build using the sandcastle help builder system, released by Microsoft in 2008. The +project file is gdatadocumentation.shfbproj in \trunk\clients\cs\misc. To help with this, +you can use the pushdoc.cmd file located in the same directory. This will kick of the building of the +helpfile, and then copy the .CHM and the created HTML files to the \docs\ part of the subversion repository. + +Now, to update the HTML part of the documentation, that's kind of tricky. In the past our hosting system was +not robust enough to handle one directory, containing several thousand help files. To overcome that I wrote a python +script that splits the documentation across directories, updating the indexes and links accordingly. You run this +by using splitdocs.py in the /trunk/clints/cs/misc directory. When that's all done, and you verified that +the docs work, you can submit this in the docs dir. Note, that this takes a while. The index.html file produced +by the python script is the one that is linked to from the codesite page. + +Also tricky is to not forget to set all newly created HTML pages to be of type text/html in subversion, so that +they conform to browser standards and are displayed as HTML pages. + +Setup + +Setup is the last thing you build. You first go and change the version number to a fix/round number as described above. +Then you use pushdlls, run the unittests etc. When this is all fine, you build documentation and checkin everything. + +Now you use pushsetuptree.cmd in trunk/clients/cs/misc to pretty much get a fresh tree out of subversion. Then you open +another project, in trunk/clients/cs/setup, called Google Data API Setup.sln. You will need to ADD or DELETE all modified +files from the projects. Yes, by now, you can create setups differently, but in VS2003, when this whole thing started, this +was the best way to do it, and i was always to lazy to change the process to something slightly more elegant, but with no other +real benefits. + +Build the setup, check it in, and then put it on the codesite download page, following the naming conventions used there. +The created setup does NOT include the source code anymore. + + +Linux release + +There is a demand for linux releases. To do this, use the maketar.sh setup script, and then upload the files to codesite, +following the naming conventions used there. diff -Nru gdata-sharp-1.4.0.2/misc/gdatadocumentation.shfbproj gdata-sharp-1.7.0.1/misc/gdatadocumentation.shfbproj --- gdata-sharp-1.4.0.2/misc/gdatadocumentation.shfbproj 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/misc/gdatadocumentation.shfbproj 2010-11-23 18:10:27.000000000 +0000 @@ -0,0 +1,129 @@ + + + + Debug + AnyCPU + 2.0 + {d1021f64-71b3-46d3-a481-dbff31a9fe58} + 1.9.0.0 + + Documentation + Documentation + Documentation + + c:\gdata.doc\ + Google.GData.Documentation + + + + + + + + + + + + + + + + + + + + + + + + With Google Analytics, you can gather, view, and analyze data about your website traffic. By embedding our basic JavaScript snippet into your pages, you see which content gets the most visits, average page views and time on site for visits, which ads are driving the most visitors to your site, and more. You can also use the simple administrative interface to set up goals and filters to control what data goes into your reports based on your business needs. The best part: this sophisticated, full-featured web analytics package is free + The Google Contacts Data API allows client applications to view and update Contacts content in the form of Google Data API feeds. Your client application can request a list of a user's contacts, edit or delete content in an existing contact, and query the content in an existing contact. + +Here are some of the things you can do with the Contacts Data API: +Synchronize Google contacts with contacts on a mobile device +Maintain relationships between people in social applications +Give users the ability to communicate directly with their friends from external applications using phone, email, and IM + The Google Documents List Data API allows client applications to programmatically access and manipulate user data stored with Google Documents + With Google Analytics, you can gather, view, and analyze data about your website traffic. By embedding our basic JavaScript snippet into your pages, you see which content gets the most visits, average page views and time on site for visits, which ads are driving the most visitors to your site, and more. You can also use the simple administrative interface to set up goals and filters to control what data goes into your reports based on your business needs. The best part: this sophisticated, full-featured web analytics package is free + Google Apps provides powerful communication and collaboration tools right from the browser, as well as a platform to develop your critical business applications on top of Google infrastructure. The Google Apps Administrative APIs enable you develop applications that automate administrative tasks and integrate with your existing infrastructure: + + + + The Blogger Data API allows client applications to view and update Blogger content in the form of Google Data API feeds. Your client application can use the Data API to create new blog posts, edit or delete existing posts, and query for posts that match particular criteria. + The Calendar Data API lets you incorporate Calendar functionality into your own application or website. You can edit calendars, create and delete events, send invitations, and more. + This is core, atom level parsing and object model assembly that is required for all the other, service specific assemblies to work. + The Google Contacts Data API allows client applications to view and update Contacts content in the form of Google Data API feeds. Your client application can request a list of a user's contacts, edit or delete content in an existing contact, and query the content in an existing contact. + +Here are some of the things you can do with the Contacts Data API: +Synchronize Google contacts with contacts on a mobile device +Maintain relationships between people in social applications +Give users the ability to communicate directly with their friends from external applications using phone, email, and IM + The Google Documents List Data API allows client applications to programmatically access and manipulate user data stored with Google Documents + This assembly holds common extensions that are used in several services. + + + + + + The Picasa Web Albums Data API allows for websites and programs to integrate with Picasa Web Albums, enabling users to create albums, upload and retrieve photos, comment on photos, and more! + +Here are some of the things developers have done with the API: + +Created applications to easily upload photos from devices, desktop applications, and other web services. +Created full-featured mobile clients for browsing and uploading to PWA. +Integrated PWA with blogging software to easily show PWA albums and photos. +Used PWA to power digital photo frames. + + The Picasa Web Albums Data API allows for websites and programs to integrate with Picasa Web Albums, enabling users to create albums, upload and retrieve photos, comment on photos, and more! + +Here are some of the things developers have done with the API: + +Created applications to easily upload photos from devices, desktop applications, and other web services. +Created full-featured mobile clients for browsing and uploading to PWA. +Integrated PWA with blogging software to easily show PWA albums and photos. +Used PWA to power digital photo frames. + + The Data API lets you incorporate YouTube functionality into your own application or website. You can perform searches, upload videos, create playlists, and more. + + HtmlHelp1, Website + + + False + Summary, Parameter, Returns, AutoDocumentCtors, TypeParameter, AutoDocumentDispose + True + + + Top + Index + Google GData Documentation + + + + + + + + + + \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/misc/GDataProject.shfb gdata-sharp-1.7.0.1/misc/GDataProject.shfb --- gdata-sharp-1.4.0.2/misc/GDataProject.shfb 2009-02-26 15:27:05.000000000 +0000 +++ gdata-sharp-1.7.0.1/misc/GDataProject.shfb 2010-11-23 18:10:27.000000000 +0000 @@ -1,6 +1,7 @@  + @@ -19,6 +20,12 @@ This namespace contains helper classes to ease the development of Google Contacts based applications. They are used in the samples and the project templates. You can find usage scenarios of those helper clasess in the unittests for contacts as well as in the project template for it. This namespace contains helper classes to ease the development of Google Documents based applications. They are used in the samples and the project templates. You can find usage scenarios of those helper clasess in the unittests for documents as well as in the project template for it. This namespace contains elements and methods to deal with AccessControl lists. AccessControl lists are used, for example, in the Google Calendar to enable authorization and security on a per calendar level + With the Google Analytics Data Export API, you can develop client applications that download Analytics data in the form of Google Data API feeds. Your client application can use the Data Export API to request data from an existing Analytics profile for an authorized user, and refine the results of the request using query parameters. Currently, the Data Export API supports read-only access to your Google Analytics data. The current feeds in the Data Export API contain two general categories of Analytics data: + + * Analytics accounts and website profiles + * Analytics report data from a single profile + +As a developer, you can use this API for a number of use cases. For example, you might create a customized dashboard to integrate your most commonly viewed or requested page statistics, thus allowing other team members to view reports without having to access the Google Analytics reporting interface. Google Apps allows website administrators to offer their users cobranded versions of a variety of personalized Google applications, such as Gmail. This document describes the Google Apps Provisioning API, which enables Google partners to programmatically enable access to these applications. Specifically, the API provides functions for creating, retrieving, updating and deleting user accounts, nicknames and email lists. This version of the Provisioning API follows the principles of the Google Data (GData) APIs. GData APIs are based on both the Atom 1.0 and RSS 2.0 syndication formats in addition to the Atom Publishing Protocol. Learn more about GData APIs. @@ -135,7 +142,7 @@ InheritedMembers, InheritedFrameworkMembers, Protected, SealedProtected - D:\TempHTML\ + c:\TempHTML\ True diff -Nru gdata-sharp-1.4.0.2/misc/gdata-sharp-analytics.pc.in gdata-sharp-1.7.0.1/misc/gdata-sharp-analytics.pc.in --- gdata-sharp-1.4.0.2/misc/gdata-sharp-analytics.pc.in 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/misc/gdata-sharp-analytics.pc.in 2009-05-20 09:45:51.000000000 +0000 @@ -0,0 +1,9 @@ +prefix=@prefix@ +libdir=${prefix}/lib + +Name: GData Sharp Analytics +Description: CLI bindings to Google's Analytics webservice +Version: @VERSION@ + +Requires: gdata-sharp-core +Libs: -r:${libdir}/mono/GData-Sharp/Google.GData.Analytics.dll diff -Nru gdata-sharp-1.4.0.2/misc/gdata-sharp-core.pc.in gdata-sharp-1.7.0.1/misc/gdata-sharp-core.pc.in --- gdata-sharp-1.4.0.2/misc/gdata-sharp-core.pc.in 2009-02-05 10:15:17.000000000 +0000 +++ gdata-sharp-1.7.0.1/misc/gdata-sharp-core.pc.in 2009-03-25 15:27:09.000000000 +0000 @@ -5,4 +5,4 @@ Description: CLI bindings to Google's online services (Core libraries) Version: @VERSION@ -Libs: -r:${libdir}/mono/GData-Sharp/Google.GData.Client.dll -r${libdir}/mono/GData-Sharp/Google.GData.Extensions.dll +Libs: -r:${libdir}/mono/GData-Sharp/Google.GData.Client.dll -r:${libdir}/mono/GData-Sharp/Google.GData.Extensions.dll diff -Nru gdata-sharp-1.4.0.2/misc/Google.GData.Client.dll.config gdata-sharp-1.7.0.1/misc/Google.GData.Client.dll.config --- gdata-sharp-1.4.0.2/misc/Google.GData.Client.dll.config 2007-08-08 23:48:51.000000000 +0000 +++ gdata-sharp-1.7.0.1/misc/Google.GData.Client.dll.config 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ - - - - diff -Nru gdata-sharp-1.4.0.2/misc/maketar.sh gdata-sharp-1.7.0.1/misc/maketar.sh --- gdata-sharp-1.4.0.2/misc/maketar.sh 2008-12-17 14:37:36.000000000 +0000 +++ gdata-sharp-1.7.0.1/misc/maketar.sh 2009-03-23 14:51:12.000000000 +0000 @@ -7,7 +7,7 @@ declare -rx SCRIPT=${O##*/} declare -rx SVNLOCATION="http://google-gdata.googlecode.com/svn/trunk/clients/cs/" declare -rx SVN="/usr/local/bin/svn" -declare -rx OUTPUTDIR="libgoogle-data-mono-1.3.1.0" +declare -rx OUTPUTDIR="libgoogle-data-mono-1.4.0.2" declare -rx EXPORTDIR="$OUTPUTDIR" # sanity checks diff -Nru gdata-sharp-1.4.0.2/misc/pushdlls.cmd gdata-sharp-1.7.0.1/misc/pushdlls.cmd --- gdata-sharp-1.4.0.2/misc/pushdlls.cmd 2009-02-26 14:57:02.000000000 +0000 +++ gdata-sharp-1.7.0.1/misc/pushdlls.cmd 2010-12-06 15:27:57.000000000 +0000 @@ -5,7 +5,11 @@ if errorlevel 1 goto buildError devenv /rebuild Debug "..\src\Google Data API SDK.sln" if errorlevel 1 goto buildError -devenv /rebuild Release ..\src\VS2005.mobile\gdatamobile.sln +devenv /rebuild Release "..\src\VS2005.mobile\gdatamobile.sln" +if errorlevel 1 goto buildError +devenv /rebuild Debug "..\src\VS2005.mobile\gdatamobile.sln" +if errorlevel 1 goto buildError +devenv /rebuild Release "..\src\youtube\YouTube SDK\YouTube SDK.sln" if errorlevel 1 goto buildError # copy the DLLS @@ -18,11 +22,13 @@ xcopy /y ..\src\gapps\bin\Release\*.dll ..\lib\Release\*.* xcopy /y ..\src\gacl\bin\Release\*.dll ..\lib\Release\*.* xcopy /y ..\src\gphotos\bin\Release\*.dll ..\lib\Release\*.* -xcopy /y ..\src\gdocuments\bin\Release\*.dll ..\lib\Release\*.* +xcopy /y ..\src\documents3\bin\Release\*.dll ..\lib\Release\*.* xcopy /y ..\src\gcontacts\bin\Release\*.dll ..\lib\Release\*.* xcopy /y ..\src\youtube\bin\Release\*.dll ..\lib\Release\*.* xcopy /y ..\src\ghealth\bin\Release\*.dll ..\lib\Release\*.* xcopy /y ..\src\blogger\bin\Release\*.dll ..\lib\Release\*.* +xcopy /y ..\src\analytics\bin\Release\*.dll ..\lib\Release\*.* +xcopy /y ..\src\WebmasterTools\bin\Release\*.dll ..\lib\Release\*.* # copy the debug DLLS xcopy /y ..\src\core\bin\Debug\*.dll ..\lib\Debug\*.* @@ -34,22 +40,21 @@ xcopy /y ..\src\gapps\bin\Debug\*.dll ..\lib\Debug\*.* xcopy /y ..\src\gacl\bin\Debug\*.dll ..\lib\Debug\*.* xcopy /y ..\src\gphotos\bin\Debug\*.dll ..\lib\Debug\*.* -xcopy /y ..\src\gdocuments\bin\Debug\*.dll ..\lib\Debug\*.* +xcopy /y ..\src\documents3\bin\Debug\*.dll ..\lib\Debug\*.* xcopy /y ..\src\gcontacts\bin\Debug\*.dll ..\lib\Debug\*.* xcopy /y ..\src\youtube\bin\Debug\*.dll ..\lib\Debug\*.* xcopy /y ..\src\ghealth\bin\Debug\*.dll ..\lib\Debug\*.* -xcopy /y ..\src\unittests\bin\Debug\*.dll ..\lib\Debug\*.* xcopy /y ..\src\blogger\bin\Debug\*.dll ..\lib\Debug\*.* +xcopy /y ..\src\analytics\bin\Debug\*.dll ..\lib\Debug\*.* +xcopy /y ..\src\WebmasterTools\bin\Debug\*.dll ..\lib\Debug\*.* +# copy the YouTube setup +xcopy /y "..\src\youtube\YouTube SDK\YouTube SDK\Release\YouTube SDK.msi" ..\lib\Setup\*.* # copy asp dlls for the youtube sample -xcopy /y ..\src\gdata\bin\asp\*.dll ..\samples\YouTubeSample\bin\*.* -xcopy /y ..\src\gdata\bin\asp\*.dll ..\samples\YouTubeSample\bin\*.* xcopy /y ..\src\youtube\bin\asp\*.dll ..\samples\YouTubeSample\bin\*.* - - -#copy the mobile DLLS +# copy the mobile DLLS xcopy /y ..\src\VS2005.mobile\GBaseMobile\bin\Release\*.dll ..\lib\Mobile\WindowsMobile\*.* xcopy /y ..\src\VS2005.mobile\GCalendarMobile\bin\Release\*.dll ..\lib\Mobile\WindowsMobile\*.* xcopy /y ..\src\VS2005.mobile\GCodeSearchMobile\bin\Release\*.dll ..\lib\Mobile\WindowsMobile\*.* @@ -64,63 +69,63 @@ xcopy /y ..\src\VS2005.mobile\GHealthMobile\bin\Release\*.dll ..\lib\Mobile\WindowsMobile\*.* xcopy /y ..\src\VS2005.mobile\GYouTubeMobile\bin\Release\*.dll ..\lib\Mobile\WindowsMobile\*.* xcopy /y ..\src\VS2005.mobile\GBloggerMobile\bin\Release\*.dll ..\lib\Mobile\WindowsMobile\*.* - +xcopy /y ..\src\VS2005.mobile\GAnalyticsMobile\bin\Release\*.dll ..\lib\Mobile\WindowsMobile\*.* +# build the Samples devenv /rebuild Release "..\samples\Google Data APIs Samples.sln" # copy all exe files +xcopy /y ..\samples\Analytics\bin\Release\*.exe ..\lib\Release\*.* +xcopy /y ..\samples\Analytics_AccountFeed_Sample\bin\Release\*.exe ..\lib\Release\*.* +xcopy /y ..\samples\Analytics_DataFeed_Sample\bin\Release\*.exe ..\lib\Release\*.* +xcopy /y ..\samples\appsforyourdomain\bin\Release\*.exe ..\lib\Release\*.* xcopy /y ..\samples\Blogger\bin\Release\*.exe ..\lib\Release\*.* xcopy /y ..\samples\Calendar\bin\Release\*.exe ..\lib\Release\*.* xcopy /y ..\samples\CodeSearch\bin\Release\*.exe ..\lib\Release\*.* -xcopy /y ..\samples\spreadsheets\bin\Release\*.exe ..\lib\Release\*.* -xcopy /y ..\samples\gbase\bin\Release\*.exe ..\lib\Release\*.* -xcopy /y ..\samples\gbase\*.exe ..\lib\Release\*.* -xcopy /y ..\samples\\appsforyourdomain\bin\Release\*.exe ..\lib\Release\*.* -xcopy /y ..\samples\ExecRequest\bin\Release\*.exe ..\lib\Release\*.* -xcopy /y ..\samples\PhotoBrowser\bin\Release\*.exe ..\lib\Release\*.* +xcopy /y ..\samples\DocListExporter\bin\Release\*.exe ..\lib\Release\*.* xcopy /y ..\samples\DocListUploader\bin\Release\*.exe ..\lib\Release\*.* +xcopy /y ..\samples\ExecRequest\bin\Release\*.exe ..\lib\Release\*.* +xcopy /y ..\samples\gapps_google_mail_settings_sample\bin\Release\*.exe ..\lib\Release\*.* +xcopy /y ..\samples\gapps_multidomain_sample\bin\Release\*.exe ..\lib\Release\*.* +xcopy /y ..\samples\gapps_orgmanagement_sample\bin\Release\*.exe ..\lib\Release\*.* +xcopy /y ..\samples\gbase\bin\*.exe ..\lib\Release\*.* +xcopy /y ..\samples\gbase\bin\Release\*.exe ..\lib\Release\*.* xcopy /y ..\samples\health\bin\Release\*.exe ..\lib\Release\*.* +xcopy /y ..\samples\PhotoBrowser\bin\Release\*.exe ..\lib\Release\*.* +xcopy /y ..\samples\spreadsheets\bin\Release\*.exe ..\lib\Release\*.* xcopy /y ..\samples\YouTubeNotifier\bin\Release\*.exe ..\lib\Release\*.* -xcopy /y ..\samples\DocListExporter\bin\Release\*.exe ..\lib\Release\*.* - - # copy the xml doc files -xcopy /y ..\src\gdata\bin\*.xml ..\docs\*.* +xcopy /y ..\src\analytics\bin\*.xml ..\docs\*.* +xcopy /y ..\src\blogger\bin\*.xml ..\docs\*.* +xcopy /y ..\src\core\bin\*.xml ..\docs\*.* +xcopy /y ..\src\documents3\bin\*.xml ..\docs\*.* +xcopy /y ..\src\extensions\bin\*.xml ..\docs\*.* +xcopy /y ..\src\gacl\bin\*.xml ..\docs\*.* +xcopy /y ..\src\gapps\bin\*.xml ..\docs\*.* xcopy /y ..\src\gbase\bin\*.xml ..\docs\*.* -xcopy /y ..\src\gextension\bin\*.xml ..\docs\*.* -xcopy /y ..\src\gspreadsheets\bin\*.xml ..\docs\*.* xcopy /y ..\src\gcalendar\bin\*.xml ..\docs\*.* xcopy /y ..\src\gcodesearch\bin\*.xml ..\docs\*.* -xcopy /y ..\src\gapps\bin\*.xml ..\docs\*.* -xcopy /y ..\src\gacl\bin\*.xml ..\docs\*.* -xcopy /y ..\src\gphotos\bin\*.xml ..\docs\*.* -xcopy /y ..\src\gdoclist\bin\*.xml ..\docs\*.* xcopy /y ..\src\gcontacts\bin\*.xml ..\docs\*.* -xcopy /y ..\src\youtube\bin\*.xml ..\docs\*.* xcopy /y ..\src\ghealth\bin\*.xml ..\docs\*.* -xcopy /y ..\src\blogger\bin\*.xml ..\docs\*.* - -#copy the Merge module files - -xcopy /y ..\src\MergeModules\CoreMergeModule\Release\*.msm ..\lib\MergeModules\*.* -xcopy /y ..\src\MergeModules\YouTubeMergeModule\Release\*.msm ..\lib\MergeModules\*.* +xcopy /y ..\src\gphotos\bin\*.xml ..\docs\*.* +xcopy /y ..\src\gspreadsheets\bin\*.xml ..\docs\*.* +xcopy /y ..\src\webmastertools\bin\*.xml ..\docs\*.* +xcopy /y ..\src\youtube\bin\*.xml ..\docs\*.* +cd ..\lib\release\ rem run ILMerge on PhotoBrowser.exe -cd ..\lib\release\ -ilmerge Photobrowser.exe Google.GData.Client.Dll Google.GData.Extensions.Dll Google.GData.Photos.Dll /out:PhotoTool.exe +ilmerge Photobrowser.exe Google.GData.Client.dll Google.GData.Extensions.dll Google.GData.Photos.dll /out:PhotoTool.exe del Photobrowser.exe del Phototool.pdb rem run ILMerge on DocListExport.exe -cd ..\lib\release\ -ilmerge DocListExport.exe Google.GData.Client.Dll Google.GData.Extensions.Dll Google.GData.AccessControl.Dll Google.GData.Documents.dll /out:DocListExporter.exe +ilmerge DocListExport.exe Google.GData.Client.dll Google.GData.Extensions.dll Google.GData.AccessControl.dll Google.GData.Documents.dll /out:DocListExporter.exe del DocListExport.exe - rem run ILMerge on YouTubeNotifier.exe -ilmerge NotifierForYT.exe Google.GData.Client.Dll Google.GData.Extensions.Dll Google.GData.YouTube.Dll /out:nfyt.exe +ilmerge NotifierForYT.exe Google.GData.Client.dll Google.GData.Extensions.dll Google.GData.YouTube.dll /out:nfyt.exe del NotifierForYT.exe goto doneBuilding @@ -131,6 +136,3 @@ :doneBuilding cd .\..\..\misc - - - diff -Nru gdata-sharp-1.4.0.2/misc/pushdoc.cmd gdata-sharp-1.7.0.1/misc/pushdoc.cmd --- gdata-sharp-1.4.0.2/misc/pushdoc.cmd 2008-09-01 16:10:59.000000000 +0000 +++ gdata-sharp-1.7.0.1/misc/pushdoc.cmd 2010-11-23 18:10:27.000000000 +0000 @@ -1,26 +1,23 @@ -@echo off -set shfb_home=%ProgramFiles%\EWSoftware\Sandcastle Help File Builder -set src_home=..\src\VS2003 +#@echo off set out_dir=..\lib set doc_dir=..\docs set target_dir=..\..\..\..\docs -set temp_dir=d:\tempHTML +set temp_dir=c:\gdata.doc time /t rem build documentation -"%shfb_home%\SandcastleBuilderConsole.exe" GDataProject.shfb +msbuild.exe gdatadocumentation.shfbproj move "%temp_dir%\Google.GData.Documentation.chm" "%doc_dir%\" move "%temp_dir%\*.log" . echo "%temp_dir%\*.*" echo "%target_dir%\*.*" -move /y "%temp_dir%\*.*" "%target_dir%\" -echo "now moving html files" -move /y "%temp_dir%\html\*.*" "%target_dir%\html\" -echo "now moving the index" -move /y "%target_dir%\Index.html" "%target_dir%\orgindex.html" -echo "now moving addtional contents" -move /y "%temp_dir%\AdditionalContent\*.*" "target_dir%\AdditionalContent\" +mkdir "%target_dir%\html" + +copy /y "%temp_dir%\*.*" "%target_dir%\*.*" +copy /y "%temp_dir%\html\*.*" "%target_dir%\html\" +copy /y "%target_dir%\Index.html" "%target_dir%\orgindex.html" +copy /y "%temp_dir%\AdditionalContent\*.*" "%target_dir%\AdditionalContent\" time /t diff -Nru gdata-sharp-1.4.0.2/RELEASE_NOTES.HTML gdata-sharp-1.7.0.1/RELEASE_NOTES.HTML --- gdata-sharp-1.4.0.2/RELEASE_NOTES.HTML 2009-02-27 15:37:17.000000000 +0000 +++ gdata-sharp-1.7.0.1/RELEASE_NOTES.HTML 2010-11-23 18:10:27.000000000 +0000 @@ -1,1253 +1,646 @@ + - - Release Notes - - - -

This document lists the changes in the different releases

-

- 1.4.0.2 -

-
    -
  • - Features -
  • -
      -
    • Added PlaylistID and PlaylistTitle support to the - subscription entries in youtube feeds, added support for - subscriptions to the Google.YouTube namespace
    • -
    • - Added Google Contacts v2 support, including a new, vertical - model like the YouTube programming model. You can find this - in the Google.Contacts namespace. -
    • -
    • - Added Batch access to the new generics model. You can now - create a FeedRequest object, and use it's Batch method to send a - List of entry objects to the server. Entry and Feed expose - access to the batch data. -
    • -
    • Added Google Documents v2 support including the new - download functionallity
    • -
    • - Added a new Google Documents exporter sample. It allows you to - populate a treeview with your Google Documents and then export - each individual file in a variety of formats. -
    • -
    • - Extended the YouTube Notifier sample to use the User Events feed - as well. -
    • -
    -
  • - Bugfixes/changes -
  • + + Release Notes + + +

    This document lists the changes in the different releases

    +

    1.7.0.0

    +
      +
    • Features
    • +
    • +
        +
      • Added support for Organization Units to the Provisioning API.
      • +
      • Added support for Multiple Domains to the Provisioning API.
      • +
      • Added default retry count for failed requests.
      • +
      +
    • +
    • Bugfixes/changes
    • +
    • +
        +
      • Fixed ResumableUpload implementation. Kudos to Andrew Fields. (issue 431)
      • +
      • Many small fixes to the project setup and build scripts.
      • +
      +
    • +
    +

    1.6.0.0

    +
      +
    • Features
    • +
    • +
        +
      • Bugfixes and unittests for OAuth support. As far as we know, OAuth, in all variations works fine now
      • +
      • Added support for the new analytics api by Morten Christensen (http://blog.sitereactor.dk) (see details below). You can find this in the Google.GData.Analytics namespace.
      • +
      • Added AnalyticsService extends the basic Service abstraction to define a service that is preconfigured for access to the Google Analytics data API.
      • +
      • Added AccountQuery and DataQuery subclasses of FeedQuery, to create an Analytics Account and Data query URI.
      • +
      • Added AccountFeed and DataFeed (SourceFeed is also added) that lets you access the analytics accounts you own and data for those accounts.
      • +
      • Added AccountEntry and DataEntry for getting entries in an account or data feed.
      • +
      • Added extensions for all of the above, including: aggregates, dimension, metric, property, tableId and tableName. These are all located in the Analytics namespace (Google.GData.Analytics).
      • +
      • Unit tests for the analytics project added to the unittest project in the VS2005 solution (Created by Alex Maitland)
      • +
      • Simple sample application created and added to the sample library and VS2005 solution (Created by Morten Christensen)
      • +
      • Added support for OAuth requests using the new RequestSettings object. RequestSettings got one more constructor.
      • +
      • Added support for Contacts V3, including structured address/name informations
      • +
      • Documentlist: Added support for writersCanInvite
      • +
      • Documentlist: Added support for resourceId
      • +
      • Documentlist: Added a property to get the ACL URI directly on the Document object
      • +
      • ResumableUpload: Added support for a generic resumable upload component, and a complex YouTube sample for this
      • +
      +
    • +
    • Bugfixes/changes
    • +
    • +
        +
      • For a complete list of bugfixes included in this release, click here +
      • Atom Content handling was still weird/wrong/incomplete. I changed this again, hopefully for the last time:
          -
        • Added the missing contacts DLL to the setup program.
        • -
        • Changed the new Feed model code to lazily load the feed on - construction.
        • -
        • - Removed the CreateInstance methods from the new feedmodel and - changed the internals to lazyily create the inner objects on - demand. That means, no more Video v = Vidoe.CreateInstance() - in your code, but Video v = new Video() is now fine. -
        • -
        • Removed an incorrect check for HTTP.StatusOK (200) as the - result for an HTTP.Delete operation. Delete can return any 2xx - code in theory. -
        • -
        • - Fixed issue 209, an feed.Entries.Add(entryOfAnotherFeed) did - create a source element automatically. That was too smart for - it's own good. There is an explict method - Entries.MoveOrCopy(entry) that does that, add will just change - the ownership to the new collection. -
        • -
        • - Changed Google.Client.Entry.ID to Google.Client.Entry.Id -
        • -
        • - fixed the feed.Entries iterator to restart from the beginning - when you want to use it again. Note that you should cache the - output of the iterator is you want to use that in a loop. -
        • -
        • Fixed issue 217, a call to setUserCredentials now automatically invalidates - a stored authtoken.
        • -
        • Fixed issue 200. A feedQuery now supports an etag property, and several new - service method overloads for query and send support an etag as a parameter.
        • -
        • Service.Query(FeedQuery, ifModifiedSince) is now marked obsolete. You can use the ModifiedSince - property on the FeedQuery object and Query(FeedQuery) instead.
        • -
        • Added the ability to store a client token to - GDataCredentials. Setting the credentials property will take - this into account.
        • -
        • Changed the base apps feed uri for Google Apps
        • -
        • - Changed GBatchStatus and GBatchError to use the correct - namespace, it was incorrectly using the prefix instead. -
        • -
        • fixed issue 218, setting org.Title or org.name in a - contact to null or an empty string did not remove the - element.
        • -
        • - fixed issue 203, you can now retrieve the ACL feed for a - document -
        • -
        • - fixed issue 200, feedquery now has an etag property to create - if-match queries. -
        • -
        • - Fixed issue 221, setting private to false in an YouTubeEntry - resulted in failure to persist that entr. -
        • - -
        • Added a setter for Entry.Id
        • -
        • Added a batch method for Feed
        • -
        • YouTube.Video.VideoId now has a setter
        • -
        • YouTube.YouTubeRequest has an AddComment method.
        • -
        • Google.Client.FeedRequest has a new Get(Uri uri) method
        • - -
        • Added AppControl and IsDraft accessors to - Google.Client.Entry
        • -
        • Added a Get(uri) method to the - Google.Client.FeedRequest
        • - -
        • Fixed YouTubeEntry.State to actually parse and return the - yt:state element
        • - -
        • Added property accessors to YouTube.State
        • - -
        • Added a State property accessor - to Google.YouTube.YouTubeRequest
        • -
        • Added a - GetVideoMetaData method to YouTubeRequest
        • -
        • Changed Get on the FeedRequest to Retrieve for single - entries. This was required for the new overloads introduced. - Also, as Retrieve directly accesses the service, compared to - Get wich is defered, a name change is a good distinction. -
        • -
        • Video.Rating, ViewCount and CommentCount returns -1 as default - if no value was found.
        • - -
        • Lot's of addtions to the Entry Model and it's subclasses. Check - the documentation for details
        • - -
        -
      - - -

      - 1.3.1.0 -

      -
      • - Features + everything that is text/html, or text, or text/* will be treated as text, and ReadString will be called.
      • -
          -
        • Added a mergemodule for the Core libraries.
        • -
        • Added a mergemodule for the YouTube libraries.
        • -
        • Added a new sample application for YouTube, the YouTube Notifier
        • -
        • - Added a YouTubeQuery.GetYouTubeCategories method that returns a - collection of category objects based on parsing the youtube - category file hosted on the web. -
        • -
        • YouTube project template.
        • -
        • - New, simpler, YouTube object model. Look at the items in the new - Google.YouTube namespace. This new code is used in the YouTube - Sample application, the template above, and the youtubetest.cs - file in the unittests. -
        • -
        • - Added a ModifiedSince property on the FeedQuery object. If set - to something different than DateTime.MinValue this results in an - if-modified-since HTTP header produced if the FeedQuery is used - in a Service.Query call. -
        • -
        • OAuth support for two-legged authentication. Look in samples/OAuth for a usage example. Code for this - graciously provided by Andrew Smith and Eran Sandler. Note that due to different support on the Compact Framework, - this is not available in the Windows Mobile build.
        • -
      • - Bugfixes/changes + everything that is xml media type will be treated by being processed into extension elements
      • -
          -
        • - Fixed issue 198. HealthEntry.CCR returned null, as a wrong cast - after the recent refactory that happened to the extensions - returned always null. - -
        • -
        • - Fixed issue 195. Service.Update could call itself, resulting in - recursion. -
        • -
        • - Fixed bug 194. CreatePicasaUri was confusing because it used the - albumname as a parameter compared to an albumid. Changed to now - use an AlbumID. -
        • -
        • - Removed the ASP build and marked the standard release assemblies - as Partially Trusted. -
        • -
        • - Fixed issue 191, Overloaded AuthSubUtil.getRequestUrl(hostedDomain, nextUrl, scope, secure, session) is broken -
        • -
        • - Fixed issue 189, Cannot select Contacts by group -
        • -
        • Fixed an issue in AlbumEntry Accessor for Picasa, where ComentingEnabled accidently - set the wrong element in the xml
        • -
        • - Removed the Service(service, application, library) constructor - as this variation did not use the passsed in information. If you - used this, just remove the 3rd parameter. -
        • -
        • - Entry.Update and Entry.Delete will now thow an - InvalidOperationException when they are called without a valid - service object being set, instead of not doing anything - silently. -
        • -
        • - Removed the usage of StringCollection and replaced it with a - generic List -
        • -
        • - CommentingEnabled was accidently setting the CommentCount - element. -
        • -
        • - Made the created useragent string more uniform and meaningful -
        • -
        • - AtomFeed.Entries are not an ILIst<> an no longer an arraylist. -
        • -
        • - Fixed several v2 related YouTube issues -
        • -
        • - Fixed issue 186 by removing the verification check at the end of the reminder parser -
        • -
        -
      - - -

      - 1.2.3.0 -

      -
      • - Features -
      • -
          -
        • Added support for EMail Settings in Google Apps
        • - -
        • Added support for the protocol version 2
        • -
            -
          • YouTube will work against version 2 of the protocol by - default. Added support for the version 2 of the YouTube - feed. Old methods are marked as obsolete and will be removed - in future releases.
          • -
          • Bloogger will work against version 2 of the protocol by - default.
          • -
          -
        • - Created a blogger service, feed, entry and query class. The - query class allows the OrderBy parameter. This also fixes issue - 151 on the public issue list. Added a PostUri method to the - blogger entry. -
        • -
        • - Added the Error subelement collection to GDataBatchStatus. - Removed the Value element as it was not used. -
        • -
        • Issue 166: Added a GetTokenInfo helper method that returns - a Dictionary with the Information returned about the - authentication token.
        • -
        • Added a bool property Private to the YouTubeEntry - identifying if a video is private
        • -
        • Added a script to create a linux friendly tarball
        • -
        • Issue 165: Added the ability to access the error collection - from inside the batch error.
        • -
        -
      • - -
      - Bugfixes/changes -
    • -
        -
      • Fixed issue 154: you can now access the publishing priority - element on a GBaseEntry directly.
      • -
      • Fixed issue 176: onProgress events were potentially not - being raised in the Async Methods.
      • -
      • Fixed issue 178: Groups feeds on the contacts service did - not work when using https.
      • -
      • Fixed issue 180: Passwords with some special characters - were incorrectly encoded, leading to a failure in - authentication.
      • -
      • Removed the version dependency for the NUNIT tests, so that the - tests can now be used with different installed versions of the - NUNIT framework. -
      • -
      • Some typographical changes. getExtensionValue and - setExtension are now named GetExtensionValue and - SetExtensionValue
      • -
      • - Unknown extension elements are now stored in a Wrapper - XmlExtension element, which implements the usual - IExtensionElements interfaces to enable removing untyped lists - internally. -
      • -
      • - Moved the core of the extension functionallity, so just the base - classes, into the Google.GData.Client, so that the base - AtomFeed/AtomEntry can be extended using this extension system. - Otherwise there would be a circular reference between client.dll - and extension.dll -
      • -
      -
    - -

    1.2.2.0

    -
      -
    • Features
    • -
        -
      • Added a SetRequestFactory method on the AppsService. This - allows a user of the AppsService to set advanced HTTP properties - for the underlying service objects used (like setting a proxy - server, additional headers etc.) by creating a new RequestFactory - object and passing it into the service. To make it easy to create - this factory object a helper CreateRequestFactory was added to - the AppsService object as well. -
      • -
      • - Asyncronous/background support including a sample application. - You can now easily fire off that long running YouTube upload, or - the download of a picture as a seperate thread, so that your main - application is no longer blocked. It uses the AsyncOperation - pattern, and is not available (due to missing base support in the - compact framework) in the Windows Mobile build.
        - The sample PhotoBrowser application was changed to use that - pattern, and a page in the helpfile introduces the concept. -
      • -
      • Added support for Issue 163: the calendar recently - introduced several new elements, this adds support for syncEvent, - uui and sequence
      • + everything that is not above, has to be base 64 encoded, and that encoded stuff will be read with ReadString again +
      + This is now completely per atom spec. So xhtml (which i do not believe any service uses) will be treated over subelements.
    -
  • Bugfixes
  • + +
+

1.4.0.2

+
    +
  • Features
  • +
    • -
    • - Fixed a bug in CommentingEnabled on the PhotoAccessor, which was - setting internally the wrong property. -
    • -
    • - Changed the behaviour of AlbumEntry.AlbumAuthor. The setter will - now create a new author is no author is present. -
    • -
    • Fixed an issue regarding content, type=text. This element was not encoding correctly - which could lead to server errors based on the contents of the element.
    • -
    • Fixed issue 164, the code will now throw an exception if we - get an empty location header in a redirect situation
    • -
    • - Fixed issue 161, changed the WebProxy property on the - RequestFactory object to IWebProxy to make this interface more - flexible. -
    • -
    • Removed an obsolete size check for the authentication - response for client login and login for webapplications.
    • -
    • Fixed issue 160, FirstName in the profile feed of YouTube - was spelled wrong and hence not loaded correctly.
    • -
    • Fixed issue 157, Slug Header encoding. This was not - correctly confirming to RFC5023. Introduced a new helper method - in the utilities class for this purpose.
    • -
    • Fixed issue 147, a composite feed with a comment was not loading
    • -
    • Fixed issue 148, RemoveAt did not remove the object from the - containing collection, only locally. Fixed by overriding the - OnRemove method.
    • -
    • Fixed issue 155, there was no way to create a read only - youtube service, or rephrased, one that did not require a - developer key
    • -
    • Fixed issue 159, a typo in the makefile that prevented gac - install/uninstall
    • -
    • Fixed issue 156, if an exception happened during upload, the - resource was kept open
    • -
    • Fixed issue 149, the Who element failed to parse attendee - status if a whitespace element was encountered
    • -
    • Fixed issue 144, recurrenceexception is not parsed correctly
    • -
    • Fixed issue 145, FeedLink element parser error
    • -
    • Fixed issue 146. Passwords containing percentage signs were not - properly encoded. -
    • -
    -
- - -

1.2.1.0

-
    -
  • Features
  • -
      -
    • Added media:rating to media:group
    • -
    • Added the most-popular constants to the defined youtube - queries
    • -
    • Added missing convienience classes to YouTube (Comments, - Complaints etc, check the YouTube documentation)
    • -
    • Added PDF support to the Google Documents API
    • -
    • Added a CategoryQueriesAsParameter property on the feedquery - class, and making that false by default. On the YouTubeQuery this - is true by default. The effect is that category queries will not - be created by extending/changing the path portion of the URL, but - instead using a new parameter "category" and putting the - categories comma delimited into the query part of the uri.
    • - -
    -
  • Bugfixes
  • -
      -
    • Fixed issue 135. There was a bug in the FeedQuery parsing - code that resulted in URIs with date parameters that are encoded - to potentially throw
    • -
    • Removed the Cookie property and replaced it with a Cookies - properter on the RequestFactory. The old code, using just a simple - string, was implemented for mobile benefits, as the - CookieContainer, that is used now, does not exist on the compact - framework. The simple solution though is creating problems in some - scenarios, and had to be removed.
    • -
    • Added over 100 more unittests for the YouTube service
    • -
    • Fixed issue 102, 142
    • - -
    -
- - -

1.2.0.0

-
    +
  • Added PlaylistID and PlaylistTitle support to the subscription entries in youtube feeds, added support for subscriptions to the Google.YouTube namespace
  • +
  • Added Google Contacts v2 support, including a new, vertical model like the YouTube programming model. You can find this in the Google.Contacts namespace.
  • +
  • Added Batch access to the new generics model. You can now create a FeedRequest object, and use it's Batch method to send a List of entry objects to the server. Entry and Feed expose access to the batch data.
  • +
  • Added Google Documents v2 support including the new download functionallity
  • +
  • Added a new Google Documents exporter sample. It allows you to populate a treeview with your Google Documents and then export each individual file in a variety of formats.
  • +
  • Extended the YouTube Notifier sample to use the User Events feed as well.
  • +
+ +
  • Bugfixes/changes
  • +
  • +
      +
    • Added the missing contacts DLL to the setup program.
    • +
    • Changed the new Feed model code to lazily load the feed on construction.
    • +
    • Removed the CreateInstance methods from the new feedmodel and changed the internals to lazyily create the inner objects on demand. That means, no more Video v = Vidoe.CreateInstance() in your code, but Video v = new Video() is now fine.
    • +
    • Removed an incorrect check for HTTP.StatusOK (200) as the result for an HTTP.Delete operation. Delete can return any 2xx code in theory.
    • +
    • Fixed issue 209, an feed.Entries.Add(entryOfAnotherFeed) did create a source element automatically. That was too smart for it's own good. There is an explict method Entries.MoveOrCopy(entry) that does that, add will just change the ownership to the new collection.
    • +
    • Changed Google.Client.Entry.ID to Google.Client.Entry.Id
    • +
    • fixed the feed.Entries iterator to restart from the beginning when you want to use it again. Note that you should cache the output of the iterator is you want to use that in a loop.
    • +
    • Fixed issue 217, a call to setUserCredentials now automatically invalidates a stored authtoken.
    • +
    • Fixed issue 200. A feedQuery now supports an etag property, and several new service method overloads for query and send support an etag as a parameter.
    • +
    • Service.Query(FeedQuery, ifModifiedSince) is now marked obsolete. You can use the ModifiedSince property on the FeedQuery object and Query(FeedQuery) instead.
    • +
    • Added the ability to store a client token to GDataCredentials. Setting the credentials property will take this into account.
    • +
    • Changed the base apps feed uri for Google Apps
    • +
    • Changed GBatchStatus and GBatchError to use the correct namespace, it was incorrectly using the prefix instead.
    • +
    • fixed issue 218, setting org.Title or org.name in a contact to null or an empty string did not remove the element.
    • +
    • fixed issue 203, you can now retrieve the ACL feed for a document
    • +
    • fixed issue 200, feedquery now has an etag property to create if-match queries.
    • +
    • Fixed issue 221, setting private to false in an YouTubeEntry resulted in failure to persist that entr.
    • +
    • Added a setter for Entry.Id
    • +
    • Added a batch method for Feed
    • +
    • YouTube.Video.VideoId now has a setter
    • +
    • YouTube.YouTubeRequest has an AddComment method.
    • +
    • Google.Client.FeedRequest has a new Get(Uri uri) method
    • +
    • Added AppControl and IsDraft accessors to Google.Client.Entry
    • +
    • Added a Get(uri) method to the Google.Client.FeedRequest
    • +
    • Fixed YouTubeEntry.State to actually parse and return the yt:state element
    • +
    • Added property accessors to YouTube.State
    • +
    • Added a State property accessor to Google.YouTube.YouTubeRequest
    • +
    • Added a GetVideoMetaData method to YouTubeRequest
    • +
    • Changed Get on the FeedRequest to Retrieve for single entries. This was required for the new overloads introduced. Also, as Retrieve directly accesses the service, compared to Get wich is defered, a name change is a good distinction.
    • +
    • Video.Rating, ViewCount and CommentCount returns -1 as default if no value was found.
    • +
    • Lot's of addtions to the Entry Model and it's subclasses. Check the documentation for details
    • +
    +
  • + +

    1.3.1.0

    +
    • Features
    • -
        -
      • - Added support for the gd:rating element -
      • -
      • Added direct properties for Url, Height, Width for the - MediaThumbnail
      • -
      • - Added support for mediarss:category as a childcollection of - media:group -
      • -
      • - Created a real app:control extension. This one is currently only - used in the YouTube namespace. -
      • -
      • - Added support for YouTube -
      • +
      • +
          +
        • Added a mergemodule for the Core libraries.
        • +
        • Added a mergemodule for the YouTube libraries.
        • +
        • Added a new sample application for YouTube, the YouTube Notifier
        • +
        • Added a YouTubeQuery.GetYouTubeCategories method that returns a collection of category objects based on parsing the youtube category file hosted on the web.
        • +
        • YouTube project template.
        • +
        • New, simpler, YouTube object model. Look at the items in the new Google.YouTube namespace. This new code is used in the YouTube Sample application, the template above, and the youtubetest.cs file in the unittests.
        • +
        • Added a ModifiedSince property on the FeedQuery object. If set to something different than DateTime.MinValue this results in an if-modified-since HTTP header produced if the FeedQuery is used in a Service.Query call.
        • +
        • OAuth support for two-legged authentication. Look in samples/OAuth for a usage example. Code for this graciously provided by Andrew Smith and Eran Sandler. Note that due to different support on the Compact Framework, this is not available in the Windows Mobile build.
        • +
        +
      • +
      • Bugfixes/changes
      • +
      • +
          +
        • Fixed issue 198. HealthEntry.CCR returned null, as a wrong cast after the recent refactory that happened to the extensions returned always null.
        • +
        • Fixed issue 195. Service.Update could call itself, resulting in recursion.
        • +
        • Fixed bug 194. CreatePicasaUri was confusing because it used the albumname as a parameter compared to an albumid. Changed to now use an AlbumID.
        • +
        • Removed the ASP build and marked the standard release assemblies as Partially Trusted.
        • +
        • Fixed issue 191, Overloaded AuthSubUtil.getRequestUrl(hostedDomain, nextUrl, scope, secure, session) is broken
        • +
        • Fixed issue 189, Cannot select Contacts by group
        • +
        • Fixed an issue in AlbumEntry Accessor for Picasa, where ComentingEnabled accidently set the wrong element in the xml
        • +
        • Removed the Service(service, application, library) constructor as this variation did not use the passsed in information. If you used this, just remove the 3rd parameter.
        • +
        • Entry.Update and Entry.Delete will now thow an InvalidOperationException when they are called without a valid service object being set, instead of not doing anything silently.
        • +
        • Removed the usage of StringCollection and replaced it with a generic List
        • +
        • CommentingEnabled was accidently setting the CommentCount element.
        • +
        • Made the created useragent string more uniform and meaningful
        • +
        • AtomFeed.Entries are not an ILIst<> an no longer an arraylist.
        • +
        • Fixed several v2 related YouTube issues
        • +
        • Fixed issue 186 by removing the verification check at the end of the reminder parser
        • +
        +
      • +
      +

      1.2.3.0

      +
        +
      • Features
      • +
      • +
          +
        • Added support for EMail Settings in Google Apps
        • +
        • Added support for the protocol version 2
        • +
        • +
            +
          • YouTube will work against version 2 of the protocol by default. Added support for the version 2 of the YouTube feed. Old methods are marked as obsolete and will be removed in future releases.
          • +
          • Bloogger will work against version 2 of the protocol by default.
          • +
          +
        • +
        • Created a blogger service, feed, entry and query class. The query class allows the OrderBy parameter. This also fixes issue 151 on the public issue list. Added a PostUri method to the blogger entry.
        • +
        • Added the Error subelement collection to GDataBatchStatus. Removed the Value element as it was not used.
        • +
        • Issue 166: Added a GetTokenInfo helper method that returns a Dictionary with the Information returned about the authentication token.
        • +
        • Added a bool property Private to the YouTubeEntry identifying if a video is private
        • +
        • Added a script to create a linux friendly tarball
        • +
        • Issue 165: Added the ability to access the error collection from inside the batch error.
        • +
        +
      • +
      Bugfixes/changes +
        +
      • Fixed issue 154: you can now access the publishing priority element on a GBaseEntry directly.
      • +
      • Fixed issue 176: onProgress events were potentially not being raised in the Async Methods.
      • +
      • Fixed issue 178: Groups feeds on the contacts service did not work when using https.
      • +
      • Fixed issue 180: Passwords with some special characters were incorrectly encoded, leading to a failure in authentication.
      • +
      • Removed the version dependency for the NUNIT tests, so that the tests can now be used with different installed versions of the NUNIT framework.
      • +
      • Some typographical changes. getExtensionValue and setExtension are now named GetExtensionValue and SetExtensionValue
      • +
      • Unknown extension elements are now stored in a Wrapper XmlExtension element, which implements the usual IExtensionElements interfaces to enable removing untyped lists internally.
      • +
      • Moved the core of the extension functionallity, so just the base classes, into the Google.GData.Client, so that the base AtomFeed/AtomEntry can be extended using this extension system. Otherwise there would be a circular reference between client.dll and extension.dll
      • +
      +

      1.2.2.0

      +
        +
      • Features
      • +
      • +
          +
        • Added a SetRequestFactory method on the AppsService. This allows a user of the AppsService to set advanced HTTP properties for the underlying service objects used (like setting a proxy server, additional headers etc.) by creating a new RequestFactory object and passing it into the service. To make it easy to create this factory object a helper CreateRequestFactory was added to the AppsService object as well.
        • +
        • Asyncronous/background support including a sample application. You can now easily fire off that long running YouTube upload, or the download of a picture as a seperate thread, so that your main application is no longer blocked. It uses the AsyncOperation pattern, and is not available (due to missing base support in the compact framework) in the Windows Mobile build.
          + The sample PhotoBrowser application was changed to use that pattern, and a page in the helpfile introduces the concept.
        • +
        • Added support for Issue 163: the calendar recently introduced several new elements, this adds support for syncEvent, uui and sequence
        • +
        +
      • +
      • Bugfixes
      • +
      • +
          +
        • Fixed a bug in CommentingEnabled on the PhotoAccessor, which was setting internally the wrong property.
        • +
        • Changed the behaviour of AlbumEntry.AlbumAuthor. The setter will now create a new author is no author is present.
        • +
        • Fixed an issue regarding content, type=text. This element was not encoding correctly which could lead to server errors based on the contents of the element.
        • +
        • Fixed issue 164, the code will now throw an exception if we get an empty location header in a redirect situation
        • +
        • Fixed issue 161, changed the WebProxy property on the RequestFactory object to IWebProxy to make this interface more flexible.
        • +
        • Removed an obsolete size check for the authentication response for client login and login for webapplications.
        • +
        • Fixed issue 160, FirstName in the profile feed of YouTube was spelled wrong and hence not loaded correctly.
        • +
        • Fixed issue 157, Slug Header encoding. This was not correctly confirming to RFC5023. Introduced a new helper method in the utilities class for this purpose.
        • +
        • Fixed issue 147, a composite feed with a comment was not loading
        • +
        • Fixed issue 148, RemoveAt did not remove the object from the containing collection, only locally. Fixed by overriding the OnRemove method.
        • +
        • Fixed issue 155, there was no way to create a read only youtube service, or rephrased, one that did not require a developer key
        • +
        • Fixed issue 159, a typo in the makefile that prevented gac install/uninstall
        • +
        • Fixed issue 156, if an exception happened during upload, the resource was kept open
        • +
        • Fixed issue 149, the Who element failed to parse attendee status if a whitespace element was encountered
        • +
        • Fixed issue 144, recurrenceexception is not parsed correctly
        • +
        • Fixed issue 145, FeedLink element parser error
        • +
        • Fixed issue 146. Passwords containing percentage signs were not properly encoded.
        • +
        +
      • +
      +

      1.2.1.0

      +
        +
      • Features
      • +
      • +
          +
        • Added media:rating to media:group
        • +
        • Added the most-popular constants to the defined youtube queries
        • +
        • Added missing convienience classes to YouTube (Comments, Complaints etc, check the YouTube documentation)
        • +
        • Added PDF support to the Google Documents API
        • +
        • Added a CategoryQueriesAsParameter property on the feedquery class, and making that false by default. On the YouTubeQuery this is true by default. The effect is that category queries will not be created by extending/changing the path portion of the URL, but instead using a new parameter "category" and putting the categories comma delimited into the query part of the uri.
        • +
        +
      • +
      • Bugfixes
      • +
      • +
          +
        • Fixed issue 135. There was a bug in the FeedQuery parsing code that resulted in URIs with date parameters that are encoded to potentially throw
        • +
        • Removed the Cookie property and replaced it with a Cookies properter on the RequestFactory. The old code, using just a simple string, was implemented for mobile benefits, as the CookieContainer, that is used now, does not exist on the compact framework. The simple solution though is creating problems in some scenarios, and had to be removed.
        • +
        • Added over 100 more unittests for the YouTube service
        • +
        • Fixed issue 102, 142
        • +
        +
      • +
      +

      1.2.0.0

      +
        +
      • Features
      • +
      • +
          +
        • Added support for the gd:rating element
        • +
        • Added direct properties for Url, Height, Width for the MediaThumbnail
        • +
        • Added support for mediarss:category as a childcollection of media:group
        • +
        • Created a real app:control extension. This one is currently only used in the YouTube namespace.
        • +
        • Added support for YouTube
        • Added support for Google Health
        • -
        • Added HealthTool in the samples directory as a supporting - tool for Google Health
        • -
        • - Added support for the timeout property of the http request. You do - this by setting tbe timeout on the GDataRequestFactory to something - else than -1, which indicates the default of the created HTTPRequest - object. -
        • +
        • Added HealthTool in the samples directory as a supporting tool for Google Health
        • +
        • Added support for the timeout property of the http request. You do this by setting tbe timeout on the GDataRequestFactory to something else than -1, which indicates the default of the created HTTPRequest object.
        • Added support for the new Contacts feed. -
            -
          • ContactEntry now has a collection of ExtendedProperties
          • -
          • ContactEntry now has a collection of GroupMemberships
          • -
          • The ContactsQuery.CreateContactsUri returns a FULL - projection now by default. There is a new - CreateContactsUri(user,projection) to get the old behaviour, - or get other projections
          • -
          • There is a new ContactsQuery.CreateGroupsUri helper
          • -
          • ContactsQuery now supports the group parameter
          • - -
          -
        • -
        - -
      • Bugfixes/Changes
      • -
          -
        • It a text element is of type XHTML we now use the - XmlWriter.WriteRaw method. This leaves encoding/decoding in the hands - of the user of the API, but it seems to be the only way to guarantee - that all kind of xhtml can be created.
        • -
        • Changed the way AtomUris are loaded. In the past they were, for - readability reasons, decoded on the load. This caused issue in - certain situations, where the server expected the encoded version to - be exactly the same later on. For that reason, AtomUris are now not - decoded/encoded automatically, but this is left to the programmer. -
        • -
        • - Changed the Service.StreamInsert to a more appropriate name. It is - now called Service.EntrySend and virtual -
        • -
        • - Added a MediaService subclass that is going to be used for all - media/mime multipart enabled services (YouTube, Picasa) -
        • -
        • Fixed a memory leak related to the embedded gzip stream
        • -
        • Fixed a parsing bug in the AtomLink class
        • -
        • Fixed the build script for building ASP dlls. A corruption in - the solution file resulted in those not being rebuild anymore since - 1.1.3.1 +
            +
          • ContactEntry now has a collection of ExtendedProperties
          • +
          • ContactEntry now has a collection of GroupMemberships
          • +
          • The ContactsQuery.CreateContactsUri returns a FULL projection now by default. There is a new CreateContactsUri(user,projection) to get the old behaviour, or get other projections
          • +
          • There is a new ContactsQuery.CreateGroupsUri helper
          • +
          • ContactsQuery now supports the group parameter
          • +
        • -
        • - Fixed issue 120: cellQuery range and return-empty problem on empty - cells. Created a set of new helpers on the feedQuery object that - solve that issue. -
        • -
        • Fixed another round of FxCop violations. Where this has an external - effect, this is noted below. -
            -
          • Changed Apps.IpWhiteListed to Apps.IPWhiteListed
          • -
          +
        + +
      • Bugfixes/Changes
      • +
      • +
          +
        • It a text element is of type XHTML we now use the XmlWriter.WriteRaw method. This leaves encoding/decoding in the hands of the user of the API, but it seems to be the only way to guarantee that all kind of xhtml can be created.
        • +
        • Changed the way AtomUris are loaded. In the past they were, for readability reasons, decoded on the load. This caused issue in certain situations, where the server expected the encoded version to be exactly the same later on. For that reason, AtomUris are now not decoded/encoded automatically, but this is left to the programmer.
        • +
        • Changed the Service.StreamInsert to a more appropriate name. It is now called Service.EntrySend and virtual
        • +
        • Added a MediaService subclass that is going to be used for all media/mime multipart enabled services (YouTube, Picasa)
        • +
        • Fixed a memory leak related to the embedded gzip stream
        • +
        • Fixed a parsing bug in the AtomLink class
        • +
        • Fixed the build script for building ASP dlls. A corruption in the solution file resulted in those not being rebuild anymore since 1.1.3.1
        • +
        • Fixed issue 120: cellQuery range and return-empty problem on empty cells. Created a set of new helpers on the feedQuery object that solve that issue.
        • +
        • Fixed another round of FxCop violations. Where this has an external effect, this is noted below. +
            +
          • Changed Apps.IpWhiteListed to Apps.IPWhiteListed
          • +
        • -
        • - Service.SetAuthenticationToken will now work for ClientLogin and - AuthSub -
        • -
        • - The PhotoBrowser sample application will no longer crash when photos - can not be retrieved, or when you cancel the login screen. -
        • -
        -
      - -

      1.1.4.1

      -
        +
      • Service.SetAuthenticationToken will now work for ClientLogin and AuthSub
      • +
      • The PhotoBrowser sample application will no longer crash when photos can not be retrieved, or when you cancel the login screen.
      • +
      + +
    +

    1.1.4.1

    +
    • Features
    • -
        -
      • Added PrimaryEmail, PrimaryPostalAddress, PrimaryPhonenumber - and PrimaryIMAddress to the ContactEntry as convienience - accessors
      • -
      +
    • +
        +
      • Added PrimaryEmail, PrimaryPostalAddress, PrimaryPhonenumber and PrimaryIMAddress to the ContactEntry as convienience accessors
      • +
      +
    • Bugfixes
    • -
        -
      • Added the Recurrence class as an extension element back to the - EventEntry
      • -
      • Fixed the setup to put the contacts.cs file into the correct - place, so that the SDK solution file would work
      • +
      • +
          +
        • Added the Recurrence class as an extension element back to the EventEntry
        • +
        • Fixed the setup to put the contacts.cs file into the correct place, so that the SDK solution file would work
        • Removed the default app.ico files from the sample solutions
        • Corrected a reference in the apps migration sample project
        • -
        • The setup program did not put the Access Control Extension into - the correct place, so some references might have been wrong
        • -
        • Fixed a bug in FeedQuery that would error if no uri was - precalculated
        • -
        - -
      - -

      1.1.4.0

      -
        +
      • The setup program did not put the Access Control Extension into the correct place, so some references might have been wrong
      • +
      • Fixed a bug in FeedQuery that would error if no uri was precalculated
      • +
      + +
    +

    1.1.4.0

    +
    • Features
    • -
        -
      • Moved the codebase to .NET 2.0. Note this means that gradually more - code will change to use generics and other .NET 2.0 only features.
      • -
      • Added project templates for VS 2005 that are installed by the - setup program. If you use the .zip download, copy the templates into - the VS 2005 template folder
      • -
      • The setup program now points VS 2005 to the lib/release path - for the Google DLLs. The DLLs are no longer installed in the - GAC
      • +
      • +
          +
        • Moved the codebase to .NET 2.0. Note this means that gradually more code will change to use generics and other .NET 2.0 only features.
        • +
        • Added project templates for VS 2005 that are installed by the setup program. If you use the .zip download, copy the templates into the VS 2005 template folder
        • +
        • The setup program now points VS 2005 to the lib/release path for the Google DLLs. The DLLs are no longer installed in the GAC
        • Implemented IComparable and equal operators for AtomId
        • Google Contacts support
        • -
        • - Added a GDataVersionConflictException that is thrown when you tried - to modified/update a resource and the server detected a version - conflict. -
        • -
        • - Added support for the hd parameter for AuthSubRequests, so that a - particular domain can be specified. -
        • -
        • - Added support for a UseSSL property on the FeedQuery class. If set, - requests are made against the https version of the feed, if - available. This is mostly relevant for hosted domains. -
        • -
        • Added a UriEncodeUnsafe to the Utilities class to help with - encoding of user emails during the URL construction
        • -
        • Added new VS 2005 solution files for all targets for the contacts library.
        • -
        +
      • Added a GDataVersionConflictException that is thrown when you tried to modified/update a resource and the server detected a version conflict.
      • +
      • Added support for the hd parameter for AuthSubRequests, so that a particular domain can be specified.
      • +
      • Added support for a UseSSL property on the FeedQuery class. If set, requests are made against the https version of the feed, if available. This is mostly relevant for hosted domains.
      • +
      • Added a UriEncodeUnsafe to the Utilities class to help with encoding of user emails during the URL construction
      • +
      • Added new VS 2005 solution files for all targets for the contacts library.
      • +
      +
    • Bugfixes/changes
    • -
        -
      • Changed a lot of codeplaces due to a new FxCop run. Where this - has a public, visible effect, it is noted below:
      • -
          -
        • removed the setter for CustomHeaders, - Google.GData.Client.GDataRequestFactory.CustomHeaders
        • -
        +
      • +
          +
        • Changed a lot of codeplaces due to a new FxCop run. Where this has a public, visible effect, it is noted below:
        • +
        • +
            +
          • removed the setter for CustomHeaders, Google.GData.Client.GDataRequestFactory.CustomHeaders
          • +
          +
        • Updated to VS 2005 solution files. VS 2003 files are removed.
        • Changed documentation build to January Sandcastle release
        • -
        • Entry.SetAlternateUri was not setting the correct link - releationship and mediatype.
        • -
        • - small bugfixes to the base code (exceptions sometimes on missing attributes) -
        • -
        • Fixed a number of bugs in the calendar extension classes that - occured if you set new objects into the accessors
        • -
        • Fixed a crashing bug in the equal operator of the EnumConstruct - class
        • -
        • Fixed issue 105: Cannot add a reminder in a Recurring event using C# Calendar library
        • -
        • The Reminders property is now a typed generic collection
        • - -
        - - - -

        1.1.3.0

        -
          -
        • Features
        • -
            -
          • Added conditional Get support. The service object has an overloaded Query method now, - that allows you to pass a ifModifiedSince DateTime object into it.s
          • -
          • Added Authsub token revocation support. There is a new method - revokeToken in AuthsubUtil, similiar to the java class library
          • - -
          -
        • Bugfixes/changes
        • -
        • Issue 93: ReFixed Title Exact Queries for Spreadsheets. Using - Title-Exact resulted in two question marks in the query string.
        • -
        • Fixed the GeoRSS where extension, which lived in a mistyped namespace.
        • -
        • Fixed the Latitude property, which was misspelled Lattitude
        • -
        • Added the Doclist assemblies to the setup program
        • s -
        • Added MediaGroup.Contents as a Collection: as there - could be more than one. So all previous usages should be changed - to access the first element in a collection. The old method will remain - in there.
        • -
        -
      - - -

      1.1.2.0

      -
        +
      • Entry.SetAlternateUri was not setting the correct link releationship and mediatype.
      • +
      • small bugfixes to the base code (exceptions sometimes on missing attributes)
      • +
      • Fixed a number of bugs in the calendar extension classes that occured if you set new objects into the accessors
      • +
      • Fixed a crashing bug in the equal operator of the EnumConstruct class
      • +
      • Fixed issue 105: Cannot add a reminder in a Recurring event using C# Calendar library
      • +
      • The Reminders property is now a typed generic collection
      • +
      +

      1.1.3.0

      +
        +
      • Features
      • +
      • +
          +
        • Added conditional Get support. The service object has an overloaded Query method now, that allows you to pass a ifModifiedSince DateTime object into it.s
        • +
        • Added Authsub token revocation support. There is a new method revokeToken in AuthsubUtil, similiar to the java class library
        • +
        +
      • +
      • Bugfixes/changes
      • +
      • Issue 93: ReFixed Title Exact Queries for Spreadsheets. Using Title-Exact resulted in two question marks in the query string.
      • +
      • Fixed the GeoRSS where extension, which lived in a mistyped namespace.
      • +
      • Fixed the Latitude property, which was misspelled Lattitude
      • +
      • Added the Doclist assemblies to the setup program
      • +
      • s
      • +
      • Added MediaGroup.Contents as a Collection: as there could be more than one. So all previous usages should be changed to access the first element in a collection. The old method will remain in there.
      • +
      + +
    +

    1.1.2.0

    +
    • Features
    • -
        -
      • The SpreadsheetEntry has a new property, Worksheets. This - property returns a WorksheetFeed object that can be used to - retrieve the Worksheets feed for a given Spreadsheet.
      • -
      • The SpreadsheetEntry has a new property, WorksheetsLink. This - property returns a string that can be used to retrieve the - Worksheets feed uri for a given Spreadsheet.
      • -
      • Added CreateBatchFeed to the Atomfeed object. This will create - a default batch feed for you, if the feed supports batching. The - created batch feed will contain all currently dirty entries.
      • +
      • +
          +
        • The SpreadsheetEntry has a new property, Worksheets. This property returns a WorksheetFeed object that can be used to retrieve the Worksheets feed for a given Spreadsheet.
        • +
        • The SpreadsheetEntry has a new property, WorksheetsLink. This property returns a string that can be used to retrieve the Worksheets feed uri for a given Spreadsheet.
        • +
        • Added CreateBatchFeed to the Atomfeed object. This will create a default batch feed for you, if the feed supports batching. The created batch feed will contain all currently dirty entries.
        • Added a GDataBatchRequestException for that operation.
        • Added Delete(Uri uir) to the service interface.
        • -
        • Added more constructors to the CellEntry object, and moved - accessors for the CellEntry.Cell up to the CellEntry object. So - instead of writing CellEntry.Cell.Column, you can call - CellEntry.Column directly (and others).
        • -
        • Added an index accessor to the CellFeed, you can now access - Cells on the CellFeed like this: CellEntry entry = CellFeed[1,1]. - This will retrieve not existing cells if needed.
        • -
        • Added QueryCellFeed() and QueryCellFeedLink(ReturnEmptyCells - parameter) to the WorksheetEntry. The method with no parameters will - get you the serverdefault cell feed.
        • -
        • Added the CellFeedLink property on the WorksheetEntry. This - returns the URI to the CellFeed as string.
        • -
        • Added an overloaded Insert method to the WorksheetFeed so that - you do not need to cast the return anymore.
        • -
        • Added support for the Apps Migration API. The Google Apps Email Migration API - allows administrators and users of Google Apps to migrate mail from legacy - email systems into their domain's hosted Gmail accounts. - Your client application can upload email messages into these - accounts using standard Google data API feeds.
        • -
        • Added the gapps_migration_sample: A simple application that demonstrates how to migrate - email messages to a Google Apps email account. See the readme file in the - samples/appsforyourdomain/migration directory for more details
        • - -
        +
      • Added more constructors to the CellEntry object, and moved accessors for the CellEntry.Cell up to the CellEntry object. So instead of writing CellEntry.Cell.Column, you can call CellEntry.Column directly (and others).
      • +
      • Added an index accessor to the CellFeed, you can now access Cells on the CellFeed like this: CellEntry entry = CellFeed[1,1]. This will retrieve not existing cells if needed.
      • +
      • Added QueryCellFeed() and QueryCellFeedLink(ReturnEmptyCells parameter) to the WorksheetEntry. The method with no parameters will get you the serverdefault cell feed.
      • +
      • Added the CellFeedLink property on the WorksheetEntry. This returns the URI to the CellFeed as string.
      • +
      • Added an overloaded Insert method to the WorksheetFeed so that you do not need to cast the return anymore.
      • +
      • Added support for the Apps Migration API. The Google Apps Email Migration API allows administrators and users of Google Apps to migrate mail from legacy email systems into their domain's hosted Gmail accounts. Your client application can upload email messages into these accounts using standard Google data API feeds.
      • +
      • Added the gapps_migration_sample: A simple application that demonstrates†how to migrate email messages to a Google Apps email account. See the readme file in the samples/appsforyourdomain/migration directory for more details
      • +
      +
    • Bugfixes/changes
    • -
        -
      • When an entry was copied from one feed to another, the internal - service object was set incorrectly.
      • +
      • +
          +
        • When an entry was copied from one feed to another, the internal service object was set incorrectly.
        • Added unittests for the new spreadsheet code.
        • -
        • Issue 90: Corrected the override for Equals and GetHashCode for an EnumConstruct
        • -
        • Issue 93: Fixed Title Exact Queries for Spreadsheets
        • -
        • Issue 94: Fixed some incorrect Exception handlings
        • -
        -
      - - -

      1.1.1.0

      - -
        +
      • Issue 90: Corrected the override for Equals and GetHashCode for an EnumConstruct
      • +
      • Issue 93: Fixed Title Exact Queries for Spreadsheets
      • +
      • Issue 94: Fixed some incorrect Exception handlings
      • +
      + +
    +

    1.1.1.0

    +
    • Features
    • -
        -
      • Added an EventId property to the EventEntry object. This one - parses the atomId URI to just provided the EventId, which is used - elsewhere (e.g., for recurring events).
      • -
      • Added QueryAuthToken() on the service. If the Service is a - Google authenticated service, you can use this to obtain an - authentication token for ClientLogin
      • -
      • Added CreatePicasaUri helper on the PicasaQuery classes to - create a Uri based on a userID
      • -
      • Added new PhotoBrowser sample project. The resulting file PhotoTool.exe is produced - using the ILMerge tool from Microsoft (free download). That way, PhotoTool.exe is - a standalone application with no further assembly dependencies.
      • - -
      +
    • +
        +
      • Added an EventId property to the EventEntry object. This one parses the atomId URI to just provided the EventId, which is used elsewhere (e.g., for recurring events).
      • +
      • Added QueryAuthToken() on the service. If the Service is a Google authenticated service, you can use this to obtain an authentication token for ClientLogin
      • +
      • Added CreatePicasaUri helper on the PicasaQuery classes to create a Uri based on a userID
      • +
      • Added new PhotoBrowser sample project. The resulting file PhotoTool.exe is produced using the ILMerge tool from Microsoft (free download). That way, PhotoTool.exe is a standalone application with no further assembly dependencies.
      • +
      +
    • Bugfixes/Changes
    • -
        -
      • Fixed the parsing of the OriginalEvent@id attribute. The - SimpleContainer parent class was broken in the sense that it did not - call the generic parsing method at all. So all SimpleContainers - would not have read in attributes, luckily OriginalEvent was the - only instance of this.
      • -
      • Fixed the OriginalStartTime get/set method which was using the - wrong constant of the OriginalEvent object.
      • -
      • Fixed the onclear() handler of the new extensionCollection base - class. It was incorrectly casting to When obects, which could cause - a runtime error when called.
      • -
      • Fixed a bug in the simplecontainer class that could lead to an - exception if the extension list was empty
      • -
      • Fixed a bug in Originalevent where the wrong prefix was - persisted, making saving an originalevent impossible
      • -
      • Fixed NULL response object being used for authentication exceptions. - Now the correct object used for the authentication request is passed - to the exception.
      • -
      • Changed the AuthException code to provide the status code - detail as well
      • -
      • CalendarEntry did use the wrong namespace to find the location - object, hence retrieval of a calendar location was broken.
      • -
      • Fixed ExtensionBase to not save NULL attributes as empty - strings. This could cause Picasa updates to fail.
      • -
      • Fixed MediaGroup to allow the retrieval of multiple Thumbnails. - Introduced the ThumbnailCollection for this. To enable this, - SimpleContainer and AtomBase now implement IExtensionContainer, a - common interface that encapsulates owning Extension elements. -
      • -
      • Added a default constructor to CalendarQuery so that you can - use it on .NET CF with a starting URI
      • -
      • Changed the Reminder element to send an empty one to enable - creation of default Reminders in the calendar
      • -
      -
    - -

    1.1.0.0

    - -
      -
    • Features -
        -
      • - added GZip support for .NET 1.1, 2.0 and .NET Compact Framework 2.0. -
      • -
      • - added the ability to use authsubtokens to the ExecRequest utility (including - exchange of a onetime token to a session token). Just run ExecRequest for the - command line parameters, or read the help file page about it. -
      • -
      • - Support for Google Calendar WebContent Gadgets is included. A WebContent element - has a SortedList property to set and retrieve those preferences. See caltest.cs - for an example. +
      • +
          +
        • Fixed the parsing of the OriginalEvent@id attribute. The SimpleContainer parent class was broken in the sense that it did not call the generic parsing method at all. So all SimpleContainers would not have read in attributes, luckily OriginalEvent was the only instance of this.
        • +
        • Fixed the OriginalStartTime get/set method which was using the wrong constant of the OriginalEvent object.
        • +
        • Fixed the onclear() handler of the new extensionCollection base class. It was incorrectly casting to When obects, which could cause a runtime error when called.
        • +
        • Fixed a bug in the simplecontainer class that could lead to an exception if the extension list was empty
        • +
        • Fixed a bug in Originalevent where the wrong prefix was persisted, making saving an originalevent impossible
        • +
        • Fixed NULL response object being used for authentication exceptions. Now the correct object used for the authentication request is passed to the exception.
        • +
        • Changed the AuthException code to provide the status code detail as well
        • +
        • CalendarEntry did use the wrong namespace to find the location object, hence retrieval of a calendar location was broken.
        • +
        • Fixed ExtensionBase to not save NULL attributes as empty strings. This could cause Picasa updates to fail.
        • +
        • Fixed MediaGroup to allow the retrieval of multiple Thumbnails. Introduced the ThumbnailCollection for this. To enable this, SimpleContainer and AtomBase now implement IExtensionContainer, a common interface that encapsulates owning Extension elements.
        • +
        • Added a default constructor to CalendarQuery so that you can use it on .NET CF with a starting URI
        • +
        • Changed the Reminder element to send an empty one to enable creation of default Reminders in the calendar
        • +
      • -
      • - Picasa support: -
          -
        • Added all media extensions (media:rss, exif and photo>
        • -
        • Added a PhotoEntry and PhotoFeed class that contain all of - those extensions
        • +
        +

        1.1.0.0

        +
          +
        • Features +
            +
          • added GZip support for .NET 1.1, 2.0 and .NET Compact Framework 2.0.
          • +
          • added the ability to use authsubtokens to the ExecRequest utility (including exchange of a onetime token to a session token). Just run ExecRequest for the command line parameters, or read the help file page about it.
          • +
          • Support for Google Calendar WebContent Gadgets is included. A WebContent element has a SortedList property to set and retrieve those preferences. See caltest.cs for an example.
          • +
          • Picasa support: +
              +
            • Added all media extensions (media:rss, exif and photo>
            • +
            • Added a PhotoEntry and PhotoFeed class that contain all of those extensions
            • Added unittests to query an album and insert a new photo
            • -
            -
          • -
          • Added the QuickAdd feature for the Google Calendar. An EventEntry - has a QuickAdd boolean property. Setting it to true causes an insert to - be treated like a quickAdd operation. -
          • - -
          • Added the webcontentlink class to the Google Calendar Support to enable - easier creation of Gadgets in calendars.
          • - -
          • Batch support for Google Calendar
          • -
          • ASP .NET support for medium trust
          • - -
        • - -
        • Changes and Bugfixes -
            -
          • - Complete refactoring of Apps extension to use the new extension system - (IExtensionElementFactory, AbstractEntry and AbstractFeed). -
          • - -
          • - To enable ASP.NET hosting in medium trust, we removed the usage of the - NetworkCredentials class. From now on, credentials are either passed as username/password, - or using the GDataCredentials. (issue 57) -
          • -
          • - Changed "adminUserName" to "adminEmailAddress" in AppsService so that it's more - clear what information is actually required for this parameter. -
          • - -
          • - fixed a Google Base issue (The server doesn't accept scientific notations for - floats) -
          • -
          • - fixed typo in the blogger sample (www..blogger), which made the sample hard to - use -
          • - -
          • - make the GAuthToken property of the GAuthRequestFactory public. It was - mistakenly marked internal, so that the token could not be retrieved by a client - application for caching. -
          • -
          • - fixed a parsing issue that resulted in Batch Upload hanging if an unknown - element was encountered -
          • -
          • - added a helper method on AtomBase (entry and feed) to find exensionelements by - specifying a localname and an optional namespace (issue 81) -
          • -
          • - the extension mechanism was reworked by creating an ExtensionElementFactory - interface that takes care of parsing elements. ElementFactories are registered - on the AtomBase (entry and feed) level. -
          • -
          • - Fixed Issue 60, mulitple Reminders per Event. Note, that this introduces slight - changes when dealing with this. A new property, EventEntry.Reminders, was - created. The old property, EventEntry.Reminder, still exists, and only works on - the first Reminder in the list. Setting the old property will delete all - addtional reminders.The Reminders property is of type ArrayList (this is an - artifact of being .NET 1.1 compatible, once we move to .NET 2.0 or later, if - that ever happens, this could/should be typed). -
          • -
          • - Modified data model for Spreadsheets worksheets to make it easier to change and - construct associated meta-data -
          • -
          • - Added the ctz parameter to the EventQuery class. This parameter allows to - specify the timezone that is used to calculate start/end times for the returned - events -
          • -
          • - Added an AlternateUri Property on the AtomEntry class. This property - returns the AtomUri of a rel=alternate type=html LINK entry. As this is - similiar to the ill named LINK helper on the spreadsheet entry, that - helper was removed, as they do serve the same purpose, and the link - helper was read only. -
          • -
          • - Added an FeedUri Property on the AtomEntry class. This property - returns the AtomUri of a rel=#feed type=atom+xml LINK entry. -
          • -
          • - Added an MediaUri Property on the AtomEntry class. This property - returns the AtomUri of a rel=#edit-media type=atom+xml LINK entry. -
          • -
          • Added new methods on the AtomCategory collection. Find searches for a - category of a given term, or a term/scheme combination. Also changed the - implementation of the Contains method to compare not just object - fidelity, but also term/value pairs +
        • -
        • Added a ConvertToXSDSTring() helper in the Utilites class. As booleans - are represented as "True"/"False" in .NET, and xsd requires - "true"/"false" this helper takes care of that conversion. -
        • -
        • Added the ability to create custom AtomBase subclassed objects to - custom feeds/entries. Look at CreateAtomSubElement() in AtomBase. This - is used to create custom clases like WebContentLink in the derived - services
        • -
      • - -
      - -

      1.0.9.9

      -
        -
      • - added GBase support for m:adjusted_name and gm:adjusted_value inside attributes - (returned only when adjustments are enabled) -
      • - Google Apps changes: -
          -
        • - Added new AppsService.createUser methods with hashed password support -
        • - Updated AppsException with new Google Apps error codes -
        • - Added the following properties to Login.cs: string hashFunctionName -
        • - to hash user account password, bool agreedToTerms -
        • - to see if the user has accepted the Google Apps Terms Of Service, bool admin -
        • - to see if the user is a domain admin, bool changePasswordAtNextLogin -
        • - to force the user to change password at next login -
        • - Updated unittests to test new properties -
        -
      - -

      1.0.9.8

      -
        -
      • - fixed a parsing bug in SpreadsheetService -
      • - fixed a bug in GDataRequestException that would prevent AppsException from - accessing the server's response. -
      • - modified AppsException to comply with new GDataRequestException -
      • - fixed a bug in CalculateBaseUri, that caused a crash if the passed in parameters - are all NULL. This caused composite feeds to not load if there was a comment - feed embedded -
      • - fixed a bug in the CalendarEventEntry, it was not parsing extendedProperties. - They are now parsed and added correctly to the ExtensionElements -
      • - added ACL support. This resulted in changes in the CalendarService.Query method -
      • - as a CalendarService can now return an EventFeed or an AccessControlFeed is - returns now an AtomFeed that you can cast to what you are expecting. Added Query - overloads to accept EventQuery or AclQuery and return the appropriate Feeds -
      • - added a cmd line tool to query/insert/update to a service based on streams -
      • - modified the Spreadsheet service to use the new scheme of service subclassing. - This should fix a bundle of issues with regard to entry castings. -
      • - changed persistence of gd:extendedProperty to save the value attribute, even if - there is no data to persist -
      • - Added an ASP.NET release (lib/ASP.NET) where the DLLs are build with the - AllowPartiallyTrustedCallers attribute n enabled. Please use with caution and - refer to the readme.txt in that subdirectory for more information. -
      - -

      1.0.9.7

      -
        -
      • - fixed an incorrect trace statement in request.cs that had the result of - disabling reading the error response. -
      - -

      1.0.9.6

      -
        -
      • - added Google Apps for Your Domain support, a new helper DLL Google.GData.Apps.dll, - and a sample, as well as unittests. Version number is increased to distinguish - from Subversion, as this will be a binary download as well. -
      - -

      1.0.9.5

      -
        -
      • - fix for incorrect encoding of usernames/passwords during authentication (you - could run into problems if you had an email like "foo&joe@test.com" -
      • - exposure of the accountType as a property on the factory. If you happen to have - an identical user name for a Google account and a hosted account, you need to - set this property depending on which account you want to access. Default is - GOOGLE_OR_HOSTED, other values are GOOGLE or HOSTED as strings. -
      • - fixed an issue with the edit/self uris on the entry. They were not correctly - setable. -
      • - fixed an issue that one you used an authenticated service, but did not supply - credentials, we would send an empty authentication header. -
      • - added Captcha Handling and more detailed exceptions when the authentication - request fails. See authexceptions.cs for the list of potential exceptions thrown -
      • - added some preliminary unittests for the new exceptions -
      • - added a new constructor for the TokenCollection, so that captcha parsing is - handled correctly -
      • - made the debug output depending on the TRACE define, and removed that define for - the release build -
      - -

      1.0.9.4

      -
        -
      • - Google Base: fix for incorrect Price attribute behaviour -
      • - Google Base: fix for incorrectly persisting duplicate attributes -
      • - Fix for Content.Type having no default value (issue 41) -
      • - Fix for Content.Type="text/html" parsing incorrectly. The strict check for type= - "text" is now relaxed to be type="text*", so all text subtypes will be treated - the same -
      • - Fix for Content.Type = "html" and "text/html" persistence. What the code does - now is: first HTMLDecode the value held, than run the standard XMLWriter.WriteString - over it (which does HTML encoding). This seems to work fine. -
      • - Added the gm:stats tags to the Windows Mobile build, accidently forgot to change - that project file -
      • - the calendarfeed discarded entries unknown to it in the calendar namespace. This - is fixed now. Unknown entries to the parser are now correctly added to the - extension elements. -
      • - added the return-empty parameter to the cellquery class -
      • - added URL encoding to the authentication parameters (username/passwords etc that - had unallowed FORM post chars caused failed login attempts) -
      - - - -

      1.0.9.3

      -
        -
      • - Google Base changes: New features: -
          -
        • - GBaseQuery supports the following optional parameters; orderby, sortorder, - refine and content -
        • - Support for gm:stats tags -
        • - GBaseUriFactory can now generate the feed uri of other customers - Fixes: -
        • - Fixed the GBaseAttributeType hierarchy for date/dateTime/dateTimeRange -
        • - Fixed the type of the hardcoded ExpirationDate property in GBaseAttributes -
        -
      • - Added a Makefile for Mono builds. This one replaces the Ant file. -
      - -

      1.0.9.2

      -
        -
      • - Removed the MethodOverride default for the CalendarService. If you need that (due - to firewalls not allowing PUT/DELETE requests, you can reenable this with - setting the MethodOverride flag on the factory: ((GDataGAuthRequestFactory)calsvc.RequestFactory).MethodOverride - = false; -
      • - Changed the X-Method-Override behaviour for DELETE, to fix an issue with .NET - mobile (the mobile client would crash when the contentLength was set to 0 and no - stream was requested). -
      - -

      1.0.9.1

      -
    • - Added a KeepAlive property to the factory object. This is set to true by default. - .NET 2.0 clients, are due to behaviour changes in that runtime encouraged to set - this to false. - -

      1.0.9

      -
    • - Fixed an issue where the login services changed the response contenttype. The - check for text/plain is now more relaxed. -
    • - Added the missing location calls for Geolocation for GoogleBase -
    • - Fixed a build issue for Windows Mobile in release. The code now compiles for - PocketPC and WindowsMobile symbols defined. -

      1.0.8

      -
    • - Fixed issue 13 from the public issue list. If a content element contained xhtml, - and not just text, the content was not read correctly. -
    • - Fixed issue 17 from the public issue list. XHTML content was not persisted - correctly. -
    • - Added support for hosted domain feeds. This is done automatically, no - codechanges needed for the application developer. The authentication code was - changed to ask for Hosted domains first, then google accounts. -
    • - Added support for the app:control/app:draft element, but only in the way to - expose a boolean on the AtomEntry. The new member on AtomEntry is called IsDraft. -
    • - Changed the way atom:content is parsed. Text & HTML types use xmlreader.ReadString() - to get the inner content. XHTML and all other types use readInnerXml() to get - the content. -
    • - changed Exception handling. The code now throws more detailed exceptions based - on what was happening: -> GDataRequestException: generic exception -> - GDataForbiddenException: exception thrown when the server return a Forbidden on - authentication -> GDataRedirectException: exception thrown when the server - returned a redirect -
    • - changed redirect handling on Post. The library will follow redirects on Post - automatically by default, to accomodate Blogger (which currently may return 302s - on posts). This can be turned off by setting the .StrictRedirect property to - true on the GDataAuthRequestFactory. If it is turned off, the code will throw if - a redirect is happening on an HTTP verb other than GET. -
    • - changed redirect handling for DELETE/PUT the same as for POST -
    • - removed cookie handling. The code will handle cookies now without using the - CookieContainer (one hurdle on the way to the CompactFramework Port). -
    • - Fixed persistence of "initialized" date values for udpated/published on the atom.entry. - This resolves an issue with the Blogger. -
    • - Added EventEntry.Notifications. This property (boolean) indicates if an update - on an entry should send notifications to the attendees of the Event. -
    • - Fixed the gbase project (the NumberFormat.cs file was missing in the project - file). -
    • - Added a proxy property for the GDataRequestFactory. -
    • - Setting content-length correctly to fix WindowsMobile issues. This fix is a user - submitted, and created by Steeve Morin -
    • - Fixes to the authsub code, provided by Ryan Boyd -
    • - The DLLs were renamed, to follow the Windows .NET standard. gdata.dll -> - Google.GData.Client.dll gbase.dll -> Google.GData.GoogleBase.dll - gcalendar.dll -> Google.GData.Calendar.dll gcodesearch.dll -> Google.GData.CodeSearch.dll - gextensions.dll -> Google.GData.Extensions.dll and the new one -> - Google.GData.Spreadsheets.dll - - -

      1.0.7

      -
    • - Added support for published-min/published-max as standard query parameters -
    • - Added support for codesearch. A new DLL gcodesearch.dll and a new sample for - this is available. -
    • - Added support for the WebContent calendar extension -
    • - Added signing to the gbase.dll -

      1.0.6

      -
    • - Added support for sortoder, futurevents, singleevents on the calendarquery -
    • - Added a ResponseString property on the GDataRequestException to make debugging - server side errors easier -
    • - Fixed an issue with the GoogleBaseService, if you did set the RequestFactory - property twice, you would create too many header entries, and hence end up with - request denied responses -
    • - Added the shipping attribute for GoogleBase -
    • - Changed the payment attribute to payment_accepted for GoogleBase -

      1.0.5

      -
    • - Added batch support for GoogleFeeds, the first property to support this is the - GoogleBase product -
    • - Added a unittest for GoogleBase. This code shows update/insert/delete against - base for single entries and batch entries refer to clients/cs/src/unittests/gbase.cs - for sample code. -
    • - Added IComparable to atomuri.cs (based on a feature request on our issue list) -
    • - GDataAuthRequestFactory is now a subclass of GDataRequestFactory -
    • - Moved GCookies from GDataAuthRequestFactory to GDataRequestFactory and renamed - it to Cookies -
    • - removed the debug binaries from the lib directory -
    • - added a GoogleBase sample application in VB ! -
    • - added the build executables to the lib directory -
    • - added GoogleBase classes (similiar to the java classes) to access Google base - specific feeds - Known issues: -
    • - recurrenceException is not fully tested -
    • - authsubutil and gauthsubrequest are not fully tested - -

      1.0.4

      -
    • - Fixed a .NET 2.0 issue in calendarservice.cs, that dropped connections during - repeated calls. -
    • - Made the execution path more robust. -
    • - Added a property, numberOfRetries on the GAuthRequestFactory to indicate how - often an Execution should be retried if the server returns an error. -
    • - Fixed a bug in the daterange query creation (the +sign for the timezone was not - escaped properly) -
    • - Fixed an issue with updating, where if you used the same AtomEntry/EventEntry - several times to update, it could happen that extension elements were doubled, - and the update failed. -
    • - Fixed a bug in the parsing of all elements. This could cause an endless loop - when the content was empty. -
    • - Fixed several content creation issues (issues 5-9 on the issue list) -
    • - added support for the gd:extendedProperty -
    • - Added a calendar example application -
    • - added a sample application to access Blogger feeds, and post to blogger feeds. - Known issues: -
    • - recurrenceException is not fully tested -
    • - authsubutil and gauthsubrequest are not fully tested Solved issues: -
    • - .NET 2.0 seems to loose resources in some circumstances. Hard to reproduce. - - -

      1.0.3

      -
    • - Fixed the namespace creation for extensions, the wireformat should no longer - create the namespace declaration when it's not required -
    • - Fixed the reminder persistence code -
    • - added a TimeZone property on the EventFeed to retrieve the timezone value -
    • - added a FindEvent method on the EventFeed. This one takes an OriginalEvent - object, and returns the Event that this is based on. This will go to the server - if required. -
    • - Fixed recurrance issues in the extensions -
    • - Moved EventFeed and EventEntry from the Google.GData.Extensions namespace to the - Google.GData.Calendar namespace -
    • - Fixed a bug in the parsing of Atom:Content elements. This could cause an endless - loop when the content was empty. -

      1.0.2

      -
    • - Fixed a problem persisting feedlink elements -
    • - added an AllDay flag to the When class to allow parsing and persting of all day - events -
    • - cleaned up the persistence code in the extension classes -
    • - fixed a problem that resulted in persisting multiple extensionn objects instead - of one -
    • - added a timestamp method to the Tracing class to help measuring performance in - simple cases -

      1.0.1

      -
    • - Correctly uses 'rel.previous' instead of 'rel.prev' as required by Atom - Publishing Protocol. -
    • - Corrected the time-shift portion of the DateTime output for time zones with a - negative shift from UTC. -
    • - Corrected the time-shift to permit fractional hour shifts from UTC. -
    • - Correctly output "startTime" and "endTime" as attributes of the "when" extension - rather than child elements. -
    • - Refactored class hierarchy, now based on IExtensionElement. -

      1.0.0

      -
    • - Initial Release - - - +
    • Added the QuickAdd feature for the Google Calendar. An EventEntry has a QuickAdd boolean property. Setting it to true causes an insert to be treated like a quickAdd operation.
    • +
    • Added the webcontentlink class to the Google Calendar Support to enable easier creation of Gadgets in calendars.
    • +
    • Batch support for Google Calendar
    • +
    • ASP .NET support for medium trust
    • +
    + +
  • Changes and Bugfixes +
      +
    • Complete refactoring of Apps extension to use the new extension system (IExtensionElementFactory, AbstractEntry and AbstractFeed).
    • +
    • To enable ASP.NET hosting in medium trust, we removed the usage of the NetworkCredentials class. From now on, credentials are either passed as username/password, or using the GDataCredentials. (issue 57)
    • +
    • Changed "adminUserName" to "adminEmailAddress" in AppsService so that it's more clear what information is actually required for this parameter.
    • +
    • fixed a Google Base issue (The server doesn't accept scientific notations for floats)
    • +
    • fixed typo in the blogger sample (www..blogger), which made the sample hard to use
    • +
    • make the GAuthToken property of the GAuthRequestFactory public. It was mistakenly marked internal, so that the token could not be retrieved by a client application for caching.
    • +
    • fixed a parsing issue that resulted in Batch Upload hanging if an unknown element was encountered
    • +
    • added a helper method on AtomBase (entry and feed) to find exensionelements by specifying a localname and an optional namespace (issue 81)
    • +
    • the extension mechanism was reworked by creating an ExtensionElementFactory interface that takes care of parsing elements. ElementFactories are registered on the AtomBase (entry and feed) level.
    • +
    • Fixed Issue 60, mulitple Reminders per Event. Note, that this introduces slight changes when dealing with this. A new property, EventEntry.Reminders, was created. The old property, EventEntry.Reminder, still exists, and only works on the first Reminder in the list. Setting the old property will delete all addtional reminders.The Reminders property is of type ArrayList (this is an artifact of being .NET 1.1 compatible, once we move to .NET 2.0 or later, if that ever happens, this could/should be typed).
    • +
    • Modified data model for Spreadsheets worksheets to make it easier to change and construct associated meta-data
    • +
    • Added the ctz parameter to the EventQuery class. This parameter allows to specify the timezone that is used to calculate start/end times for the returned events
    • +
    • Added an AlternateUri Property on the AtomEntry class. This property returns the AtomUri of a rel=alternate type=html LINK entry. As this is similiar to the ill named LINK helper on the spreadsheet entry, that helper was removed, as they do serve the same purpose, and the link helper was read only.
    • +
    • Added an FeedUri Property on the AtomEntry class. This property returns the AtomUri of a rel=#feed type=atom+xml LINK entry.
    • +
    • Added an MediaUri Property on the AtomEntry class. This property returns the AtomUri of a rel=#edit-media type=atom+xml LINK entry.
    • +
    • Added new methods on the AtomCategory collection. Find searches for a category of a given term, or a term/scheme combination. Also changed the implementation of the Contains method to compare not just object fidelity, but also term/value pairs
    • +
    • Added a ConvertToXSDSTring() helper in the Utilites class. As booleans are represented as "True"/"False" in .NET, and xsd requires "true"/"false" this helper takes care of that conversion.
    • +
    • Added the ability to create custom AtomBase subclassed objects to custom feeds/entries. Look at CreateAtomSubElement() in AtomBase. This is used to create custom clases like WebContentLink in the derived services
    • +
    +
  • + +

    1.0.9.9

    +
      +
    • added GBase support for m:adjusted_name and gm:adjusted_value inside attributes (returned only when adjustments are enabled)
    • +
    • Google Apps changes: +
        +
      • Added new AppsService.createUser methods with hashed password support
      • +
      • Updated AppsException with new Google Apps error codes
      • +
      • Added the following properties to Login.cs: string hashFunctionName
      • +
      • to hash user account password, bool agreedToTerms
      • +
      • to see if the user has accepted the Google Apps Terms Of Service, bool admin
      • +
      • to see if the user is a domain admin, bool changePasswordAtNextLogin
      • +
      • to force the user to change password at next login
      • +
      • Updated unittests to test new properties
      • +
      +
    • +
    +

    1.0.9.8

    +
      +
    • fixed a parsing bug in SpreadsheetService
    • +
    • fixed a bug in GDataRequestException that would prevent AppsException from accessing the server's response.
    • +
    • modified AppsException to comply with new GDataRequestException
    • +
    • fixed a bug in CalculateBaseUri, that caused a crash if the passed in parameters are all NULL. This caused composite feeds to not load if there was a comment feed embedded
    • +
    • fixed a bug in the CalendarEventEntry, it was not parsing extendedProperties. They are now parsed and added correctly to the ExtensionElements
    • +
    • added ACL support. This resulted in changes in the CalendarService.Query method
    • +
    • as a CalendarService can now return an EventFeed or an AccessControlFeed is returns now an AtomFeed that you can cast to what you are expecting. Added Query overloads to accept EventQuery or AclQuery and return the appropriate Feeds
    • +
    • added a cmd line tool to query/insert/update to a service based on streams
    • +
    • modified the Spreadsheet service to use the new scheme of service subclassing. This should fix a bundle of issues with regard to entry castings.
    • +
    • changed persistence of gd:extendedProperty to save the value attribute, even if there is no data to persist
    • +
    • Added an ASP.NET release (lib/ASP.NET) where the DLLs are build with the AllowPartiallyTrustedCallers attribute n enabled. Please use with caution and refer to the readme.txt in that subdirectory for more information.
    • +
    +

    1.0.9.7

    +
      +
    • fixed an incorrect trace statement in request.cs that had the result of disabling reading the error response.
    • +
    +

    1.0.9.6

    +
      +
    • added Google Apps for Your Domain support, a new helper DLL Google.GData.Apps.dll, and a sample, as well as unittests. Version number is increased to distinguish from Subversion, as this will be a binary download as well.
    • +
    +

    1.0.9.5

    +
      +
    • fix for incorrect encoding of usernames/passwords during authentication (you could run into problems if you had an email like "foo&joe@test.com"
    • +
    • exposure of the accountType as a property on the factory. If you happen to have an identical user name for a Google account and a hosted account, you need to set this property depending on which account you want to access. Default is GOOGLE_OR_HOSTED, other values are GOOGLE or HOSTED as strings.
    • +
    • fixed an issue with the edit/self uris on the entry. They were not correctly setable.
    • +
    • fixed an issue that one you used an authenticated service, but did not supply credentials, we would send an empty authentication header.
    • +
    • added Captcha Handling and more detailed exceptions when the authentication request fails. See authexceptions.cs for the list of potential exceptions thrown
    • +
    • added some preliminary unittests for the new exceptions
    • +
    • added a new constructor for the TokenCollection, so that captcha parsing is handled correctly
    • +
    • made the debug output depending on the TRACE define, and removed that define for the release build
    • +
    +

    1.0.9.4

    +
      +
    • Google Base: fix for incorrect Price attribute behaviour
    • +
    • Google Base: fix for incorrectly persisting duplicate attributes
    • +
    • Fix for Content.Type having no default value (issue 41)
    • +
    • Fix for Content.Type="text/html" parsing incorrectly. The strict check for type= "text" is now relaxed to be type="text*", so all text subtypes will be treated the same
    • +
    • Fix for Content.Type = "html" and "text/html" persistence. What the code does now is: first HTMLDecode the value held, than run the standard XMLWriter.WriteString over it (which does HTML encoding). This seems to work fine.
    • +
    • Added the gm:stats tags to the Windows Mobile build, accidently forgot to change that project file
    • +
    • the calendarfeed discarded entries unknown to it in the calendar namespace. This is fixed now. Unknown entries to the parser are now correctly added to the extension elements.
    • +
    • added the return-empty parameter to the cellquery class
    • +
    • added URL encoding to the authentication parameters (username/passwords etc that had unallowed FORM post chars caused failed login attempts)
    • +
    +

    1.0.9.3

    +
      +
    • Google Base changes: New features: +
        +
      • GBaseQuery supports the following optional parameters; orderby, sortorder, refine and content
      • +
      • Support for gm:stats tags
      • +
      • GBaseUriFactory can now generate the feed uri of other customers Fixes:
      • +
      • Fixed the GBaseAttributeType hierarchy for date/dateTime/dateTimeRange
      • +
      • Fixed the type of the hardcoded ExpirationDate property in GBaseAttributes
      • +
      +
    • +
    • Added a Makefile for Mono builds. This one replaces the Ant file.
    • +
    +

    1.0.9.2

    +
      +
    • Removed the MethodOverride default for the CalendarService. If you need that (due to firewalls not allowing PUT/DELETE requests, you can reenable this with setting the MethodOverride flag on the factory: ((GDataGAuthRequestFactory)calsvc.RequestFactory).MethodOverride = false;
    • +
    • Changed the X-Method-Override behaviour for DELETE, to fix an issue with .NET mobile (the mobile client would crash when the contentLength was set to 0 and no stream was requested).
    • +
    +

    1.0.9.1

    +
      +
    • Added a KeepAlive property to the factory object. This is set to true by default. .NET 2.0 clients, are due to behaviour changes in that runtime encouraged to set this to false.
    • +
    +

    1.0.9

    +
      +
    • Fixed an issue where the login services changed the response contenttype. The check for text/plain is now more relaxed.
    • +
    • Added the missing location calls for Geolocation for GoogleBase
    • +
    • Fixed a build issue for Windows Mobile in release. The code now compiles for PocketPC and WindowsMobile symbols defined.
    • +
    +

    1.0.8

    +
      +
    • Fixed issue 13 from the public issue list. If a content element contained xhtml, and not just text, the content was not read correctly.
    • +
    • Fixed issue 17 from the public issue list. XHTML content was not persisted correctly.
    • +
    • Added support for hosted domain feeds. This is done automatically, no codechanges needed for the application developer. The authentication code was changed to ask for Hosted domains first, then google accounts.
    • +
    • Added support for the app:control/app:draft element, but only in the way to expose a boolean on the AtomEntry. The new member on AtomEntry is called IsDraft.
    • +
    • Changed the way atom:content is parsed. Text & HTML types use xmlreader.ReadString() to get the inner content. XHTML and all other types use readInnerXml() to get the content.
    • +
    • changed Exception handling. The code now throws more detailed exceptions based on what was happening: -> GDataRequestException: generic exception -> GDataForbiddenException: exception thrown when the server return a Forbidden on authentication -> GDataRedirectException: exception thrown when the server returned a redirect
    • +
    • changed redirect handling on Post. The library will follow redirects on Post automatically by default, to accomodate Blogger (which currently may return 302s on posts). This can be turned off by setting the .StrictRedirect property to true on the GDataAuthRequestFactory. If it is turned off, the code will throw if a redirect is happening on an HTTP verb other than GET.
    • +
    • changed redirect handling for DELETE/PUT the same as for POST
    • +
    • removed cookie handling. The code will handle cookies now without using the CookieContainer (one hurdle on the way to the CompactFramework Port).
    • +
    • Fixed persistence of "initialized" date values for udpated/published on the atom.entry. This resolves an issue with the Blogger.
    • +
    • Added EventEntry.Notifications. This property (boolean) indicates if an update on an entry should send notifications to the attendees of the Event.
    • +
    • Fixed the gbase project (the NumberFormat.cs file was missing in the project file).
    • +
    • Added a proxy property for the GDataRequestFactory.
    • +
    • Setting content-length correctly to fix WindowsMobile issues. This fix is a user submitted, and created by Steeve Morin
    • +
    • Fixes to the authsub code, provided by Ryan Boyd
    • +
    • The DLLs were renamed, to follow the Windows .NET standard. gdata.dll -> Google.GData.Client.dll gbase.dll -> Google.GData.GoogleBase.dll gcalendar.dll -> Google.GData.Calendar.dll gcodesearch.dll -> Google.GData.CodeSearch.dll gextensions.dll -> Google.GData.Extensions.dll and the new one -> Google.GData.Spreadsheets.dll
    • +
    +

    1.0.7

    +
      +
    • Added support for published-min/published-max as standard query parameters
    • +
    • Added support for codesearch. A new DLL gcodesearch.dll and a new sample for this is available.
    • +
    • Added support for the WebContent calendar extension
    • +
    • Added signing to the gbase.dll
    • +
    +

    1.0.6

    +
      +
    • Added support for sortoder, futurevents, singleevents on the calendarquery
    • +
    • Added a ResponseString property on the GDataRequestException to make debugging server side errors easier
    • +
    • Fixed an issue with the GoogleBaseService, if you did set the RequestFactory property twice, you would create too many header entries, and hence end up with request denied responses
    • +
    • Added the shipping attribute for GoogleBase
    • +
    • Changed the payment attribute to payment_accepted for GoogleBase
    • +
    +

    1.0.5

    +
      +
    • Added batch support for GoogleFeeds, the first property to support this is the GoogleBase product
    • +
    • Added a unittest for GoogleBase. This code shows update/insert/delete against base for single entries and batch entries refer to clients/cs/src/unittests/gbase.cs for sample code.
    • +
    • Added IComparable to atomuri.cs (based on a feature request on our issue list)
    • +
    • GDataAuthRequestFactory is now a subclass of GDataRequestFactory
    • +
    • Moved GCookies from GDataAuthRequestFactory to GDataRequestFactory and renamed it to Cookies
    • +
    • removed the debug binaries from the lib directory
    • +
    • added a GoogleBase sample application in VB !
    • +
    • added the build executables to the lib directory
    • +
    • added GoogleBase classes (similiar to the java classes) to access Google base specific feeds Known issues:
    • +
    • recurrenceException is not fully tested
    • +
    • authsubutil and gauthsubrequest are not fully tested
    • +
    +

    1.0.4

    +
      +
    • Fixed a .NET 2.0 issue in calendarservice.cs, that dropped connections during repeated calls.
    • +
    • Made the execution path more robust.
    • +
    • Added a property, numberOfRetries on the GAuthRequestFactory to indicate how often an Execution should be retried if the server returns an error.
    • +
    • Fixed a bug in the daterange query creation (the +sign for the timezone was not escaped properly)
    • +
    • Fixed an issue with updating, where if you used the same AtomEntry/EventEntry several times to update, it could happen that extension elements were doubled, and the update failed.
    • +
    • Fixed a bug in the parsing of all elements. This could cause an endless loop when the content was empty.
    • +
    • Fixed several content creation issues (issues 5-9 on the issue list)
    • +
    • added support for the gd:extendedProperty
    • +
    • Added a calendar example application
    • +
    • added a sample application to access Blogger feeds, and post to blogger feeds. Known issues:
    • +
    • recurrenceException is not fully tested
    • +
    • authsubutil and gauthsubrequest are not fully tested Solved issues:
    • +
    • .NET 2.0 seems to loose resources in some circumstances. Hard to reproduce.
    • +
    +

    1.0.3

    +
      +
    • Fixed the namespace creation for extensions, the wireformat should no longer create the namespace declaration when it's not required
    • +
    • Fixed the reminder persistence code
    • +
    • added a TimeZone property on the EventFeed to retrieve the timezone value
    • +
    • added a FindEvent method on the EventFeed. This one takes an OriginalEvent object, and returns the Event that this is based on. This will go to the server if required.
    • +
    • Fixed recurrance issues in the extensions
    • +
    • Moved EventFeed and EventEntry from the Google.GData.Extensions namespace to the Google.GData.Calendar namespace
    • +
    • Fixed a bug in the parsing of Atom:Content elements. This could cause an endless loop when the content was empty.
    • +
    +

    1.0.2

    +
      +
    • Fixed a problem persisting feedlink elements
    • +
    • added an AllDay flag to the When class to allow parsing and persting of all day events
    • +
    • cleaned up the persistence code in the extension classes
    • +
    • fixed a problem that resulted in persisting multiple extensionn objects instead of one
    • +
    • added a timestamp method to the Tracing class to help measuring performance in simple cases
    • +
    +

    1.0.1

    +
      +
    • Correctly uses 'rel.previous' instead of 'rel.prev' as required by Atom Publishing Protocol.
    • +
    • Corrected the time-shift portion of the DateTime output for time zones with a negative shift from UTC.
    • +
    • Corrected the time-shift to permit fractional hour shifts from UTC.
    • +
    • Correctly output "startTime" and "endTime" as attributes of the "when" extension rather than child elements.
    • +
    • Refactored class hierarchy, now based on IExtensionElement.
    • +
    +

    1.0.0

    +
      +
    • Initial Release
    • +
    + + diff -Nru gdata-sharp-1.4.0.2/samples/analytics/analytics.cs gdata-sharp-1.7.0.1/samples/analytics/analytics.cs --- gdata-sharp-1.4.0.2/samples/analytics/analytics.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/analytics/analytics.cs 2009-05-21 12:06:55.000000000 +0000 @@ -0,0 +1,92 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; +using Google.GData.Analytics; +using Google.GData.Extensions; + +namespace Analytics +{ + public partial class Analytics : Form + { + public Analytics() + { + InitializeComponent(); + } + + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.Run(new Analytics()); + } + + private void Go_Click(object sender, System.EventArgs e) + { + RefreshFeed(); + } + + private void RefreshFeed() + { + string userName = this.Username.Text; + string passWord = this.Password.Text; + + AccountQuery query = new AccountQuery(); + AnalyticsService service = new AnalyticsService("AnalyticsSampleApp"); + if (!string.IsNullOrEmpty(userName)) + { + service.setUserCredentials(userName, passWord); + } + + AccountFeed accountFeed = service.Query(query); + foreach (AccountEntry entry in accountFeed.Entries) + { + ListViewItem item = new ListViewItem(entry.Title.Text); + //item.SubItems.Add(entry.Title.Text); + item.SubItems.Add(entry.ProfileId.Value); + this.ProfileIds.Items.Add(item); + } + } + + private void GoGet_Click(object sender, EventArgs e) + { + PageviewFeed(); + } + + private void PageviewFeed() + { + string userName = this.Username.Text; + string passWord = this.Password.Text; + string profileId = this.ProfileIds.SelectedItems[0].SubItems[1].Text; + const string dataFeedUrl = "https://www.google.com/analytics/feeds/data"; + + AnalyticsService service = new AnalyticsService("AnalyticsSampleApp"); + if (!string.IsNullOrEmpty(userName)) + { + service.setUserCredentials(userName, passWord); + } + + DataQuery query = new DataQuery(dataFeedUrl); + query.Ids = profileId; + query.Metrics = "ga:pageviews"; + query.Dimensions = "ga:browser"; + query.Sort = "ga:browser,ga:pageviews"; + query.GAStartDate = DateTime.Now.AddDays(-14).ToString("yyyy-MM-dd"); + query.GAEndDate = DateTime.Now.AddDays(-2).ToString("yyyy-MM-dd"); + + DataFeed dataFeed = service.Query(query); + foreach (DataEntry entry in dataFeed.Entries) + { + ListViewItem item = new ListViewItem(entry.Title.Text); + item.SubItems.Add(entry.Metrics[0].Value); + this.ListPageviews.Items.Add(item); + } + } + } +} diff -Nru gdata-sharp-1.4.0.2/samples/analytics/Analytics.csproj gdata-sharp-1.7.0.1/samples/analytics/Analytics.csproj --- gdata-sharp-1.4.0.2/samples/analytics/Analytics.csproj 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/analytics/Analytics.csproj 2009-10-27 16:30:40.000000000 +0000 @@ -0,0 +1,82 @@ + + + Debug + AnyCPU + 8.0.50727 + 2.0 + {FA8A1FDC-138B-48D9-8288-711B911C589A} + WinExe + Properties + Analytics + Analytics + + + + + 2.0 + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + False + ..\..\lib\Release\Google.GData.Analytics.dll + + + False + ..\..\lib\Release\Google.GData.Client.dll + + + False + ..\..\lib\Release\Google.GData.Extensions.dll + + + + + + + + + + AssemblyVersion.cs + + + Form + + + analytics.cs + + + + + + Designer + analytics.cs + + + + + \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/samples/analytics/analytics.Designer.cs gdata-sharp-1.7.0.1/samples/analytics/analytics.Designer.cs --- gdata-sharp-1.4.0.2/samples/analytics/analytics.Designer.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/analytics/analytics.Designer.cs 2009-05-20 09:45:51.000000000 +0000 @@ -0,0 +1,202 @@ +namespace Analytics +{ + partial class Analytics + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.Username = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.Password = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.ProfileIds = new System.Windows.Forms.ListView(); + this.columnHeader1 = new System.Windows.Forms.ColumnHeader(); + this.columnHeader2 = new System.Windows.Forms.ColumnHeader(); + this.label3 = new System.Windows.Forms.Label(); + this.Go = new System.Windows.Forms.Button(); + this.label4 = new System.Windows.Forms.Label(); + this.columnHeader3 = new System.Windows.Forms.ColumnHeader(); + this.columnHeader4 = new System.Windows.Forms.ColumnHeader(); + this.GetPageviews = new System.Windows.Forms.Button(); + this.ListPageviews = new System.Windows.Forms.ListView(); + this.SuspendLayout(); + // + // Username + // + this.Username.Location = new System.Drawing.Point(16, 38); + this.Username.Name = "Username"; + this.Username.Size = new System.Drawing.Size(119, 20); + this.Username.TabIndex = 0; + this.Username.Text = "sample@gmail.com"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(13, 20); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(55, 13); + this.label1.TabIndex = 1; + this.label1.Text = "Username"; + // + // Password + // + this.Password.Location = new System.Drawing.Point(158, 38); + this.Password.Name = "Password"; + this.Password.PasswordChar = '*'; + this.Password.Size = new System.Drawing.Size(119, 20); + this.Password.TabIndex = 2; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(155, 20); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(53, 13); + this.label2.Text = "Password"; + // + // ProfileIds + // + this.ProfileIds.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2}); + this.ProfileIds.FullRowSelect = true; + this.ProfileIds.GridLines = true; + this.ProfileIds.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.ProfileIds.Location = new System.Drawing.Point(16, 135); + this.ProfileIds.Name = "ProfileIds"; + this.ProfileIds.Size = new System.Drawing.Size(300, 135); + this.ProfileIds.TabIndex = 4; + this.ProfileIds.UseCompatibleStateImageBehavior = false; + this.ProfileIds.View = System.Windows.Forms.View.Details; + // + // columnHeader1 + // + this.columnHeader1.Text = "Title"; + this.columnHeader1.Width = 150; + // + // columnHeader2 + // + this.columnHeader2.Text = "Profile ID"; + this.columnHeader2.Width = 125; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(13, 113); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(53, 13); + this.label3.Text = "Profile Ids"; + // + // Go + // + this.Go.Location = new System.Drawing.Point(16, 65); + this.Go.Name = "Go"; + this.Go.Size = new System.Drawing.Size(75, 23); + this.Go.TabIndex = 3; + this.Go.Text = "Get Profiles"; + this.Go.UseVisualStyleBackColor = true; + this.Go.Click += new System.EventHandler(this.Go_Click); + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(389, 113); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(59, 13); + this.label4.Text = "Pageviews"; + // + // columnHeader3 + // + this.columnHeader3.Text = "Title"; + this.columnHeader3.Width = 150; + // + // columnHeader4 + // + this.columnHeader4.Text = "Pageviews"; + this.columnHeader4.Width = 125; + // + // GetPageviews + // + this.GetPageviews.Location = new System.Drawing.Point(16, 278); + this.GetPageviews.Name = "GetPageviews"; + this.GetPageviews.Size = new System.Drawing.Size(96, 23); + this.GetPageviews.TabIndex = 5; + this.GetPageviews.Text = "Get Pageviews"; + this.GetPageviews.UseVisualStyleBackColor = true; + this.GetPageviews.Click += new System.EventHandler(this.GoGet_Click); + // + // ListPageviews + // + this.ListPageviews.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader3, + this.columnHeader4}); + this.ListPageviews.FullRowSelect = true; + this.ListPageviews.GridLines = true; + this.ListPageviews.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.ListPageviews.Location = new System.Drawing.Point(392, 135); + this.ListPageviews.Name = "ListPageviews"; + this.ListPageviews.Size = new System.Drawing.Size(300, 135); + this.ListPageviews.UseCompatibleStateImageBehavior = false; + this.ListPageviews.View = System.Windows.Forms.View.Details; + // + // Analytics + // + this.ClientSize = new System.Drawing.Size(794, 313); + this.Controls.Add(this.GetPageviews); + this.Controls.Add(this.label4); + this.Controls.Add(this.ListPageviews); + this.Controls.Add(this.Go); + this.Controls.Add(this.label3); + this.Controls.Add(this.ProfileIds); + this.Controls.Add(this.label2); + this.Controls.Add(this.Password); + this.Controls.Add(this.label1); + this.Controls.Add(this.Username); + this.Name = "Analytics"; + this.Text = "Google Analytics Demo Application"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox Username; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox Password; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.ListView ProfileIds; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Button Go; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.ListView ListPageviews; + private System.Windows.Forms.ColumnHeader columnHeader3; + private System.Windows.Forms.ColumnHeader columnHeader4; + private System.Windows.Forms.Button GetPageviews; + } +} diff -Nru gdata-sharp-1.4.0.2/samples/analytics/analytics.resx gdata-sharp-1.7.0.1/samples/analytics/analytics.resx --- gdata-sharp-1.4.0.2/samples/analytics/analytics.resx 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/analytics/analytics.resx 2009-05-20 09:45:51.000000000 +0000 @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + False + + diff -Nru gdata-sharp-1.4.0.2/samples/analytics/AssemblyInfo.cs gdata-sharp-1.7.0.1/samples/analytics/AssemblyInfo.cs --- gdata-sharp-1.4.0.2/samples/analytics/AssemblyInfo.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/analytics/AssemblyInfo.cs 2009-05-20 09:45:51.000000000 +0000 @@ -0,0 +1,24 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Analytics")] +[assembly: AssemblyConfiguration("")] + + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("8efcdca0-801c-48ef-879a-224077b33b80")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyFileVersion("1.0.0.0")] diff -Nru gdata-sharp-1.4.0.2/samples/Analytics_AccountFeed_Sample/accountFeed.cs gdata-sharp-1.7.0.1/samples/Analytics_AccountFeed_Sample/accountFeed.cs --- gdata-sharp-1.4.0.2/samples/Analytics_AccountFeed_Sample/accountFeed.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/Analytics_AccountFeed_Sample/accountFeed.cs 2010-05-11 08:05:33.000000000 +0000 @@ -0,0 +1,268 @@ +// Copyright 2010 Google Inc. All Rights Reserved. + +/* Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Collections.Generic; +using System.Text; +using Google.Analytics; +using Google.GData.Analytics; +using Google.GData.Client; +using Google.GData.Extensions; + +namespace SampleAnalyticsClient +{ + public class AccountFeedExample + { + + private static String CLIENT_USERNAME = "INSERT_LOGIN_EMAIL_HERE"; + private static String CLIENT_PASS = "INSERT_PASSWORD_HERE"; + + public AccountFeed accountFeed; + + public static void Main(String[] args) + { + + AccountFeedExample example; + + try + { + example = new AccountFeedExample(); + } + catch (AuthenticationException e) + { + Console.Error.WriteLine("Authentication failed : " + e.Message); + return; + } + catch (Exception e) + { + Console.Error.WriteLine("Authentication Failed : " + e.Message); + return; + } + + + example.printFeedDetails(); + example.printAdvancedSegments(); + example.printCustomVarForOneEntry(); + example.printGoalsForOneEntry(); + example.printAccountEntries(); + } + + /** + * Creates a new service object, attempts to authorize using the Client Login + * authorization mechanism and requests data from the Google Analytics API. + * @throws AuthenticationException if an error occurs with authorizing with + * Google Accounts. + * @throws IOException if a network error occurs. + * @throws ServiceException if an error occurs with the Google Analytics API. + */ + public AccountFeedExample() + { + + // Configure GA API. + AnalyticsService asv = new AnalyticsService("gaExportAPI_acctSample_v2.0"); + + // Client Login Authorization. + asv.setUserCredentials(CLIENT_USERNAME, CLIENT_PASS); + + // GA Account Feed query uri. + + AccountQuery query = new AccountQuery(); + + // Send our request to the Analytics API and wait for the results to + // come back. + accountFeed = asv.Query(query); + } + + /** + * Prints the important Google Analytics related data in the Account Feed. + */ + public void printFeedDetails() + { + Console.WriteLine("\n-------- Important Feed Data --------"); + Console.WriteLine( + "\nFeed Title = " + accountFeed.Title + + "\nTotal Results = " + accountFeed.TotalResults + + "\nStart Index = " + accountFeed.StartIndex + + "\nItems Per Page = " + accountFeed.ItemsPerPage + + "\nFeed ID = " + accountFeed.Id); + } + + /** + * Prints the advanced segments for this user. + */ + public void printAdvancedSegments() + { + Console.WriteLine("\n-------- Advanced Segments --------"); + if (accountFeed.Segments.Count == 0) + { + Console.WriteLine("No advanced segments found"); + } + else + { + foreach (Segment segment in accountFeed.Segments) + { + Console.WriteLine( + "\nSegment Name = " + segment.Name + + "\nSegment ID = " + segment.Id + + "\nSegment Definition = " + segment.Definition.Value); + } + } + } + + /** + * Prints custom variable information for the first profile that has custom + * variables configured. + */ + public void printCustomVarForOneEntry() + { + Console.WriteLine("\n-------- Custom Variables --------"); + if (accountFeed.Entries.Count == 0) + { + Console.WriteLine("No entries found."); + } + else + { + // Go through each entry to see if any has a Custom Variable defined. + foreach (AccountEntry entry in accountFeed.Entries) + { + if (entry.CustomVariables.Count > 0) + { + foreach (CustomVariable customVariable in entry.CustomVariables) + { + Console.WriteLine( + "\nCustom Variable Index = " + customVariable.Index + + "\nCustom Variable Name = " + customVariable.Name + + "\nCustom Variable Scope = " + customVariable.Scope); + } + return; + } + } + Console.WriteLine("\nNo custom variables defined for this user"); + } + } + + /** + * Prints all the goal information for one profile. + */ + public void printGoalsForOneEntry() + { + Console.WriteLine("\n-------- Goal Configuration --------"); + if (accountFeed.Entries.Count == 0) + { + Console.WriteLine("No entries found."); + } + else + { + // Go through each entry to see if any have Goal information. + foreach (AccountEntry entry in accountFeed.Entries) + { + if (entry.Goals.Count > 0) + { + foreach (Goal goal in entry.Goals) + { + // Print common information for all Goals in this profile. + Console.WriteLine("\n----- Goal -----"); + Console.WriteLine( + "\nGoal Number = " + goal.Number + + "\nGoal Name = " + goal.Name + + "\nGoal Value = " + goal.Value + + "\nGoal Active = " + goal.Active); + if (goal.Destination != null) + { + printDestinationGoal(goal.Destination); + } + else if (goal.Engagement != null) + { + printEngagementGoal(goal.Engagement); + } + } + return; + } + } + } + } + + /** + * Prints the important information for destination goals including all the + * configured steps if they exist. + * @param destination the destination goal configuration. + */ + public void printDestinationGoal(Destination destination) + { + Console.WriteLine("\n\t----- Destination Goal -----"); + Console.WriteLine( + "\n\tExpression = " + destination.Expression + + "\n\tMatch Type = " + destination.MatchType + + "\n\tStep 1 Required = " + destination.Step1Required + + "\n\tCase Sensitive = " + destination.CaseSensitive); + + // Print goal steps. + if (destination.Steps.Count > 0) + { + Console.WriteLine("\n\t----- Destination Goal Steps -----"); + foreach (Step step in destination.Steps) + { + Console.WriteLine( + "\n\tStep Number = " + step.Number + + "\n\tStep Name = " + step.Name + + "\n\tStep Path = " + step.Path); + } + } + } + + + /** + * Prints the important information for Engagement Goals. + * @param engagement The engagement goal configuration. + */ + public void printEngagementGoal(Engagement engagement) + { + Console.WriteLine("\n\t----- Engagement Goal -----"); + Console.WriteLine( + "\n\tGoal Type = " + engagement.Type + + "\n\tGoal Comparison = " + engagement.Comparison + + "\n\tGoal Threshold = " + engagement.Threshold); + } + + /** + * Prints the important Google Analytics related data in each Account Entry. + */ + public void printAccountEntries() + { + Console.WriteLine("\n-------- First 1000 Profiles In Account Feed --------"); + if (accountFeed.Entries.Count == 0) + { + Console.WriteLine("No entries found."); + } + else + { + foreach (AccountEntry entry in accountFeed.Entries) + { + Console.WriteLine( + "\nWeb Property Id = " + entry.Properties[3].Value + + "\nAccount Name = " + entry.Properties[1].Value + + "\nAccount ID = " + entry.Properties[0].Value + + "\nProfile Name = " + entry.Title.Text + + "\nProfile ID = " + entry.Properties[2].Value + + "\nTable Id = " + entry.ProfileId.Value + + "\nCurrency = " + entry.Properties[4].Value + + "\nTimeZone = " + entry.Properties[5].Value + + (entry.CustomVariables.Count > 0 ? "\nThis profile has custom variables" : "") + + (entry.Goals.Count > 0 ? "\nThis profile has goals" : "")); + } + } + } + } +} diff -Nru gdata-sharp-1.4.0.2/samples/Analytics_AccountFeed_Sample/Analytics_AccountFeed_Sample.csproj gdata-sharp-1.7.0.1/samples/Analytics_AccountFeed_Sample/Analytics_AccountFeed_Sample.csproj --- gdata-sharp-1.4.0.2/samples/Analytics_AccountFeed_Sample/Analytics_AccountFeed_Sample.csproj 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/Analytics_AccountFeed_Sample/Analytics_AccountFeed_Sample.csproj 2010-05-11 08:05:33.000000000 +0000 @@ -0,0 +1,71 @@ + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {D4C48882-F3E0-48E7-98C7-301702AD7A3E} + Exe + Properties + Analytics_AccountFeed_Sample + Analytics_AccountFeed_Sample + v3.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + False + ..\..\lib\Release\Google.GData.Analytics.dll + + + False + ..\..\lib\Release\Google.GData.Client.dll + + + False + ..\..\lib\Release\Google.GData.Extensions.dll + + + + 3.5 + + + 3.5 + + + 3.5 + + + + + + + + + + + diff -Nru gdata-sharp-1.4.0.2/samples/Analytics_AccountFeed_Sample/Properties/AssemblyInfo.cs gdata-sharp-1.7.0.1/samples/Analytics_AccountFeed_Sample/Properties/AssemblyInfo.cs --- gdata-sharp-1.4.0.2/samples/Analytics_AccountFeed_Sample/Properties/AssemblyInfo.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/Analytics_AccountFeed_Sample/Properties/AssemblyInfo.cs 2010-05-11 08:05:33.000000000 +0000 @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Analytics_AccountFeed_Sample")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Google")] +[assembly: AssemblyProduct("Analytics_AccountFeed_Sample")] +[assembly: AssemblyCopyright("Copyright © Google 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("a4835f89-df72-420b-a5c4-00f5cb32acbf")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff -Nru gdata-sharp-1.4.0.2/samples/Analytics_DataFeed_Sample/Analytics_DataFeed_Sample.csproj gdata-sharp-1.7.0.1/samples/Analytics_DataFeed_Sample/Analytics_DataFeed_Sample.csproj --- gdata-sharp-1.4.0.2/samples/Analytics_DataFeed_Sample/Analytics_DataFeed_Sample.csproj 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/Analytics_DataFeed_Sample/Analytics_DataFeed_Sample.csproj 2010-05-11 08:05:33.000000000 +0000 @@ -0,0 +1,67 @@ + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {85408B33-1109-435A-B17C-CB2A80BC562F} + Exe + Properties + Analytics_DataFeed_Sample + Analytics_DataFeed_Sample + v3.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + False + ..\..\lib\Release\Google.GData.Analytics.dll + + + False + ..\..\lib\Release\Google.GData.Client.dll + + + + 3.5 + + + 3.5 + + + 3.5 + + + + + + + + + + + diff -Nru gdata-sharp-1.4.0.2/samples/Analytics_DataFeed_Sample/dataFeed.cs gdata-sharp-1.7.0.1/samples/Analytics_DataFeed_Sample/dataFeed.cs --- gdata-sharp-1.4.0.2/samples/Analytics_DataFeed_Sample/dataFeed.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/Analytics_DataFeed_Sample/dataFeed.cs 2010-05-11 08:05:33.000000000 +0000 @@ -0,0 +1,244 @@ +// Copyright 2010 Google Inc. All Rights Reserved. + +/* Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Collections.Generic; +using System.Text; +using Google.Analytics; +using Google.GData.Analytics; +using Google.GData.Client; +using Google.GData.Extensions; + + + + +namespace SampleAnalyticsClient +{ + + + public class DataFeedExample + { + + private const String CLIENT_USERNAME = "INSERT_LOGIN_EMAIL_HERE"; + private const String CLIENT_PASS = "INSERT_PASSWORD_HERE"; + private const String TABLE_ID = "INSERT_TABLE_ID_HERE"; + + public DataFeed feed; + public DataFeed feed2; + + public static void Main(String[] args) + { + DataFeedExample example; + + try + { + example = new DataFeedExample(); + } + catch (AuthenticationException e) + { + Console.Error.WriteLine("Authentication failed : " + e.Message); + return; + } + catch (Google.GData.Client.GDataRequestException e) + { + Console.Error.WriteLine("Authentication failed : " + e.Message); + return; + } + + example.printFeedData(); + example.printFeedDataSources(); + example.printFeedAggregates(); + example.printSegmentInfo(); + example.printDataForOneEntry(); + + Console.WriteLine(example.getEntriesAsTable()); + } + + /** + * Creates a new service object, attempts to authorize using the Client Login + * authorization mechanism and requests data from the Google Analytics API. + */ + public DataFeedExample() + { + + // Configure GA API. + AnalyticsService asv = new AnalyticsService("gaExportAPI_acctSample_v2.0"); + + // Client Login Authorization. + asv.setUserCredentials(CLIENT_USERNAME, CLIENT_PASS); + + // GA Data Feed query uri. + String baseUrl = "https://www.google.com/analytics/feeds/data"; + + DataQuery query = new DataQuery(baseUrl); + query.Ids = TABLE_ID; + query.Dimensions = "ga:source,ga:medium"; + query.Metrics = "ga:visits,ga:bounces"; + query.Segment = "gaid::-11"; + query.Filters = "ga:medium==referral"; + query.Sort = "-ga:visits"; + query.NumberToRetrieve = 5; + query.GAStartDate = "2010-03-01"; + query.GAEndDate = "2010-03-15"; + Uri url = query.Uri; + Console.WriteLine("URL: " + url.ToString()); + + + // Send our request to the Analytics API and wait for the results to + // come back. + + feed = asv.Query(query); + + + } + + /** + * Prints the important Google Analytics relates data in the Data Feed. + */ + public void printFeedData() + { + Console.WriteLine("\n-------- Important Feed Information --------"); + Console.WriteLine( + "\nFeed Title = " + feed.Title.Text + + "\nFeed ID = " + feed.Id.Uri + + "\nTotal Results = " + feed.TotalResults + + "\nSart Index = " + feed.StartIndex + + "\nItems Per Page = " + feed.ItemsPerPage + ); + } + + /** + * Prints the important information about the data sources in the feed. + * Note: the GA Export API currently has exactly one data source. + */ + public void printFeedDataSources() + { + + DataSource gaDataSource = feed.DataSource; + Console.WriteLine("\n-------- Data Source Information --------"); + Console.WriteLine( + "\nTable Name = " + gaDataSource.TableName + + "\nTable ID = " + gaDataSource.TableId + + "\nWeb Property Id = " + gaDataSource.WebPropertyId + + "\nProfile Id = " + gaDataSource.ProfileId + + "\nAccount Name = " + gaDataSource.AccountName); + } + + /** + * Prints all the metric names and values of the aggregate data. The + * aggregate metrics represent the sum of the requested metrics across all + * of the entries selected by the query and not just the rows returned. + */ + public void printFeedAggregates() + { + Console.WriteLine("\n-------- Aggregate Metric Values --------"); + Aggregates aggregates = feed.Aggregates; + + foreach (Metric metric in aggregates.Metrics) + { + Console.WriteLine( + "\nMetric Name = " + metric.Name + + "\nMetric Value = " + metric.Value + + "\nMetric Type = " + metric.Type + + "\nMetric CI = " + metric.ConfidenceInterval); + } + } + + /** + * Prints segment information if the query has an advanced segment defined. + */ + public void printSegmentInfo() + { + if (feed.Segments.Count > 0) + { + Console.WriteLine("\n-------- Advanced Segments Information --------"); + foreach (Segment segment in feed.Segments) + { + Console.WriteLine( + "\nSegment Name = " + segment.Name + + "\nSegment ID = " + segment.Id + + "\nSegment Definition = " + segment.Definition.Value); + } + } + } + + /** + * Prints all the important information from the first entry in the + * data feed. + */ + public void printDataForOneEntry() + { + Console.WriteLine("\n-------- Important Entry Information --------\n"); + if (feed.Entries.Count == 0) + { + Console.WriteLine("No entries found"); + } + else + { + DataEntry singleEntry = feed.Entries[0] as DataEntry; + + // Properties specific to all the entries returned in the feed. + Console.WriteLine("Entry ID = " + singleEntry.Id.Uri); + Console.WriteLine("Entry Title = " + singleEntry.Title.Text); + + // Iterate through all the dimensions. + foreach (Dimension dimension in singleEntry.Dimensions) + { + Console.WriteLine("Dimension Name = " + dimension.Name); + Console.WriteLine("Dimension Value = " + dimension.Value); + } + + // Iterate through all the metrics. + foreach (Metric metric in singleEntry.Metrics) + { + Console.WriteLine("Metric Name = " + metric.Name); + Console.WriteLine("Metric Value = " + metric.Value); + Console.WriteLine("Metric Type = " + metric.Type); + Console.WriteLine("Metric CI = " + metric.ConfidenceInterval); + } + } + } + + /** + * Get the data feed values in the feed as a string. + * @return {String} This returns the contents of the feed. + */ + public String getEntriesAsTable() + { + if (feed.Entries.Count == 0) + { + return "No entries found"; + } + DataEntry singleEntry = feed.Entries[0] as DataEntry; + + StringBuilder feedDataLines = new StringBuilder("\n-------- All Entries In A Table --------\n"); + + // Put all the dimension and metric names into an array. + foreach (Dimension dimension in singleEntry.Dimensions) + { + String[] args = { dimension.Name, dimension.Value }; + feedDataLines.AppendLine(String.Format("\n{0} \t= {1}", args)); + } + foreach (Metric metric in singleEntry.Metrics) + { + String[] args = { metric.Name, metric.Value }; + feedDataLines.AppendLine(String.Format("\n{0} \t= {1}", args)); + } + + feedDataLines.Append("\n"); + return feedDataLines.ToString(); + } + } +} diff -Nru gdata-sharp-1.4.0.2/samples/Analytics_DataFeed_Sample/Properties/AssemblyInfo.cs gdata-sharp-1.7.0.1/samples/Analytics_DataFeed_Sample/Properties/AssemblyInfo.cs --- gdata-sharp-1.4.0.2/samples/Analytics_DataFeed_Sample/Properties/AssemblyInfo.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/Analytics_DataFeed_Sample/Properties/AssemblyInfo.cs 2010-05-11 08:05:33.000000000 +0000 @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Analytics_DataFeed_Sample")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Google")] +[assembly: AssemblyProduct("Analytics_DataFeed_Sample")] +[assembly: AssemblyCopyright("Copyright © Google 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("04a77ae7-3633-4aed-9fa6-30ca08ba4aaa")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff -Nru gdata-sharp-1.4.0.2/samples/appsforyourdomain/gapps_migration_sample.csproj gdata-sharp-1.7.0.1/samples/appsforyourdomain/gapps_migration_sample.csproj --- gdata-sharp-1.4.0.2/samples/appsforyourdomain/gapps_migration_sample.csproj 2008-04-23 08:15:01.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/appsforyourdomain/gapps_migration_sample.csproj 2009-10-27 16:30:40.000000000 +0000 @@ -1,4 +1,4 @@ - + Local 8.0.50727 @@ -26,6 +26,7 @@ + 2.0 bin\Debug\ diff -Nru gdata-sharp-1.4.0.2/samples/appsforyourdomain/gapps_sample.csproj gdata-sharp-1.7.0.1/samples/appsforyourdomain/gapps_sample.csproj --- gdata-sharp-1.4.0.2/samples/appsforyourdomain/gapps_sample.csproj 2008-12-08 12:13:37.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/appsforyourdomain/gapps_sample.csproj 2009-10-27 16:30:40.000000000 +0000 @@ -1,4 +1,4 @@ - + Local 8.0.50727 @@ -26,6 +26,7 @@ + 2.0 bin\Debug\ @@ -132,4 +133,4 @@ - + \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/samples/blogger/blogger.cs gdata-sharp-1.7.0.1/samples/blogger/blogger.cs --- gdata-sharp-1.4.0.2/samples/blogger/blogger.cs 2007-09-03 14:24:29.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/blogger/blogger.cs 2009-05-20 09:45:51.000000000 +0000 @@ -4,6 +4,7 @@ using System.ComponentModel; using System.Windows.Forms; using Google.GData.Client; +using Google.GData.Blogger; using System.Net; namespace Blogger @@ -209,8 +210,8 @@ string userName = this.UserName.Text; string passWord = this.Password.Text; - FeedQuery query = new FeedQuery(); - Service service = new Service("blogger", "BloggerSampleApp"); + BloggerQuery query = new BloggerQuery(); + BloggerService service = new BloggerService("BloggerSampleApp.NET"); if (userName != null && userName.Length > 0) { @@ -226,14 +227,14 @@ // start repainting this.FeedChooser.BeginUpdate(); - AtomFeed bloggerFeed = service.Query(query); + BloggerFeed bloggerFeed = service.Query(query); // Display a wait cursor while the TreeNodes are being created. this.FeedChooser.DisplayMember = "Title"; while (bloggerFeed != null && bloggerFeed.Entries.Count > 0) { - foreach (AtomEntry entry in bloggerFeed.Entries) + foreach (BloggerEntry entry in bloggerFeed.Entries) { int iIndex = this.FeedChooser.Items.Add(new ListEntry(entry)); } @@ -281,8 +282,8 @@ if (this.feedUri != null) { - FeedQuery query = new FeedQuery(); - Service service = new Service("blogger", "BloggerSampleApp"); + BloggerQuery query = new BloggerQuery(); + BloggerService service = new BloggerService("BloggerSampleApp.NET"); if (userName != null && userName.Length > 0) { @@ -297,7 +298,7 @@ Cursor.Current = Cursors.WaitCursor; - AtomFeed bloggerFeed = service.Query(query); + BloggerFeed bloggerFeed = service.Query(query); // Reset the cursor to the default for all controls. Cursor.Current = Cursors.Default; @@ -307,7 +308,7 @@ // now populate the calendar while (bloggerFeed != null && bloggerFeed.Entries.Count > 0) { - foreach (AtomEntry entry in bloggerFeed.Entries) + foreach (BloggerEntry entry in bloggerFeed.Entries) { int iIndex = this.FeedView.Nodes.Add(new TreeNode(entry.Title.Text)); if (iIndex >= 0) @@ -354,7 +355,7 @@ { // now add this to the feed. - AtomEntry entry = new AtomEntry(); + BloggerEntry entry = new BloggerEntry(); entry.Content.Content = dlg.Entry; entry.Content.Type = "html"; @@ -364,8 +365,7 @@ string userName = this.UserName.Text; string passWord = this.Password.Text; - FeedQuery query = new FeedQuery(); - Service service = new Service("blogger", "BloggerSampleApp"); + BloggerService service = new BloggerService("BloggerSampleApp.NET"); if (userName != null && userName.Length > 0) { @@ -392,7 +392,7 @@ if (listEntry != null) { - AtomEntry entry = listEntry.Entry; + BloggerEntry entry = listEntry.Entry; if (entry != null) { @@ -423,9 +423,9 @@ /// public class ListEntry { - private AtomEntry entry; - - public AtomEntry Entry + private BloggerEntry entry; + + public BloggerEntry Entry { get { @@ -437,7 +437,7 @@ } } - public ListEntry(AtomEntry entry) + public ListEntry(BloggerEntry entry) { this.entry = entry; } diff -Nru gdata-sharp-1.4.0.2/samples/blogger/Blogger.csproj gdata-sharp-1.7.0.1/samples/blogger/Blogger.csproj --- gdata-sharp-1.4.0.2/samples/blogger/Blogger.csproj 2008-04-23 08:15:01.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/blogger/Blogger.csproj 2009-10-27 16:30:40.000000000 +0000 @@ -1,4 +1,4 @@ - + Local 8.0.50727 @@ -26,6 +26,7 @@ + 2.0 bin\Debug\ @@ -97,6 +98,10 @@ prompt + + False + ..\..\lib\Release\Google.GData.Blogger.dll + False ..\..\lib\Release\Google.GData.Client.dll diff -Nru gdata-sharp-1.4.0.2/samples/calendar/Calendar.csproj gdata-sharp-1.7.0.1/samples/calendar/Calendar.csproj --- gdata-sharp-1.4.0.2/samples/calendar/Calendar.csproj 2008-04-23 08:15:01.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/calendar/Calendar.csproj 2009-10-27 16:30:40.000000000 +0000 @@ -1,4 +1,4 @@ - + Local 8.0.50727 @@ -26,6 +26,7 @@ + 2.0 bin\Debug\ diff -Nru gdata-sharp-1.4.0.2/samples/codesearch/CodeSearch.csproj gdata-sharp-1.7.0.1/samples/codesearch/CodeSearch.csproj --- gdata-sharp-1.4.0.2/samples/codesearch/CodeSearch.csproj 2008-04-23 08:15:01.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/codesearch/CodeSearch.csproj 2009-10-27 16:30:40.000000000 +0000 @@ -1,4 +1,4 @@ - + Local 8.0.50727 @@ -26,6 +26,7 @@ + 2.0 bin\Debug\ diff -Nru gdata-sharp-1.4.0.2/samples/DocListExporter/DocListExporter.csproj gdata-sharp-1.7.0.1/samples/DocListExporter/DocListExporter.csproj --- gdata-sharp-1.4.0.2/samples/DocListExporter/DocListExporter.csproj 2009-02-18 10:04:39.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/DocListExporter/DocListExporter.csproj 2009-10-27 16:30:40.000000000 +0000 @@ -1,14 +1,34 @@ - + Debug AnyCPU - 8.0.50727 + 9.0.30729 2.0 {6C6C0183-78AA-4DC4-BB1A-35A181F11F89} WinExe Properties DocListExport DocListExport + + + 2.0 + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true true @@ -28,21 +48,21 @@ 4 - + False - ..\..\lib\Release\Google.GData.AccessControl.dll + ..\..\src\documents3\bin\Debug\Google.GData.AccessControl.dll - + False - ..\..\lib\Release\Google.GData.Client.dll + ..\..\src\documents3\bin\Debug\Google.GData.Client.dll - + False - ..\..\lib\Release\Google.GData.Documents.dll + ..\..\src\documents3\bin\Debug\Google.GData.Documents.dll - + False - ..\..\lib\Release\Google.GData.Extensions.dll + ..\..\src\documents3\bin\Debug\Google.GData.Extensions.dll @@ -93,6 +113,33 @@ True + + + False + .NET Framework Client Profile + false + + + False + .NET Framework 2.0 %28x86%29 + true + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + false + + + False + .NET Framework 3.5 SP1 + false + + + \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/samples/gapps_multidomain_sample/multidomaindemo.cs gdata-sharp-1.7.0.1/samples/gapps_multidomain_sample/multidomaindemo.cs --- gdata-sharp-1.4.0.2/samples/gapps_multidomain_sample/multidomaindemo.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/gapps_multidomain_sample/multidomaindemo.cs 2010-11-02 15:10:58.000000000 +0000 @@ -0,0 +1,161 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Google.GData.Extensions.Apps; +using Google.GData.Apps; + + +namespace GoogleAppsConsoleApplication +{ + class AppsMultiDomainDemo + { + private static string primaryDomain; + private static string secondaryDomain; + private static string adminEmail; + private static string adminPassword; + private static string testUserEmail; + + /// + /// This console application demonstrates all the Google Apps + /// MultiDomain Management APIs. + /// + /// Command-line arguments: args[0] is + /// the primary domain, args[1] is the secondary domain, + /// args[2] is the admin email address, args[3] is the admin + /// password and args[4] is test user(email address) + /// + /// Example: AppsMultiDomainDemo example.com alias.com admin@example.com my_password test_user_email + public static void Main(string[] args) + { + if (args.Length != 5) + { + Console.WriteLine("Syntax: AppsMultiDomainDemo "); + } + else + { + primaryDomain = args[0]; + secondaryDomain = args[1]; + adminEmail = args[2]; + adminPassword = args[3]; + testUserEmail = args[4]; + + MultiDomainManagementService service = new MultiDomainManagementService(primaryDomain, "multidomainapis-apps-demo"); + service.setUserCredentials(adminEmail, adminPassword); + + RunSample(service); + } + } + + /// + /// + /// + /// + private static void RunSample(MultiDomainManagementService service) + { + const String testUserPassword = "password"; + const String testUserFirstName = "Liz"; + const String testUserLastName = "Smith"; + const bool testUserIsAdmin = true; + const String testUserNewFirstName = "Elizabeth"; + String testUserNewEmail = "liz@" + secondaryDomain; + String testUserAliasEmail = "helpdesk@" + secondaryDomain; + + try + { + // Create a new Domain User + Console.WriteLine("\n-----------Creating domain user-----------"); + AppsExtendedEntry entry = service.CreateDomainUser(primaryDomain, testUserEmail, testUserPassword, + testUserFirstName, testUserLastName, testUserIsAdmin); + Console.WriteLine("Created: " + + entry.getPropertyValueByName(AppsMultiDomainNameTable.UserEmail)); + + // Update Domain User and list all properties + Console.WriteLine("\n-----------Updating domain user----"); + IDictionary updates = + new Dictionary(); + updates[MultiDomainManagementService.MultiDomainUserProperty.FirstName] = testUserNewFirstName; + entry = service.UpdateDomainUser(primaryDomain, testUserEmail, updates); + foreach (PropertyElement element in entry.Properties) + { + Console.WriteLine(String.Format("{0} - {1}", element.Name, element.Value)); + } + + // Create a new Domain User to be renamed + Console.WriteLine("\n-----------Creating domain user to be renamed-----------"); + String tempEmail = "TOBERENAMED@" + primaryDomain; + entry = service.CreateDomainUser(primaryDomain, tempEmail, testUserPassword, + testUserFirstName, testUserLastName, testUserIsAdmin); + Console.WriteLine("Created: " + + entry.getPropertyValueByName(AppsMultiDomainNameTable.UserEmail)); + + // Rename Domain User + Console.WriteLine("\n-----------Renaming domain user---------------------"); + entry = service.RenameDomainUser(primaryDomain, tempEmail, testUserNewEmail); + Console.WriteLine("Renamed domain user: " + + entry.getPropertyValueByName(AppsMultiDomainNameTable.NewEmail)); + + // Retrieve Domain User + Console.WriteLine("\n-----------Retrieving domain user----"); + entry = service.RetrieveDomainUser(primaryDomain, testUserEmail); + String firstName = + entry.getPropertyValueByName(AppsMultiDomainNameTable.FirstName); + Console.WriteLine("FirstName: " + firstName); + + // Retrieve all domain users unit and list the emails + Console.WriteLine("\n-----------Retrieving all domain users----"); + AppsExtendedFeed feed = service.RetrieveAllDomainUsers(primaryDomain); + foreach (AppsExtendedEntry unit in feed.Entries) + { + Console.WriteLine( + unit.getPropertyValueByName(AppsMultiDomainNameTable.UserEmail)); + } + + // Create a new User Alias + Console.WriteLine("\n-----------Creating user alias-----------"); + entry = service.CreateDomainUserAlias(primaryDomain, testUserEmail, testUserAliasEmail); + Console.WriteLine("Created Alias: " + + entry.getPropertyValueByName(AppsMultiDomainNameTable.AliasEmail)); + + // Retrieve User Alias + entry = service.RetrieveDomainUserAlias(primaryDomain, testUserAliasEmail); + String userEmail = + entry.getPropertyValueByName(AppsMultiDomainNameTable.UserEmail); + Console.WriteLine("UserEmail: " + userEmail); + + // Retrieve all user aliases for the domain + Console.WriteLine("\n-----------Retrieving all user aliases----"); + feed = service.RetrieveAllDomainUserAlias(primaryDomain); + foreach (AppsExtendedEntry unit in feed.Entries) + { + Console.WriteLine( + unit.getPropertyValueByName(AppsMultiDomainNameTable.UserEmail)); + } + + // Retrieve all aliases for an user + Console.WriteLine("\n-----------Retrieving all aliases for user----"); + feed = service.RetrieveAllDomainUserAliasForUser(primaryDomain, testUserEmail); + foreach (AppsExtendedEntry unit in feed.Entries) + { + Console.WriteLine( + unit.getPropertyValueByName(AppsMultiDomainNameTable.AliasEmail)); + } + + // Delete User Alias + Console.WriteLine("\n-----------Deleting alias----"); + service.DeleteDomainUserAlias(primaryDomain, testUserAliasEmail); + + // Delete User + Console.WriteLine("\n-----------Deleting user----"); + service.DeleteDomainUser(primaryDomain, testUserEmail); + } + catch (AppsException a) + { + Console.WriteLine("A Google Apps error occurred."); + Console.WriteLine(); + Console.WriteLine("Error code: {0}", a.ErrorCode); + Console.WriteLine("Invalid input: {0}", a.InvalidInput); + Console.WriteLine("Reason: {0}", a.Reason); + } + } + } +} diff -Nru gdata-sharp-1.4.0.2/samples/gapps_multidomain_sample/Properties/AssemblyInfo.cs gdata-sharp-1.7.0.1/samples/gapps_multidomain_sample/Properties/AssemblyInfo.cs --- gdata-sharp-1.4.0.2/samples/gapps_multidomain_sample/Properties/AssemblyInfo.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/gapps_multidomain_sample/Properties/AssemblyInfo.cs 2010-11-02 15:10:58.000000000 +0000 @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("gapps-multidomain-sample")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("gapps-multidomain-sample")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("7b360483-8d77-4b7e-a56e-95c591d102cd")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff -Nru gdata-sharp-1.4.0.2/samples/gapps_orgmanagement_sample/gapps_orgmanagement_sample.csproj gdata-sharp-1.7.0.1/samples/gapps_orgmanagement_sample/gapps_orgmanagement_sample.csproj --- gdata-sharp-1.4.0.2/samples/gapps_orgmanagement_sample/gapps_orgmanagement_sample.csproj 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/gapps_orgmanagement_sample/gapps_orgmanagement_sample.csproj 2010-11-02 14:24:29.000000000 +0000 @@ -0,0 +1,67 @@ + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {30E8E083-41DE-4E34-8F2D-A9FBF01CCE03} + Exe + Properties + gapps_orgmanagement_sample + AppsOrgManagementDemo + v2.0 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + False + ..\..\lib\Release\Google.GData.Apps.dll + + + False + ..\..\lib\Release\Google.GData.Client.dll + + + False + ..\..\lib\Release\Google.GData.Extensions.dll + + + + + + + + AssemblyVersion.cs + + + + + + + + + diff -Nru gdata-sharp-1.4.0.2/samples/gapps_orgmanagement_sample/orgmanagementdemo.cs gdata-sharp-1.7.0.1/samples/gapps_orgmanagement_sample/orgmanagementdemo.cs --- gdata-sharp-1.4.0.2/samples/gapps_orgmanagement_sample/orgmanagementdemo.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/gapps_orgmanagement_sample/orgmanagementdemo.cs 2010-11-02 14:44:12.000000000 +0000 @@ -0,0 +1,183 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Google.GData.Client; +using Google.GData.Extensions.Apps; +using Google.GData.Apps; + + +namespace GoogleAppsConsoleApplication +{ + class AppsOrgManagementDemo + { + private static string domain; + private static string adminEmail; + private static string adminPassword; + private static string testUser; + + /// + /// This console application demonstrates all the Google Apps + /// Organization Management APIs. + /// + /// Command-line arguments: args[0] is + /// the domain, args[1] is the admin email address, args[2] + /// is the admin password and arg[3] is test user(email address) + /// + /// Example: AppsOrgManagementDemo example.com admin@example.com my_password test_user_email + public static void Main(string[] args) + { + if (args.Length != 4) + { + Console.WriteLine( + "Syntax: AppsOrgManagementDemo "); + } + else + { + domain = args[0]; + adminEmail = args[1]; + adminPassword = args[2]; + testUser = args[3]; + + OrganizationService service = new OrganizationService(domain, "organizationapis-apps-demo"); + service.setUserCredentials(adminEmail, adminPassword); + + RunSample(service); + } + } + + /// + /// + /// + /// + private static void RunSample(OrganizationService service) + { + try + { + const String testOrgunit = "TestOrgUnitForSample"; + const String testOrgunitDescription = "Test Organization"; + + // Retrieve customer Id + AppsExtendedEntry entry = service.RetrieveCustomerId(service.DomainName); + String customerId = + entry.getPropertyValueByName(AppsOrganizationNameTable.CustomerId); + Console.WriteLine("CustomerId: " + customerId); + + // Delete, if all already exists + try + { + service.DeleteOrganizationUnit(customerId, testOrgunit); + } + catch + { + } + + // Create a new Organization Unit + Console.WriteLine("\n-----------Creating organization unit-----------"); + entry = service.CreateOrganizationUnit( + customerId, testOrgunit, "/", testOrgunitDescription, false); + + Console.WriteLine("Created: " + + entry.getPropertyValueByName(AppsOrganizationNameTable.OrgUnitName)); + + // Retrieve Organization Unit and list all properties + Console.WriteLine("\n-----------Retrieving organization unit---------"); + entry = service.RetrieveOrganizationUnit(customerId, testOrgunit); + + foreach (PropertyElement element in entry.Properties) + { + Console.WriteLine(String.Format("{0} - {1}", element.Name, element.Value)); + } + + // Update organization unit and list all properties + Console.WriteLine("\n-----------Updating organization unit----"); + IDictionary updates = + new Dictionary(); + updates[OrganizationService.OrgUnitProperty.Description] = "Updated description"; + entry = service.UpdateOrganizationUnit(customerId, testOrgunit, updates); + foreach (PropertyElement element in entry.Properties) + { + Console.WriteLine(String.Format("{0} - {1}", element.Name, element.Value)); + } + + // Retrieve all organization units and list the names + Console.WriteLine("\n-----------Retrieving all organization units----"); + AppsExtendedFeed feed = service.RetrieveAllOrganizationUnits(customerId); + foreach (AppsExtendedEntry unit in feed.Entries) + { + Console.WriteLine( + unit.getPropertyValueByName(AppsOrganizationNameTable.OrgUnitName)); + } + + // Retrieve child organization unit of a given unit + Console.WriteLine("\n-----------Retrieving child organization units----"); + feed = service.RetrieveChildOrganizationUnits(customerId, testOrgunit); + foreach (AppsExtendedEntry unit in feed.Entries) + { + Console.WriteLine( + unit.getPropertyValueByName(AppsOrganizationNameTable.OrgUnitName)); + } + + // Retrieve org user + Console.WriteLine("\n-----------Retrieving Org User-------------------"); + entry = service.RetrieveOrganizationUser(customerId, testUser); + Console.WriteLine("Retrieved OrgUser"); + foreach (PropertyElement element in entry.Properties) + { + Console.WriteLine(String.Format("{0} - {1}", element.Name, element.Value)); + } + + + // update org user i.e. move from one org unit to another + Console.WriteLine("\n-----------Updating Org User---------------------"); + entry = service.UpdateOrganizationUser(customerId, testUser, testOrgunit, "/"); + Console.WriteLine("Updated OrgUser"); + foreach (PropertyElement element in entry.Properties) + { + Console.WriteLine(String.Format("{0} - {1}", element.Name, element.Value)); + } + + // Retrieve all org users + Console.WriteLine("\n-----------Retrieving all Org Users--------------"); + feed = service.RetrieveAllOrganizationUsers(customerId); + Console.WriteLine("Retrieved User count: " + feed.Entries.Count); + + //using pagination + Console.WriteLine("\n--------Retrieving all Org Users(paginated)------"); + feed = service.RetrieveFirstPageOrganizationUsers(customerId); + Console.WriteLine("Retrieved User count: " + feed.Entries.Count); + AtomLink next, prev = null; + while ((next = feed.Links.FindService("next", null)) != null && prev != next) + { + feed = service.RetrieveNextPageFromResumeKey(next.HRef.ToString()); + prev = next; + Console.WriteLine("Retrieved User count: " + feed.Entries.Count); + } + + + // Retrieve org users by org unit + Console.WriteLine("\n-----------Retrieving Org Users by orgunit--------------"); + feed = service.RetrieveAllOrganizationUsersByOrgUnit(customerId, testOrgunit); + Console.WriteLine("Retrieved User count: " + feed.Entries.Count); + + //cleanup + try + { + Console.WriteLine("\nCleaning up..."); + entry = service.UpdateOrganizationUser(customerId, testUser, "/", testOrgunit); + service.DeleteOrganizationUnit(customerId, testOrgunit); + } + catch + { + } + } + catch (AppsException a) + { + Console.WriteLine("A Google Apps error occurred."); + Console.WriteLine(); + Console.WriteLine("Error code: {0}", a.ErrorCode); + Console.WriteLine("Invalid input: {0}", a.InvalidInput); + Console.WriteLine("Reason: {0}", a.Reason); + } + } + } +} diff -Nru gdata-sharp-1.4.0.2/samples/gbase/gbase_customertool.csproj gdata-sharp-1.7.0.1/samples/gbase/gbase_customertool.csproj --- gdata-sharp-1.4.0.2/samples/gbase/gbase_customertool.csproj 2008-04-23 08:15:01.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/gbase/gbase_customertool.csproj 2009-10-27 16:30:40.000000000 +0000 @@ -1,4 +1,4 @@ - + Local 8.0.50727 @@ -26,6 +26,7 @@ + 2.0 bin\Debug\ diff -Nru gdata-sharp-1.4.0.2/samples/gbase/gbase_demo.vbproj gdata-sharp-1.7.0.1/samples/gbase/gbase_demo.vbproj --- gdata-sharp-1.4.0.2/samples/gbase/gbase_demo.vbproj 2008-02-27 14:50:14.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/gbase/gbase_demo.vbproj 2009-10-27 16:30:40.000000000 +0000 @@ -1,4 +1,4 @@ - + Local 8.0.50727 @@ -29,6 +29,7 @@ WindowsFormsWithCustomSubMain + 2.0 bin\ diff -Nru gdata-sharp-1.4.0.2/samples/gbase/gbase_querytool.csproj gdata-sharp-1.7.0.1/samples/gbase/gbase_querytool.csproj --- gdata-sharp-1.4.0.2/samples/gbase/gbase_querytool.csproj 2008-04-23 08:15:01.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/gbase/gbase_querytool.csproj 2009-10-27 16:30:40.000000000 +0000 @@ -1,4 +1,4 @@ - + Local 8.0.50727 @@ -26,6 +26,7 @@ + 2.0 bin\Debug\ diff -Nru gdata-sharp-1.4.0.2/samples/Google Data APIs Samples.sln gdata-sharp-1.7.0.1/samples/Google Data APIs Samples.sln --- gdata-sharp-1.4.0.2/samples/Google Data APIs Samples.sln 2009-02-17 09:22:54.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/Google Data APIs Samples.sln 2010-11-02 15:10:58.000000000 +0000 @@ -1,5 +1,5 @@ -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "gapps_migration_sample", "appsforyourdomain\gapps_migration_sample.csproj", "{5B456106-A6A7-4EAA-B32C-5EDB92FC2453}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "gapps_sample", "appsforyourdomain\gapps_sample.csproj", "{25DF4CCD-68C9-400E-87FF-8FCFAF76C998}" @@ -34,6 +34,20 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DocListExporter", "DocListExporter\DocListExporter.csproj", "{6C6C0183-78AA-4DC4-BB1A-35A181F11F89}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Analytics", "analytics\Analytics.csproj", "{FA8A1FDC-138B-48D9-8288-711B911C589A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YouTubeUploader", "YouTubeUploader\YouTubeUploader\YouTubeUploader.csproj", "{725130CA-A753-45A8-855F-EA22728E3F95}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LumenWorks.Framework.IO", "YouTubeUploader\LumenWorks.Framework.IO\LumenWorks.Framework.IO.csproj", "{E3B83D68-C90C-4874-8E5F-DEC8D038BC7C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Analytics_AccountFeed_Sample", "Analytics_AccountFeed_Sample\Analytics_AccountFeed_Sample.csproj", "{D4C48882-F3E0-48E7-98C7-301702AD7A3E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Analytics_DataFeed_Sample", "Analytics_DataFeed_Sample\Analytics_DataFeed_Sample.csproj", "{85408B33-1109-435A-B17C-CB2A80BC562F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "gapps_orgmanagement_sample", "gapps_orgmanagement_sample\gapps_orgmanagement_sample.csproj", "{30E8E083-41DE-4E34-8F2D-A9FBF01CCE03}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "gapps_multidomain_sample", "gapps_multidomain_sample\gapps_multidomain_sample.csproj", "{ED8392F9-96FB-40B8-AE94-4628C1FBCAF7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution ASP|Any CPU = ASP|Any CPU @@ -178,6 +192,62 @@ {6C6C0183-78AA-4DC4-BB1A-35A181F11F89}.DocListUploader - Release|Any CPU.Build.0 = Release|Any CPU {6C6C0183-78AA-4DC4-BB1A-35A181F11F89}.Release|Any CPU.ActiveCfg = Release|Any CPU {6C6C0183-78AA-4DC4-BB1A-35A181F11F89}.Release|Any CPU.Build.0 = Release|Any CPU + {FA8A1FDC-138B-48D9-8288-711B911C589A}.ASP|Any CPU.ActiveCfg = Release|Any CPU + {FA8A1FDC-138B-48D9-8288-711B911C589A}.ASP|Any CPU.Build.0 = Release|Any CPU + {FA8A1FDC-138B-48D9-8288-711B911C589A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FA8A1FDC-138B-48D9-8288-711B911C589A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FA8A1FDC-138B-48D9-8288-711B911C589A}.DocListUploader - Release|Any CPU.ActiveCfg = Release|Any CPU + {FA8A1FDC-138B-48D9-8288-711B911C589A}.DocListUploader - Release|Any CPU.Build.0 = Release|Any CPU + {FA8A1FDC-138B-48D9-8288-711B911C589A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FA8A1FDC-138B-48D9-8288-711B911C589A}.Release|Any CPU.Build.0 = Release|Any CPU + {725130CA-A753-45A8-855F-EA22728E3F95}.ASP|Any CPU.ActiveCfg = Release|Any CPU + {725130CA-A753-45A8-855F-EA22728E3F95}.ASP|Any CPU.Build.0 = Release|Any CPU + {725130CA-A753-45A8-855F-EA22728E3F95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {725130CA-A753-45A8-855F-EA22728E3F95}.Debug|Any CPU.Build.0 = Debug|Any CPU + {725130CA-A753-45A8-855F-EA22728E3F95}.DocListUploader - Release|Any CPU.ActiveCfg = Release|Any CPU + {725130CA-A753-45A8-855F-EA22728E3F95}.DocListUploader - Release|Any CPU.Build.0 = Release|Any CPU + {725130CA-A753-45A8-855F-EA22728E3F95}.Release|Any CPU.ActiveCfg = Release|Any CPU + {725130CA-A753-45A8-855F-EA22728E3F95}.Release|Any CPU.Build.0 = Release|Any CPU + {E3B83D68-C90C-4874-8E5F-DEC8D038BC7C}.ASP|Any CPU.ActiveCfg = Release|Any CPU + {E3B83D68-C90C-4874-8E5F-DEC8D038BC7C}.ASP|Any CPU.Build.0 = Release|Any CPU + {E3B83D68-C90C-4874-8E5F-DEC8D038BC7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E3B83D68-C90C-4874-8E5F-DEC8D038BC7C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E3B83D68-C90C-4874-8E5F-DEC8D038BC7C}.DocListUploader - Release|Any CPU.ActiveCfg = Release|Any CPU + {E3B83D68-C90C-4874-8E5F-DEC8D038BC7C}.DocListUploader - Release|Any CPU.Build.0 = Release|Any CPU + {E3B83D68-C90C-4874-8E5F-DEC8D038BC7C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E3B83D68-C90C-4874-8E5F-DEC8D038BC7C}.Release|Any CPU.Build.0 = Release|Any CPU + {D4C48882-F3E0-48E7-98C7-301702AD7A3E}.ASP|Any CPU.ActiveCfg = Release|Any CPU + {D4C48882-F3E0-48E7-98C7-301702AD7A3E}.ASP|Any CPU.Build.0 = Release|Any CPU + {D4C48882-F3E0-48E7-98C7-301702AD7A3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D4C48882-F3E0-48E7-98C7-301702AD7A3E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D4C48882-F3E0-48E7-98C7-301702AD7A3E}.DocListUploader - Release|Any CPU.ActiveCfg = Release|Any CPU + {D4C48882-F3E0-48E7-98C7-301702AD7A3E}.DocListUploader - Release|Any CPU.Build.0 = Release|Any CPU + {D4C48882-F3E0-48E7-98C7-301702AD7A3E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D4C48882-F3E0-48E7-98C7-301702AD7A3E}.Release|Any CPU.Build.0 = Release|Any CPU + {85408B33-1109-435A-B17C-CB2A80BC562F}.ASP|Any CPU.ActiveCfg = Release|Any CPU + {85408B33-1109-435A-B17C-CB2A80BC562F}.ASP|Any CPU.Build.0 = Release|Any CPU + {85408B33-1109-435A-B17C-CB2A80BC562F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {85408B33-1109-435A-B17C-CB2A80BC562F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {85408B33-1109-435A-B17C-CB2A80BC562F}.DocListUploader - Release|Any CPU.ActiveCfg = Release|Any CPU + {85408B33-1109-435A-B17C-CB2A80BC562F}.DocListUploader - Release|Any CPU.Build.0 = Release|Any CPU + {85408B33-1109-435A-B17C-CB2A80BC562F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {85408B33-1109-435A-B17C-CB2A80BC562F}.Release|Any CPU.Build.0 = Release|Any CPU + {30E8E083-41DE-4E34-8F2D-A9FBF01CCE03}.ASP|Any CPU.ActiveCfg = Release|Any CPU + {30E8E083-41DE-4E34-8F2D-A9FBF01CCE03}.ASP|Any CPU.Build.0 = Release|Any CPU + {30E8E083-41DE-4E34-8F2D-A9FBF01CCE03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {30E8E083-41DE-4E34-8F2D-A9FBF01CCE03}.Debug|Any CPU.Build.0 = Debug|Any CPU + {30E8E083-41DE-4E34-8F2D-A9FBF01CCE03}.DocListUploader - Release|Any CPU.ActiveCfg = Release|Any CPU + {30E8E083-41DE-4E34-8F2D-A9FBF01CCE03}.DocListUploader - Release|Any CPU.Build.0 = Release|Any CPU + {30E8E083-41DE-4E34-8F2D-A9FBF01CCE03}.Release|Any CPU.ActiveCfg = Release|Any CPU + {30E8E083-41DE-4E34-8F2D-A9FBF01CCE03}.Release|Any CPU.Build.0 = Release|Any CPU + {ED8392F9-96FB-40B8-AE94-4628C1FBCAF7}.ASP|Any CPU.ActiveCfg = Release|Any CPU + {ED8392F9-96FB-40B8-AE94-4628C1FBCAF7}.ASP|Any CPU.Build.0 = Release|Any CPU + {ED8392F9-96FB-40B8-AE94-4628C1FBCAF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ED8392F9-96FB-40B8-AE94-4628C1FBCAF7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ED8392F9-96FB-40B8-AE94-4628C1FBCAF7}.DocListUploader - Release|Any CPU.ActiveCfg = Release|Any CPU + {ED8392F9-96FB-40B8-AE94-4628C1FBCAF7}.DocListUploader - Release|Any CPU.Build.0 = Release|Any CPU + {ED8392F9-96FB-40B8-AE94-4628C1FBCAF7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ED8392F9-96FB-40B8-AE94-4628C1FBCAF7}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff -Nru gdata-sharp-1.4.0.2/samples/health/HealthTool.csproj gdata-sharp-1.7.0.1/samples/health/HealthTool.csproj --- gdata-sharp-1.4.0.2/samples/health/HealthTool.csproj 2008-05-28 09:11:26.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/health/HealthTool.csproj 2009-10-27 16:30:40.000000000 +0000 @@ -1,4 +1,4 @@ - + Local 8.0.50727 @@ -26,6 +26,7 @@ + 2.0 bin\Debug\ diff -Nru gdata-sharp-1.4.0.2/samples/PhotoBrowser/Browser.cs gdata-sharp-1.7.0.1/samples/PhotoBrowser/Browser.cs --- gdata-sharp-1.4.0.2/samples/PhotoBrowser/Browser.cs 2008-11-12 15:50:03.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/PhotoBrowser/Browser.cs 2009-08-14 13:44:57.000000000 +0000 @@ -7,6 +7,7 @@ using Google.GData.Photos; using Google.GData.Extensions.MediaRss; using Google.GData.Tools; +using Google.Picasa; using System.IO; namespace PhotoBrowser @@ -330,7 +331,9 @@ Icon error = new Icon(SystemIcons.Exclamation, 40, 40); this.AlbumPicture.Image = error.ToBitmap(); } - this.AlbumInspector.SelectedObject = new AlbumAccessor(entry); + Album a = new Album(); + a.AtomEntry = entry; + this.AlbumInspector.SelectedObject = a; this.Cursor = Cursors.Default; } else diff -Nru gdata-sharp-1.4.0.2/samples/PhotoBrowser/GoogleClientLogin.cs gdata-sharp-1.7.0.1/samples/PhotoBrowser/GoogleClientLogin.cs --- gdata-sharp-1.4.0.2/samples/PhotoBrowser/GoogleClientLogin.cs 2008-02-29 12:39:15.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/PhotoBrowser/GoogleClientLogin.cs 2009-12-08 13:15:18.000000000 +0000 @@ -233,7 +233,7 @@ private void Login_Click(object sender, System.EventArgs e) { this.service.setUserCredentials(this.Username.Text, this.Password.Text); - this.authToken = this.service.QueryAuthenticationToken(); + this.authToken = this.service.QueryClientLoginToken(); this.Close(); } } diff -Nru gdata-sharp-1.4.0.2/samples/PhotoBrowser/NewAlbumDialog.cs gdata-sharp-1.7.0.1/samples/PhotoBrowser/NewAlbumDialog.cs --- gdata-sharp-1.4.0.2/samples/PhotoBrowser/NewAlbumDialog.cs 2008-09-05 07:55:31.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/PhotoBrowser/NewAlbumDialog.cs 2010-03-19 15:52:11.000000000 +0000 @@ -5,6 +5,7 @@ using System.Windows.Forms; using Google.GData.Photos; using Google.GData.Extensions.MediaRss; +using Google.Picasa; namespace PhotoBrowser { @@ -222,24 +223,23 @@ private void Ok_Click(object sender, System.EventArgs e) { - AlbumEntry entry = new AlbumEntry(); - AlbumAccessor acc = new AlbumAccessor(entry); - entry.Title.Text = this.AlbumName.Text; - entry.Summary.Text = this.AlbumDescription.Text; + Album acc = new Album(); + acc.Title = this.AlbumName.Text; + acc.Summary = this.AlbumDescription.Text; if (this.AlbumLocation.Text.Length > 0) { acc.Location = this.AlbumLocation.Text; } if (this.AlbumKeywords.Text.Length > 0) { - entry.Media = new MediaGroup(); + acc.PicasaEntry.Media = new MediaGroup(); MediaKeywords keywords = new MediaKeywords(this.AlbumKeywords.Text); - entry.Media.Keywords = keywords; + acc.PicasaEntry.Media.Keywords = keywords; } acc.Access = this.AlbumPublic.Checked ? "public" : "private"; acc.CommentingEnabled = this.AllowComments.Checked; - this.newEntry = this.service.Insert(this.feed, entry); + this.newEntry = this.service.Insert(this.feed, acc.PicasaEntry); this.Close(); } diff -Nru gdata-sharp-1.4.0.2/samples/PhotoBrowser/PhotoBrowser.cs gdata-sharp-1.7.0.1/samples/PhotoBrowser/PhotoBrowser.cs --- gdata-sharp-1.4.0.2/samples/PhotoBrowser/PhotoBrowser.cs 2008-10-20 14:01:49.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/PhotoBrowser/PhotoBrowser.cs 2009-08-14 13:44:57.000000000 +0000 @@ -8,6 +8,7 @@ using Google.GData.Client; using Google.GData.Extensions.MediaRss; using Google.GData.Extensions; +using Google.Picasa; using System.IO; namespace PhotoBrowser @@ -286,7 +287,9 @@ Icon error = new Icon(SystemIcons.Exclamation, 40, 40); this.PhotoPreview.Image = error.ToBitmap(); } - this.PhotoInspector.SelectedObject = new PhotoAccessor(entry); + Photo photo = new Photo(); + photo.AtomEntry = entry; + this.PhotoInspector.SelectedObject = photo; this.Cursor = Cursors.Default; this.DownloadPhoto.Enabled = true; } diff -Nru gdata-sharp-1.4.0.2/samples/PhotoBrowser/PhotoBrowser.csproj gdata-sharp-1.7.0.1/samples/PhotoBrowser/PhotoBrowser.csproj --- gdata-sharp-1.4.0.2/samples/PhotoBrowser/PhotoBrowser.csproj 2008-12-16 11:11:21.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/PhotoBrowser/PhotoBrowser.csproj 2010-12-06 13:36:40.000000000 +0000 @@ -1,7 +1,7 @@ - + Local - 8.0.50727 + 9.0.30729 2.0 {40CB899F-54ED-4863-BF78-58BA793A1478} Debug @@ -25,6 +25,7 @@ + 2.0 bin\Debug\ @@ -73,15 +74,15 @@ prompt - + False ..\..\lib\Release\Google.GData.Client.dll - + False ..\..\lib\Release\Google.GData.Extensions.dll - + False ..\..\lib\Release\Google.GData.Photos.dll diff -Nru gdata-sharp-1.4.0.2/samples/spreadsheets/SpreadsheetCmdLine.csproj gdata-sharp-1.7.0.1/samples/spreadsheets/SpreadsheetCmdLine.csproj --- gdata-sharp-1.4.0.2/samples/spreadsheets/SpreadsheetCmdLine.csproj 2008-04-23 08:15:01.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/spreadsheets/SpreadsheetCmdLine.csproj 2009-10-27 16:30:40.000000000 +0000 @@ -1,4 +1,4 @@ - + Debug AnyCPU @@ -9,6 +9,11 @@ Properties SpreadsheetCmdLine SpreadsheetCmdLine + + + 2.0 + + true diff -Nru gdata-sharp-1.4.0.2/samples/spreadsheets/Spreadsheet.csproj gdata-sharp-1.7.0.1/samples/spreadsheets/Spreadsheet.csproj --- gdata-sharp-1.4.0.2/samples/spreadsheets/Spreadsheet.csproj 2008-09-01 16:50:03.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/spreadsheets/Spreadsheet.csproj 2009-10-27 16:30:40.000000000 +0000 @@ -1,4 +1,4 @@ - + Local 8.0.50727 @@ -26,6 +26,7 @@ + 2.0 bin\Debug\ diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeNotifier/Form1.cs gdata-sharp-1.7.0.1/samples/YouTubeNotifier/Form1.cs --- gdata-sharp-1.4.0.2/samples/YouTubeNotifier/Form1.cs 2009-02-27 14:38:35.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeNotifier/Form1.cs 2010-02-15 11:26:47.000000000 +0000 @@ -30,7 +30,6 @@ private const string AppKey = "NotifierYT"; private const string YTNOTIFIERKEY = "Software\\GoogleYouTubeNotifier"; - private const string YTCLIENTID = "ytapi-FrankMantek-TestaccountforGD-sjgv537n-0"; private const string YTDEVKEY = "AI39si4v3E6oIYiI60ndCNDqnPP5lCqO28DSvvDPnQt-Mqia5uPz2e4E-gMSBVwHXwyn_LF1tWox4LyM-0YQd2o4i_3GcXxa2Q"; private List allActivities = new List(); @@ -113,7 +112,6 @@ YouTubeRequestSettings settings = new YouTubeRequestSettings(AppKey, - YTCLIENTID, YTDEVKEY, this.userName.Text, ""); @@ -139,7 +137,6 @@ { // let's see if we get a valid authtoken back for the passed in credentials.... YouTubeRequestSettings settings = new YouTubeRequestSettings(AppKey, - YTCLIENTID, YTDEVKEY, this.userName.Text, this.passWord.Text); @@ -147,7 +144,7 @@ this.ytRequest = new YouTubeRequest(settings); try { - this.authToken = this.ytRequest.Service.QueryAuthenticationToken(); + this.authToken = this.ytRequest.Service.QueryClientLoginToken(); this.passWord.Text = ""; } catch @@ -286,7 +283,6 @@ // let's see if we get a valid authtoken back for the passed in credentials.... YouTubeRequestSettings settings = new YouTubeRequestSettings("YouTubeNotifier", - YTCLIENTID, YTDEVKEY); // settings.PageSize = 15; YouTubeRequest r = new YouTubeRequest(settings); diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeNotifier/Properties/Resources.Designer.cs gdata-sharp-1.7.0.1/samples/YouTubeNotifier/Properties/Resources.Designer.cs --- gdata-sharp-1.4.0.2/samples/YouTubeNotifier/Properties/Resources.Designer.cs 2009-02-26 14:57:02.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeNotifier/Properties/Resources.Designer.cs 2010-03-23 16:40:45.000000000 +0000 @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:2.0.50727.1433 +// Runtime Version:2.0.50727.4927 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeNotifier/Properties/Resources.resx gdata-sharp-1.7.0.1/samples/YouTubeNotifier/Properties/Resources.resx --- gdata-sharp-1.4.0.2/samples/YouTubeNotifier/Properties/Resources.resx 2009-02-26 14:57:02.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeNotifier/Properties/Resources.resx 2010-03-23 16:40:45.000000000 +0000 @@ -119,6 +119,6 @@ - ..\Resources\NotifierForYT.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\gdata-youtube.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeNotifier/Properties/Settings.Designer.cs gdata-sharp-1.7.0.1/samples/YouTubeNotifier/Properties/Settings.Designer.cs --- gdata-sharp-1.4.0.2/samples/YouTubeNotifier/Properties/Settings.Designer.cs 2009-02-26 14:57:02.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeNotifier/Properties/Settings.Designer.cs 2009-10-27 16:30:40.000000000 +0000 @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:2.0.50727.1433 +// Runtime Version:2.0.50727.4200 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -12,7 +12,7 @@ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "8.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); Binary files /tmp/UhUzKTrMiD/gdata-sharp-1.4.0.2/samples/YouTubeNotifier/Resources/gdata-youtube.png and /tmp/kt1AG0Pm9_/gdata-sharp-1.7.0.1/samples/YouTubeNotifier/Resources/gdata-youtube.png differ Binary files /tmp/UhUzKTrMiD/gdata-sharp-1.4.0.2/samples/YouTubeNotifier/Resources/NotifierForYT.png and /tmp/kt1AG0Pm9_/gdata-sharp-1.7.0.1/samples/YouTubeNotifier/Resources/NotifierForYT.png differ Binary files /tmp/UhUzKTrMiD/gdata-sharp-1.4.0.2/samples/YouTubeNotifier/Resources/Thumbs.db and /tmp/kt1AG0Pm9_/gdata-sharp-1.7.0.1/samples/YouTubeNotifier/Resources/Thumbs.db differ diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeNotifier/YouTubeNotifier.csproj gdata-sharp-1.7.0.1/samples/YouTubeNotifier/YouTubeNotifier.csproj --- gdata-sharp-1.4.0.2/samples/YouTubeNotifier/YouTubeNotifier.csproj 2009-02-26 14:57:02.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeNotifier/YouTubeNotifier.csproj 2010-11-02 15:10:58.000000000 +0000 @@ -1,8 +1,8 @@ - + Debug AnyCPU - 8.0.50727 + 9.0.30729 2.0 {91B3DC78-1120-4803-A2D6-88753174F819} WinExe @@ -11,6 +11,11 @@ NotifierForYT + + + 2.0 + + true @@ -30,15 +35,15 @@ 4 - + False ..\..\lib\Release\Google.GData.Client.dll - + False ..\..\lib\Release\Google.GData.Extensions.dll - + False ..\..\lib\Release\Google.GData.YouTube.dll diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeSample/App_Code/ListVideos.cs gdata-sharp-1.7.0.1/samples/YouTubeSample/App_Code/ListVideos.cs --- gdata-sharp-1.4.0.2/samples/YouTubeSample/App_Code/ListVideos.cs 2009-02-27 17:00:31.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeSample/App_Code/ListVideos.cs 2010-06-22 15:02:23.000000000 +0000 @@ -63,7 +63,6 @@ if (request == null) { YouTubeRequestSettings settings = new YouTubeRequestSettings("YouTubeAspSample", - "ytapi-FrankMantek-TestaccountforGD-sjgv537n-0", "AI39si4v3E6oIYiI60ndCNDqnPP5lCqO28DSvvDPnQt-Mqia5uPz2e4E-gMSBVwHXwyn_LF1tWox4LyM-0YQd2o4i_3GcXxa2Q", HttpContext.Current.Session["token"] as string ); diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeSample/Web.Config gdata-sharp-1.7.0.1/samples/YouTubeSample/Web.Config --- gdata-sharp-1.4.0.2/samples/YouTubeSample/Web.Config 2008-05-28 10:38:01.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeSample/Web.Config 2009-11-17 13:24:03.000000000 +0000 @@ -8,7 +8,15 @@ \Windows\Microsoft.Net\Framework\v2.x\Config --> - + + + +
    + +
    +
    +
    +
    - + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeSample/YourVideo.aspx.cs gdata-sharp-1.7.0.1/samples/YouTubeSample/YourVideo.aspx.cs --- gdata-sharp-1.4.0.2/samples/YouTubeSample/YourVideo.aspx.cs 2008-11-24 13:11:18.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeSample/YourVideo.aspx.cs 2010-02-15 11:26:47.000000000 +0000 @@ -46,7 +46,7 @@ String.IsNullOrEmpty(this.Keyword.Text) == false) { - GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory(YouTubeService.YTService, "TesterApp"); + GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory(ServiceNames.YouTube, "TesterApp"); YouTubeService service = new YouTubeService(authFactory.ApplicationName, "ytapi-FrankMantek-TestaccountforGD-sjgv537n-0", diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeSample.sln gdata-sharp-1.7.0.1/samples/YouTubeSample.sln --- gdata-sharp-1.4.0.2/samples/YouTubeSample.sln 2008-05-28 10:38:01.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeSample.sln 2010-06-22 15:02:23.000000000 +0000 @@ -1,23 +1,24 @@  -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = ".\YouTubeSample\", ".\YouTubeSample\", "{6EC1E1BD-4D9E-4306-B9DA-6F9A096D17C8}" +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "YouTubeSample", "YouTubeSample\", "{6EC1E1BD-4D9E-4306-B9DA-6F9A096D17C8}" ProjectSection(WebsiteProperties) = preProject + TargetFramework = "3.5" Debug.AspNetCompiler.VirtualPath = "/YouTubeSample" - Debug.AspNetCompiler.PhysicalPath = ".\YouTubeSample\" + Debug.AspNetCompiler.PhysicalPath = "YouTubeSample\" Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\YouTubeSample\" Debug.AspNetCompiler.Updateable = "true" Debug.AspNetCompiler.ForceOverwrite = "true" Debug.AspNetCompiler.FixedNames = "false" Debug.AspNetCompiler.Debug = "True" Release.AspNetCompiler.VirtualPath = "/YouTubeSample" - Release.AspNetCompiler.PhysicalPath = ".\YouTubeSample\" + Release.AspNetCompiler.PhysicalPath = "YouTubeSample\" Release.AspNetCompiler.TargetPath = "PrecompiledWeb\YouTubeSample\" Release.AspNetCompiler.Updateable = "true" Release.AspNetCompiler.ForceOverwrite = "true" Release.AspNetCompiler.FixedNames = "false" Release.AspNetCompiler.Debug = "False" - VWDPort = "1390" + VWDPort = "54060" DefaultWebSiteLanguage = "Visual C#" EndProjectSection EndProject diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CachedCsvReader.cs gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CachedCsvReader.cs --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CachedCsvReader.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CachedCsvReader.cs 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,412 @@ +// LumenWorks.Framework.IO.CSV.CachedCsvReader +// Copyright (c) 2005 Sébastien Lorion +// +// MIT license (http://en.wikipedia.org/wiki/MIT_License) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.IO; + +using LumenWorks.Framework.IO.Csv.Resources; + +namespace LumenWorks.Framework.IO.Csv +{ + /// + /// Represents a reader that provides fast, cached, dynamic access to CSV data. + /// + /// The number of records is limited to - 1. + public partial class CachedCsvReader + : CsvReader, IListSource + { + #region Fields + + /// + /// Contains the cached records. + /// + private List _records; + + /// + /// Contains the current record index (inside the cached records array). + /// + private long _currentRecordIndex; + + /// + /// Indicates if a new record is being read from the CSV stream. + /// + private bool _readingStream; + + /// + /// Contains the binding list linked to this reader. + /// + private CsvBindingList _bindingList; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the CsvReader class. + /// + /// A pointing to the CSV file. + /// if field names are located on the first non commented line, otherwise, . + /// + /// is a . + /// + /// + /// Cannot read from . + /// + public CachedCsvReader(TextReader reader, bool hasHeaders) + : this(reader, hasHeaders, DefaultBufferSize) + { + } + + /// + /// Initializes a new instance of the CsvReader class. + /// + /// A pointing to the CSV file. + /// if field names are located on the first non commented line, otherwise, . + /// The buffer size in bytes. + /// + /// is a . + /// + /// + /// Cannot read from . + /// + public CachedCsvReader(TextReader reader, bool hasHeaders, int bufferSize) + : this(reader, hasHeaders, DefaultDelimiter, DefaultQuote, DefaultEscape, DefaultComment, true, bufferSize) + { + } + + /// + /// Initializes a new instance of the CsvReader class. + /// + /// A pointing to the CSV file. + /// if field names are located on the first non commented line, otherwise, . + /// The delimiter character separating each field (default is ','). + /// + /// is a . + /// + /// + /// Cannot read from . + /// + public CachedCsvReader(TextReader reader, bool hasHeaders, char delimiter) + : this(reader, hasHeaders, delimiter, DefaultQuote, DefaultEscape, DefaultComment, true, DefaultBufferSize) + { + } + + /// + /// Initializes a new instance of the CsvReader class. + /// + /// A pointing to the CSV file. + /// if field names are located on the first non commented line, otherwise, . + /// The delimiter character separating each field (default is ','). + /// The buffer size in bytes. + /// + /// is a . + /// + /// + /// Cannot read from . + /// + public CachedCsvReader(TextReader reader, bool hasHeaders, char delimiter, int bufferSize) + : this(reader, hasHeaders, delimiter, DefaultQuote, DefaultEscape, DefaultComment, true, bufferSize) + { + } + + /// + /// Initializes a new instance of the CsvReader class. + /// + /// A pointing to the CSV file. + /// if field names are located on the first non commented line, otherwise, . + /// The delimiter character separating each field (default is ','). + /// The quotation character wrapping every field (default is '''). + /// + /// The escape character letting insert quotation characters inside a quoted field (default is '\'). + /// If no escape character, set to '\0' to gain some performance. + /// + /// The comment character indicating that a line is commented out (default is '#'). + /// if spaces at the start and end of a field are trimmed, otherwise, . Default is . + /// + /// is a . + /// + /// + /// Cannot read from . + /// + public CachedCsvReader(TextReader reader, bool hasHeaders, char delimiter, char quote, char escape, char comment, bool trimSpaces) + : this(reader, hasHeaders, delimiter, quote, escape, comment, trimSpaces, DefaultBufferSize) + { + } + + /// + /// Initializes a new instance of the CsvReader class. + /// + /// A pointing to the CSV file. + /// if field names are located on the first non commented line, otherwise, . + /// The delimiter character separating each field (default is ','). + /// The quotation character wrapping every field (default is '''). + /// + /// The escape character letting insert quotation characters inside a quoted field (default is '\'). + /// If no escape character, set to '\0' to gain some performance. + /// + /// The comment character indicating that a line is commented out (default is '#'). + /// if spaces at the start and end of a field are trimmed, otherwise, . Default is . + /// The buffer size in bytes. + /// + /// is a . + /// + /// + /// must be 1 or more. + /// + public CachedCsvReader(TextReader reader, bool hasHeaders, char delimiter, char quote, char escape, char comment, bool trimSpaces, int bufferSize) + : base(reader, hasHeaders, delimiter, quote, escape, comment, trimSpaces, bufferSize) + { + _records = new List(); + _currentRecordIndex = -1; + } + + #endregion + + #region Properties + + #region State + + /// + /// Gets the current record index in the CSV file. + /// + /// The current record index in the CSV file. + public override long CurrentRecordIndex + { + get + { + return _currentRecordIndex; + } + } + + /// + /// Gets a value that indicates whether the current stream position is at the end of the stream. + /// + /// if the current stream position is at the end of the stream; otherwise . + public override bool EndOfStream + { + get + { + if (_currentRecordIndex < base.CurrentRecordIndex) + return false; + else + return base.EndOfStream; + } + } + + #endregion + + #endregion + + #region Indexers + + /// + /// Gets the field at the specified index. + /// + /// The field at the specified index. + /// + /// must be included in [0, [. + /// + /// + /// No record read yet. Call ReadLine() first. + /// + /// + /// The CSV data appears to be missing a field. + /// + /// + /// The CSV appears to be corrupt at the current position. + /// + /// + /// The instance has been disposed of. + /// + public override String this[int field] + { + get + { + if (_readingStream) + return base[field]; + else if (_currentRecordIndex > -1) + { + if (field > -1 && field < this.FieldCount) + return _records[(int) _currentRecordIndex][field]; + else + throw new ArgumentOutOfRangeException("field", field, string.Format(CultureInfo.InvariantCulture, ExceptionMessage.FieldIndexOutOfRange, field)); + } + else + throw new InvalidOperationException(ExceptionMessage.NoCurrentRecord); + } + } + + #endregion + + #region Methods + + #region Read + + /// + /// Reads the CSV stream from the current position to the end of the stream. + /// + /// + /// The instance has been disposed of. + /// + public virtual void ReadToEnd() + { + _currentRecordIndex = base.CurrentRecordIndex; + + while (ReadNextRecord()) ; + } + + /// + /// Reads the next record. + /// + /// + /// Indicates if the reader will proceed to the next record after having read headers. + /// if it stops after having read headers; otherwise, . + /// + /// + /// Indicates if the reader will skip directly to the next line without parsing the current one. + /// To be used when an error occurs. + /// + /// if a record has been successfully reads; otherwise, . + /// + /// The instance has been disposed of. + /// + protected override bool ReadNextRecord(bool onlyReadHeaders, bool skipToNextLine) + { + if (_currentRecordIndex < base.CurrentRecordIndex) + { + _currentRecordIndex++; + return true; + } + else + { + _readingStream = true; + + try + { + bool canRead = base.ReadNextRecord(onlyReadHeaders, skipToNextLine); + + if (canRead) + { + string[] record = new string[this.FieldCount]; + + if (base.CurrentRecordIndex > -1) + { + CopyCurrentRecordTo(record); + _records.Add(record); + } + else + { + MoveTo(0); + CopyCurrentRecordTo(record); + MoveTo(-1); + } + + if (!onlyReadHeaders) + _currentRecordIndex++; + } + else + { + // No more records to read, so set array size to only what is needed + _records.Capacity = _records.Count; + } + + return canRead; + } + finally + { + _readingStream = false; + } + } + } + + #endregion + + #region Move + + /// + /// Moves before the first record. + /// + public void MoveToStart() + { + _currentRecordIndex = -1; + } + + /// + /// Moves to the last record read so far. + /// + public void MoveToLastCachedRecord() + { + _currentRecordIndex = base.CurrentRecordIndex; + } + + /// + /// Moves to the specified record index. + /// + /// The record index. + /// + /// Record index must be > 0. + /// + /// + /// The instance has been disposed of. + /// + public override void MoveTo(long record) + { + if (record < -1) + throw new ArgumentOutOfRangeException("record", record, ExceptionMessage.RecordIndexLessThanZero); + + if (record <= base.CurrentRecordIndex) + _currentRecordIndex = record; + else + { + _currentRecordIndex = base.CurrentRecordIndex; + + long offset = record - _currentRecordIndex; + + // read to the last record before the one we want + while (offset-- > 0 && ReadNextRecord()) ; + } + } + + #endregion + + #endregion + + #region IListSource Members + + bool IListSource.ContainsListCollection + { + get { return false; } + } + + System.Collections.IList IListSource.GetList() + { + if (_bindingList == null) + _bindingList = new CsvBindingList(this); + + return _bindingList; + } + + #endregion + } +} diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CachedCsvReader.CsvBindingList.cs gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CachedCsvReader.CsvBindingList.cs --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CachedCsvReader.CsvBindingList.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CachedCsvReader.CsvBindingList.cs 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,404 @@ +// LumenWorks.Framework.IO.CSV.CachedCsvReader.CsvBindingList +// Copyright (c) 2006 Sébastien Lorion +// +// MIT license (http://en.wikipedia.org/wiki/MIT_License) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; + +namespace LumenWorks.Framework.IO.Csv +{ + public partial class CachedCsvReader + : CsvReader + { + /// + /// Represents a binding list wrapper for a CSV reader. + /// + private class CsvBindingList + : IBindingList, ITypedList, IList, IList + { + #region Fields + + /// + /// Contains the linked CSV reader. + /// + private CachedCsvReader _csv; + + /// + /// Contains the cached record count. + /// + private int _count; + + /// + /// Contains the cached property descriptors. + /// + private PropertyDescriptorCollection _properties; + + /// + /// Contains the current sort property. + /// + private CsvPropertyDescriptor _sort; + + /// + /// Contains the current sort direction. + /// + private ListSortDirection _direction; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the CsvBindingList class. + /// + /// + public CsvBindingList(CachedCsvReader csv) + { + _csv = csv; + _count = -1; + _direction = ListSortDirection.Ascending; + } + + #endregion + + #region IBindingList members + + public void AddIndex(PropertyDescriptor property) + { + } + + public bool AllowNew + { + get + { + return false; + } + } + + public void ApplySort(PropertyDescriptor property, System.ComponentModel.ListSortDirection direction) + { + _sort = (CsvPropertyDescriptor) property; + _direction = direction; + + _csv.ReadToEnd(); + + _csv._records.Sort(new CsvRecordComparer(_sort.Index, _direction)); + } + + public PropertyDescriptor SortProperty + { + get + { + return _sort; + } + } + + public int Find(PropertyDescriptor property, object key) + { + int fieldIndex = ((CsvPropertyDescriptor) property).Index; + string value = (string) key; + + int recordIndex = 0; + int count = this.Count; + + while (recordIndex < count && _csv[recordIndex, fieldIndex] != value) + recordIndex++; + + if (recordIndex == count) + return -1; + else + return recordIndex; + } + + public bool SupportsSorting + { + get + { + return true; + } + } + + public bool IsSorted + { + get + { + return _sort != null; + } + } + + public bool AllowRemove + { + get + { + return false; + } + } + + public bool SupportsSearching + { + get + { + return true; + } + } + + public System.ComponentModel.ListSortDirection SortDirection + { + get + { + return _direction; + } + } + + public event System.ComponentModel.ListChangedEventHandler ListChanged + { + add { } + remove { } + } + + public bool SupportsChangeNotification + { + get + { + return false; + } + } + + public void RemoveSort() + { + _sort = null; + _direction = ListSortDirection.Ascending; + } + + public object AddNew() + { + throw new NotSupportedException(); + } + + public bool AllowEdit + { + get + { + return false; + } + } + + public void RemoveIndex(PropertyDescriptor property) + { + } + + #endregion + + #region ITypedList Members + + public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors) + { + if (_properties == null) + { + PropertyDescriptor[] properties = new PropertyDescriptor[_csv.FieldCount]; + + for (int i = 0; i < properties.Length; i++) + properties[i] = new CsvPropertyDescriptor(((System.Data.IDataReader) _csv).GetName(i), i); + + _properties = new PropertyDescriptorCollection(properties); + } + + return _properties; + } + + public string GetListName(PropertyDescriptor[] listAccessors) + { + return string.Empty; + } + + #endregion + + #region IList Members + + public int IndexOf(string[] item) + { + throw new NotSupportedException(); + } + + public void Insert(int index, string[] item) + { + throw new NotSupportedException(); + } + + public void RemoveAt(int index) + { + throw new NotSupportedException(); + } + + public string[] this[int index] + { + get + { + _csv.MoveTo(index); + return _csv._records[index]; + } + set + { + throw new NotSupportedException(); + } + } + + #endregion + + #region ICollection Members + + public void Add(string[] item) + { + throw new NotSupportedException(); + } + + public void Clear() + { + throw new NotSupportedException(); + } + + public bool Contains(string[] item) + { + throw new NotSupportedException(); + } + + public void CopyTo(string[][] array, int arrayIndex) + { + _csv.MoveToStart(); + + while (_csv.ReadNextRecord()) + _csv.CopyCurrentRecordTo(array[arrayIndex++]); + } + + public int Count + { + get + { + if (_count < 0) + { + _csv.ReadToEnd(); + _count = (int) _csv.CurrentRecordIndex + 1; + } + + return _count; + } + } + + public bool IsReadOnly + { + get { return true; } + } + + public bool Remove(string[] item) + { + throw new NotSupportedException(); + } + + #endregion + + #region IEnumerable Members + + public IEnumerator GetEnumerator() + { + return _csv.GetEnumerator(); + } + + #endregion + + #region IList Members + + public int Add(object value) + { + throw new NotSupportedException(); + } + + public bool Contains(object value) + { + throw new NotSupportedException(); + } + + public int IndexOf(object value) + { + throw new NotSupportedException(); + } + + public void Insert(int index, object value) + { + throw new NotSupportedException(); + } + + public bool IsFixedSize + { + get { return true; } + } + + public void Remove(object value) + { + throw new NotSupportedException(); + } + + object IList.this[int index] + { + get + { + return this[index]; + } + set + { + throw new NotSupportedException(); + } + } + + #endregion + + #region ICollection Members + + public void CopyTo(Array array, int index) + { + _csv.MoveToStart(); + + while (_csv.ReadNextRecord()) + _csv.CopyCurrentRecordTo((string[]) array.GetValue(index++)); + } + + public bool IsSynchronized + { + get { return false; } + } + + public object SyncRoot + { + get { return null; } + } + + #endregion + + #region IEnumerable Members + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } + + #endregion + } + } +} \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CachedCsvReader.CsvPropertyDescriptor.cs gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CachedCsvReader.CsvPropertyDescriptor.cs --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CachedCsvReader.CsvPropertyDescriptor.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CachedCsvReader.CsvPropertyDescriptor.cs 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,126 @@ +// LumenWorks.Framework.IO.CSV.CachedCsvReader.CsvPropertyDescriptor +// Copyright (c) 2006 Sébastien Lorion +// +// MIT license (http://en.wikipedia.org/wiki/MIT_License) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.ComponentModel; + +namespace LumenWorks.Framework.IO.Csv +{ + public partial class CachedCsvReader + : CsvReader + { + /// + /// Represents a CSV field property descriptor. + /// + private class CsvPropertyDescriptor + : PropertyDescriptor + { + #region Fields + + /// + /// Contains the field index. + /// + private int _index; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the CsvPropertyDescriptor class. + /// + /// The field name. + /// The field index. + public CsvPropertyDescriptor(string fieldName, int index) + : base(fieldName, null) + { + _index = index; + } + + #endregion + + #region Properties + + /// + /// Gets the field index. + /// + /// The field index. + public int Index + { + get { return _index; } + } + + #endregion + + #region Overrides + + public override bool CanResetValue(object component) + { + return false; + } + + public override object GetValue(object component) + { + return ((string[]) component)[_index]; + } + + public override void ResetValue(object component) + { + } + + public override void SetValue(object component, object value) + { + } + + public override bool ShouldSerializeValue(object component) + { + return false; + } + + public override Type ComponentType + { + get + { + return typeof(CachedCsvReader); + } + } + + public override bool IsReadOnly + { + get + { + return true; + } + } + + public override Type PropertyType + { + get + { + return typeof(string); + } + } + + #endregion + } + } +} diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CachedCsvReader.CsvRecordComparer.cs gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CachedCsvReader.CsvRecordComparer.cs --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CachedCsvReader.CsvRecordComparer.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CachedCsvReader.CsvRecordComparer.cs 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,85 @@ +// LumenWorks.Framework.IO.CSV.CachedCsvReader.CsvRecordComparer +// Copyright (c) 2006 Sébastien Lorion +// +// MIT license (http://en.wikipedia.org/wiki/MIT_License) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using Debug = System.Diagnostics.Debug; +using System.Globalization; + +namespace LumenWorks.Framework.IO.Csv +{ + public partial class CachedCsvReader + : CsvReader + { + /// + /// Represents a CSV record comparer. + /// + private class CsvRecordComparer + : IComparer + { + #region Fields + + /// + /// Contains the field index of the values to compare. + /// + private int _field; + + /// + /// Contains the sort direction. + /// + private ListSortDirection _direction; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the CsvRecordComparer class. + /// + /// The field index of the values to compare. + /// The sort direction. + public CsvRecordComparer(int field, ListSortDirection direction) + { + if (field < 0) + throw new ArgumentOutOfRangeException("field", field, string.Format(CultureInfo.InvariantCulture, Resources.ExceptionMessage.FieldIndexOutOfRange, field)); + + _field = field; + _direction = direction; + } + + #endregion + + #region IComparer Members + + public int Compare(string[] x, string[] y) + { + Debug.Assert(x != null && y != null && x.Length == y.Length && _field < x.Length); + + int result = String.Compare(x[_field], y[_field], StringComparison.CurrentCulture); + + return (_direction == ListSortDirection.Ascending ? result : -result); + } + + #endregion + } + } +} \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CsvReader.cs gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CsvReader.cs --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CsvReader.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CsvReader.cs 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,2442 @@ +// LumenWorks.Framework.IO.CSV.CsvReader +// Copyright (c) 2005 Sébastien Lorion +// +// MIT license (http://en.wikipedia.org/wiki/MIT_License) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using Debug = System.Diagnostics.Debug; +using System.Globalization; +using System.IO; + +using LumenWorks.Framework.IO.Csv.Resources; + +namespace LumenWorks.Framework.IO.Csv +{ + /// + /// Represents a reader that provides fast, non-cached, forward-only access to CSV data. + /// + public partial class CsvReader + : IDataReader, IEnumerable, IDisposable + { + #region Constants + + /// + /// Defines the default buffer size. + /// + public const int DefaultBufferSize = 0x1000; + + /// + /// Defines the default delimiter character separating each field. + /// + public const char DefaultDelimiter = ','; + + /// + /// Defines the default quote character wrapping every field. + /// + public const char DefaultQuote = '"'; + + /// + /// Defines the default escape character letting insert quotation characters inside a quoted field. + /// + public const char DefaultEscape = '"'; + + /// + /// Defines the default comment character indicating that a line is commented out. + /// + public const char DefaultComment = '#'; + + #endregion + + #region Fields + + /// + /// Contains the field header comparer. + /// + private static readonly StringComparer _fieldHeaderComparer = StringComparer.CurrentCultureIgnoreCase; + + #region Settings + + /// + /// Contains the pointing to the CSV file. + /// + private TextReader _reader; + + /// + /// Contains the buffer size. + /// + private int _bufferSize; + + /// + /// Contains the comment character indicating that a line is commented out. + /// + private char _comment; + + /// + /// Contains the escape character letting insert quotation characters inside a quoted field. + /// + private char _escape; + + /// + /// Contains the delimiter character separating each field. + /// + private char _delimiter; + + /// + /// Contains the quotation character wrapping every field. + /// + private char _quote; + + /// + /// Indicates if spaces at the start and end of a field are trimmed. + /// + private bool _trimSpaces; + + /// + /// Indicates if field names are located on the first non commented line. + /// + private bool _hasHeaders; + + /// + /// Contains the default action to take when a parsing error has occured. + /// + private ParseErrorAction _defaultParseErrorAction; + + /// + /// Contains the action to take when a field is missing. + /// + private MissingFieldAction _missingFieldAction; + + /// + /// Indicates if the reader supports multiline. + /// + private bool _supportsMultiline; + + /// + /// Indicates if the reader will skip empty lines. + /// + private bool _skipEmptyLines; + + #endregion + + #region State + + /// + /// Indicates if the class is initialized. + /// + private bool _initialized; + + /// + /// Contains the field headers. + /// + private string[] _fieldHeaders; + + /// + /// Contains the dictionary of field indexes by header. The key is the field name and the value is its index. + /// + private Dictionary _fieldHeaderIndexes; + + /// + /// Contains the current record index in the CSV file. + /// A value of means that the reader has not been initialized yet. + /// Otherwise, a negative value means that no record has been read yet. + /// + private long _currentRecordIndex; + + /// + /// Contains the starting position of the next unread field. + /// + private int _nextFieldStart; + + /// + /// Contains the index of the next unread field. + /// + private int _nextFieldIndex; + + /// + /// Contains the array of the field values for the current record. + /// A null value indicates that the field have not been parsed. + /// + private string[] _fields; + + /// + /// Contains the maximum number of fields to retrieve for each record. + /// + private int _fieldCount; + + /// + /// Contains the read buffer. + /// + private char[] _buffer; + + /// + /// Contains the current read buffer length. + /// + private int _bufferLength; + + /// + /// Indicates if the end of the reader has been reached. + /// + private bool _eof; + + /// + /// Indicates if the last read operation reached an EOL character. + /// + private bool _eol; + + /// + /// Indicates if the first record is in cache. + /// This can happen when initializing a reader with no headers + /// because one record must be read to get the field count automatically + /// + private bool _firstRecordInCache; + + /// + /// Indicates if one or more field are missing for the current record. + /// Resets after each successful record read. + /// + private bool _missingFieldFlag; + + /// + /// Indicates if a parse error occured for the current record. + /// Resets after each successful record read. + /// + private bool _parseErrorFlag; + + #endregion + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the CsvReader class. + /// + /// A pointing to the CSV file. + /// if field names are located on the first non commented line, otherwise, . + /// + /// is a . + /// + /// + /// Cannot read from . + /// + public CsvReader(TextReader reader, bool hasHeaders) + : this(reader, hasHeaders, DefaultDelimiter, DefaultQuote, DefaultEscape, DefaultComment, true, DefaultBufferSize) + { + } + + /// + /// Initializes a new instance of the CsvReader class. + /// + /// A pointing to the CSV file. + /// if field names are located on the first non commented line, otherwise, . + /// The buffer size in bytes. + /// + /// is a . + /// + /// + /// Cannot read from . + /// + public CsvReader(TextReader reader, bool hasHeaders, int bufferSize) + : this(reader, hasHeaders, DefaultDelimiter, DefaultQuote, DefaultEscape, DefaultComment, true, bufferSize) + { + } + + /// + /// Initializes a new instance of the CsvReader class. + /// + /// A pointing to the CSV file. + /// if field names are located on the first non commented line, otherwise, . + /// The delimiter character separating each field (default is ','). + /// + /// is a . + /// + /// + /// Cannot read from . + /// + public CsvReader(TextReader reader, bool hasHeaders, char delimiter) + : this(reader, hasHeaders, delimiter, DefaultQuote, DefaultEscape, DefaultComment, true, DefaultBufferSize) + { + } + + /// + /// Initializes a new instance of the CsvReader class. + /// + /// A pointing to the CSV file. + /// if field names are located on the first non commented line, otherwise, . + /// The delimiter character separating each field (default is ','). + /// The buffer size in bytes. + /// + /// is a . + /// + /// + /// Cannot read from . + /// + public CsvReader(TextReader reader, bool hasHeaders, char delimiter, int bufferSize) + : this(reader, hasHeaders, delimiter, DefaultQuote, DefaultEscape, DefaultComment, true, bufferSize) + { + } + + /// + /// Initializes a new instance of the CsvReader class. + /// + /// A pointing to the CSV file. + /// if field names are located on the first non commented line, otherwise, . + /// The delimiter character separating each field (default is ','). + /// The quotation character wrapping every field (default is '''). + /// + /// The escape character letting insert quotation characters inside a quoted field (default is '\'). + /// If no escape character, set to '\0' to gain some performance. + /// + /// The comment character indicating that a line is commented out (default is '#'). + /// if spaces at the start and end of a field are trimmed, otherwise, . Default is . + /// + /// is a . + /// + /// + /// Cannot read from . + /// + public CsvReader(TextReader reader, bool hasHeaders, char delimiter, char quote, char escape, char comment, bool trimSpaces) + : this(reader, hasHeaders, delimiter, quote, escape, comment, trimSpaces, DefaultBufferSize) + { + } + + /// + /// Initializes a new instance of the CsvReader class. + /// + /// A pointing to the CSV file. + /// if field names are located on the first non commented line, otherwise, . + /// The delimiter character separating each field (default is ','). + /// The quotation character wrapping every field (default is '''). + /// + /// The escape character letting insert quotation characters inside a quoted field (default is '\'). + /// If no escape character, set to '\0' to gain some performance. + /// + /// The comment character indicating that a line is commented out (default is '#'). + /// if spaces at the start and end of a field are trimmed, otherwise, . Default is . + /// The buffer size in bytes. + /// + /// is a . + /// + /// + /// must be 1 or more. + /// + public CsvReader(TextReader reader, bool hasHeaders, char delimiter, char quote, char escape, char comment, bool trimSpaces, int bufferSize) + { +#if DEBUG + _allocStack = new System.Diagnostics.StackTrace(); +#endif + + if (reader == null) + throw new ArgumentNullException("reader"); + + if (bufferSize <= 0) + throw new ArgumentOutOfRangeException("bufferSize", bufferSize, ExceptionMessage.BufferSizeTooSmall); + + _bufferSize = bufferSize; + + if (reader is StreamReader) + { + Stream stream = ((StreamReader) reader).BaseStream; + + if (stream.CanSeek) + { + // Handle bad implementations returning 0 or less + if (stream.Length > 0) + _bufferSize = (int) Math.Min(bufferSize, stream.Length); + } + } + + _reader = reader; + _delimiter = delimiter; + _quote = quote; + _escape = escape; + _comment = comment; + + _hasHeaders = hasHeaders; + _trimSpaces = trimSpaces; + _supportsMultiline = true; + _skipEmptyLines = true; + + _currentRecordIndex = -1; + _defaultParseErrorAction = ParseErrorAction.RaiseEvent; + } + + #endregion + + #region Events + + /// + /// Occurs when there is an error while parsing the CSV stream. + /// + public event EventHandler ParseError; + + /// + /// Raises the event. + /// + /// The that contains the event data. + protected virtual void OnParseError(ParseErrorEventArgs e) + { + EventHandler handler = ParseError; + + if (handler != null) + handler(this, e); + } + + #endregion + + #region Properties + + #region Settings + + /// + /// Gets the comment character indicating that a line is commented out. + /// + /// The comment character indicating that a line is commented out. + public char Comment + { + get + { + return _comment; + } + } + + /// + /// Gets the escape character letting insert quotation characters inside a quoted field. + /// + /// The escape character letting insert quotation characters inside a quoted field. + public char Escape + { + get + { + return _escape; + } + } + + /// + /// Gets the delimiter character separating each field. + /// + /// The delimiter character separating each field. + public char Delimiter + { + get + { + return _delimiter; + } + } + + /// + /// Gets the quotation character wrapping every field. + /// + /// The quotation character wrapping every field. + public char Quote + { + get + { + return _quote; + } + } + + /// + /// Indicates if field names are located on the first non commented line. + /// + /// if field names are located on the first non commented line, otherwise, . + public bool HasHeaders + { + get + { + return _hasHeaders; + } + } + + /// + /// Indicates if spaces at the start and end of a field are trimmed. + /// + /// if spaces at the start and end of a field are trimmed, otherwise, . + public bool TrimSpaces + { + get + { + return _trimSpaces; + } + } + + /// + /// Gets the buffer size. + /// + public int BufferSize + { + get + { + return _bufferSize; + } + } + + /// + /// Gets or sets the default action to take when a parsing error has occured. + /// + /// The default action to take when a parsing error has occured. + public ParseErrorAction DefaultParseErrorAction + { + get + { + return _defaultParseErrorAction; + } + set + { + _defaultParseErrorAction = value; + } + } + + /// + /// Gets or sets the action to take when a field is missing. + /// + /// The action to take when a field is missing. + public MissingFieldAction MissingFieldAction + { + get + { + return _missingFieldAction; + } + set + { + _missingFieldAction = value; + } + } + + /// + /// Gets or sets a value indicating if the reader supports multiline fields. + /// + /// A value indicating if the reader supports multiline field. + public bool SupportsMultiline + { + get + { + return _supportsMultiline; + } + set + { + _supportsMultiline = value; + } + } + + /// + /// Gets or sets a value indicating if the reader will skip empty lines. + /// + /// A value indicating if the reader will skip empty lines. + public bool SkipEmptyLines + { + get + { + return _skipEmptyLines; + } + set + { + _skipEmptyLines = value; + } + } + + #endregion + + #region State + + /// + /// Gets the maximum number of fields to retrieve for each record. + /// + /// The maximum number of fields to retrieve for each record. + /// + /// The instance has been disposed of. + /// + public int FieldCount + { + get + { + EnsureInitialize(); + return _fieldCount; + } + } + + /// + /// Gets a value that indicates whether the current stream position is at the end of the stream. + /// + /// if the current stream position is at the end of the stream; otherwise . + public virtual bool EndOfStream + { + get + { + return _eof; + } + } + + /// + /// Gets the field headers. + /// + /// The field headers or an empty array if headers are not supported. + /// + /// The instance has been disposed of. + /// + public string[] GetFieldHeaders() + { + EnsureInitialize(); + Debug.Assert(_fieldHeaders != null, "Field headers must be non null."); + + string[] fieldHeaders = new string[_fieldHeaders.Length]; + + for (int i = 0; i < fieldHeaders.Length; i++) + fieldHeaders[i] = _fieldHeaders[i]; + + return fieldHeaders; + } + + /// + /// Gets the current record index in the CSV file. + /// + /// The current record index in the CSV file. + public virtual long CurrentRecordIndex + { + get + { + return _currentRecordIndex; + } + } + + /// + /// Indicates if one or more field are missing for the current record. + /// Resets after each successful record read. + /// + public bool MissingFieldFlag + { + get { return _missingFieldFlag; } + } + + /// + /// Indicates if a parse error occured for the current record. + /// Resets after each successful record read. + /// + public bool ParseErrorFlag + { + get { return _parseErrorFlag; } + } + + #endregion + + #endregion + + #region Indexers + + /// + /// Gets the field with the specified name and record position. must be . + /// + /// + /// The field with the specified name and record position. + /// + /// + /// is or an empty string. + /// + /// + /// The CSV does not have headers ( property is ). + /// + /// + /// not found. + /// + /// + /// Record index must be > 0. + /// + /// + /// Cannot move to a previous record in forward-only mode. + /// + /// + /// Cannot read record at . + /// + /// + /// The CSV appears to be corrupt at the current position. + /// + /// + /// The instance has been disposed of. + /// + public string this[int record, string field] + { + get + { + MoveTo(record); + return this[field]; + } + } + + /// + /// Gets the field at the specified index and record position. + /// + /// + /// The field at the specified index and record position. + /// A is returned if the field cannot be found for the record. + /// + /// + /// must be included in [0, [. + /// + /// + /// Record index must be > 0. + /// + /// + /// Cannot move to a previous record in forward-only mode. + /// + /// + /// Cannot read record at . + /// + /// + /// The CSV appears to be corrupt at the current position. + /// + /// + /// The instance has been disposed of. + /// + public string this[int record, int field] + { + get + { + MoveTo(record); + return this[field]; + } + } + + /// + /// Gets the field with the specified name. must be . + /// + /// + /// The field with the specified name. + /// + /// + /// is or an empty string. + /// + /// + /// The CSV does not have headers ( property is ). + /// + /// + /// not found. + /// + /// + /// The CSV appears to be corrupt at the current position. + /// + /// + /// The instance has been disposed of. + /// + public string this[string field] + { + get + { + if (string.IsNullOrEmpty(field)) + throw new ArgumentNullException("field"); + + if (!_hasHeaders) + throw new InvalidOperationException(ExceptionMessage.NoHeaders); + + int index = GetFieldIndex(field); + + if (index < 0) + throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, ExceptionMessage.FieldHeaderNotFound, field), "field"); + + return this[index]; + } + } + + /// + /// Gets the field at the specified index. + /// + /// The field at the specified index. + /// + /// must be included in [0, [. + /// + /// + /// No record read yet. Call ReadLine() first. + /// + /// + /// The CSV appears to be corrupt at the current position. + /// + /// + /// The instance has been disposed of. + /// + public virtual string this[int field] + { + get + { + return ReadField(field, false, false); + } + } + + #endregion + + #region Methods + + #region EnsureInitialize + + /// + /// Ensures that the reader is initialized. + /// + private void EnsureInitialize() + { + if (!_initialized) + this.ReadNextRecord(true, false); + + Debug.Assert(_fieldHeaders != null); + Debug.Assert(_fieldHeaders.Length > 0 || (_fieldHeaders.Length == 0 && _fieldHeaderIndexes == null)); + } + + #endregion + + #region GetFieldIndex + + /// + /// Gets the field index for the provided header. + /// + /// The header to look for. + /// The field index for the provided header. -1 if not found. + /// + /// The instance has been disposed of. + /// + public int GetFieldIndex(string header) + { + EnsureInitialize(); + + int index; + + if (_fieldHeaderIndexes != null && _fieldHeaderIndexes.TryGetValue(header, out index)) + return index; + else + return -1; + } + + #endregion + + #region CopyCurrentRecordTo + + /// + /// Copies the field array of the current record to a one-dimensional array, starting at the beginning of the target array. + /// + /// The one-dimensional that is the destination of the fields of the current record. + /// + /// is . + /// + /// + /// The number of fields in the record is greater than the available space from to the end of . + /// + public void CopyCurrentRecordTo(string[] array) + { + CopyCurrentRecordTo(array, 0); + } + + /// + /// Copies the field array of the current record to a one-dimensional array, starting at the beginning of the target array. + /// + /// The one-dimensional that is the destination of the fields of the current record. + /// The zero-based index in at which copying begins. + /// + /// is . + /// + /// + /// is les than zero or is equal to or greater than the length . + /// + /// + /// No current record. + /// + /// + /// The number of fields in the record is greater than the available space from to the end of . + /// + public void CopyCurrentRecordTo(string[] array, int index) + { + if (array == null) + throw new ArgumentNullException("array"); + + if (index < 0 || index >= array.Length) + throw new ArgumentOutOfRangeException("index", index, string.Empty); + + if (_currentRecordIndex < 0 || !_initialized) + throw new InvalidOperationException(ExceptionMessage.NoCurrentRecord); + + if (array.Length - index < _fieldCount) + throw new ArgumentException(ExceptionMessage.NotEnoughSpaceInArray, "array"); + + for (int i = 0; i < _fieldCount; i++) + { + if (_parseErrorFlag) + array[index + i] = null; + else + array[index + i] = this[i]; + } + } + + #endregion + + #region GetCurrentRawData + + /// + /// Gets the current raw CSV data. + /// + /// Used for exception handling purpose. + /// The current raw CSV data. + public string GetCurrentRawData() + { + if (_buffer != null && _bufferLength > 0) + return new string(_buffer, 0, _bufferLength); + else + return string.Empty; + } + + #endregion + + #region IsWhiteSpace + + /// + /// Indicates whether the specified Unicode character is categorized as white space. + /// + /// A Unicode character. + /// if is white space; otherwise, . + private bool IsWhiteSpace(char c) + { + // Handle cases where the delimiter is a whitespace (e.g. tab) + if (c == _delimiter) + return false; + else + { + // See char.IsLatin1(char c) in Reflector + if (c <= '\x00ff') + return (c == ' ' || c == '\t'); + else + return (System.Globalization.CharUnicodeInfo.GetUnicodeCategory(c) == System.Globalization.UnicodeCategory.SpaceSeparator); + } + } + + #endregion + + #region MoveTo + + /// + /// Moves to the specified record index. + /// + /// The record index. + /// + /// Record index must be > 0. + /// + /// + /// Cannot move to a previous record in forward-only mode. + /// + /// + /// The instance has been disposed of. + /// + public virtual void MoveTo(long record) + { + if (record < 0) + throw new ArgumentOutOfRangeException("record", record, ExceptionMessage.RecordIndexLessThanZero); + + if (record < _currentRecordIndex) + throw new InvalidOperationException(ExceptionMessage.CannotMovePreviousRecordInForwardOnly); + + // Get number of record to read + + long offset = record - _currentRecordIndex; + + if (offset > 0) + { + do + { + if (!ReadNextRecord()) + throw new EndOfStreamException(string.Format(CultureInfo.InvariantCulture, ExceptionMessage.CannotReadRecordAtIndex, _currentRecordIndex - offset)); + } + while (--offset > 0); + } + } + + #endregion + + #region ParseNewLine + + /// + /// Parses a new line delimiter. + /// + /// The starting position of the parsing. Will contain the resulting end position. + /// if a new line delimiter was found; otherwise, . + /// + /// The instance has been disposed of. + /// + private bool ParseNewLine(ref int pos) + { + Debug.Assert(pos <= _bufferLength); + + // Check if already at the end of the buffer + if (pos == _bufferLength) + { + pos = 0; + + if (!ReadBuffer()) + return false; + } + + char c = _buffer[pos]; + + // Treat \r as new line only if it's not the delimiter + + if (c == '\r' && _delimiter != '\r') + { + pos++; + + // Skip following \n (if there is one) + + if (pos < _bufferLength) + { + if (_buffer[pos] == '\n') + pos++; + } + else + { + if (ReadBuffer()) + { + if (_buffer[0] == '\n') + pos = 1; + else + pos = 0; + } + } + + if (pos >= _bufferLength) + { + ReadBuffer(); + pos = 0; + } + + return true; + } + else if (c == '\n') + { + pos++; + + if (pos >= _bufferLength) + { + ReadBuffer(); + pos = 0; + } + + return true; + } + + return false; + } + + /// + /// Determines whether the character at the specified position is a new line delimiter. + /// + /// The position of the character to verify. + /// + /// if the character at the specified position is a new line delimiter; otherwise, . + /// + private bool IsNewLine(int pos) + { + Debug.Assert(pos < _bufferLength); + + char c = _buffer[pos]; + + if (c == '\n') + return true; + else if (c == '\r' && _delimiter != '\r') + return true; + else + return false; + } + + #endregion + + #region ReadBuffer + + /// + /// Fills the buffer with data from the reader. + /// + /// if data was successfully read; otherwise, . + /// + /// The instance has been disposed of. + /// + private bool ReadBuffer() + { + if (_eof) + return false; + + CheckDisposed(); + + _bufferLength = _reader.Read(_buffer, 0, _bufferSize); + + if (_bufferLength > 0) + return true; + else + { + _eof = true; + _buffer = null; + + return false; + } + } + + #endregion + + #region ReadField + + /// + /// Reads the field at the specified index. + /// Any unread fields with an inferior index will also be read as part of the required parsing. + /// + /// The field index. + /// Indicates if the reader is currently initializing. + /// Indicates if the value(s) are discarded. + /// + /// The field at the specified index. + /// A indicates that an error occured or that the last field has been reached during initialization. + /// + /// + /// is out of range. + /// + /// + /// There is no current record. + /// + /// + /// The CSV data appears to be missing a field. + /// + /// + /// The CSV data appears to be malformed. + /// + /// + /// The instance has been disposed of. + /// + private string ReadField(int field, bool initializing, bool discardValue) + { + if (!initializing) + { + if (field < 0 || field >= _fieldCount) + throw new ArgumentOutOfRangeException("field", field, string.Format(CultureInfo.InvariantCulture, ExceptionMessage.FieldIndexOutOfRange, field)); + + if (_currentRecordIndex < 0) + throw new InvalidOperationException(ExceptionMessage.NoCurrentRecord); + + // Directly return field if cached + if (_fields[field] != null) + return _fields[field]; + else if (_missingFieldFlag) + return HandleMissingField(null, field, ref _nextFieldStart); + } + + CheckDisposed(); + + int index = _nextFieldIndex; + + while (index < field + 1) + { + // Handle case where stated start of field is past buffer + // This can occur because _nextFieldStart is simply 1 + last char position of previous field + if (_nextFieldStart == _bufferLength) + { + _nextFieldStart = 0; + + // Possible EOF will be handled later (see Handle_EOF1) + ReadBuffer(); + } + + string value = null; + + if (_missingFieldFlag) + { + value = HandleMissingField(value, index, ref _nextFieldStart); + } + else if (_nextFieldStart == _bufferLength) + { + // Handle_EOF1: Handle EOF here + + // If current field is the requested field, then the value of the field is "" as in "f1,f2,f3,(\s*)" + // otherwise, the CSV is malformed + + if (index == field) + { + if (!discardValue) + { + value = string.Empty; + _fields[index] = value; + } + } + else + { + value = HandleMissingField(value, index, ref _nextFieldStart); + } + } + else + { + // Trim spaces at start + if (_trimSpaces) + SkipWhiteSpaces(ref _nextFieldStart); + + if (_eof) + value = string.Empty; + else if (_buffer[_nextFieldStart] != _quote) + { + // Non-quoted field + + int start = _nextFieldStart; + int pos = _nextFieldStart; + + for (; ; ) + { + while (pos < _bufferLength) + { + char c = _buffer[pos]; + + if (c == _delimiter) + { + _nextFieldStart = pos + 1; + + break; + } + else if (c == '\r' || c == '\n') + { + _nextFieldStart = pos; + _eol = true; + + break; + } + else + pos++; + } + + if (pos < _bufferLength) + break; + else + { + if (!discardValue) + value += new string(_buffer, start, pos - start); + + start = 0; + pos = 0; + _nextFieldStart = 0; + + if (!ReadBuffer()) + break; + } + } + + if (!discardValue) + { + if (!_trimSpaces) + { + if (!_eof && pos > start) + value += new string(_buffer, start, pos - start); + } + else + { + if (!_eof && pos > start) + { + // Do the trimming + pos--; + while (pos > -1 && IsWhiteSpace(_buffer[pos])) + pos--; + pos++; + + if (pos > 0) + value += new string(_buffer, start, pos - start); + } + else + pos = -1; + + // If pos <= 0, that means the trimming went past buffer start, + // and the concatenated value needs to be trimmed too. + if (pos <= 0) + { + pos = (value == null ? -1 : value.Length - 1); + + // Do the trimming + while (pos > -1 && IsWhiteSpace(value[pos])) + pos--; + + pos++; + + if (pos > 0 && pos != value.Length) + value = value.Substring(0, pos); + } + } + + if (value == null) + value = string.Empty; + } + + if (_eol || _eof) + { + _eol = ParseNewLine(ref _nextFieldStart); + + // Reaching a new line is ok as long as the parser is initializing or it is the last field + if (!initializing && index != _fieldCount - 1) + { + if (value != null && value.Length == 0) + value = null; + + value = HandleMissingField(value, index, ref _nextFieldStart); + } + } + + if (!discardValue) + _fields[index] = value; + } + else + { + // Quoted field + + // Skip quote + int start = _nextFieldStart + 1; + int pos = start; + + bool quoted = true; + bool escaped = false; + + for (; ; ) + { + while (pos < _bufferLength) + { + char c = _buffer[pos]; + + if (escaped) + { + escaped = false; + start = pos; + } + // IF current char is escape AND (escape and quote are different OR next char is a quote) + else if (c == _escape && (_escape != _quote || (pos + 1 < _bufferLength && _buffer[pos + 1] == _quote) || (pos + 1 == _bufferLength && _reader.Peek() == _quote))) + { + if (!discardValue) + value += new string(_buffer, start, pos - start); + + escaped = true; + } + else if (c == _quote) + { + quoted = false; + break; + } + + pos++; + } + + if (!quoted) + break; + else + { + if (!discardValue && !escaped) + value += new string(_buffer, start, pos - start); + + start = 0; + pos = 0; + _nextFieldStart = 0; + + if (!ReadBuffer()) + { + HandleParseError(new MalformedCsvException(GetCurrentRawData(), _nextFieldStart, Math.Max(0, _currentRecordIndex), index), ref _nextFieldStart); + return null; + } + } + } + + if (!_eof) + { + // Append remaining parsed buffer content + if (!discardValue && pos > start) + value += new string(_buffer, start, pos - start); + + // Skip quote + _nextFieldStart = pos + 1; + + // Skip whitespaces between the quote and the delimiter/eol + SkipWhiteSpaces(ref _nextFieldStart); + + // Skip delimiter + bool delimiterSkipped; + if (_nextFieldStart < _bufferLength && _buffer[_nextFieldStart] == _delimiter) + { + _nextFieldStart++; + delimiterSkipped = true; + } + else + { + delimiterSkipped = false; + } + + // Skip new line delimiter if initializing or last field + // (if the next field is missing, it will be caught when parsed) + if (!_eof && !delimiterSkipped && (initializing || index == _fieldCount - 1)) + _eol = ParseNewLine(ref _nextFieldStart); + + // If no delimiter is present after the quoted field and it is not the last field, then it is a parsing error + if (!delimiterSkipped && !_eof && !(_eol || IsNewLine(_nextFieldStart))) + HandleParseError(new MalformedCsvException(GetCurrentRawData(), _nextFieldStart, Math.Max(0, _currentRecordIndex), index), ref _nextFieldStart); + } + + if (!discardValue) + { + if (value == null) + value = string.Empty; + + _fields[index] = value; + } + } + } + + _nextFieldIndex = Math.Max(index + 1, _nextFieldIndex); + + if (index == field) + { + // If initializing, return null to signify the last field has been reached + + if (initializing) + { + if (_eol || _eof) + return null; + else + return string.IsNullOrEmpty(value) ? string.Empty : value; + } + else + return value; + } + + index++; + } + + // Getting here is bad ... + HandleParseError(new MalformedCsvException(GetCurrentRawData(), _nextFieldStart, Math.Max(0, _currentRecordIndex), index), ref _nextFieldStart); + return null; + } + + #endregion + + #region ReadNextRecord + + /// + /// Reads the next record. + /// + /// if a record has been successfully reads; otherwise, . + /// + /// The instance has been disposed of. + /// + public bool ReadNextRecord() + { + return ReadNextRecord(false, false); + } + + /// + /// Reads the next record. + /// + /// + /// Indicates if the reader will proceed to the next record after having read headers. + /// if it stops after having read headers; otherwise, . + /// + /// + /// Indicates if the reader will skip directly to the next line without parsing the current one. + /// To be used when an error occurs. + /// + /// if a record has been successfully reads; otherwise, . + /// + /// The instance has been disposed of. + /// + protected virtual bool ReadNextRecord(bool onlyReadHeaders, bool skipToNextLine) + { + if (_eof) + { + if (_firstRecordInCache) + { + _firstRecordInCache = false; + _currentRecordIndex++; + + return true; + } + else + return false; + } + + CheckDisposed(); + + if (!_initialized) + { + _buffer = new char[_bufferSize]; + + // will be replaced if and when headers are read + _fieldHeaders = new string[0]; + + if (!ReadBuffer()) + return false; + + if (!SkipEmptyAndCommentedLines(ref _nextFieldStart)) + return false; + + // Keep growing _fields array until the last field has been found + // and then resize it to its final correct size + + _fieldCount = 0; + _fields = new string[16]; + + while (ReadField(_fieldCount, true, false) != null) + { + if (_parseErrorFlag) + { + _fieldCount = 0; + Array.Clear(_fields, 0, _fields.Length); + _parseErrorFlag = false; + _nextFieldIndex = 0; + } + else + { + _fieldCount++; + + if (_fieldCount == _fields.Length) + Array.Resize(ref _fields, (_fieldCount + 1) * 2); + } + } + + // _fieldCount contains the last field index, but it must contains the field count, + // so increment by 1 + _fieldCount++; + + if (_fields.Length != _fieldCount) + Array.Resize(ref _fields, _fieldCount); + + _initialized = true; + + // If headers are present, call ReadNextRecord again + if (_hasHeaders) + { + // Don't count first record as it was the headers + _currentRecordIndex = -1; + + _firstRecordInCache = false; + + _fieldHeaders = new string[_fieldCount]; + _fieldHeaderIndexes = new Dictionary(_fieldCount, _fieldHeaderComparer); + + for (int i = 0; i < _fields.Length; i++) + { + _fieldHeaders[i] = _fields[i]; + _fieldHeaderIndexes.Add(_fields[i], i); + } + + // Proceed to first record + if (!onlyReadHeaders) + { + // Calling again ReadNextRecord() seems to be simpler, + // but in fact would probably cause many subtle bugs because the derived does not expect a recursive behavior + // so simply do what is needed here and no more. + + if (!SkipEmptyAndCommentedLines(ref _nextFieldStart)) + return false; + + Array.Clear(_fields, 0, _fields.Length); + _nextFieldIndex = 0; + _eol = false; + + _currentRecordIndex++; + return true; + } + } + else + { + if (onlyReadHeaders) + { + _firstRecordInCache = true; + _currentRecordIndex = -1; + } + else + { + _firstRecordInCache = false; + _currentRecordIndex = 0; + } + } + } + else + { + if (skipToNextLine) + SkipToNextLine(ref _nextFieldStart); + else if (_currentRecordIndex > -1 && !_missingFieldFlag) + { + // If not already at end of record, move there + if (!_eol && !_eof) + { + if (!_supportsMultiline) + SkipToNextLine(ref _nextFieldStart); + else + { + // a dirty trick to handle the case where extra fields are present + while (ReadField(_nextFieldIndex, true, true) != null) + { + } + } + } + } + + if (!_firstRecordInCache && !SkipEmptyAndCommentedLines(ref _nextFieldStart)) + return false; + + if (_hasHeaders || !_firstRecordInCache) + _eol = false; + + // Check to see if the first record is in cache. + // This can happen when initializing a reader with no headers + // because one record must be read to get the field count automatically + if (_firstRecordInCache) + _firstRecordInCache = false; + else + { + Array.Clear(_fields, 0, _fields.Length); + _nextFieldIndex = 0; + } + + _missingFieldFlag = false; + _parseErrorFlag = false; + _currentRecordIndex++; + } + + return true; + } + + #endregion + + #region SkipEmptyAndCommentedLines + + /// + /// Skips empty and commented lines. + /// If the end of the buffer is reached, its content be discarded and filled again from the reader. + /// + /// + /// The position in the buffer where to start parsing. + /// Will contains the resulting position after the operation. + /// + /// if the end of the reader has not been reached; otherwise, . + /// + /// The instance has been disposed of. + /// + private bool SkipEmptyAndCommentedLines(ref int pos) + { + if (pos < _bufferLength) + DoSkipEmptyAndCommentedLines(ref pos); + + while (pos >= _bufferLength && !_eof) + { + if (ReadBuffer()) + { + pos = 0; + DoSkipEmptyAndCommentedLines(ref pos); + } + else + return false; + } + + return !_eof; + } + + /// + /// Worker method. + /// Skips empty and commented lines. + /// + /// + /// The position in the buffer where to start parsing. + /// Will contains the resulting position after the operation. + /// + /// + /// The instance has been disposed of. + /// + private void DoSkipEmptyAndCommentedLines(ref int pos) + { + while (pos < _bufferLength) + { + if (_buffer[pos] == _comment) + { + pos++; + SkipToNextLine(ref pos); + } + else if (_skipEmptyLines && ParseNewLine(ref pos)) + continue; + else + break; + } + } + + #endregion + + #region SkipWhiteSpaces + + /// + /// Skips whitespace characters. + /// + /// The starting position of the parsing. Will contain the resulting end position. + /// if the end of the reader has not been reached; otherwise, . + /// + /// The instance has been disposed of. + /// + private bool SkipWhiteSpaces(ref int pos) + { + for (; ; ) + { + while (pos < _bufferLength && IsWhiteSpace(_buffer[pos])) + pos++; + + if (pos < _bufferLength) + break; + else + { + pos = 0; + + if (!ReadBuffer()) + return false; + } + } + + return true; + } + + #endregion + + #region SkipToNextLine + + /// + /// Skips ahead to the next NewLine character. + /// If the end of the buffer is reached, its content be discarded and filled again from the reader. + /// + /// + /// The position in the buffer where to start parsing. + /// Will contains the resulting position after the operation. + /// + /// if the end of the reader has not been reached; otherwise, . + /// + /// The instance has been disposed of. + /// + private bool SkipToNextLine(ref int pos) + { + // ((pos = 0) == 0) is a little trick to reset position inline + while ((pos < _bufferLength || (ReadBuffer() && ((pos = 0) == 0))) && !ParseNewLine(ref pos)) + pos++; + + return !_eof; + } + + #endregion + + #region HandleParseError + + /// + /// Handles a parsing error. + /// + /// The parsing error that occured. + /// The current position in the buffer. + /// + /// is . + /// + private void HandleParseError(MalformedCsvException error, ref int pos) + { + if (error == null) + throw new ArgumentNullException("error"); + + _parseErrorFlag = true; + + switch (_defaultParseErrorAction) + { + case ParseErrorAction.ThrowException: + throw error; + + case ParseErrorAction.RaiseEvent: + ParseErrorEventArgs e = new ParseErrorEventArgs(error, ParseErrorAction.ThrowException); + OnParseError(e); + + switch (e.Action) + { + case ParseErrorAction.ThrowException: + throw e.Error; + + case ParseErrorAction.RaiseEvent: + throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, ExceptionMessage.ParseErrorActionInvalidInsideParseErrorEvent, e.Action), e.Error); + + case ParseErrorAction.AdvanceToNextLine: + // already at EOL when fields are missing, so don't skip to next line in that case + if (!_missingFieldFlag && pos >= 0) + SkipToNextLine(ref pos); + break; + + default: + throw new NotSupportedException(string.Format(CultureInfo.InvariantCulture, ExceptionMessage.ParseErrorActionNotSupported, e.Action), e.Error); + } + break; + + case ParseErrorAction.AdvanceToNextLine: + // already at EOL when fields are missing, so don't skip to next line in that case + if (!_missingFieldFlag && pos >= 0) + SkipToNextLine(ref pos); + break; + + default: + throw new NotSupportedException(string.Format(CultureInfo.InvariantCulture, ExceptionMessage.ParseErrorActionNotSupported, _defaultParseErrorAction), error); + } + } + + #endregion + + #region HandleMissingField + + /// + /// Handles a missing field error. + /// + /// The partially parsed value, if available. + /// The missing field index. + /// The current position in the raw data. + /// + /// The resulting value according to . + /// If the action is set to , + /// then the parse error will be handled according to . + /// + private string HandleMissingField(string value, int fieldIndex, ref int currentPosition) + { + if (fieldIndex < 0 || fieldIndex >= _fieldCount) + throw new ArgumentOutOfRangeException("fieldIndex", fieldIndex, string.Format(CultureInfo.InvariantCulture, ExceptionMessage.FieldIndexOutOfRange, fieldIndex)); + + _missingFieldFlag = true; + + for (int i = fieldIndex + 1; i < _fieldCount; i++) + _fields[i] = null; + + if (value != null) + return value; + else + { + switch (_missingFieldAction) + { + case MissingFieldAction.ParseError: + HandleParseError(new MissingFieldCsvException(GetCurrentRawData(), currentPosition, Math.Max(0, _currentRecordIndex), fieldIndex), ref currentPosition); + return value; + + case MissingFieldAction.ReplaceByEmpty: + return string.Empty; + + case MissingFieldAction.ReplaceByNull: + return null; + + default: + throw new NotSupportedException(string.Format(CultureInfo.InvariantCulture, ExceptionMessage.MissingFieldActionNotSupported, _missingFieldAction)); + } + } + } + + #endregion + + #endregion + + #region IDataReader support methods + + /// + /// Validates the state of the data reader. + /// + /// The validations to accomplish. + /// + /// No current record. + /// + /// + /// This operation is invalid when the reader is closed. + /// + private void ValidateDataReader(DataReaderValidations validations) + { + if ((validations & DataReaderValidations.IsInitialized) != 0 && !_initialized) + throw new InvalidOperationException(ExceptionMessage.NoCurrentRecord); + + if ((validations & DataReaderValidations.IsNotClosed) != 0 && _isDisposed) + throw new InvalidOperationException(ExceptionMessage.ReaderClosed); + } + + /// + /// Copy the value of the specified field to an array. + /// + /// The index of the field. + /// The offset in the field value. + /// The destination array where the field value will be copied. + /// The destination array offset. + /// The number of characters to copy from the field value. + /// + private long CopyFieldToArray(int field, long fieldOffset, Array destinationArray, int destinationOffset, int length) + { + EnsureInitialize(); + + if (field < 0 || field >= _fieldCount) + throw new ArgumentOutOfRangeException("field", field, string.Format(CultureInfo.InvariantCulture, ExceptionMessage.FieldIndexOutOfRange, field)); + + if (fieldOffset < 0 || fieldOffset >= int.MaxValue) + throw new ArgumentOutOfRangeException("fieldOffset"); + + // Array.Copy(...) will do the remaining argument checks + + if (length == 0) + return 0; + + string value = this[field]; + + if (value == null) + value = string.Empty; + + Debug.Assert(fieldOffset < int.MaxValue); + + Debug.Assert(destinationArray.GetType() == typeof(char[]) || destinationArray.GetType() == typeof(byte[])); + + if (destinationArray.GetType() == typeof(char[])) + Array.Copy(value.ToCharArray((int) fieldOffset, length), 0, destinationArray, destinationOffset, length); + else + { + char[] chars = value.ToCharArray((int) fieldOffset, length); + byte[] source = new byte[chars.Length]; ; + + for (int i = 0; i < chars.Length; i++) + source[i] = Convert.ToByte(chars[i]); + + Array.Copy(source, 0, destinationArray, destinationOffset, length); + } + + return length; + } + + #endregion + + #region IDataReader Members + + int IDataReader.RecordsAffected + { + get + { + // For SELECT statements, -1 must be returned. + return -1; + } + } + + bool IDataReader.IsClosed + { + get + { + return _eof; + } + } + + bool IDataReader.NextResult() + { + ValidateDataReader(DataReaderValidations.IsNotClosed); + + return false; + } + + void IDataReader.Close() + { + Dispose(); + } + + bool IDataReader.Read() + { + ValidateDataReader(DataReaderValidations.IsNotClosed); + + return ReadNextRecord(); + } + + int IDataReader.Depth + { + get + { + ValidateDataReader(DataReaderValidations.IsNotClosed); + + return 0; + } + } + + DataTable IDataReader.GetSchemaTable() + { + EnsureInitialize(); + ValidateDataReader(DataReaderValidations.IsNotClosed); + + DataTable schema = new DataTable("SchemaTable"); + schema.Locale = CultureInfo.InvariantCulture; + schema.MinimumCapacity = _fieldCount; + + schema.Columns.Add(SchemaTableColumn.AllowDBNull, typeof(bool)).ReadOnly = true; + schema.Columns.Add(SchemaTableColumn.BaseColumnName, typeof(string)).ReadOnly = true; + schema.Columns.Add(SchemaTableColumn.BaseSchemaName, typeof(string)).ReadOnly = true; + schema.Columns.Add(SchemaTableColumn.BaseTableName, typeof(string)).ReadOnly = true; + schema.Columns.Add(SchemaTableColumn.ColumnName, typeof(string)).ReadOnly = true; + schema.Columns.Add(SchemaTableColumn.ColumnOrdinal, typeof(int)).ReadOnly = true; + schema.Columns.Add(SchemaTableColumn.ColumnSize, typeof(int)).ReadOnly = true; + schema.Columns.Add(SchemaTableColumn.DataType, typeof(object)).ReadOnly = true; + schema.Columns.Add(SchemaTableColumn.IsAliased, typeof(bool)).ReadOnly = true; + schema.Columns.Add(SchemaTableColumn.IsExpression, typeof(bool)).ReadOnly = true; + schema.Columns.Add(SchemaTableColumn.IsKey, typeof(bool)).ReadOnly = true; + schema.Columns.Add(SchemaTableColumn.IsLong, typeof(bool)).ReadOnly = true; + schema.Columns.Add(SchemaTableColumn.IsUnique, typeof(bool)).ReadOnly = true; + schema.Columns.Add(SchemaTableColumn.NumericPrecision, typeof(short)).ReadOnly = true; + schema.Columns.Add(SchemaTableColumn.NumericScale, typeof(short)).ReadOnly = true; + schema.Columns.Add(SchemaTableColumn.ProviderType, typeof(int)).ReadOnly = true; + + schema.Columns.Add(SchemaTableOptionalColumn.BaseCatalogName, typeof(string)).ReadOnly = true; + schema.Columns.Add(SchemaTableOptionalColumn.BaseServerName, typeof(string)).ReadOnly = true; + schema.Columns.Add(SchemaTableOptionalColumn.IsAutoIncrement, typeof(bool)).ReadOnly = true; + schema.Columns.Add(SchemaTableOptionalColumn.IsHidden, typeof(bool)).ReadOnly = true; + schema.Columns.Add(SchemaTableOptionalColumn.IsReadOnly, typeof(bool)).ReadOnly = true; + schema.Columns.Add(SchemaTableOptionalColumn.IsRowVersion, typeof(bool)).ReadOnly = true; + + string[] columnNames; + + if (_hasHeaders) + columnNames = _fieldHeaders; + else + { + columnNames = new string[_fieldCount]; + + for (int i = 0; i < _fieldCount; i++) + columnNames[i] = "Column" + i.ToString(CultureInfo.InvariantCulture); + } + + // null marks columns that will change for each row + object[] schemaRow = new object[] { + true, // 00- AllowDBNull + null, // 01- BaseColumnName + string.Empty, // 02- BaseSchemaName + string.Empty, // 03- BaseTableName + null, // 04- ColumnName + null, // 05- ColumnOrdinal + int.MaxValue, // 06- ColumnSize + typeof(string), // 07- DataType + false, // 08- IsAliased + false, // 09- IsExpression + false, // 10- IsKey + false, // 11- IsLong + false, // 12- IsUnique + DBNull.Value, // 13- NumericPrecision + DBNull.Value, // 14- NumericScale + (int) DbType.String, // 15- ProviderType + + string.Empty, // 16- BaseCatalogName + string.Empty, // 17- BaseServerName + false, // 18- IsAutoIncrement + false, // 19- IsHidden + true, // 20- IsReadOnly + false // 21- IsRowVersion + }; + + for (int i = 0; i < columnNames.Length; i++) + { + schemaRow[1] = columnNames[i]; // Base column name + schemaRow[4] = columnNames[i]; // Column name + schemaRow[5] = i; // Column ordinal + + schema.Rows.Add(schemaRow); + } + + return schema; + } + + #endregion + + #region IDataRecord Members + + int IDataRecord.GetInt32(int i) + { + ValidateDataReader(DataReaderValidations.IsInitialized | DataReaderValidations.IsNotClosed); + + string value = this[i]; + + return Int32.Parse(value == null ? string.Empty : value, CultureInfo.CurrentCulture); + } + + object IDataRecord.this[string name] + { + get + { + ValidateDataReader(DataReaderValidations.IsInitialized | DataReaderValidations.IsNotClosed); + return this[name]; + } + } + + object IDataRecord.this[int i] + { + get + { + ValidateDataReader(DataReaderValidations.IsInitialized | DataReaderValidations.IsNotClosed); + return this[i]; + } + } + + object IDataRecord.GetValue(int i) + { + ValidateDataReader(DataReaderValidations.IsInitialized | DataReaderValidations.IsNotClosed); + + if (((IDataRecord) this).IsDBNull(i)) + return DBNull.Value; + else + return this[i]; + } + + bool IDataRecord.IsDBNull(int i) + { + ValidateDataReader(DataReaderValidations.IsInitialized | DataReaderValidations.IsNotClosed); + return (string.IsNullOrEmpty(this[i])); + } + + long IDataRecord.GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length) + { + ValidateDataReader(DataReaderValidations.IsInitialized | DataReaderValidations.IsNotClosed); + + return CopyFieldToArray(i, fieldOffset, buffer, bufferoffset, length); + } + + byte IDataRecord.GetByte(int i) + { + ValidateDataReader(DataReaderValidations.IsInitialized | DataReaderValidations.IsNotClosed); + return Byte.Parse(this[i], CultureInfo.CurrentCulture); + } + + Type IDataRecord.GetFieldType(int i) + { + EnsureInitialize(); + ValidateDataReader(DataReaderValidations.IsInitialized | DataReaderValidations.IsNotClosed); + + if (i < 0 || i >= _fieldCount) + throw new ArgumentOutOfRangeException("i", i, string.Format(CultureInfo.InvariantCulture, ExceptionMessage.FieldIndexOutOfRange, i)); + + return typeof(string); + } + + decimal IDataRecord.GetDecimal(int i) + { + ValidateDataReader(DataReaderValidations.IsInitialized | DataReaderValidations.IsNotClosed); + return Decimal.Parse(this[i], CultureInfo.CurrentCulture); + } + + int IDataRecord.GetValues(object[] values) + { + ValidateDataReader(DataReaderValidations.IsInitialized | DataReaderValidations.IsNotClosed); + + IDataRecord record = (IDataRecord) this; + + for (int i = 0; i < _fieldCount; i++) + values[i] = record.GetValue(i); + + return _fieldCount; + } + + string IDataRecord.GetName(int i) + { + EnsureInitialize(); + ValidateDataReader(DataReaderValidations.IsNotClosed); + + if (i < 0 || i >= _fieldCount) + throw new ArgumentOutOfRangeException("i", i, string.Format(CultureInfo.InvariantCulture, ExceptionMessage.FieldIndexOutOfRange, i)); + + if (_hasHeaders) + return _fieldHeaders[i]; + else + return "Column" + i.ToString(CultureInfo.InvariantCulture); + } + + long IDataRecord.GetInt64(int i) + { + ValidateDataReader(DataReaderValidations.IsInitialized | DataReaderValidations.IsNotClosed); + return Int64.Parse(this[i], CultureInfo.CurrentCulture); + } + + double IDataRecord.GetDouble(int i) + { + ValidateDataReader(DataReaderValidations.IsInitialized | DataReaderValidations.IsNotClosed); + return Double.Parse(this[i], CultureInfo.CurrentCulture); + } + + bool IDataRecord.GetBoolean(int i) + { + ValidateDataReader(DataReaderValidations.IsInitialized | DataReaderValidations.IsNotClosed); + + string value = this[i]; + + int result; + + if (Int32.TryParse(value, out result)) + return (result != 0); + else + return Boolean.Parse(value); + } + + Guid IDataRecord.GetGuid(int i) + { + ValidateDataReader(DataReaderValidations.IsInitialized | DataReaderValidations.IsNotClosed); + return new Guid(this[i]); + } + + DateTime IDataRecord.GetDateTime(int i) + { + ValidateDataReader(DataReaderValidations.IsInitialized | DataReaderValidations.IsNotClosed); + return DateTime.Parse(this[i], CultureInfo.CurrentCulture); + } + + int IDataRecord.GetOrdinal(string name) + { + EnsureInitialize(); + ValidateDataReader(DataReaderValidations.IsNotClosed); + + int index; + + if (!_fieldHeaderIndexes.TryGetValue(name, out index)) + throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, ExceptionMessage.FieldHeaderNotFound, name), "name"); + + return index; + } + + string IDataRecord.GetDataTypeName(int i) + { + ValidateDataReader(DataReaderValidations.IsInitialized | DataReaderValidations.IsNotClosed); + return typeof(string).FullName; + } + + float IDataRecord.GetFloat(int i) + { + ValidateDataReader(DataReaderValidations.IsInitialized | DataReaderValidations.IsNotClosed); + return Single.Parse(this[i], CultureInfo.CurrentCulture); + } + + IDataReader IDataRecord.GetData(int i) + { + ValidateDataReader(DataReaderValidations.IsInitialized | DataReaderValidations.IsNotClosed); + + if (i == 0) + return this; + else + return null; + } + + long IDataRecord.GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length) + { + ValidateDataReader(DataReaderValidations.IsInitialized | DataReaderValidations.IsNotClosed); + + return CopyFieldToArray(i, fieldoffset, buffer, bufferoffset, length); + } + + string IDataRecord.GetString(int i) + { + ValidateDataReader(DataReaderValidations.IsInitialized | DataReaderValidations.IsNotClosed); + return this[i]; + } + + char IDataRecord.GetChar(int i) + { + ValidateDataReader(DataReaderValidations.IsInitialized | DataReaderValidations.IsNotClosed); + return Char.Parse(this[i]); + } + + short IDataRecord.GetInt16(int i) + { + ValidateDataReader(DataReaderValidations.IsInitialized | DataReaderValidations.IsNotClosed); + return Int16.Parse(this[i], CultureInfo.CurrentCulture); + } + + #endregion + + #region IEnumerable Members + + /// + /// Returns an that can iterate through CSV records. + /// + /// An that can iterate through CSV records. + /// + /// The instance has been disposed of. + /// + public CsvReader.RecordEnumerator GetEnumerator() + { + return new CsvReader.RecordEnumerator(this); + } + + /// + /// Returns an that can iterate through CSV records. + /// + /// An that can iterate through CSV records. + /// + /// The instance has been disposed of. + /// + IEnumerator IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } + + #endregion + + #region IEnumerable Members + + /// + /// Returns an that can iterate through CSV records. + /// + /// An that can iterate through CSV records. + /// + /// The instance has been disposed of. + /// + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + #endregion + + #region IDisposable members + +#if DEBUG + /// + /// Contains the stack when the object was allocated. + /// + private System.Diagnostics.StackTrace _allocStack; +#endif + + /// + /// Contains the disposed status flag. + /// + private bool _isDisposed = false; + + /// + /// Contains the locking object for multi-threading purpose. + /// + private readonly object _lock = new object(); + + /// + /// Occurs when the instance is disposed of. + /// + public event EventHandler Disposed; + + /// + /// Gets a value indicating whether the instance has been disposed of. + /// + /// + /// if the instance has been disposed of; otherwise, . + /// + [System.ComponentModel.Browsable(false)] + public bool IsDisposed + { + get { return _isDisposed; } + } + + /// + /// Raises the event. + /// + /// A that contains the event data. + protected virtual void OnDisposed(EventArgs e) + { + EventHandler handler = Disposed; + + if (handler != null) + handler(this, e); + } + + /// + /// Checks if the instance has been disposed of, and if it has, throws an ; otherwise, does nothing. + /// + /// + /// The instance has been disposed of. + /// + /// + /// Derived classes should call this method at the start of all methods and properties that should not be accessed after a call to . + /// + protected void CheckDisposed() + { + if (_isDisposed) + throw new ObjectDisposedException(this.GetType().FullName); + } + + /// + /// Releases all resources used by the instance. + /// + /// + /// Calls with the disposing parameter set to to free unmanaged and managed resources. + /// + public void Dispose() + { + if (!_isDisposed) + { + Dispose(true); + GC.SuppressFinalize(this); + } + } + + /// + /// Releases the unmanaged resources used by this instance and optionally releases the managed resources. + /// + /// + /// to release both managed and unmanaged resources; to release only unmanaged resources. + /// + protected virtual void Dispose(bool disposing) + { + // Refer to http://www.bluebytesoftware.com/blog/PermaLink,guid,88e62cdf-5919-4ac7-bc33-20c06ae539ae.aspx + // Refer to http://www.gotdotnet.com/team/libraries/whitepapers/resourcemanagement/resourcemanagement.aspx + + // No exception should ever be thrown except in critical scenarios. + // Unhandled exceptions during finalization will tear down the process. + if (!_isDisposed) + { + try + { + // Dispose-time code should call Dispose() on all owned objects that implement the IDisposable interface. + // "owned" means objects whose lifetime is solely controlled by the container. + // In cases where ownership is not as straightforward, techniques such as HandleCollector can be used. + // Large managed object fields should be nulled out. + + // Dispose-time code should also set references of all owned objects to null, after disposing them. This will allow the referenced objects to be garbage collected even if not all references to the "parent" are released. It may be a significant memory consumption win if the referenced objects are large, such as big arrays, collections, etc. + if (disposing) + { + // Acquire a lock on the object while disposing. + + if (_reader != null) + { + lock (_lock) + { + if (_reader != null) + { + _reader.Dispose(); + + _reader = null; + _buffer = null; + _eof = true; + } + } + } + } + } + finally + { + // Ensure that the flag is set + _isDisposed = true; + + // Catch any issues about firing an event on an already disposed object. + try + { + OnDisposed(EventArgs.Empty); + } + catch { } + } + } + } + + /// + /// Releases unmanaged resources and performs other cleanup operations before the instance is reclaimed by garbage collection. + /// + ~CsvReader() + { +#if DEBUG + Debug.WriteLine("FinalizableObject was not disposed" + _allocStack.ToString()); +#endif + + Dispose(false); + } + + #endregion + } +} \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CsvReader.DataReaderValidations.cs gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CsvReader.DataReaderValidations.cs --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CsvReader.DataReaderValidations.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CsvReader.DataReaderValidations.cs 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,50 @@ +// LumenWorks.Framework.IO.CSV.CsvReader.DataReaderValidations +// Copyright (c) 2005 Sébastien Lorion +// +// MIT license (http://en.wikipedia.org/wiki/MIT_License) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System; + +namespace LumenWorks.Framework.IO.Csv +{ + public partial class CsvReader + { + /// + /// Defines the data reader validations. + /// + [Flags] + private enum DataReaderValidations + { + /// + /// No validation. + /// + None = 0, + + /// + /// Validate that the data reader is initialized. + /// + IsInitialized = 1, + + /// + /// Validate that the data reader is not closed. + /// + IsNotClosed = 2 + } + } +} \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CsvReader.RecordEnumerator.cs gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CsvReader.RecordEnumerator.cs --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CsvReader.RecordEnumerator.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/CsvReader.RecordEnumerator.cs 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,164 @@ +// LumenWorks.Framework.IO.CSV.CsvReader.RecordEnumerator +// Copyright (c) 2005 Sébastien Lorion +// +// MIT license (http://en.wikipedia.org/wiki/MIT_License) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections; +using System.Collections.Generic; + +using LumenWorks.Framework.IO.Csv.Resources; + +namespace LumenWorks.Framework.IO.Csv +{ + public partial class CsvReader + { + /// + /// Supports a simple iteration over the records of a . + /// + public struct RecordEnumerator + : IEnumerator, IEnumerator + { + #region Fields + + /// + /// Contains the enumerated . + /// + private CsvReader _reader; + + /// + /// Contains the current record. + /// + private string[] _current; + + /// + /// Contains the current record index. + /// + private long _currentRecordIndex; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// The to iterate over. + /// + /// is a . + /// + public RecordEnumerator(CsvReader reader) + { + if (reader == null) + throw new ArgumentNullException("reader"); + + _reader = reader; + _current = null; + + _currentRecordIndex = reader._currentRecordIndex; + } + + #endregion + + #region IEnumerator Members + + /// + /// Gets the current record. + /// + public string[] Current + { + get { return _current; } + } + + /// + /// Advances the enumerator to the next record of the CSV. + /// + /// if the enumerator was successfully advanced to the next record, if the enumerator has passed the end of the CSV. + public bool MoveNext() + { + if (_reader._currentRecordIndex != _currentRecordIndex) + throw new InvalidOperationException(ExceptionMessage.EnumerationVersionCheckFailed); + + if (_reader.ReadNextRecord()) + { + _current = new string[_reader._fieldCount]; + + _reader.CopyCurrentRecordTo(_current); + _currentRecordIndex = _reader._currentRecordIndex; + + return true; + } + else + { + _current = null; + _currentRecordIndex = _reader._currentRecordIndex; + + return false; + } + } + + #endregion + + #region IEnumerator Members + + /// + /// Sets the enumerator to its initial position, which is before the first record in the CSV. + /// + public void Reset() + { + if (_reader._currentRecordIndex != _currentRecordIndex) + throw new InvalidOperationException(ExceptionMessage.EnumerationVersionCheckFailed); + + _reader.MoveTo(-1); + + _current = null; + _currentRecordIndex = _reader._currentRecordIndex; + } + + /// + /// Gets the current record. + /// + object IEnumerator.Current + { + get + { + if (_reader._currentRecordIndex != _currentRecordIndex) + throw new InvalidOperationException(ExceptionMessage.EnumerationVersionCheckFailed); + + return this.Current; + } + } + + #endregion + + #region IDisposable Members + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + _reader = null; + _current = null; + } + + #endregion + } + } +} \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/Events/ParseErrorEventArgs.cs gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/Events/ParseErrorEventArgs.cs --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/Events/ParseErrorEventArgs.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/Events/ParseErrorEventArgs.cs 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,85 @@ +// LumenWorks.Framework.IO.CSV.ParseErrorEventArgs +// Copyright (c) 2006 Sébastien Lorion +// +// MIT license (http://en.wikipedia.org/wiki/MIT_License) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System; + +namespace LumenWorks.Framework.IO.Csv +{ + /// + /// Provides data for the event. + /// + public class ParseErrorEventArgs + : EventArgs + { + #region Fields + + /// + /// Contains the error that occured. + /// + private MalformedCsvException _error; + + /// + /// Contains the action to take. + /// + private ParseErrorAction _action; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the ParseErrorEventArgs class. + /// + /// The error that occured. + /// The default action to take. + public ParseErrorEventArgs(MalformedCsvException error, ParseErrorAction defaultAction) + : base() + { + _error = error; + _action = defaultAction; + } + + #endregion + + #region Properties + + /// + /// Gets the error that occured. + /// + /// The error that occured. + public MalformedCsvException Error + { + get { return _error; } + } + + /// + /// Gets or sets the action to take. + /// + /// The action to take. + public ParseErrorAction Action + { + get { return _action; } + set { _action = value; } + } + + #endregion + } +} \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/Exceptions/MalformedCsvException.cs gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/Exceptions/MalformedCsvException.cs --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/Exceptions/MalformedCsvException.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/Exceptions/MalformedCsvException.cs 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,221 @@ +// LumenWorks.Framework.IO.Csv.MalformedCsvException +// Copyright (c) 2005 Sébastien Lorion +// +// MIT license (http://en.wikipedia.org/wiki/MIT_License) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System; +using System.Globalization; +using System.Runtime.Serialization; +using System.Security.Permissions; + +using LumenWorks.Framework.IO.Csv.Resources; + +namespace LumenWorks.Framework.IO.Csv +{ + /// + /// Represents the exception that is thrown when a CSV file is malformed. + /// + [Serializable()] + public class MalformedCsvException + : Exception + { + #region Fields + + /// + /// Contains the message that describes the error. + /// + private string _message; + + /// + /// Contains the raw data when the error occured. + /// + private string _rawData; + + /// + /// Contains the current field index. + /// + private int _currentFieldIndex; + + /// + /// Contains the current record index. + /// + private long _currentRecordIndex; + + /// + /// Contains the current position in the raw data. + /// + private int _currentPosition; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the MalformedCsvException class. + /// + public MalformedCsvException() + : this(null, null) + { + } + + /// + /// Initializes a new instance of the MalformedCsvException class. + /// + /// The message that describes the error. + public MalformedCsvException(string message) + : this(message, null) + { + } + + /// + /// Initializes a new instance of the MalformedCsvException class. + /// + /// The message that describes the error. + /// The exception that is the cause of the current exception. + public MalformedCsvException(string message, Exception innerException) + : base(String.Empty, innerException) + { + _message = (message == null ? string.Empty : message); + + _rawData = string.Empty; + _currentPosition = -1; + _currentRecordIndex = -1; + _currentFieldIndex = -1; + } + + /// + /// Initializes a new instance of the MalformedCsvException class. + /// + /// The raw data when the error occured. + /// The current position in the raw data. + /// The current record index. + /// The current field index. + public MalformedCsvException(string rawData, int currentPosition, long currentRecordIndex, int currentFieldIndex) + : this(rawData, currentPosition, currentRecordIndex, currentFieldIndex, null) + { + } + + /// + /// Initializes a new instance of the MalformedCsvException class. + /// + /// The raw data when the error occured. + /// The current position in the raw data. + /// The current record index. + /// The current field index. + /// The exception that is the cause of the current exception. + public MalformedCsvException(string rawData, int currentPosition, long currentRecordIndex, int currentFieldIndex, Exception innerException) + : base(String.Empty, innerException) + { + _rawData = (rawData == null ? string.Empty : rawData); + _currentPosition = currentPosition; + _currentRecordIndex = currentRecordIndex; + _currentFieldIndex = currentFieldIndex; + + _message = String.Format(CultureInfo.InvariantCulture, ExceptionMessage.MalformedCsvException, _currentRecordIndex, _currentFieldIndex, _currentPosition, _rawData); + } + + /// + /// Initializes a new instance of the MalformedCsvException class with serialized data. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. + protected MalformedCsvException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + _message = info.GetString("MyMessage"); + + _rawData = info.GetString("RawData"); + _currentPosition = info.GetInt32("CurrentPosition"); + _currentRecordIndex = info.GetInt64("CurrentRecordIndex"); + _currentFieldIndex = info.GetInt32("CurrentFieldIndex"); + } + + #endregion + + #region Properties + + /// + /// Gets the raw data when the error occured. + /// + /// The raw data when the error occured. + public string RawData + { + get { return _rawData; } + } + + /// + /// Gets the current position in the raw data. + /// + /// The current position in the raw data. + public int CurrentPosition + { + get { return _currentPosition; } + } + + /// + /// Gets the current record index. + /// + /// The current record index. + public long CurrentRecordIndex + { + get { return _currentRecordIndex; } + } + + /// + /// Gets the current field index. + /// + /// The current record index. + public int CurrentFieldIndex + { + get { return _currentFieldIndex; } + } + + #endregion + + #region Overrides + + /// + /// Gets a message that describes the current exception. + /// + /// A message that describes the current exception. + public override string Message + { + get { return _message; } + } + + /// + /// When overridden in a derived class, sets the with information about the exception. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. + public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) + { + base.GetObjectData(info, context); + + info.AddValue("MyMessage", _message); + + info.AddValue("RawData", _rawData); + info.AddValue("CurrentPosition", _currentPosition); + info.AddValue("CurrentRecordIndex", _currentRecordIndex); + info.AddValue("CurrentFieldIndex", _currentFieldIndex); + } + + #endregion + } +} \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/Exceptions/MissingFieldCsvException.cs gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/Exceptions/MissingFieldCsvException.cs --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/Exceptions/MissingFieldCsvException.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/Exceptions/MissingFieldCsvException.cs 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,107 @@ +// LumenWorks.Framework.IO.Csv.MissingFieldCsvException +// Copyright (c) 2005 Sébastien Lorion +// +// MIT license (http://en.wikipedia.org/wiki/MIT_License) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System; +using System.Globalization; +using System.Runtime.Serialization; +using System.Security.Permissions; + +using LumenWorks.Framework.IO.Csv.Resources; + +namespace LumenWorks.Framework.IO.Csv +{ + /// + /// Represents the exception that is thrown when a there is a missing field in a record of the CSV file. + /// + /// + /// MissingFieldException would have been a better name, but there is already a . + /// + [Serializable()] + public class MissingFieldCsvException + : MalformedCsvException + { + #region Constructors + + /// + /// Initializes a new instance of the MissingFieldCsvException class. + /// + public MissingFieldCsvException() + : base() + { + } + + /// + /// Initializes a new instance of the MissingFieldCsvException class. + /// + /// The message that describes the error. + public MissingFieldCsvException(string message) + : base(message) + { + } + + /// + /// Initializes a new instance of the MissingFieldCsvException class. + /// + /// The message that describes the error. + /// The exception that is the cause of the current exception. + public MissingFieldCsvException(string message, Exception innerException) + : base(message, innerException) + { + } + + /// + /// Initializes a new instance of the MissingFieldCsvException class. + /// + /// The raw data when the error occured. + /// The current position in the raw data. + /// The current record index. + /// The current field index. + public MissingFieldCsvException(string rawData, int currentPosition, long currentRecordIndex, int currentFieldIndex) + : base(rawData, currentPosition, currentRecordIndex, currentFieldIndex) + { + } + + /// + /// Initializes a new instance of the MissingFieldCsvException class. + /// + /// The raw data when the error occured. + /// The current position in the raw data. + /// The current record index. + /// The current field index. + /// The exception that is the cause of the current exception. + public MissingFieldCsvException(string rawData, int currentPosition, long currentRecordIndex, int currentFieldIndex, Exception innerException) + : base(rawData, currentPosition, currentRecordIndex, currentFieldIndex, innerException) + { + } + + /// + /// Initializes a new instance of the MissingFieldCsvException class with serialized data. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. + protected MissingFieldCsvException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + + #endregion + } +} \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/MissingFieldAction.cs gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/MissingFieldAction.cs --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/MissingFieldAction.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/MissingFieldAction.cs 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,46 @@ +// LumenWorks.Framework.IO.CSV.MissingFieldAction +// Copyright (c) 2006 Sébastien Lorion +// +// MIT license (http://en.wikipedia.org/wiki/MIT_License) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System; + +namespace LumenWorks.Framework.IO.Csv +{ + /// + /// Specifies the action to take when a field is missing. + /// + public enum MissingFieldAction + { + /// + /// Treat as a parsing error. + /// + ParseError = 0, + + /// + /// Replaces by an empty value. + /// + ReplaceByEmpty = 1, + + /// + /// Replaces by a null value (). + /// + ReplaceByNull = 2, + } +} \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/ParseErrorAction.cs gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/ParseErrorAction.cs --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/ParseErrorAction.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/ParseErrorAction.cs 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,46 @@ +// LumenWorks.Framework.IO.CSV.ParseErrorAction +// Copyright (c) 2006 Sébastien Lorion +// +// MIT license (http://en.wikipedia.org/wiki/MIT_License) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System; + +namespace LumenWorks.Framework.IO.Csv +{ + /// + /// Specifies the action to take when a parsing error has occured. + /// + public enum ParseErrorAction + { + /// + /// Raises the event. + /// + RaiseEvent = 0, + + /// + /// Tries to advance to next line. + /// + AdvanceToNextLine = 1, + + /// + /// Throws an exception. + /// + ThrowException = 2, + } +} diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/Resources/ExceptionMessage.Designer.cs gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/Resources/ExceptionMessage.Designer.cs --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/Resources/ExceptionMessage.Designer.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/Resources/ExceptionMessage.Designer.cs 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,207 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.42 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace LumenWorks.Framework.IO.Csv.Resources { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class ExceptionMessage { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal ExceptionMessage() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("LumenWorks.Framework.IO.Csv.Resources.ExceptionMessage", typeof(ExceptionMessage).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Buffer size must be 1 or more.. + /// + internal static string BufferSizeTooSmall { + get { + return ResourceManager.GetString("BufferSizeTooSmall", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot move to a previous record in forward-only mode.. + /// + internal static string CannotMovePreviousRecordInForwardOnly { + get { + return ResourceManager.GetString("CannotMovePreviousRecordInForwardOnly", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot read record at index '{0}'.. + /// + internal static string CannotReadRecordAtIndex { + get { + return ResourceManager.GetString("CannotReadRecordAtIndex", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enumeration has either not started or has already finished.. + /// + internal static string EnumerationFinishedOrNotStarted { + get { + return ResourceManager.GetString("EnumerationFinishedOrNotStarted", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Collection was modified; enumeration operation may not execute.. + /// + internal static string EnumerationVersionCheckFailed { + get { + return ResourceManager.GetString("EnumerationVersionCheckFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to '{0}' field header not found.. + /// + internal static string FieldHeaderNotFound { + get { + return ResourceManager.GetString("FieldHeaderNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Field index must be included in [0, FieldCount[. Specified field index was : '{0}'.. + /// + internal static string FieldIndexOutOfRange { + get { + return ResourceManager.GetString("FieldIndexOutOfRange", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The CSV appears to be corrupt near record '{0}' field '{1} at position '{2}'. Current raw data : '{3}'.. + /// + internal static string MalformedCsvException { + get { + return ResourceManager.GetString("MalformedCsvException", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to '{0}' is not a supported missing field action.. + /// + internal static string MissingFieldActionNotSupported { + get { + return ResourceManager.GetString("MissingFieldActionNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No current record.. + /// + internal static string NoCurrentRecord { + get { + return ResourceManager.GetString("NoCurrentRecord", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The CSV does not have headers (CsvReader.HasHeaders property is false).. + /// + internal static string NoHeaders { + get { + return ResourceManager.GetString("NoHeaders", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The number of fields in the record is greater than the available space from index to the end of the destination array.. + /// + internal static string NotEnoughSpaceInArray { + get { + return ResourceManager.GetString("NotEnoughSpaceInArray", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to '{0}' is not a valid ParseErrorAction while inside a ParseError event.. + /// + internal static string ParseErrorActionInvalidInsideParseErrorEvent { + get { + return ResourceManager.GetString("ParseErrorActionInvalidInsideParseErrorEvent", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to '{0}' is not a supported ParseErrorAction.. + /// + internal static string ParseErrorActionNotSupported { + get { + return ResourceManager.GetString("ParseErrorActionNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This operation is invalid when the reader is closed.. + /// + internal static string ReaderClosed { + get { + return ResourceManager.GetString("ReaderClosed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Record index must be 0 or more.. + /// + internal static string RecordIndexLessThanZero { + get { + return ResourceManager.GetString("RecordIndexLessThanZero", resourceCulture); + } + } + } +} diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/Resources/ExceptionMessage.resx gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/Resources/ExceptionMessage.resx --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/Resources/ExceptionMessage.resx 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Csv/Resources/ExceptionMessage.resx 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Buffer size must be 1 or more. + + + Cannot move to a previous record in forward-only mode. + + + Cannot read record at index '{0}'. + index:int + + + Enumeration has either not started or has already finished. + + + Collection was modified; enumeration operation may not execute. + + + '{0}' field header not found. + header:string + + + Field index must be included in [0, FieldCount[. Specified field index was : '{0}'. + index:int + + + The CSV appears to be corrupt near record '{0}' field '{1} at position '{2}'. Current raw data : '{3}'. + currentRecordIndex:int;currentFieldIndex:int;currentPosition:int;rawData:string + + + '{0}' is not a supported missing field action. + missingFieldAction:LumenWorks.Framework.IO.Csv.MissingFieldAction + + + No current record. + + + The CSV does not have headers (CsvReader.HasHeaders property is false). + + + The number of fields in the record is greater than the available space from index to the end of the destination array. + + + '{0}' is not a valid ParseErrorAction while inside a ParseError event. + parseErrorAction:LumenWorks.Framework.IO.Csv.ParseErrorAction + + + '{0}' is not a supported ParseErrorAction. + parseErrorAction:LumenWorks.Framework.IO.Csv.ParseErrorAction + + + This operation is invalid when the reader is closed. + + + Record index must be 0 or more. + + \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/LumenWorks.Framework.IO.csproj gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/LumenWorks.Framework.IO.csproj --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/LumenWorks.Framework.IO.csproj 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/LumenWorks.Framework.IO.csproj 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,74 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {E3B83D68-C90C-4874-8E5F-DEC8D038BC7C} + Library + Properties + LumenWorks.Framework.IO + LumenWorks.Framework.IO + v2.0 + 512 + + + + + + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + bin\Release\LumenWorks.Framework.IO.XML + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Properties/AssemblyInfo.cs gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Properties/AssemblyInfo.cs --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/LumenWorks.Framework.IO/Properties/AssemblyInfo.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/LumenWorks.Framework.IO/Properties/AssemblyInfo.cs 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("LumenWorks.Framework.IO")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("leto")] +[assembly: AssemblyProduct("LumenWorks.Framework.IO")] +[assembly: AssemblyCopyright("Copyright © Sébastien Lorion 2006")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("a8577790-f852-47a5-94ec-ec5fdf155a55")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("3.0.0.0")] +[assembly: AssemblyFileVersion("3.0.0.0")] diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/csvhandling.cs gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/csvhandling.cs --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/csvhandling.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/csvhandling.cs 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,130 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using System.Windows.Forms; +using System.Diagnostics; +using LumenWorks.Framework.IO.Csv; + + + +/// this file contains the CSV related support code + +namespace YouTubeUploader +{ + public partial class YouTubeUploader : Form + { + + private void OpenCSVFile_Click(object sender, EventArgs e) + { + if (this.chooseCSVFile.ShowDialog() == DialogResult.OK) + { + LoadCSVFile(this.chooseCSVFile.FileName); + } + } + + private void LoadCSVFile(String filename) + { + this.csvDisplayGrid.DataSource = null; + this.csvDisplayGrid.Columns.Clear(); + this.csvDisplayGrid.Rows.Clear(); + + lock (this.flag) + { + this.queue = new List(); + this.retryQueue = new List(); + } + + + Stream f = File.Open(filename, FileMode.Open); + using (CachedCsvReader csv = new CachedCsvReader(new StreamReader(f, Encoding.UTF8), true)) + { + this.csvDisplayGrid.DataSource = csv; + while (this.csvDisplayGrid.Columns.Count > COLUMN_MAX) + { + this.csvDisplayGrid.Columns.RemoveAt(6); + } + if (this.csvDisplayGrid.Columns.Count != COLUMN_MAX) + { + MessageBox.Show("The file " + filename + " is not in the correct format"); + this.csvDisplayGrid.DataSource = null; + } + } + + + // now add a status column + DataGridViewColumn status = new DataGridViewColumn(); + status.Name = "Upload Status"; + status.CellTemplate = new DataGridViewTextBoxCell(); + this.csvDisplayGrid.Columns.Add(status); + + DataGridViewColumn vid = new DataGridViewColumn(); + vid.Name = "Video ID"; + vid.CellTemplate = new DataGridViewTextBoxCell(); + this.csvDisplayGrid.Columns.Add(vid); + + this.Upload.Enabled = true; + + SetTitle(); + + Trace.TraceInformation("Loaded csv file: " + filename + "successfully"); + + } + + + private void ChooseOutputFile_Click(object sender, EventArgs e) + { + try + { + if (this.saveOutput.ShowDialog() == DialogResult.OK) + { + SaveGridAsCSV(this.saveOutput.FileName); + } + } + catch (Exception ex) + { + MessageBox.Show("There was a problem saving your output file: ", ex.Message); + } + } + + private void SaveGridAsCSV(String filename) + { + + Stream file = File.Open(filename, FileMode.Create); + + StreamWriter writer = new StreamWriter(file); + // iterate over the contents, and create a CSV file + int counter = 0; + foreach (DataGridViewColumn col in this.csvDisplayGrid.Columns) + { + OutputCell(writer, col.Name, ref counter); + } + writer.WriteLine(); + + foreach (DataGridViewRow row in this.csvDisplayGrid.Rows) + { + counter = 0; + foreach (DataGridViewCell cell in row.Cells) + { + if (cell.Value != null) + OutputCell(writer, cell.Value.ToString(), ref counter); + } + writer.WriteLine(); + } + writer.Flush(); + writer.Close(); + } + + private void OutputCell(StreamWriter writer, string value, ref int index) + { + if (index > 0) + { + writer.Write(","); + } + writer.Write("\"" + value + "\""); + index++; + } + + } +} diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/GoogleClientLogin.cs gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/GoogleClientLogin.cs --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/GoogleClientLogin.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/GoogleClientLogin.cs 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,239 @@ +using System; +using System.Drawing; +using System.Collections; +using System.ComponentModel; +using System.Windows.Forms; +using Google.GData.Client; + +namespace Google.GData.Tools +{ + /// + /// This is a sample implementation for a login dialog. It returns you the authToken gained + /// from the Google Client Login Service + /// + public class GoogleClientLogin : System.Windows.Forms.Form + { + + private System.Windows.Forms.TextBox Password; + private System.Windows.Forms.Button Login; + private System.Windows.Forms.Button Cancel; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox Username; + private GDataCredentials credentials = null; + private Label label3; + private TextBox Account; + private bool accountChanged = false; + + /// + /// Required designer variable. + /// + private System.ComponentModel.Container components = null; + + /// + /// allows you to construct the dialog with a given service + /// + /// the service object to use + public GoogleClientLogin(string username) + { + // + // Required for Windows Form Designer support + // + InitializeComponent(); + + this.Username.Text = username; + } + + + + /// + /// Clean up any resources being used. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (components != null) + { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.Login = new System.Windows.Forms.Button(); + this.Cancel = new System.Windows.Forms.Button(); + this.Username = new System.Windows.Forms.TextBox(); + this.Password = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.Account = new System.Windows.Forms.TextBox(); + this.SuspendLayout(); + // + // Login + // + this.Login.DialogResult = System.Windows.Forms.DialogResult.OK; + this.Login.Location = new System.Drawing.Point(240, 104); + this.Login.Name = "Login"; + this.Login.Size = new System.Drawing.Size(80, 32); + this.Login.TabIndex = 5; + this.Login.Text = "&Login"; + this.Login.Click += new System.EventHandler(this.Login_Click); + // + // Cancel + // + this.Cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.Cancel.Location = new System.Drawing.Point(144, 104); + this.Cancel.Name = "Cancel"; + this.Cancel.Size = new System.Drawing.Size(80, 32); + this.Cancel.TabIndex = 4; + this.Cancel.Text = "&Cancel"; + this.Cancel.Click += new System.EventHandler(this.Cancel_Click); + // + // Username + // + this.Username.Location = new System.Drawing.Point(110, 16); + this.Username.Name = "Username"; + this.Username.Size = new System.Drawing.Size(210, 22); + this.Username.TabIndex = 1; + this.Username.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Username_KeyUp); + // + // Password + // + this.Password.Location = new System.Drawing.Point(110, 48); + this.Password.Name = "Password"; + this.Password.PasswordChar = '*'; + this.Password.Size = new System.Drawing.Size(210, 22); + this.Password.TabIndex = 2; + // + // label1 + // + this.label1.Location = new System.Drawing.Point(16, 16); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(88, 32); + this.label1.TabIndex = 5; + this.label1.Text = "Username:"; + // + // label2 + // + this.label2.Location = new System.Drawing.Point(16, 48); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(88, 32); + this.label2.TabIndex = 6; + this.label2.Text = "Password: "; + // + // label3 + // + this.label3.Location = new System.Drawing.Point(16, 80); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(88, 44); + this.label3.TabIndex = 8; + this.label3.Text = "YouTube Account:"; + // + // Account + // + this.Account.Location = new System.Drawing.Point(110, 80); + this.Account.Name = "Account"; + this.Account.Size = new System.Drawing.Size(210, 22); + this.Account.TabIndex = 3; + this.Account.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.Account_KeyPress); + // + // GoogleClientLogin + // + this.AcceptButton = this.Login; + this.AutoScaleBaseSize = new System.Drawing.Size(6, 15); + this.CancelButton = this.Cancel; + this.ClientSize = new System.Drawing.Size(344, 152); + this.Controls.Add(this.label3); + this.Controls.Add(this.Account); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.Controls.Add(this.Password); + this.Controls.Add(this.Username); + this.Controls.Add(this.Cancel); + this.Controls.Add(this.Login); + this.Name = "GoogleClientLogin"; + this.Text = "GoogleClientLogin"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + #endregion + + + /// + /// returns the authentication token + /// + public GDataCredentials Credentials + { + get + { + return this.credentials; + } + } + + public string YoutubeAccount + { + get + { + return this.Account.Text; + } + } + + + + /// + /// returns the user name + /// + public string User + { + get + { + return this.Username.Text; + } + } + + private void Cancel_Click(object sender, System.EventArgs e) + { + this.Close(); + } + + private void Login_Click(object sender, System.EventArgs e) + { + this.credentials = new GDataCredentials(this.Username.Text, this.Password.Text); + this.Close(); + } + + private void Account_KeyPress(object sender, KeyPressEventArgs e) + { + this.accountChanged = true; + } + + + private void UpdateAccount() + { + // only autoupdate this if it has not changed yet + if (this.accountChanged == false) + { + string value = this.Username.Text; + string firstpart = value.Split('@')[0]; + this.Account.Text = firstpart; + } + } + + + private void Username_KeyUp(object sender, KeyEventArgs e) + { + UpdateAccount(); + } + + } +} diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/GoogleClientLogin.resx gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/GoogleClientLogin.resx --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/GoogleClientLogin.resx 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/GoogleClientLogin.resx 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/insertandretry.cs gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/insertandretry.cs --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/insertandretry.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/insertandretry.cs 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,312 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using System.Windows.Forms; +using System.Diagnostics; + +using Google.GData.Client; +using Google.GData.YouTube; +using Google.GData.Tools; +using Google.YouTube; +using Google.GData.Extensions.MediaRss; +using Google.GData.Client.ResumableUpload; + + +/// this file contains the CSV related support code + +namespace YouTubeUploader +{ + public partial class YouTubeUploader : Form + { + private ResumableUploader ru = null; + + + /// + /// userstate is the object that get's passed to the async code to identify a particular upload + /// this object remembers the http operation, the row in the spreadsheet, progress, etc. + /// This object get's added to the the current queue, or the retryqueue + /// + internal class UserState + { + private DataGridViewRow row; + private long currentPosition; + private string httpVerb; + private Uri resumeUri; + private int retryCounter; + private string errorText; + + + internal UserState(DataGridViewRow r) + { + this.row = r; + this.currentPosition = 0; + this.retryCounter = 0; + } + + internal DataGridViewRow Row + { + get + { + return this.row; + } + } + + internal long CurrentPosition + { + get + { + return this.currentPosition; + } + set + { + this.currentPosition = value; + } + } + + + internal string Error + { + get + { + return this.errorText; + } + set + { + this.errorText = value; + } + } + + internal int RetryCounter + { + get + { + return this.retryCounter; + } + set + { + this.retryCounter = value; + } + } + + + internal string HttpVerb + { + get + { + return this.httpVerb; + } + set + { + this.httpVerb = value; + } + } + + internal Uri ResumeUri + { + get + { + return this.resumeUri; + } + set + { + this.resumeUri = value; + } + } + } + + // helper to create a resumableuploader object and setup the event handlers + private void EnsureRU() + { + this.ru = new ResumableUploader((int)this.ChunkSize.Value); + this.ru.AsyncOperationCompleted += new AsyncOperationCompletedEventHandler(this.OnDone); + this.ru.AsyncOperationProgress += new AsyncOperationProgressEventHandler(this.OnProgress); + } + + + + // retry one row.The userstate was removed from the retry queue before that call + private bool RetryRow(UserState us) + { + if (us != null) + { + Trace.Indent(); + Trace.TraceInformation("Retrying a row, current position is: " + us.CurrentPosition + "for uri: " + us.ResumeUri); + Trace.Unindent(); + if (us.CurrentPosition > 0 && us.ResumeUri != null) + { + string contentType = MediaFileSource.GetContentTypeForFileName(us.Row.Cells[COLUMNINDEX_FILENAME].Value.ToString()); + MediaFileSource mfs = new MediaFileSource(us.Row.Cells[COLUMNINDEX_FILENAME].Value.ToString(), contentType); + + Stream s = mfs.Data; + + s.Seek(us.CurrentPosition, SeekOrigin.Begin); + + + lock (this.flag) + { + this.queue.Add(us); + } + us.Row.Cells[COLUMNINDEX_STATUS].Value = "Retrying (" + us.RetryCounter + ") - Last error was: " + us.Error; + ru.ResumeAsync(this.youTubeAuthenticator, us.ResumeUri, us.HttpVerb, s, contentType, us); + + return true; + } + + // else treat this as a new one, a resume from null + return InsertVideo(us.Row, us.RetryCounter+1); + } + return false; + } + + + /// + /// insert a new video. + /// + /// + /// + /// + private bool InsertVideo(DataGridViewRow row, int retryCounter) + { + Trace.TraceInformation("Entering InsertVideo: starting a new upload"); + Video v = new Video(); + v.Title = row.Cells[0].Value.ToString(); + v.Description = row.Cells[1].Value.ToString(); + v.Keywords = row.Cells[2].Value.ToString(); + v.Tags.Add(new MediaCategory(row.Cells[3].Value.ToString())); + v.Private = row.Cells[4].Value.ToString().ToLower() == "true"; + + string contentType = MediaFileSource.GetContentTypeForFileName(row.Cells[COLUMNINDEX_FILENAME].Value.ToString()); + + v.MediaSource = new MediaFileSource(row.Cells[COLUMNINDEX_FILENAME].Value.ToString(), contentType); + + // add the upload uri to it + AtomLink link = new AtomLink("http://uploads.gdata.youtube.com/resumable/feeds/api/users/" + this.youtubeAccount + "/uploads"); + link.Rel = ResumableUploader.CreateMediaRelation; + v.YouTubeEntry.Links.Add(link); + + UserState u = new UserState(row); + u.RetryCounter = retryCounter; + + lock (this.flag) + { + this.queue.Add(u); + } + ru.InsertAsync(this.youTubeAuthenticator, v.YouTubeEntry, u); + + + row.Cells[COLUMNINDEX_STATUS].Value = "Queued up..."; + row.Cells[COLUMNINDEX_STATUS].Tag = u; + + return true; + } + + // when an upload is completed successfully we parse the return stream + // to setup the videoid. + // also all retry counts will be reset to 0, as a successful upload incidates + // a restored network condition (e.g.). + private void ParseAndFinish(UserState u, Stream s) + { + + YouTubeRequestSettings ys = new YouTubeRequestSettings(YouTubeUploader.ApplicationName, + this.developerKey); + YouTubeRequest ytr = new YouTubeRequest(ys); + Video v = ytr.ParseVideo(s); + + Trace.TraceInformation("Upload successful"); + u.Row.Cells[COLUMNINDEX_STATUS].Value = "Upload successful"; + u.Row.Cells[COLUMNINDEX_STATUS].Tag = u; + u.Row.Cells[COLUMNINDEX_VIDEOID].Value = v.VideoId; + // we had one successful upload, reset the retry counts to 0 + lock (this.flag) + { + foreach (UserState us in retryQueue) + { + us.RetryCounter = 0; + } + } + } + + + + private void RemoveFromProcessingQueue(UserState u) + { + lock (this.flag) + { + this.queue.Remove(u); + } + } + + private bool AddToRetryQueue(UserState u) + { + u.RetryCounter++; + if (u.RetryCounter > (int)this.automaticRetries.Value) + { + u.Row.Cells[COLUMNINDEX_STATUS].Value = "Number of retries exceeded. Last error was: " + u.Error; + return false; + } + + lock (this.flag) + { + this.retryQueue.Add(u); + + } + return true; + } + + + // moves an entry into the retry queue + // and enables the retry timer + private void TryARetry(UserState u) + { + if (AddToRetryQueue(u) == true) + { + this.RetryTimer.Enabled = true; + } + } + + // cancels all currently active threads and empties the queue + private void CancelProcessingQueue() + { + // this will go over all rows and tries to upload them + lock (this.flag) + { + this.RetryTimer.Enabled = false; + foreach (UserState u in this.queue) + { + this.ru.CancelAsync(u); + } + this.queue = new List(); + + } + } + + // walks over the retry queue and moves them into the processing queue + // if the queue has free slots + private void RetryRows() + { + if (this.retryQueue.Count > 0) + { + this.RetryTimer.Enabled = true; + while (this.queue.Count < (int)this.MaxQueue.Value && + this.retryQueue.Count > 0) + { + lock (this.flag) + { + UserState u = this.retryQueue[0]; + this.retryQueue.Remove(u); + RetryRow(u); + } + } + } + else + { + this.RetryTimer.Enabled = false; + if (Finished() == true) + ToggleButtons(true); + } + } + + } +} diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/Program.cs gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/Program.cs --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/Program.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/Program.cs 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; + +namespace YouTubeUploader +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new YouTubeUploader()); + } + } +} diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/Properties/AssemblyInfo.cs gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/Properties/AssemblyInfo.cs --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/Properties/AssemblyInfo.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/Properties/AssemblyInfo.cs 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("YouTubeUploader")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("YouTubeUploader")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2009")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("a2f72b72-7ae4-41c8-ac53-bf3689d11390")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/Properties/Resources.Designer.cs gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/Properties/Resources.Designer.cs --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/Properties/Resources.Designer.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/Properties/Resources.Designer.cs 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,70 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.4927 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace YouTubeUploader.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("YouTubeUploader.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + internal static System.Drawing.Bitmap gdata_youtube { + get { + object obj = ResourceManager.GetObject("gdata_youtube", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/Properties/Resources.resx gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/Properties/Resources.resx --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/Properties/Resources.resx 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/Properties/Resources.resx 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\resources\gdata-youtube.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/Properties/Settings.Designer.cs gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/Properties/Settings.Designer.cs --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/Properties/Settings.Designer.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/Properties/Settings.Designer.cs 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.4927 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace YouTubeUploader.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/Properties/Settings.settings gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/Properties/Settings.settings --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/Properties/Settings.settings 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/Properties/Settings.settings 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,7 @@ + + + + + + + Binary files /tmp/UhUzKTrMiD/gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/Resources/gdata-youtube.png and /tmp/kt1AG0Pm9_/gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/Resources/gdata-youtube.png differ diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/YouTubeUploader.cs gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/YouTubeUploader.cs --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/YouTubeUploader.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/YouTubeUploader.cs 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,512 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using System.IO; +using System.Net; +using System.Configuration; +using System.Collections.Specialized; +using System.Collections.ObjectModel; +using System.Collections; + +using YouTubeUploader.Properties; + +using System.Diagnostics; + +using Google.GData.Client; +using Google.GData.Tools; + + +/* 2. Accepts a csv file with the following columns: + +Title - string +Description - multiline string +Tags - comma separated list +Category - string +Private - True/False +Path - path to video file to upload + +Any additional columns should be ignored. + +When the user loads the csv file into the client, the client should display the contents of the file in a + * scrollable table so that the user can verify the contents of the file. + +3. The client marches down the csv file and uploads each file sequentially using the resumable API. + * It should attempt each upload a few times before giving up altogether. + +4. All the videos are uploaded to the same account. There needs to be a place in the UI for + * the user to enter their username/password for ClientLogin. + +5. As videos are uploaded, the status of the video is updated in the table. + +6. As videos are uploaded, write out a log csv file containing the following columns: + +Title - string +Description - multiline string +Tags - comma separated list +Category - string +Private - True/False +Path - path to video file to upload +Timestamp +Video ID (assigned by YT) +Status (Success/Failed) + +Error Reason (HTTP response code or "File not found" or ...) + +Note that the first couple of columns are identical to the input file's. The idea is that, in the event of failure, + * it is easy to take this output csv file, massage it in Excel (e.g. to remove all videos with the status Success) + * and use the file to kick off a second round of uploads. + * +*/ +namespace YouTubeUploader +{ + public partial class YouTubeUploader : Form + { + + private Authenticator youTubeAuthenticator; + private const int COLUMN_MAX = 6; + private const int COLUMNINDEX_FILENAME = 5; + private const int COLUMNINDEX_STATUS = 6; + private const int COLUMNINDEX_VIDEOID = 7; + + private const string CONFIG_DEVKEY = "DevKey"; + private const string CONFIG_CSVFILE = "CsvFile"; + private const string CONFIG_OUTPUTFILE = "OutputFile"; + private const string CONFIG_MAXTHREADS = "MaxThreads"; + private const string CONFIG_CHUNKSIZE = "ChunkSize"; + private const string CONFIG_RETRYCOUNT = "RetryCount"; + private const string CONFIG_USERNAME = "Username"; + private const string CONFIG_PASSWORD = "Password"; + private const string CONFIG_YTACCOUNT = "YoutubeAccount"; + + + private const string AutoStartString = "/autostart"; + private bool autoStart = false; + private List queue; + private List retryQueue; + + private const string ApplicationName = "YouTubeUploader"; + + // this is the default devkey that has very limited allowance against the service + // private const string DeveloperKeyDefault = "AI39si5Zg5AcJCNVptBgkZPLRY5DwgAgRZN3tYH9h3phjLq442KMal341c7HaxgBhOOmH0qDso6BgK65ji7VhsZ888evpZij_w"; + // this is a different devkey, uncomment this line and comment the above + private const string DeveloperKeyDefault = "AI39si5HV9zaLn4okq_gTqY4vARdZBf2_8D3bTkiK2FWgqaVVH9tITjBa6nyaAdg19Y4in-hnqcFTXu7i3d-2RIKSCvIMBARAg"; + + private string developerKey; + private string csvFileName; + private string outputFileName; + private string youtubeAccount; + + private GDataCredentials credentials; + + + private Object flag = new Object(); + + + /// + /// Default constructor + /// + public YouTubeUploader() + { + InitializeComponent(); + Bitmap b = Resources.gdata_youtube; + IntPtr Hicon = b.GetHicon(); + this.Icon = Icon.FromHandle(Hicon); + } + + // the applications is done when both queues are empty + private bool Finished() + { + if (this.queue.Count == 0 && + this.retryQueue.Count == 0) + { + return true; + } + return false; + } + + // we set the application title different if we still have pending uploads + private void SetTitle() + { + if (NumberOfUploadsPending() > 0) + { + this.Text = YouTubeUploader.ApplicationName + " - " + NumberOfUploadsPending() + " uploads pending"; + } + else + { + this.Text = YouTubeUploader.ApplicationName; + } + } + + + + // when the form loads, we want to load the application settings, + // get the cmd line args, and process that + private void YouTubeUploader_Load(object sender, EventArgs e) + { + LoadAppSettings(); + GetCmdLineArgs(); + + if (this.credentials != null) + { + try + { + this.youTubeAuthenticator = new ClientLoginAuthenticator(YouTubeUploader.ApplicationName, + ServiceNames.YouTube, this.credentials); + this.youTubeAuthenticator.DeveloperKey = this.developerKey; + + } + catch + { + this.youTubeAuthenticator = null; + } + } + + if (this.youTubeAuthenticator == null) + { + GoogleClientLogin loginDialog = new GoogleClientLogin("youremailhere@gmail.com"); + loginDialog.ShowDialog(); + + if (loginDialog.Credentials != null) + { + + this.youTubeAuthenticator = new ClientLoginAuthenticator(YouTubeUploader.ApplicationName, + ServiceNames.YouTube, loginDialog.Credentials); + this.youTubeAuthenticator.DeveloperKey = this.developerKey; + + this.youtubeAccount = loginDialog.YoutubeAccount; + + } + else + { + this.Close(); + } + } + + if (this.csvFileName != null) + { + LoadCSVFile(this.csvFileName); + if (this.autoStart == true) + Upload_Click(null, null); + } + } + + // helper to toggle the buttons (pending if we are processing uploads + // when only cancel is active) + private void ToggleButtons(bool enabled) + { + + this.OpenCSVFile.Enabled = enabled; + this.Upload.Enabled = enabled; + this.MaxQueue.Enabled = enabled; + this.ChunkSize.Enabled = enabled; + this.ChooseOutputFile.Enabled = enabled; + + EnableCancelButton(!enabled); + + this.Upload.Enabled = enabled && NumberOfUploadsPending()>0; + } + + // helper to make the cancel button visible and enabled (or not) + private void EnableCancelButton(bool value) + { + this.CancelAsync.Enabled = value; + this.CancelAsync.Visible = value; + } + + + + /// + /// the number of pending uplods is the sum of the retry queue + /// and the rows that have not been processed at all. + /// + /// + private int NumberOfUploadsPending() + { + int count = this.retryQueue.Count; + + // this will go over all rows and tries to upload them + foreach (DataGridViewRow row in this.csvDisplayGrid.Rows) + { + if (row.Cells[COLUMNINDEX_STATUS].Tag == null) + count++; + } + return count; + } + + // Upload button was clicked. Modify UI state and fill the processing queue + private void Upload_Click(object sender, EventArgs e) + { + ToggleButtons(false); + EnsureRU(); + + Trace.TraceInformation("Uploading started"); + Trace.Indent(); + Trace.TraceInformation("csv file contains " + this.csvDisplayGrid.Rows.Count + " rows"); + Trace.TraceInformation("Retry counter = " + this.automaticRetries.Value); + Trace.TraceInformation("Threads = " + this.MaxQueue.Value); + Trace.TraceInformation("Chunksize = " + this.ChunkSize.Value); + Trace.Unindent(); + + // this will go over all rows and set the status + foreach (DataGridViewRow row in this.csvDisplayGrid.Rows) + { + if (row.Cells[COLUMNINDEX_STATUS].Value == null) + row.Cells[COLUMNINDEX_STATUS].Value = "Waiting to be uploaded...."; + } + // add a max of the first 3 rows to the upload queue + + // this will go over all rows and tries to upload them + foreach (DataGridViewRow row in this.csvDisplayGrid.Rows) + { + UploadRow(row); + } + + RetryRows(); + + if (Finished() == true) + { + this.OnDone(null, null); + } + } + + + + // returns true if a row was added to the queue + private bool UploadRow(DataGridViewRow row) + { + if (this.queue.Count >= (int) this.MaxQueue.Value) + return false; + + UserState u = row.Cells[COLUMNINDEX_STATUS].Tag as UserState; + // if this was already processed, don't. It will be either + // in the queue already or moved to the retry queue + if (u != null) + return false; + + return InsertVideo(row, 1); + } + + + + + // when we get a progress notification we remember a bunch of state info send + // that info is needed to retry later + private void OnProgress(object sender, AsyncOperationProgressEventArgs e) + { + UserState u = e.UserState as UserState; + + if (u != null && u.Row != null) + { + string status = ""; + if (u.RetryCounter > 1) + { + status = "Retrying (" + (u.RetryCounter-1).ToString() + "), uploading: " + e.ProgressPercentage + "% done"; + } + else + { + status = "Uploading: " + e.ProgressPercentage + "% done"; + } + + Trace.TraceInformation("OnProgress: " + status); + Trace.Indent(); + Trace.TraceInformation("Verb: " + e.HttpVerb); + Trace.TraceInformation("Uri: " + e.Uri); + Trace.TraceInformation("Current position: " + e.Position); + Trace.Unindent(); + + u.CurrentPosition = e.Position; + u.ResumeUri = e.Uri; + u.HttpVerb = e.HttpVerb; + u.Row.Cells[COLUMNINDEX_STATUS].Value = status; + } + } + + + // send when an upload is done. This can mean it completed, it failed + // or it was cancelled + private void OnDone(object sender, AsyncOperationCompletedEventArgs e) + { + + if (e != null) + { + UserState u = e.UserState as UserState; + + Trace.TraceInformation("OnDone - Upload finished for :" + u.ResumeUri); + Trace.Indent(); + + + if (u != null && u.Row != null) + { + if (e.Cancelled == true) + { + Trace.TraceInformation("Cancelled. Current Pos = " + u.CurrentPosition); + u.Row.Cells[COLUMNINDEX_STATUS].Value = "Operation was cancelled"; + // if it was cancelled, reset the retry counter + u.RetryCounter = 0; + u.Row.Cells[COLUMNINDEX_STATUS].Tag = u; + AddToRetryQueue(u); + } + else if (e.Error != null) + { + Trace.TraceInformation("Error. Current Pos = " + u.CurrentPosition); + Trace.TraceInformation("Error was: " + e.Error.ToString() + " - " + e.Error.Message); + u.Error = e.Error.Message; + u.Row.Cells[COLUMNINDEX_STATUS].Value = e.Error.Message; + u.Row.Cells[COLUMNINDEX_STATUS].Value = "Tried (" + u.RetryCounter + ") - Last error was: " + u.Error; + u.Row.Cells[COLUMNINDEX_STATUS].Tag = u; + TryARetry(u); + + } + else + { + ParseAndFinish(u, e.ResponseStream); + } + } + + RemoveFromProcessingQueue(u); + + + // only add new ones, if we did not have a cancelation + + if (e.Cancelled == false) + { + // now add a new row, if there is one + // this will go over all rows and tries to upload them + foreach (DataGridViewRow row in this.csvDisplayGrid.Rows) + { + if (UploadRow(row) == true) + break; + } + } + + Trace.Unindent(); + } + + if (Finished() == true) + { + ToggleButtons(true); + + if (this.autoStart == true && this.outputFileName != null) + { + SaveGridAsCSV(outputFileName); + } + } + SetTitle(); + } + + + + + private void csvDisplayGrid_CellMouseEnter(object sender, DataGridViewCellEventArgs e) + { + if (e.RowIndex >= 0 && e.ColumnIndex >= 0) + { + DataGridViewCell cell = this.csvDisplayGrid.Rows[e.RowIndex].Cells[e.ColumnIndex]; + + if (e.ColumnIndex == COLUMNINDEX_FILENAME) + { + string contentType = MediaFileSource.GetContentTypeForFileName(cell.Value.ToString()); + cell.ToolTipText = "We assume this file is of type: " + contentType; + } + } + } + + private void CancelAsync_Click(object sender, EventArgs e) + { + CancelProcessingQueue(); + + ToggleButtons(true); + } + + private void GetCmdLineArgs() + { + string[] args = Environment.GetCommandLineArgs(); + + foreach (string arg in args) + { + this.autoStart = YouTubeUploader.AutoStartString.Equals(arg.ToLower()); + + } + } + + + // the retry timer ticks once a minute. + private void RetryTimer_Tick(object sender, EventArgs e) + { + // sometimes this message get's posted to us even + // though we disabled the retrytimer shortly before. + // so better check if we are still supposed to process + if (this.RetryTimer.Enabled == true) + { + Trace.TraceInformation("Entering the retryTimer"); + RetryRows(); + } + } + + // opens up the wiki page with the documentation + private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + try + { + this.linkLabel1.LinkVisited = true; + System.Diagnostics.Process.Start("http://code.google.com/p/google-gdata/wiki/YouTubeUploader"); + } + catch (Exception ex) + { + MessageBox.Show("Unable to open the documentation page: " + ex.Message); + } + + } + + private void LoadAppSettings() + { + + // Get the AppSettings collection. + NameValueCollection appSettings = ConfigurationSettings.AppSettings; + + if (appSettings[YouTubeUploader.CONFIG_DEVKEY] != null) + this.developerKey = appSettings[YouTubeUploader.CONFIG_DEVKEY]; + else + this.developerKey = YouTubeUploader.DeveloperKeyDefault; + + if (String.IsNullOrEmpty(this.developerKey)) + { + MessageBox.Show("You need to enter a developer key in the source code. Look for DeveloperKeyDefault and paste your key in"); + this.Close(); + } + + if (appSettings[YouTubeUploader.CONFIG_MAXTHREADS] != null) + this.MaxQueue.Value = Decimal.Parse(appSettings[YouTubeUploader.CONFIG_MAXTHREADS]); + else + this.MaxQueue.Value = 3; + + if (appSettings[YouTubeUploader.CONFIG_RETRYCOUNT] != null) + this.automaticRetries.Value = Decimal.Parse(appSettings[YouTubeUploader.CONFIG_RETRYCOUNT]); + else + this.automaticRetries.Value = 10; + + if (appSettings[YouTubeUploader.CONFIG_CHUNKSIZE] != null) + this.ChunkSize.Value = Decimal.Parse(appSettings[YouTubeUploader.CONFIG_CHUNKSIZE]); + else + this.ChunkSize.Value = 25; + + this.csvFileName = appSettings[YouTubeUploader.CONFIG_CSVFILE]; + this.outputFileName = appSettings[YouTubeUploader.CONFIG_OUTPUTFILE]; + if (appSettings[YouTubeUploader.CONFIG_USERNAME] != null) + { + this.credentials = new GDataCredentials(appSettings[YouTubeUploader.CONFIG_USERNAME], + appSettings[YouTubeUploader.CONFIG_PASSWORD]); + } + this.youtubeAccount = appSettings[YouTubeUploader.CONFIG_YTACCOUNT]; + + } + + + } +} + diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/YouTubeUploader.csproj gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/YouTubeUploader.csproj --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/YouTubeUploader.csproj 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/YouTubeUploader.csproj 2010-12-06 13:36:40.000000000 +0000 @@ -0,0 +1,187 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {725130CA-A753-45A8-855F-EA22728E3F95} + WinExe + Properties + YouTubeUploader + YouTubeUploader + v3.5 + 512 + A1306EA9F1B34B1B3EA53196CA01286E03A5EA44 + YouTubeUploader_TemporaryKey.pfx + false + false + false + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + Youtube Content Uploader + Google + 4 + 1.0.0.4 + false + true + true + true + LocalIntranet + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + False + ..\..\..\lib\Release\Google.GData.Client.dll + + + False + ..\..\..\lib\Release\Google.GData.Extensions.dll + + + False + ..\..\..\lib\Release\Google.GData.YouTube.dll + + + + + + 3.5 + + + + 3.5 + + + 3.5 + + + + + + + + + + Form + + + Form + + + Form + + + Form + + + YouTubeUploader.cs + + + + + GoogleClientLogin.cs + + + YouTubeUploader.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + {E3B83D68-C90C-4874-8E5F-DEC8D038BC7C} + LumenWorks.Framework.IO + + + + + False + .NET Framework Client Profile + false + + + False + .NET Framework 2.0 %28x86%29 + false + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + + + + + + \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/YouTubeUploader.Designer.cs gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/YouTubeUploader.Designer.cs --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/YouTubeUploader.Designer.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/YouTubeUploader.Designer.cs 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,288 @@ +namespace YouTubeUploader +{ + partial class YouTubeUploader + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.chooseCSVFile = new System.Windows.Forms.OpenFileDialog(); + this.OpenCSVFile = new System.Windows.Forms.Button(); + this.ChooseOutputFile = new System.Windows.Forms.Button(); + this.Upload = new System.Windows.Forms.Button(); + this.csvDisplayGrid = new System.Windows.Forms.DataGridView(); + this.saveOutput = new System.Windows.Forms.SaveFileDialog(); + this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); + this.MaxQueue = new System.Windows.Forms.NumericUpDown(); + this.ChunkSize = new System.Windows.Forms.NumericUpDown(); + this.automaticRetries = new System.Windows.Forms.NumericUpDown(); + this.linkLabel1 = new System.Windows.Forms.LinkLabel(); + this.CancelAsync = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.RetryTimer = new System.Windows.Forms.Timer(this.components); + this.panel1 = new System.Windows.Forms.Panel(); + ((System.ComponentModel.ISupportInitialize)(this.csvDisplayGrid)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.MaxQueue)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.ChunkSize)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.automaticRetries)).BeginInit(); + this.panel1.SuspendLayout(); + this.SuspendLayout(); + // + // chooseCSVFile + // + this.chooseCSVFile.FileName = "chooseCSVFile"; + this.chooseCSVFile.Filter = "CSV Files (*.csv) | *.csv"; + // + // OpenCSVFile + // + this.OpenCSVFile.Location = new System.Drawing.Point(18, 37); + this.OpenCSVFile.Name = "OpenCSVFile"; + this.OpenCSVFile.Size = new System.Drawing.Size(140, 27); + this.OpenCSVFile.TabIndex = 4; + this.OpenCSVFile.Text = "Open CSV File..."; + this.toolTip1.SetToolTip(this.OpenCSVFile, "Opens an exported CSV file"); + this.OpenCSVFile.UseVisualStyleBackColor = true; + this.OpenCSVFile.Click += new System.EventHandler(this.OpenCSVFile_Click); + // + // ChooseOutputFile + // + this.ChooseOutputFile.Enabled = false; + this.ChooseOutputFile.Location = new System.Drawing.Point(633, 39); + this.ChooseOutputFile.Name = "ChooseOutputFile"; + this.ChooseOutputFile.Size = new System.Drawing.Size(137, 27); + this.ChooseOutputFile.TabIndex = 7; + this.ChooseOutputFile.Text = "Save Output..."; + this.ChooseOutputFile.UseVisualStyleBackColor = true; + this.ChooseOutputFile.Click += new System.EventHandler(this.ChooseOutputFile_Click); + // + // Upload + // + this.Upload.Enabled = false; + this.Upload.Location = new System.Drawing.Point(164, 37); + this.Upload.Name = "Upload"; + this.Upload.Size = new System.Drawing.Size(153, 27); + this.Upload.TabIndex = 5; + this.Upload.Text = "Start Upload"; + this.Upload.UseVisualStyleBackColor = true; + this.Upload.Click += new System.EventHandler(this.Upload_Click); + // + // csvDisplayGrid + // + this.csvDisplayGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.csvDisplayGrid.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill; + this.csvDisplayGrid.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.AllCells; + this.csvDisplayGrid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.csvDisplayGrid.Location = new System.Drawing.Point(0, 0); + this.csvDisplayGrid.Name = "csvDisplayGrid"; + this.csvDisplayGrid.RowTemplate.DefaultCellStyle.WrapMode = System.Windows.Forms.DataGridViewTriState.True; + this.csvDisplayGrid.RowTemplate.Height = 24; + this.csvDisplayGrid.RowTemplate.Resizable = System.Windows.Forms.DataGridViewTriState.True; + this.csvDisplayGrid.Size = new System.Drawing.Size(945, 385); + this.csvDisplayGrid.TabIndex = 10; + this.csvDisplayGrid.CellMouseEnter += new System.Windows.Forms.DataGridViewCellEventHandler(this.csvDisplayGrid_CellMouseEnter); + // + // MaxQueue + // + this.MaxQueue.Location = new System.Drawing.Point(229, 0); + this.MaxQueue.Maximum = new decimal(new int[] { + 10, + 0, + 0, + 0}); + this.MaxQueue.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.MaxQueue.Name = "MaxQueue"; + this.MaxQueue.Size = new System.Drawing.Size(88, 22); + this.MaxQueue.TabIndex = 1; + this.toolTip1.SetToolTip(this.MaxQueue, "Defines the number of files we try to upload at the same time"); + this.MaxQueue.Value = new decimal(new int[] { + 3, + 0, + 0, + 0}); + // + // ChunkSize + // + this.ChunkSize.Location = new System.Drawing.Point(526, 0); + this.ChunkSize.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.ChunkSize.Name = "ChunkSize"; + this.ChunkSize.Size = new System.Drawing.Size(74, 22); + this.ChunkSize.TabIndex = 2; + this.toolTip1.SetToolTip(this.ChunkSize, "Defines the size of the upload in Megabytes that we are trying to upload at once." + + " If you have a 1000 MB file, e.g, and this is the default 25MB, the file will be" + + " uploaded in 40 parts"); + this.ChunkSize.Value = new decimal(new int[] { + 25, + 0, + 0, + 0}); + // + // automaticRetries + // + this.automaticRetries.Location = new System.Drawing.Point(840, 3); + this.automaticRetries.Maximum = new decimal(new int[] { + 50, + 0, + 0, + 0}); + this.automaticRetries.Name = "automaticRetries"; + this.automaticRetries.Size = new System.Drawing.Size(88, 22); + this.automaticRetries.TabIndex = 3; + this.toolTip1.SetToolTip(this.automaticRetries, "Defines the number of files we try to upload at the same time"); + this.automaticRetries.Value = new decimal(new int[] { + 3, + 0, + 0, + 0}); + // + // linkLabel1 + // + this.linkLabel1.AutoSize = true; + this.linkLabel1.Location = new System.Drawing.Point(811, 42); + this.linkLabel1.Name = "linkLabel1"; + this.linkLabel1.Size = new System.Drawing.Size(103, 17); + this.linkLabel1.TabIndex = 8; + this.linkLabel1.TabStop = true; + this.linkLabel1.Text = "Documentation"; + this.toolTip1.SetToolTip(this.linkLabel1, "Opens up the wiki page documenting this tool"); + this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked); + // + // CancelAsync + // + this.CancelAsync.Location = new System.Drawing.Point(526, 39); + this.CancelAsync.Name = "CancelAsync"; + this.CancelAsync.Size = new System.Drawing.Size(78, 27); + this.CancelAsync.TabIndex = 6; + this.CancelAsync.Text = "Cancel Upload"; + this.CancelAsync.UseVisualStyleBackColor = true; + this.CancelAsync.Visible = false; + this.CancelAsync.Click += new System.EventHandler(this.CancelAsync_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(15, 0); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(203, 17); + this.label1.TabIndex = 6; + this.label1.Text = "Number of simultanous uplads:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(362, 2); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(154, 17); + this.label2.TabIndex = 8; + this.label2.Text = "Upload part size in MB:"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.BackColor = System.Drawing.SystemColors.Control; + this.label3.Location = new System.Drawing.Point(630, 0); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(177, 17); + this.label3.TabIndex = 10; + this.label3.Text = "Automatic retries on failure"; + // + // RetryTimer + // + this.RetryTimer.Interval = 6000; + this.RetryTimer.Tick += new System.EventHandler(this.RetryTimer_Tick); + // + // panel1 + // + this.panel1.Controls.Add(this.linkLabel1); + this.panel1.Controls.Add(this.label3); + this.panel1.Controls.Add(this.automaticRetries); + this.panel1.Controls.Add(this.CancelAsync); + this.panel1.Controls.Add(this.ChunkSize); + this.panel1.Controls.Add(this.Upload); + this.panel1.Controls.Add(this.label2); + this.panel1.Controls.Add(this.ChooseOutputFile); + this.panel1.Controls.Add(this.MaxQueue); + this.panel1.Controls.Add(this.OpenCSVFile); + this.panel1.Controls.Add(this.label1); + this.panel1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.panel1.Location = new System.Drawing.Point(0, 388); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(945, 78); + this.panel1.TabIndex = 12; + // + // YouTubeUploader + // + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(945, 466); + this.Controls.Add(this.panel1); + this.Controls.Add(this.csvDisplayGrid); + this.Name = "YouTubeUploader"; + this.Text = "YouTubeUploader"; + this.Load += new System.EventHandler(this.YouTubeUploader_Load); + ((System.ComponentModel.ISupportInitialize)(this.csvDisplayGrid)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.MaxQueue)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.ChunkSize)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.automaticRetries)).EndInit(); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.OpenFileDialog chooseCSVFile; + private System.Windows.Forms.Button OpenCSVFile; + private System.Windows.Forms.Button ChooseOutputFile; + private System.Windows.Forms.Button Upload; + private System.Windows.Forms.DataGridView csvDisplayGrid; + private System.Windows.Forms.SaveFileDialog saveOutput; + private System.Windows.Forms.ToolTip toolTip1; + private System.Windows.Forms.Button CancelAsync; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.NumericUpDown MaxQueue; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.NumericUpDown ChunkSize; + private System.Windows.Forms.NumericUpDown automaticRetries; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Timer RetryTimer; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.LinkLabel linkLabel1; + } +} + diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/YouTubeUploader.resx gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/YouTubeUploader.resx --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader/YouTubeUploader.resx 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader/YouTubeUploader.resx 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 300, 17 + + + 169, 17 + + + 409, 17 + + \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader.Readme.txt gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader.Readme.txt --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader.Readme.txt 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader.Readme.txt 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,103 @@ +The YouTube Content Uploader is a sample of the Resumable Upload functionallity +in the API. It allows you to open up a .CSV file, containing metadata of new +videos you want to upload, then let the tool upload all those files in the +background. + +Note the CSV files should look like this: + +Title,Description,Tags,Category,Private,Path +(one),The first test video,"water",Education,TRUE,c:\videos\file2one.avi +(two),The second test video,"humor",Entertainment,TRUE,c:\videos\filetwo.avi + +Some spreadsheet programs might export a spreadsheet with blank columnheaders, like this: + +Title,Description,Tags,Category,Private,Path,,,,,,,,,,,,, + +The code used to parse CSVs in YouTubeUploader will choke on that. So make sure your +CSV file is done with the correct settings to create only the columns that are used. + +When you compile the sample, or use the provided binary, it will use a default +YouTube developer key, that will probably be too limited for your use case. + +You should replace that developer key with your own. + +There are 2 ways of doing so. Download the source code and replace the developer +key with your own, recompile and you are good to go. + +Alternatively, you can use the config file to provide your own key. + +.NET config files are a standard way in the .NET runtime to augment applications +and provide configuration information. + +To use such a file, you need to find the .EXE file you want to modify, +and create a .config file in the same directory. + +So for the YouTubeUploader.exe, you would create a file called +YouTubeUploader.exe.config. + +This is a normal text file, and it should look like this: + + + + + + + + + + + + + + + + +You have a standard key=value section, where you need to replace the sample values +above with whatever you want to have. + +Note, all the values are optional. So it's perfectly fine to have a file looking +like this: + + + + + + + + +if all you want to change is the default for the retry value. + +Here is an explanation of all the parameters: + +UserName -> your google account username +PassWord -> the password for that account +YoutubeAccount -> the youtube accountname + +If you provide the above 3 values, the application will, on startup, skip the +login dialog and use the provided values instaead. + +MaxThreads -> this value determines how many uploads will happen at the same time. + You can try to tune this to maximize the upload bandwidth used. + +ChunkSize -> this value determines how many Megabytes of the files will be uploaded + at once. Let's say you have a 1GB video and this value is 4, the + application will upload 250 parts of the video before it's done. Again, + you can try to finetune this depending on bandwidth available. + +RetryCount -> if an upload fails due to network or other conditions, it will be retried. + The application will stop trying to upload a file once it's retry + counter reaches this number. Note, once ANY upload succeeds, all retry + counters will be reset to 0 and the files will be tried again. + +CsvFile -> the filename of a CSV file to open on startup +OutputFile -> the filename of an output CSV file where the application should + save the results of the upload to + +DevKey -> your YouTube developer key that you like to use for uploading to + your account. + + +There is one additional parameter, that can be used on the commandline. If you start +YouTubeUploader with the /autostart parameter, it will start uploading and +saving the output automatically once it's done. + diff -Nru gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader.sln gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader.sln --- gdata-sharp-1.4.0.2/samples/YouTubeUploader/YouTubeUploader.sln 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/samples/YouTubeUploader/YouTubeUploader.sln 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YouTubeUploader", "YouTubeUploader\YouTubeUploader.csproj", "{725130CA-A753-45A8-855F-EA22728E3F95}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LumenWorks.Framework.IO", "LumenWorks.Framework.IO\LumenWorks.Framework.IO.csproj", "{E3B83D68-C90C-4874-8E5F-DEC8D038BC7C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {725130CA-A753-45A8-855F-EA22728E3F95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {725130CA-A753-45A8-855F-EA22728E3F95}.Debug|Any CPU.Build.0 = Debug|Any CPU + {725130CA-A753-45A8-855F-EA22728E3F95}.Release|Any CPU.ActiveCfg = Release|Any CPU + {725130CA-A753-45A8-855F-EA22728E3F95}.Release|Any CPU.Build.0 = Release|Any CPU + {E3B83D68-C90C-4874-8E5F-DEC8D038BC7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E3B83D68-C90C-4874-8E5F-DEC8D038BC7C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E3B83D68-C90C-4874-8E5F-DEC8D038BC7C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E3B83D68-C90C-4874-8E5F-DEC8D038BC7C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff -Nru gdata-sharp-1.4.0.2/src/analytics/accountentry.cs gdata-sharp-1.7.0.1/src/analytics/accountentry.cs --- gdata-sharp-1.4.0.2/src/analytics/accountentry.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/analytics/accountentry.cs 2010-04-06 13:06:49.000000000 +0000 @@ -0,0 +1,132 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* Created by Morten Christensen, elpadrinodk@gmail.com, http://blog.sitereactor.dk */ +using System.Collections.Generic; +using Google.GData.Client; +using Google.GData.Extensions; + +namespace Google.GData.Analytics +{ + ////////////////////////////////////////////////////////////////////// + /// + /// AccountEntry API customization class for defining entries in an account feed. + /// + ////////////////////////////////////////////////////////////////////// + + + public class AccountEntry : AbstractEntry + { + /// + /// Lazy loading for the properties and tableId. + /// + private List properties; + private List customVariables; + private List goals; + private TableId tableId; + + /// + /// Constructs a new AccountEntry instance + /// + public AccountEntry() + : base() + { + this.AddExtension(new Property()); + this.AddExtension(new TableId()); + this.AddExtension(new CustomVariable()); + this.AddExtension(new Goal()); + } + + /// + /// This field controls the properties. + /// + public List Properties + { + get + { + if (properties == null) + { + properties = FindExtensions(AnalyticsNameTable.XmlPropertyElement, + AnalyticsNameTable.gAnalyticsNamspace); + } + return properties; + } + } + + + /// + /// searches through the property list to find a specific one + /// + /// + /// + public string FindPropertyValue(string name) + { + foreach (Property p in this.Properties) + { + if (p.Name == name) + { + return p.Value; + } + } + return null; + } + + /// + /// This field controls the tableId (ProfileId). + /// + public TableId ProfileId + { + get + { + if (tableId == null) + { + tableId = FindExtension(AnalyticsNameTable.XmlTableIdElement, + AnalyticsNameTable.gAnalyticsNamspace) as TableId; + } + return tableId; + } + } + + /// + /// This field controls the Custom Variables. + /// + public List CustomVariables + { + get + { + if (customVariables == null) + { + customVariables = FindExtensions(AnalyticsNameTable.XmlCustomVariableElement, + AnalyticsNameTable.gaNamespace); + } + return customVariables; + } + } + + /// + /// This field controls the goals. + /// + public List Goals + { + get + { + if (goals == null) + { + goals = FindExtensions(AnalyticsNameTable.XmlGoalElement, AnalyticsNameTable.gaNamespace); + } + return goals; + } + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/analytics/accountfeed.cs gdata-sharp-1.7.0.1/src/analytics/accountfeed.cs --- gdata-sharp-1.4.0.2/src/analytics/accountfeed.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/analytics/accountfeed.cs 2010-04-06 13:06:49.000000000 +0000 @@ -0,0 +1,84 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* Created by Morten Christensen, elpadrinodk@gmail.com, http://blog.sitereactor.dk */ +using System; +using Google.GData.Client; +using System.Collections.Generic; + +namespace Google.GData.Analytics +{ + ////////////////////////////////////////////////////////////////////// + /// + /// This is the Google Analytics Account feed that lets you access + /// the analytics account you own. + /// + ////////////////////////////////////////////////////////////////////// + public class AccountFeed : AbstractFeed + { + + private List segments; + + /// + /// default constructor + /// + /// the base URI of the feedEntry + /// the Service to use + public AccountFeed(Uri uriBase, IService iService) + : base(uriBase, iService) + { + AddExtension(new Segment()); + + + } + + /// + /// This needs to get implemented by subclasses + /// + /// AtomEntry + public override AtomEntry CreateFeedEntry() + { + return new AccountEntry(); + } + + /// + /// Is called after we already handled the custom entry, to handle all + /// other potential parsing tasks + /// + /// + /// the atom feed parser used + protected override void HandleExtensionElements(ExtensionElementEventArgs e, + AtomFeedParser parser) + { + base.HandleExtensionElements(e, parser); + } + + + /// + /// This field controls the segments. + /// + public List Segments + { + get + { + if (segments == null) + { + segments = FindExtensions(AnalyticsNameTable.XmlSegmentElement, + AnalyticsNameTable.gAnalyticsNamspace); + } + return segments; + } + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/analytics/accountquery.cs gdata-sharp-1.7.0.1/src/analytics/accountquery.cs --- gdata-sharp-1.4.0.2/src/analytics/accountquery.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/analytics/accountquery.cs 2010-04-20 14:14:26.000000000 +0000 @@ -0,0 +1,50 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* Created by Morten Christensen, elpadrinodk@gmail.com, http://blog.sitereactor.dk */ +using Google.GData.Client; + +namespace Google.GData.Analytics +{ + ////////////////////////////////////////////////////////////////////// + /// + /// A subclass of FeedQuery, to create an Analytics Account query URI. + /// + ////////////////////////////////////////////////////////////////////// + public class AccountQuery : FeedQuery + { + /// + /// Analytics account service url, http and https + /// + + public const string HttpsFeedUrl = "https://www.google.com/analytics/feeds/accounts/default"; + + /// + /// default constructor, does nothing + /// + public AccountQuery() + : base(HttpsFeedUrl) + { + } + + /// + /// base constructor, with initial queryUri + /// + /// the query to use + public AccountQuery(string queryUri) + : base(queryUri) + { + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/analytics/aggregates.cs gdata-sharp-1.7.0.1/src/analytics/aggregates.cs --- gdata-sharp-1.4.0.2/src/analytics/aggregates.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/analytics/aggregates.cs 2009-05-26 12:48:22.000000000 +0000 @@ -0,0 +1,59 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* Created by Alex Maitland, maitlandalex@gmail.com */ +using System.Collections.Generic; +using System.Xml; +using Google.GData.Client; +using Google.GData.Extensions; + +namespace Google.GData.Analytics +{ + /// + /// GData schema extension describing aggregate results. + /// dxp:aggregates contains aggregate data for all metrics requested in the feed. + /// + public class Aggregates : SimpleContainer + { + + private List metrics; + + + /// + /// default constructor for dxp:aggregates + /// + public Aggregates() : + base(AnalyticsNameTable.XmlAggregatesElement, + AnalyticsNameTable.gAnalyticsPrefix, + AnalyticsNameTable.gAnalyticsNamspace) + { + this.ExtensionFactories.Add(new Metric()); + } + + /// + /// property accessor for the Thumbnails + /// + public List Metrics + { + get + { + if (this.metrics == null) + { + this.metrics = FindExtensions(AnalyticsNameTable.XmlMetricElement, AnalyticsNameTable.gAnalyticsNamspace); + } + return this.metrics; + } + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/analytics/Analytics.csproj gdata-sharp-1.7.0.1/src/analytics/Analytics.csproj --- gdata-sharp-1.4.0.2/src/analytics/Analytics.csproj 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/analytics/Analytics.csproj 2010-04-06 13:06:49.000000000 +0000 @@ -0,0 +1,99 @@ + + + Debug + AnyCPU + 2.0 + {A7BA16A4-7636-46CA-AAAD-3CB3361ECD40} + Library + Properties + Google.GData.Analytics + Google.GData.Analytics + true + analytics.sn + + + 2.0 + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + bin\analytics.xml + + + bin\ASP\ + TRACE;PARTIALLY_TRUSTED + true + pdbonly + AnyCPU + prompt + + + + + + + + + AssemblyVersion.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + {B6F6D938-0D45-42BA-8A67-55D92EF03995} + Core Client + + + {21BCB644-F9C3-4ADC-8BE1-4E55C6565011} + Common Data Extensions + + + + + + + + \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/src/analytics/analyticsrequest.cs gdata-sharp-1.7.0.1/src/analytics/analyticsrequest.cs --- gdata-sharp-1.4.0.2/src/analytics/analyticsrequest.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/analytics/analyticsrequest.cs 2009-05-29 12:04:04.000000000 +0000 @@ -0,0 +1,359 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + + +using System; +using System.IO; +using System.Collections; +using System.Text; +using System.Net; +using Google.GData.Client; +using Google.GData.Extensions; +using Google.GData.Analytics; +using System.Collections.Generic; + +namespace Google.Analytics +{ + /// + /// simple class to cover the AcountEntry specific extensions. Gives you access to all Account + /// specific properties inisde an account feed. + /// + /// + public class Account : Entry + { + /// + /// creates the inner contact object when needed + /// + /// + protected override void EnsureInnerObject() + { + if (this.AtomEntry == null) + { + this.AtomEntry = new AccountEntry(); + } + } + /// + /// readonly accessor to the typed underlying atom object + /// + public AccountEntry AccountEntry + { + get + { + return this.AtomEntry as AccountEntry; + } + } + + /// + /// The web property ID associated with the profile. + /// + /// + public string WebPropertyId + { + get + { + if (this.AccountEntry != null) + { + return this.AccountEntry.FindPropertyValue("ga:webPropertyId"); + } + return null; + } + } + + /// + /// The name of the account associated with the profile + /// + /// + public string AccountName + { + get + { + if (this.AccountEntry != null) + { + return this.AccountEntry.FindPropertyValue("ga:accountName"); + } + return null; + } + } + + /// + /// The id of the account associated with the profile + /// used in the tracking code for your web property (e.g. UA-30481-22). + /// + /// + public string AccountId + { + get + { + if (this.AccountEntry != null) + { + return this.AccountEntry.FindPropertyValue("ga:accountId"); + } + return null; + } + } + + /// + /// The numberic id of the profile + /// + /// + public string ProfileId + { + get + { + if (this.AccountEntry != null) + { + return this.AccountEntry.FindPropertyValue("ga:profileId"); + } + return null; + } + } + + /// + /// The unique, namespaced ID to be used when requesting data from a profile. + /// + /// + public string TableId + { + get + { + if (this.AccountEntry != null) + { + TableId t = this.AccountEntry.ProfileId; + if (t != null) + { + return t.Value; + } + } + return null; + } + } + } + + + /// + /// simple class to cover the DataEntry specific extensions. Gives you access to all Data + /// specific properties inisde an data feed. + /// + /// + public class Data : Entry + { + /// + /// creates the inner contact object when needed + /// + /// + protected override void EnsureInnerObject() + { + if (this.AtomEntry == null) + { + this.AtomEntry = new DataEntry(); + } + } + /// + /// readonly accessor to the typed underlying atom object + /// + public DataEntry DataEntry + { + get + { + return this.AtomEntry as DataEntry; + } + } + + + /// + /// This field controls the dimensions. + /// + public List Dimensions + { + get + { + if (this.DataEntry != null) + { + return this.DataEntry.Dimensions; + } + return null; + } + } + + /// + /// This field controls the metrics. + /// + public List Metrics + { + get + { + if (this.DataEntry != null) + { + return this.DataEntry.Metrics; + } + return null; + } + } + } + + + /// + /// subclass of a Feed, specific to Data entries + /// + /// + public class Dataset : Feed + { + + /// + /// default constructor that takes the underlying atomfeed + /// + /// + public Dataset(AtomFeed af) : base(af) + { + } + + /// + /// constructs a new feed object based on a service and a query + /// + /// + /// + public Dataset(Service service, FeedQuery q) + : base(service, q) + { + } + + /// + /// returns the Aggregates object that contains aggregate data for all metrics requested in the feed + /// + /// + public Aggregates Aggregates + { + get + { + Google.GData.Analytics.DataFeed f = this.AtomFeed as Google.GData.Analytics.DataFeed; + if (f != null) + { + return f.Aggregates; + } + return null; + } + } + + /// + /// returns the Aggregates object that contains aggregate data for all metrics requested in the feed + /// + /// + public DataSource DataSource + { + get + { + DataFeed f = this.AtomFeed as DataFeed; + if (f != null) + { + return f.DataSource; + } + return null; + } + } + } + + + ////////////////////////////////////////////////////////////////////// + /// + /// With the Google Analytics Data Export API, you can develop client + /// applications that download Analytics data in the form of Google Data API feeds. + /// Your client application can use the Data Export API to request data from + /// an existing Analytics profile for an authorized user, and refine the + /// results of the request using query parameters. Currently, the Data Export API + /// supports read-only access to your Google Analytics data. + /// + /// + /// The following code illustrates a possible use of + /// the AnalyticsRequest object: + /// + /// RequestSettings settings = new RequestSettings("yourApp"); + /// settings.PageSize = 50; + /// settings.AutoPaging = true; + /// AnalyticsRequest f = new AnalyticsRequest(settings); + /// Feed feed = f.GetAccounts(); + /// + /// foreach (Account a in feed.Entries) + /// { + /// } + /// + /// + ////////////////////////////////////////////////////////////////////// + public class AnalyticsRequest : FeedRequest + { + + /// + /// default constructor for a YouTubeRequest + /// + /// + public AnalyticsRequest(RequestSettings settings) : base(settings) + { + this.Service = new AnalyticsService(settings.Application); + PrepareService(); + } + + /// + /// returns a Feed of accounts for the authenticated user + /// + /// the username + /// a feed of Account objects + public Feed GetAccounts() + { + AccountQuery q = PrepareQuery(AccountQuery.HttpsFeedUrl); + return PrepareFeed(q); + } + + + /// + /// returns a Data Feed per passed in Query. The AnalyticsRequestObject + /// will modidify the passed in Query object to take the default RequestObject settings into + /// account (like paging). if you do not want that behaviour, use the Get method + /// + /// + /// + public Dataset GetReport(DataQuery q) + { + PrepareQuery(q); + return PrepareFeed(q) as Dataset; + } + + /// + /// gets a feed object of type T + /// + /// + /// The Uri to retrieve + /// + public Dataset Get(DataQuery q) + { + return PrepareFeed(q) as Dataset; + } + + + /// + /// the virtual creator function for feeds, so that we can create feedsubclasses in + /// in subclasses of the request + /// + /// + /// + protected override Feed CreateFeed(FeedQuery q) + { + if (typeof(Y) == typeof(Data)) + { + return new Dataset(this.AtomService, q) as Feed; + } + return base.CreateFeed(q); + } + + } +} diff -Nru gdata-sharp-1.4.0.2/src/analytics/analyticsservice.cs gdata-sharp-1.7.0.1/src/analytics/analyticsservice.cs --- gdata-sharp-1.4.0.2/src/analytics/analyticsservice.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/analytics/analyticsservice.cs 2010-04-06 13:06:49.000000000 +0000 @@ -0,0 +1,189 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* Created by Morten Christensen, elpadrinodk@gmail.com, http://blog.sitereactor.dk */ +using System; +using Google.GData.Client; + +namespace Google.GData.Analytics +{ + + #region Ananlytics specific constants + + public class AnalyticsNameTable + { + + // GData GA extension namespace + public const string gaNamespace = "http://schemas.google.com/ga/2009"; + /// prefix for GA namespace if writing + public const string gaPrefix = "ga"; + // GData analytics extension namespace + public const string gAnalyticsNamspace = "http://schemas.google.com/analytics/2009"; + /// prefix for gAnalyticsNamspace if writing + public const string gAnalyticsPrefix = "dxp"; + /** Dxp (Dxp) namespace prefix */ + public const string DxpPrefix = gAnalyticsNamspace + "#"; + /// xmlelement for dxp:aggregates + public const string XmlAggregatesElement = "aggregates"; + /// xmlelement for dxp:dimension + public const string XmlDimensionElement = "dimension"; + /// xmlelement for dxp:metric + public const string XmlMetricElement = "metric"; + /// xmlelement for dxp:property + public const string XmlPropertyElement = "property"; + /// xmlelement for dxp:tableId + public const string XmlTableIdElement = "tableId"; + /// xmlelement for dxp:tableName + public const string XmlTableNameElement = "tableName"; + /// xmlelement for dxp:dataSource + public const string XmlDataSourceElement = "dataSource"; + /// xml attribute name for dxp:dimension, dxp:metric and dxp:property + public const string XmlAttributeName = "name"; + /// xml attribute value for dxp:dimension, dxp:metric and dxp:property + public const string XmlAttributeValue = "value"; + /// xml attribute confidenceInterval for dxp:metric + public const string XmlAttributeConfidenceInterval = "confidenceInterval"; + + /// xml attribute number for ga:goal and ga:step + public const string XmlAttributeNumber = "number"; + /// xml attribute active for ga:goal + public const string XmlAttributeActive = "active"; + /// xmlelement for dxp:segment + public const string XmlSegmentElement = "segment"; + /// xml attribute id for dxp:segment + public const string XmlAttributeId = "id"; + /// xmlelement definition for ga:goal + public const string XmlGoalElement = "goal"; + /// xmlelement definition for ga:engagement + public const string XmlDefinitionElement = "definition"; + + /// xmlelement destination for ga:destination + public const string XmlDestinationElement = "destination"; + /// xml attribute caseSensitive for ga:destination + public const string XmlAttributeCaseSensitive = "caseSensitive"; + /// xmlelement expression for ga:destination + public const string XmlAttributeExpression = "expression"; + /// xmlelement matchType for ga:destination + public const string XmlAttributeMatchType = "matchType"; + /// xmlelement step1Required for ga:destination + public const string XmlAttributeStep1Required = "step1Required"; + + /// xmlelement definition for ga:step + public const string XmlStepElement = "step"; + /// xml attribute path for ga:step + public const string XmlAttributePath = "path"; + + /// xmlelement engagement for ga:engagement + public const string XmlEngagementElement = "engagement"; + /// xml attribute comparison for ga:destination + public const string XmlAttributeComparison = "comparison"; + /// xml attribute thresholdValue for ga:destination + public const string XmlAttributeThresholdValue = "thresholdValue"; + /// xml attribute type for ga:destination + public const string XmlAttributeType = "type"; + + /// xmlelement customVariable for ga:customVariable + public const string XmlCustomVariableElement = "customVariable"; + /// xml attribute index for ga:customVariable + public const string XmlAttributeIndex = "index"; + /// xml attribute scope for ga:customVariable + public const string XmlAttributeScope = "scope"; + + + + + + } + #endregion + + /// + /// The AnalyticsService class extends the basic Service abstraction + /// to define a service that is preconfigured for access to the + /// Google Analytics data API. + /// + public class AnalyticsService : Service + { + /// The Analytics service's name + public const string GAnalyticsService = "analytics"; + + /// + /// default constructor + /// + /// the applicationname + public AnalyticsService(string applicationName) + : base(GAnalyticsService, applicationName) + { + this.NewFeed += new ServiceEventHandler(this.OnNewFeed); + } + + /// + /// overloaded to create typed version of Query + /// + /// + /// AccountFeed + public AccountFeed Query(AccountQuery feedQuery) + { + return base.Query(feedQuery) as AccountFeed; + } + + /// + /// overloaded to create typed version of Query + /// + /// + /// DataFeed + public DataFeed Query(DataQuery feedQuery) + { + return base.Query(feedQuery) as DataFeed; + } + + /// + /// by default all services now use version 1 for the protocol. + /// this needs to be overridden by a service to specify otherwise. + /// YouTube uses version 2 + /// + /// + protected override void InitVersionInformation() + { + this.ProtocolMajor = VersionDefaults.VersionTwo; + } + + ////////////////////////////////////////////////////////////////////// + /// eventchaining. We catch this by from the base service, which + /// would not by default create an atomFeed + /// the object which send the event + /// FeedParserEventArguments, holds the feedentry + /// + ////////////////////////////////////////////////////////////////////// + protected void OnNewFeed(object sender, ServiceEventArgs e) + { + Tracing.TraceMsg("Created new Analytics Feed"); + if (e == null) + { + throw new ArgumentNullException("e"); + } + // do not use string.contains, does not exist on CF framework + if (e.Uri.AbsolutePath.IndexOf("/analytics/feeds/accounts/") != -1) + { + //https://www.google.com/analytics/feeds/accounts/default + e.Feed = new AccountFeed(e.Uri, e.Service); + } + else + { + //https://www.google.com/analytics/feeds/data + e.Feed = new DataFeed(e.Uri, e.Service); + } + } + ///////////////////////////////////////////////////////////////////////////// + } +} Binary files /tmp/UhUzKTrMiD/gdata-sharp-1.4.0.2/src/analytics/analytics.sn and /tmp/kt1AG0Pm9_/gdata-sharp-1.7.0.1/src/analytics/analytics.sn differ diff -Nru gdata-sharp-1.4.0.2/src/analytics/AssemblyInfo.cs gdata-sharp-1.7.0.1/src/analytics/AssemblyInfo.cs --- gdata-sharp-1.4.0.2/src/analytics/AssemblyInfo.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/analytics/AssemblyInfo.cs 2009-05-20 09:45:51.000000000 +0000 @@ -0,0 +1,25 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +using System.Reflection; +using System.Runtime.CompilerServices; + + +[assembly: AssemblyDelaySign(false)] +[assembly: AssemblyKeyName("")] + +[assembly: AssemblyTitle("Google Data API Analytics Library")] + + + diff -Nru gdata-sharp-1.4.0.2/src/analytics/customvariable.cs gdata-sharp-1.7.0.1/src/analytics/customvariable.cs --- gdata-sharp-1.4.0.2/src/analytics/customvariable.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/analytics/customvariable.cs 2010-04-06 13:06:49.000000000 +0000 @@ -0,0 +1,96 @@ +/* Copyright (c) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using Google.GData.Analytics; +using Google.GData.Extensions; +using Google.GData.Client; + +namespace Google.GData.Analytics +{ + public class CustomVariable : SimpleElement + { + public CustomVariable() + : base(AnalyticsNameTable.XmlCustomVariableElement, + AnalyticsNameTable.gaPrefix, + AnalyticsNameTable.gaNamespace) + { + this.Attributes.Add(AnalyticsNameTable.XmlAttributeIndex, null); + this.Attributes.Add(BaseNameTable.XmlName, null); + this.Attributes.Add(AnalyticsNameTable.XmlAttributeScope, null); + } + + public CustomVariable(String comparison, String thresholdValue, String type) + : base(AnalyticsNameTable.XmlCustomVariableElement, + AnalyticsNameTable.gaPrefix, + AnalyticsNameTable.gaNamespace) + { + this.Attributes.Add(AnalyticsNameTable.XmlAttributeIndex, null); + this.Attributes.Add(BaseNameTable.XmlName, null); + this.Attributes.Add(AnalyticsNameTable.XmlAttributeScope, null); + } + + ////////////////////////////////////////////////////////////////////// + /// Accessor for "Index" attribute. + /// + ////////////////////////////////////////////////////////////////////// + public string Index + { + get + { + return this.Attributes[AnalyticsNameTable.XmlAttributeIndex] as string; + } + set + { + this.Attributes[AnalyticsNameTable.XmlAttributeIndex] = value; + } + } + + + ////////////////////////////////////////////////////////////////////// + /// Accessor for "Name" attribute. + /// + ////////////////////////////////////////////////////////////////////// + public string Name + { + get + { + return this.Attributes[AnalyticsNameTable.XmlAttributeName] as string; + } + set + { + this.Attributes[AnalyticsNameTable.XmlAttributeName] = value; + } + } + + ////////////////////////////////////////////////////////////////////// + /// Accessor for "Scope" attribute. + /// + ////////////////////////////////////////////////////////////////////// + public string Scope + { + get + { + return this.Attributes[AnalyticsNameTable.XmlAttributeScope] as string; + } + set + { + this.Attributes[AnalyticsNameTable.XmlAttributeScope] = value; + } + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/analytics/dataentry.cs gdata-sharp-1.7.0.1/src/analytics/dataentry.cs --- gdata-sharp-1.4.0.2/src/analytics/dataentry.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/analytics/dataentry.cs 2009-05-20 09:45:51.000000000 +0000 @@ -0,0 +1,126 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* Created by Morten Christensen, elpadrinodk@gmail.com, http://blog.sitereactor.dk */ +using System.Collections.Generic; +using Google.GData.Client; +using Google.GData.Extensions; + +namespace Google.GData.Analytics +{ + ////////////////////////////////////////////////////////////////////// + /// + /// DataEntry API customization class for defining entries in a data feed. + /// + ////////////////////////////////////////////////////////////////////// + public class DataEntry : AbstractEntry + { + /// + /// Lazy loading for the dimensions and metrics. + /// + private List dimensions; + private List metrics; + + /// + /// Constructs a new DataEntry. + /// + public DataEntry() + : base() + { + this.AddExtension(new Dimension()); + this.AddExtension(new Metric()); + } + + /// + /// Basic method for retrieving Data extension elements. + /// + /// The name of the extension element to look for + /// SimpleAttribute, or NULL if the extension was not found + public SimpleAttribute getDataExtension(string extension) + { + return FindExtension(extension, AnalyticsNameTable.gAnalyticsNamspace) as SimpleAttribute; + } + + /// + /// Base method for retrieving Data extension element values. + /// + /// The name of the Data extension element to look for + /// value as string, or NULL if the extension was not found + public string getAccountExtensionValue(string extension) + { + SimpleAttribute e = getDataExtension(extension); + if (e != null) + { + return (string)e.Value; + } + return null; + } + + /// + /// Base method for setting Data extension element values. + /// + /// the name of the extension to look for + /// the new value for this extension element + /// SimpleAttribute, either a brand new one, or the one + /// returned by the service + public SimpleElement setDataExtension(string extension, string newValue) + { + if (extension == null) + { + throw new System.ArgumentNullException("extension"); + } + + SimpleAttribute ele = getDataExtension(extension); + if (ele == null) + { + ele = CreateExtension(extension, AnalyticsNameTable.gAnalyticsNamspace) as SimpleAttribute; + this.ExtensionElements.Add(ele); + } + + ele.Value = newValue; + + return ele; + } + + /// + /// This field controls the dimensions. + /// + public List Dimensions + { + get + { + if (dimensions == null) + { + dimensions = FindExtensions(AnalyticsNameTable.XmlDimensionElement, AnalyticsNameTable.gAnalyticsNamspace); + } + return dimensions; + } + } + + /// + /// This field controls the metrics. + /// + public List Metrics + { + get + { + if (metrics == null) + { + metrics = FindExtensions(AnalyticsNameTable.XmlMetricElement, AnalyticsNameTable.gAnalyticsNamspace); + } + return metrics; + } + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/analytics/datafeed.cs gdata-sharp-1.7.0.1/src/analytics/datafeed.cs --- gdata-sharp-1.4.0.2/src/analytics/datafeed.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/analytics/datafeed.cs 2010-04-06 13:06:49.000000000 +0000 @@ -0,0 +1,90 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* Created by Morten Christensen, elpadrinodk@gmail.com, http://blog.sitereactor.dk */ +using System; +using Google.GData.Client; +using Google.GData.Extensions; +using System.Collections.Generic; + +namespace Google.GData.Analytics +{ + ////////////////////////////////////////////////////////////////////// + /// DataFeed, entry + /// Returns DataEntry containing: + /// id, updated, title, dxp:dimension, dxp:metric. + /// Added Extension dxp:aggregates, which contains a list of dxp:metric. + /// + ////////////////////////////////////////////////////////////////////// + public class DataFeed : AbstractFeed + { + + private List segments; + + /// + /// default constructor + /// + /// the base URI of the feedEntry + /// the Service to use + public DataFeed(Uri uriBase, IService iService) : base(uriBase, iService) + { + AddExtension(new Aggregates()); + AddExtension(new DataSource()); + AddExtension(new Segment()); + + } + + /// + /// This needs to get implemented by subclasses + /// + /// AtomEntry + public override AtomEntry CreateFeedEntry() + { + return new DataEntry(); + } + + /// + /// returns the Aggregates object for the DataFeed. + /// + /// + public Aggregates Aggregates + { + get { return FindExtension(AnalyticsNameTable.XmlAggregatesElement, AnalyticsNameTable.gAnalyticsNamspace) as Aggregates; } + } + + /// + /// returns the DataSource object for the DataFeed. + /// + /// + public DataSource DataSource + { + get { return FindExtension(AnalyticsNameTable.XmlDataSourceElement, AnalyticsNameTable.gAnalyticsNamspace) as DataSource; } + } + + /// + /// This field controls the segments. + /// + public List Segments + { + get + { + if (segments == null) + { + segments = FindExtensions(AnalyticsNameTable.XmlSegmentElement, AnalyticsNameTable.gAnalyticsNamspace); + } + return segments; + } + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/analytics/dataquery.cs gdata-sharp-1.7.0.1/src/analytics/dataquery.cs --- gdata-sharp-1.4.0.2/src/analytics/dataquery.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/analytics/dataquery.cs 2010-04-20 14:14:26.000000000 +0000 @@ -0,0 +1,368 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* Created by Morten Christensen, elpadrinodk@gmail.com, http://blog.sitereactor.dk */ +using System; +using System.Globalization; +using System.Text; +using Google.GData.Client; + +namespace Google.GData.Analytics +{ + ////////////////////////////////////////////////////////////////////// + /// + /// A subclass of FeedQuery, to create an Analytics Data query URI. + /// + ////////////////////////////////////////////////////////////////////// + public class DataQuery : FeedQuery + { + public const string dataFeedUrl = "https://www.google.com/analytics/feeds/data"; + + /// Row keys. + private string dimensions; + + /// Last day for which to retrieve data in form YYYY-MM-DD. + private string endDate; + + /// Dimension value filters. + private string filters; + + /// Advanced Segment, either dynamic or by index + private string segment; + + /// Google Analytics profile ID, prefixed by 'ga:'. + private string ids; + + /// Comma separated list of numeric value fields. + private string metrics; + + /// Comma separated list of sort keys in order of importance. + private string sort; + + /// First day for which to retrieve data in form YYYY-MM-DD. + private string startDate; + + /// Optional. Adds extra whitespace to the feed XML to make it more readable. + private bool? prettyPrint; + + + + /// + /// default constructor, constructs a query to the default analytics feed with no parameters + /// + public DataQuery() : base(DataQuery.dataFeedUrl) + { + } + + /// + /// base constructor, with initial queryUri + /// + /// the query to use + public DataQuery(string queryUri) + : base(queryUri) + { + } + + + + /// + /// overloaded constructor + /// + /// the account id + /// + /// + /// + public DataQuery(string id, DateTime startDate, DateTime endDate) : base(DataQuery.dataFeedUrl) + { + this.Ids = id; + this.GAStartDate = startDate.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture); + this.GAEndDate = endDate.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture); + } + + /// + /// overloaded constructor + /// + /// the account id + /// + /// + /// + /// + /// + public DataQuery(string id, DateTime startDate, DateTime endDate, string metric, string dimension) : this(id, startDate, endDate) + { + this.Metrics = metric; + this.Dimensions = dimension; + } + + /// + /// overloaded constructor + /// + /// the account id + /// + /// + /// + /// + /// + /// + public DataQuery(string id, DateTime startDate, DateTime endDate, string metric, string dimension, string sorting) : + this(id, startDate, endDate, metric, dimension) + { + this.Sort = sorting; + } + + /// + /// overloaded constructor + /// + /// the account id + /// + /// + /// + /// + /// + /// + /// + public DataQuery(string id, DateTime startDate, DateTime endDate, string metric, string dimension, string sorting, string filters) : + this(id, startDate, endDate, metric, dimension, sorting) + + { + this.Filters = filters; + } + + /// + /// overloaded constructor + /// + /// the account id + /// + /// + /// + /// + /// + /// + /// + public DataQuery(string id, DateTime startDate, DateTime endDate, string metric, string dimension, string sorting, string filters, string segment) : + this(id, startDate, endDate, metric, dimension, sorting, filters) + { + this.Segment = segment; + } + + + + ////////////////////////////////////////////////////////////////////// + /// The primary data keys from which Analytics reports + /// are constructed. Like metrics, dimensions are also categorized by type. + /// For example, ga:pageTitle and ga:page are two Content report dimensions + /// and ga:browser, ga:city, and ga:pageDepth are two visitor dimensions. + /// Dimensions + ////////////////////////////////////////////////////////////////////// + public string Dimensions + { + get {return this.dimensions;} + set {this.dimensions = value;} + } + // end of accessor public string Dimensions + + ////////////////////////////////////////////////////////////////////// + /// Indicates the last day for which to retrieve data + /// in form YYYY-MM-DD. + /// EndDate + ////////////////////////////////////////////////////////////////////// + public string GAEndDate + { + get {return this.endDate;} + set {this.endDate = value;} + } + // end of accessor public string EndDate + + ////////////////////////////////////////////////////////////////////// + /// Indicates the dimension value filters. + /// Filters + ////////////////////////////////////////////////////////////////////// + public string Filters + { + get { return this.filters; } + set { this.filters = value; } + } + // end of accessor public string Filters + + ////////////////////////////////////////////////////////////////////// + /// Indicates the Segments. + /// Segments + ////////////////////////////////////////////////////////////////////// + + public string Segment + { + get { return this.segment; } + set { this.segment = value; } + } + // end of accessor public string Segments + + + + + ////////////////////////////////////////////////////////////////////// + /// Indicates the Google Analytics profile ID, + /// prefixed by 'ga:'. + /// Ids + ////////////////////////////////////////////////////////////////////// + public string Ids + { + get {return this.ids;} + set {this.ids = value;} + } + // end of accessor public string Ids + + ////////////////////////////////////////////////////////////////////// + /// Indicates the comma separated list of numeric value + /// fields.The aggregated statistics for user activity in a profile, + /// categorized by type. Examples of metrics include ga:clicks or ga:pageviews. + /// When queried by themselves, metrics provide an aggregate measure of user + /// activity for your profile, such as overall page views or bounce rate. + /// However, when paired with dimensions, they provide information in the context + /// of the dimension. For example, when pageviews are combined with + /// ga:countryOrTerritory, you see how many pageviews come from each country. + /// Metrics + ////////////////////////////////////////////////////////////////////// + public string Metrics + { + get {return this.metrics;} + set {this.metrics = value;} + } + // end of accessor public string Metrics + + ////////////////////////////////////////////////////////////////////// + /// Indicates the comma separated list of sort keys + /// in order of importance. + /// Sort + ////////////////////////////////////////////////////////////////////// + public string Sort + { + get {return this.sort;} + set {this.sort = value;} + } + // end of accessor public string Sort + + ////////////////////////////////////////////////////////////////////// + /// Indicates the first day for which to retrieve data + /// in form YYYY-MM-DD. + /// StartDate + ////////////////////////////////////////////////////////////////////// + public string GAStartDate + { + get {return this.startDate;} + set {this.startDate = value;} + } + // end of accessor public string StartDate + + ////////////////////////////////////////////////////////////////////// + /// Adds extra whitespace to the feed XML to make it + /// more readable. This can be set to true or false, where the + /// default is false. + /// PrettyPrint + ////////////////////////////////////////////////////////////////////// + public bool? PrettyPrint + { + get { return this.prettyPrint; } + set { this.prettyPrint = value; } + } + // end of accessor public bool PrettyPrint + +#if WindowsCE || PocketPC +#else + ////////////////////////////////////////////////////////////////////// + /// protected void ParseUri + /// takes an incoming Uri string and parses + /// all the properties out of it + /// throws a query exception when it finds something + /// wrong with the input, otherwise returns a baseuri + ////////////////////////////////////////////////////////////////////// + protected override Uri ParseUri(Uri targetUri) + { + base.ParseUri(targetUri); + if (targetUri != null) + { + char[] deli = { '?', '&' }; + + TokenCollection tokens = new TokenCollection(targetUri.Query, deli); + foreach (String token in tokens) + { + if (token.Length > 0) + { + char[] otherDeli = { '=' }; + String[] parameters = token.Split(otherDeli, 2); + switch (parameters[0]) + { + case "dimensions": + this.dimensions = parameters[1]; + break; + case "end-date": + this.endDate = parameters[1]; + break; + case "filters": + this.filters = parameters[1]; + break; + case "segment": + this.segment = parameters[1]; + break; + case "ids": + this.ids = parameters[1]; + break; + case "metrics": + this.metrics = parameters[1]; + break; + case "sort": + this.sort = parameters[1]; + break; + case "start-date": + this.startDate = parameters[1]; + break; + case "prettyprint": + this.prettyPrint = bool.Parse(parameters[1]); + break; + } + } + } + } + return this.Uri; + } +#endif + + ////////////////////////////////////////////////////////////////////// + /// Creates the partial URI query string based on all + /// set properties. + /// string => the query part of the URI + ////////////////////////////////////////////////////////////////////// + protected override string CalculateQuery(string basePath) + { + string path = base.CalculateQuery(basePath); + StringBuilder newPath = new StringBuilder(path, 2048); + char paramInsertion = InsertionParameter(path); + + paramInsertion = AppendQueryPart(this.Dimensions, "dimensions", paramInsertion, newPath); + paramInsertion = AppendQueryPart(this.GAEndDate, "end-date", paramInsertion, newPath); + paramInsertion = AppendQueryPart(this.Filters, "filters", paramInsertion, newPath); + paramInsertion = AppendQueryPart(this.Ids, "ids", paramInsertion, newPath); + paramInsertion = AppendQueryPart(this.Metrics, "metrics", paramInsertion, newPath); + paramInsertion = AppendQueryPart(this.Sort, "sort", paramInsertion, newPath); + paramInsertion = AppendQueryPart(this.GAStartDate, "start-date", paramInsertion, newPath); + paramInsertion = AppendQueryPart(this.Segment, "segment", paramInsertion, newPath); + + if (this.PrettyPrint == true) + { + paramInsertion = AppendQueryPart("true", "prettyprint", paramInsertion, newPath); + } + + return newPath.ToString(); + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/analytics/definition.cs gdata-sharp-1.7.0.1/src/analytics/definition.cs --- gdata-sharp-1.4.0.2/src/analytics/definition.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/analytics/definition.cs 2010-04-06 13:06:49.000000000 +0000 @@ -0,0 +1,46 @@ +/* Copyright (c) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + + +using System; +using System.Collections.Generic; +using System.Text; +using Google.GData.Analytics; +using Google.GData.Extensions; +using Google.GData.Client; + + +namespace Google.GData.Analytics +{ + public class Definition : SimpleElement + { + + public Definition() : base(AnalyticsNameTable.XmlDefinitionElement, + AnalyticsNameTable.gAnalyticsPrefix, + AnalyticsNameTable.gAnalyticsNamspace) + { + //this.Attributes.Add(BaseNameTable.XmlName, null); + this.Attributes.Add(AnalyticsNameTable.XmlAttributeId, null); + } + + + public Definition(String value) : base(AnalyticsNameTable.XmlDefinitionElement, + AnalyticsNameTable.gAnalyticsPrefix, + AnalyticsNameTable.gAnalyticsNamspace, value) + { + } + } +} + diff -Nru gdata-sharp-1.4.0.2/src/analytics/destination.cs gdata-sharp-1.7.0.1/src/analytics/destination.cs --- gdata-sharp-1.4.0.2/src/analytics/destination.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/analytics/destination.cs 2010-04-06 13:06:49.000000000 +0000 @@ -0,0 +1,138 @@ +/* Copyright (c) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + + +using System; +using System.Collections.Generic; +using System.Text; +using Google.GData.Analytics; +using Google.GData.Extensions; +using Google.GData.Client; + +namespace Google.GData.Analytics +{ + public class Destination : SimpleContainer + { + + private List steps; + public Destination() : base(AnalyticsNameTable.XmlDestinationElement, + AnalyticsNameTable.gaPrefix, + AnalyticsNameTable.gaNamespace) + { + this.Attributes.Add(AnalyticsNameTable.XmlAttributeCaseSensitive, null); + this.Attributes.Add(AnalyticsNameTable.XmlAttributeExpression, null); + this.Attributes.Add(AnalyticsNameTable.XmlAttributeMatchType, null); + this.Attributes.Add(AnalyticsNameTable.XmlAttributeStep1Required, null); + this.ExtensionFactories.Add(new Step()); + } + + public Destination(String caseSensitive, String expression, + String matchType, String step1Required) + : base(AnalyticsNameTable.XmlDestinationElement, + AnalyticsNameTable.gaPrefix, + AnalyticsNameTable.gaNamespace) + { + this.Attributes.Add(AnalyticsNameTable.XmlAttributeCaseSensitive, caseSensitive); + this.Attributes.Add(AnalyticsNameTable.XmlAttributeExpression, expression); + this.Attributes.Add(AnalyticsNameTable.XmlAttributeMatchType, matchType); + this.Attributes.Add(AnalyticsNameTable.XmlAttributeStep1Required, step1Required); + this.ExtensionFactories.Add(new Step()); + } + + + ////////////////////////////////////////////////////////////////////// + /// Accessor for "Step" sub-element. + /// + ////////////////////////////////////////////////////////////////////// + public List Steps + { + get + { + if (steps == null) + { + steps = FindExtensions(AnalyticsNameTable.XmlStepElement, AnalyticsNameTable.gaNamespace); + } + + return steps; + } + + } + + + ////////////////////////////////////////////////////////////////////// + /// Accessor for "caseSensitive" attribute. + /// + ////////////////////////////////////////////////////////////////////// + public string CaseSensitive + { + get + { + return this.Attributes[AnalyticsNameTable.XmlAttributeCaseSensitive] as string; + } + set + { + this.Attributes[AnalyticsNameTable.XmlAttributeCaseSensitive] = value; + } + } + + ////////////////////////////////////////////////////////////////////// + /// Accessor for "expression" attribute. + /// + ////////////////////////////////////////////////////////////////////// + public string Expression + { + get + { + return this.Attributes[AnalyticsNameTable.XmlAttributeExpression] as string; + } + set + { + this.Attributes[AnalyticsNameTable.XmlAttributeExpression] = value; + } + } + + ////////////////////////////////////////////////////////////////////// + /// Accessor for "matchType" attribute. + /// + ////////////////////////////////////////////////////////////////////// + public string MatchType + { + get + { + return this.Attributes[AnalyticsNameTable.XmlAttributeMatchType] as string; + } + set + { + this.Attributes[AnalyticsNameTable.XmlAttributeMatchType] = value; + } + } + + ////////////////////////////////////////////////////////////////////// + /// Accessor for "step1Required" attribute. + /// + ////////////////////////////////////////////////////////////////////// + public string Step1Required + { + get + { + return this.Attributes[AnalyticsNameTable.XmlAttributeStep1Required] as string; + } + set + { + this.Attributes[AnalyticsNameTable.XmlAttributeStep1Required] = value; + } + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/analytics/dimension.cs gdata-sharp-1.7.0.1/src/analytics/dimension.cs --- gdata-sharp-1.4.0.2/src/analytics/dimension.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/analytics/dimension.cs 2009-05-25 13:03:43.000000000 +0000 @@ -0,0 +1,56 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* Created by Morten Christensen, elpadrinodk@gmail.com, http://blog.sitereactor.dk */ +using System; +using System.Xml; +using Google.GData.Client; +using Google.GData.Extensions; + + +namespace Google.GData.Analytics +{ + /// + /// GData schema extension describing a dimension. + /// A dimension is part of a DataEntry (entry). + /// dxp:dimensionone element for each dimension in the query, + /// which includes the name and value of the dimension + /// + public class Dimension : SimpleNameValueAttribute + { + + /// + /// default constructor for an extended property + /// + public Dimension() : base(AnalyticsNameTable.XmlDimensionElement, + AnalyticsNameTable.gAnalyticsPrefix, + AnalyticsNameTable.gAnalyticsNamspace) + { + } + + + /// + /// default constructor with a value and a key name + /// + /// initial value + /// name for the key + public Dimension(string initName, string initValue) : base(AnalyticsNameTable.XmlDimensionElement, + AnalyticsNameTable.gAnalyticsPrefix, + AnalyticsNameTable.gAnalyticsNamspace) + { + this.Value = initValue; + this.Name = initName; + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/analytics/engagement.cs gdata-sharp-1.7.0.1/src/analytics/engagement.cs --- gdata-sharp-1.4.0.2/src/analytics/engagement.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/analytics/engagement.cs 2010-04-06 13:06:49.000000000 +0000 @@ -0,0 +1,96 @@ +/* Copyright (c) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using Google.GData.Analytics; +using Google.GData.Extensions; +using Google.GData.Client; + +namespace Google.GData.Analytics +{ + public class Engagement : SimpleElement + { + public Engagement() + : base(AnalyticsNameTable.XmlEngagementElement, + AnalyticsNameTable.gaPrefix, + AnalyticsNameTable.gaNamespace) + { + this.Attributes.Add(AnalyticsNameTable.XmlAttributeComparison, null); + this.Attributes.Add(AnalyticsNameTable.XmlAttributeThresholdValue, null); + this.Attributes.Add(AnalyticsNameTable.XmlAttributeType, null); + } + + public Engagement(String comparison, String thresholdValue, String type) + : base(AnalyticsNameTable.XmlEngagementElement, + AnalyticsNameTable.gaPrefix, + AnalyticsNameTable.gaNamespace) + { + this.Attributes.Add(AnalyticsNameTable.XmlAttributeComparison, comparison); + this.Attributes.Add(AnalyticsNameTable.XmlAttributeThresholdValue, thresholdValue); + this.Attributes.Add(AnalyticsNameTable.XmlAttributeType, type); + } + + ////////////////////////////////////////////////////////////////////// + /// Accessor for "Comparison" attribute. + /// + ////////////////////////////////////////////////////////////////////// + public string Comparison + { + get + { + return this.Attributes[AnalyticsNameTable.XmlAttributeComparison] as string; + } + set + { + this.Attributes[AnalyticsNameTable.XmlAttributeComparison] = value; + } + } + + ////////////////////////////////////////////////////////////////////// + /// Accessor for "thresholdValue" attribute. + /// + ////////////////////////////////////////////////////////////////////// + public string Threshold + { + get + { + return this.Attributes[AnalyticsNameTable.XmlAttributeThresholdValue] as string; + } + set + { + this.Attributes[AnalyticsNameTable.XmlAttributeThresholdValue] = value; + } + } + + ////////////////////////////////////////////////////////////////////// + /// Accessor for "type" attribute. + /// + ////////////////////////////////////////////////////////////////////// + public string Type + { + get + { + return this.Attributes[AnalyticsNameTable.XmlAttributeType] as string; + } + set + { + this.Attributes[AnalyticsNameTable.XmlAttributeType] = value; + } + } + + } +} diff -Nru gdata-sharp-1.4.0.2/src/analytics/goal.cs gdata-sharp-1.7.0.1/src/analytics/goal.cs --- gdata-sharp-1.4.0.2/src/analytics/goal.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/analytics/goal.cs 2010-04-06 13:06:49.000000000 +0000 @@ -0,0 +1,166 @@ +/* Copyright (c) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using Google.GData.Analytics; +using Google.GData.Extensions; +using Google.GData.Client; + +namespace Google.GData.Analytics +{ + + public class Goal : SimpleContainer + { + + private Destination destination; + private Engagement engagement; + public Goal() : base(AnalyticsNameTable.XmlGoalElement, + AnalyticsNameTable.gaPrefix, + AnalyticsNameTable.gaNamespace) + { + //this.Attributes.Add(BaseNameTable.XmlName, null); + this.Attributes.Add(AnalyticsNameTable.XmlAttributeName, null); + this.Attributes.Add(AnalyticsNameTable.XmlAttributeNumber, null); + this.Attributes.Add(AnalyticsNameTable.XmlAttributeValue, null); + this.Attributes.Add(AnalyticsNameTable.XmlAttributeActive, null); + + + this.ExtensionFactories.Add(new Destination()); + this.ExtensionFactories.Add(new Engagement()); + + + } + + + public Goal(String name, String number, String value, String active) + : base(AnalyticsNameTable.XmlSegmentElement, + AnalyticsNameTable.gaPrefix, + AnalyticsNameTable.gaNamespace) + { + this.Attributes.Add(AnalyticsNameTable.XmlAttributeName, name); + this.Attributes.Add(AnalyticsNameTable.XmlAttributeNumber, number); + this.Attributes.Add(AnalyticsNameTable.XmlAttributeValue, value); + this.Attributes.Add(AnalyticsNameTable.XmlAttributeActive, active); + + + this.ExtensionFactories.Add(new Destination()); + this.ExtensionFactories.Add(new Engagement()); + + } + + ////////////////////////////////////////////////////////////////////// + /// Accessor for "name" attribute. + /// + ////////////////////////////////////////////////////////////////////// + public string Name + { + get + { + return this.Attributes[BaseNameTable.XmlName] as string; + } + set + { + this.Attributes[BaseNameTable.XmlName] = value; + } + } + + ////////////////////////////////////////////////////////////////////// + /// Accessor for "Number" attribute. + /// + ////////////////////////////////////////////////////////////////////// + public string Number + { + get + { + return this.Attributes[AnalyticsNameTable.XmlAttributeNumber] as string; + } + set + { + this.Attributes[AnalyticsNameTable.XmlAttributeNumber] = value; + } + } + + ////////////////////////////////////////////////////////////////////// + /// Accessor for "Active" attribute. + /// + ////////////////////////////////////////////////////////////////////// + public string Active + { + get + { + return this.Attributes[AnalyticsNameTable.XmlAttributeActive] as string; + } + set + { + this.Attributes[AnalyticsNameTable.XmlAttributeActive] = value; + } + } + + ////////////////////////////////////////////////////////////////////// + /// Accessor for "value" attribute. + /// + ////////////////////////////////////////////////////////////////////// + public string Value + { + get + { + return this.Attributes[BaseNameTable.XmlValue] as string; + } + set + { + this.Attributes[BaseNameTable.XmlValue] = value; + } + } + + + + ////////////////////////////////////////////////////////////////////// + /// Accessor for "Destination" sub-element. + /// + ////////////////////////////////////////////////////////////////////// + public Destination Destination + { + get + { + if (destination == null) + { + destination = FindExtension(AnalyticsNameTable.XmlDestinationElement, + AnalyticsNameTable.gaNamespace) as Destination; + } + + return destination; + } + } + + ////////////////////////////////////////////////////////////////////// + /// Accessor for "Engagement" sub-element. + /// + ////////////////////////////////////////////////////////////////////// + public Engagement Engagement + { + get + { + if (engagement == null) + { + engagement = FindExtension(AnalyticsNameTable.XmlEngagementElement, + AnalyticsNameTable.gaNamespace) as Engagement; + } + return engagement; + } + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/analytics/metric.cs gdata-sharp-1.7.0.1/src/analytics/metric.cs --- gdata-sharp-1.4.0.2/src/analytics/metric.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/analytics/metric.cs 2009-05-26 12:48:22.000000000 +0000 @@ -0,0 +1,96 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* Created by Morten Christensen, elpadrinodk@gmail.com, http://blog.sitereactor.dk */ +using System; +using System.Xml; +using Google.GData.Client; +using Google.GData.Extensions; + +namespace Google.GData.Analytics +{ + /// + /// GData schema extension describing a metric. + /// A metric is part of a DataEntry (entry). + /// One element for each metric in the query. + /// A metric contains the following attributes: + /// # namethe name of the metric + /// # typeeither integer or string + /// # valuethe aggregate value for the query for that metric (e.g. 24 for 24 pageviews) + /// # cithe confidence interval, or range of values likely to include the correct value. + /// + public class Metric : SimpleNameValueAttribute + { + + + /// + /// Constructs an empty Metric instance + /// + public Metric() : base(AnalyticsNameTable.XmlMetricElement, + AnalyticsNameTable.gAnalyticsPrefix, + AnalyticsNameTable.gAnalyticsNamspace) + { + this.Attributes.Add(AnalyticsNameTable.XmlAttributeConfidenceInterval, null); + this.Attributes.Add(BaseNameTable.XmlAttributeType, null); + } + + /// + /// default constructor, takes 4 parameters + /// + /// the confidenceInterval property value + /// the name property value + /// the type property value + /// the value property value + public Metric(String confidenceInterval, String name, String type, String value) : + base(AnalyticsNameTable.XmlMetricElement, + AnalyticsNameTable.gAnalyticsPrefix, + AnalyticsNameTable.gAnalyticsNamspace) + { + this.Attributes.Add(AnalyticsNameTable.XmlAttributeConfidenceInterval, confidenceInterval); + this.Attributes.Add(BaseNameTable.XmlAttributeType, type); + } + + ////////////////////////////////////////////////////////////////////// + /// Accessor for "confidenceInterval" attribute. + /// + ////////////////////////////////////////////////////////////////////// + public string ConfidenceInterval + { + get + { + return this.Attributes[AnalyticsNameTable.XmlAttributeConfidenceInterval] as string; + } + set + { + this.Attributes[AnalyticsNameTable.XmlAttributeConfidenceInterval] = value; + } + } + + ////////////////////////////////////////////////////////////////////// + /// Accessor for "type" attribute. + /// + ////////////////////////////////////////////////////////////////////// + public string Type + { + get + { + return this.Attributes[BaseNameTable.XmlAttributeType] as string; + } + set + { + this.Attributes[BaseNameTable.XmlAttributeType] = value; + } + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/analytics/property.cs gdata-sharp-1.7.0.1/src/analytics/property.cs --- gdata-sharp-1.4.0.2/src/analytics/property.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/analytics/property.cs 2009-05-25 13:03:43.000000000 +0000 @@ -0,0 +1,56 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* Created by Morten Christensen, elpadrinodk@gmail.com, http://blog.sitereactor.dk */ +using System; +using System.Xml; +using Google.GData.Client; +using Google.GData.Extensions; + +namespace Google.GData.Analytics +{ + /// + /// GData schema extension describing a property. + /// Property is part of the feedentry (Data and Account feed). + /// Is a dxp:property element containing a name attribute with following + /// possible values: + /// ga:profileIdThe profile ID of the source, such as 1174 + /// ga:webPropertyIdThe web property ID of the source, such as UA-30481-1 + /// ga:accountNameThe name of the account as it appears in the Analytics interface. + /// + public class Property : SimpleNameValueAttribute + { + /// + /// Constructs an empty Property instance + /// + public Property() : base(AnalyticsNameTable.XmlPropertyElement, + AnalyticsNameTable.gAnalyticsPrefix, + AnalyticsNameTable.gAnalyticsNamspace) + { + } + + /// + /// default constructor, takes 2 parameters + /// + /// name property value + /// the value property value + public Property(String name, String value) : base(AnalyticsNameTable.XmlPropertyElement, + AnalyticsNameTable.gAnalyticsPrefix, + AnalyticsNameTable.gAnalyticsNamspace) + { + this.Name = name; + this.Value = value; + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/analytics/segment.cs gdata-sharp-1.7.0.1/src/analytics/segment.cs --- gdata-sharp-1.4.0.2/src/analytics/segment.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/analytics/segment.cs 2010-04-07 16:34:46.000000000 +0000 @@ -0,0 +1,105 @@ +/* Copyright (c) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using Google.GData.Analytics; +using Google.GData.Extensions; +using Google.GData.Client; + +namespace Google.GData.Analytics +{ + + /// + /// GData schema extension describing a Segment. + /// Segment is part of Data Feed + /// + /// + + public class Segment : SimpleContainer + { + + private Definition definition; + public Segment() : base(AnalyticsNameTable.XmlSegmentElement, + AnalyticsNameTable.gAnalyticsPrefix, + AnalyticsNameTable.gAnalyticsNamspace) + { + this.Attributes.Add(AnalyticsNameTable.XmlAttributeId, null); + this.ExtensionFactories.Add(new Definition()); + } + + + public Segment(String name, String id) + : base(AnalyticsNameTable.XmlSegmentElement, + AnalyticsNameTable.gAnalyticsPrefix, + AnalyticsNameTable.gAnalyticsNamspace) + { + this.Attributes.Add(BaseNameTable.XmlName, name); + this.Attributes.Add(AnalyticsNameTable.XmlAttributeId, id); + this.ExtensionFactories.Add(new Definition()); + } + + ////////////////////////////////////////////////////////////////////// + /// Accessor for "name" attribute. + /// + ////////////////////////////////////////////////////////////////////// + public string Name + { + get + { + return this.Attributes[BaseNameTable.XmlName] as string; + } + set + { + this.Attributes[BaseNameTable.XmlName] = value; + } + } + + ////////////////////////////////////////////////////////////////////// + /// Accessor for "name" attribute. + /// + ////////////////////////////////////////////////////////////////////// + public string Id + { + get + { + return this.Attributes[AnalyticsNameTable.XmlAttributeId] as string; + } + set + { + this.Attributes[AnalyticsNameTable.XmlAttributeId] = value; + } + } + + ////////////////////////////////////////////////////////////////////// + /// Accessor for "definition" attribute. + /// + ////////////////////////////////////////////////////////////////////// + public Definition Definition + { + get + { + if(definition == null) + { + definition = FindExtensions(AnalyticsNameTable.XmlDefinitionElement, + AnalyticsNameTable.gAnalyticsNamspace)[0]; + } + + return definition; + } + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/analytics/sourceentry.cs gdata-sharp-1.7.0.1/src/analytics/sourceentry.cs --- gdata-sharp-1.4.0.2/src/analytics/sourceentry.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/analytics/sourceentry.cs 2009-05-26 13:26:36.000000000 +0000 @@ -0,0 +1,148 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* Created by Morten Christensen, elpadrinodk@gmail.com, http://blog.sitereactor.dk */ +using Google.GData.Client; +using Google.GData.Extensions; +using System.Collections.Generic; + +namespace Google.GData.Analytics +{ + /// + /// dxp:dataSource: summary information about the Analytics source of the data. + /// It contains the following extensions: + /// dxp:tableId The unique, namespaced profile ID of the source, such as ga:1174 + /// dxp:tableName The name of the profile as it appears in the Analytics administrative UI + /// dxp:property + /// + public class DataSource : SimpleContainer + { + + private List properties; + + /// + /// Constructs a new DataEntry. + /// + public DataSource() : base(AnalyticsNameTable.XmlDataSourceElement, + AnalyticsNameTable.gAnalyticsPrefix, + AnalyticsNameTable.gAnalyticsNamspace) + { + this.ExtensionFactories.Add(new Property()); + this.ExtensionFactories.Add(new TableId()); + this.ExtensionFactories.Add(new TableName()); + } + + + /// + /// This field controls the tableId (ProfileId). + /// + public string TableId + { + get + { + TableId t = FindExtension(AnalyticsNameTable.XmlTableIdElement, + AnalyticsNameTable.gAnalyticsNamspace) as TableId; + + return t != null ? t.Value : null; + } + } + + /// + /// This field controls the tableName. + /// + public string TableName + { + get + { + TableName t = FindExtension(AnalyticsNameTable.XmlTableNameElement, + AnalyticsNameTable.gAnalyticsNamspace) as TableName; + + return t != null ? t.Value : null; + } + } + + + /// + /// This field controls the properties. + /// + public List Properties + { + get + { + if (properties == null) + { + properties = FindExtensions(AnalyticsNameTable.XmlPropertyElement, AnalyticsNameTable.gAnalyticsNamspace); + } + return properties; + } + } + + + /// + /// searches through the property list to find a specific one + /// + /// + /// + public string FindPropertyValue(string name) + { + foreach (Property p in this.Properties ) + { + if (p.Name == name) + { + return p.Value; + } + } + return null; + } + + + /// + /// The numeric id of the profile + /// + /// + public string ProfileId + { + get + { + return this.FindPropertyValue("ga:profileId"); + } + } + + /// + /// The web property ID associated with the profile. + /// + /// + public string WebPropertyId + { + get + { + return this.FindPropertyValue("ga:webPropertyId"); + } + } + + /// + /// The name of the account associated with the profile + /// + /// + public string AccountName + { + get + { + return this.FindPropertyValue("ga:accountName"); + } + } + + + } +} diff -Nru gdata-sharp-1.4.0.2/src/analytics/step.cs gdata-sharp-1.7.0.1/src/analytics/step.cs --- gdata-sharp-1.4.0.2/src/analytics/step.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/analytics/step.cs 2010-04-07 16:34:46.000000000 +0000 @@ -0,0 +1,97 @@ +/* Copyright (c) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using Google.GData.Analytics; +using Google.GData.Extensions; +using Google.GData.Client; + +namespace Google.GData.Analytics +{ + public class Step : SimpleElement + { + public Step() + : base(AnalyticsNameTable.XmlStepElement, + AnalyticsNameTable.gaPrefix, + AnalyticsNameTable.gaNamespace) + { + this.Attributes.Add(BaseNameTable.XmlName, null); + this.Attributes.Add(AnalyticsNameTable.XmlAttributeNumber, null); + this.Attributes.Add(AnalyticsNameTable.XmlAttributePath, null); + } + + public Step(String name, String number, String path) + : base(AnalyticsNameTable.XmlStepElement, + AnalyticsNameTable.gaPrefix, + AnalyticsNameTable.gaNamespace) + { + this.Attributes.Add(BaseNameTable.XmlName, name); + this.Attributes.Add(AnalyticsNameTable.XmlAttributeNumber, number); + this.Attributes.Add(AnalyticsNameTable.XmlAttributePath, path); + } + + + ////////////////////////////////////////////////////////////////////// + /// Accessor for "name" attribute. + /// + ////////////////////////////////////////////////////////////////////// + public string Name + { + get + { + return this.Attributes[BaseNameTable.XmlName] as string; + } + set + { + this.Attributes[BaseNameTable.XmlName] = value; + } + } + + ////////////////////////////////////////////////////////////////////// + /// Accessor for "Number" attribute. + /// + ////////////////////////////////////////////////////////////////////// + public string Number + { + get + { + return this.Attributes[AnalyticsNameTable.XmlAttributeNumber] as string; + } + set + { + this.Attributes[AnalyticsNameTable.XmlAttributeNumber] = value; + } + } + + ////////////////////////////////////////////////////////////////////// + /// Accessor for "Path" attribute. + /// + ////////////////////////////////////////////////////////////////////// + public string Path + { + get + { + return this.Attributes[AnalyticsNameTable.XmlAttributePath] as string; + } + set + { + this.Attributes[AnalyticsNameTable.XmlAttributePath] = value; + } + } + } +} + diff -Nru gdata-sharp-1.4.0.2/src/analytics/tableid.cs gdata-sharp-1.7.0.1/src/analytics/tableid.cs --- gdata-sharp-1.4.0.2/src/analytics/tableid.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/analytics/tableid.cs 2009-05-25 13:03:43.000000000 +0000 @@ -0,0 +1,48 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* Created by Morten Christensen, elpadrinodk@gmail.com, http://blog.sitereactor.dk */ +using System; +using Google.GData.Extensions; + +namespace Google.GData.Analytics +{ + /// + /// GData schema extension describing a tableId. + /// Part of a feedentry (account feed entry or DataEntry SourceEntry/dxp:dataSource). + /// dxp:tableId The unique, namespaced ID to be used when requesting data from a profile. + /// + public class TableId : SimpleElement + { + /// + /// Constructs an empty TableId instance + /// + public TableId() : base(AnalyticsNameTable.XmlTableIdElement, + AnalyticsNameTable.gAnalyticsPrefix, + AnalyticsNameTable.gAnalyticsNamspace) + { + } + + /// + /// default constructor, takes 1 parameters + /// + /// the value property value + public TableId(String value) : base(AnalyticsNameTable.XmlTableIdElement, + AnalyticsNameTable.gAnalyticsPrefix, + AnalyticsNameTable.gAnalyticsNamspace, + value) + { + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/analytics/tablename.cs gdata-sharp-1.7.0.1/src/analytics/tablename.cs --- gdata-sharp-1.4.0.2/src/analytics/tablename.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/analytics/tablename.cs 2009-05-25 13:03:43.000000000 +0000 @@ -0,0 +1,48 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* Created by Morten Christensen, elpadrinodk@gmail.com, http://blog.sitereactor.dk */ +using System; +using Google.GData.Extensions; + +namespace Google.GData.Analytics +{ + /// + /// GData schema extension describing a tableName. + /// Part of a feedentry (DataEntry SourceEntry/dxp:dataSource). + /// dxp:tableName The name of the profile as it appears in the Analytics administrative UI. + /// + public class TableName : SimpleElement + { + /// + /// Constructs an empty TableName instance + /// + public TableName() : base(AnalyticsNameTable.XmlTableNameElement, + AnalyticsNameTable.gAnalyticsPrefix, + AnalyticsNameTable.gAnalyticsNamspace) + { + } + + /// + /// default constructor, takes 1 parameters + /// + /// the value property value + public TableName(string value) : base(AnalyticsNameTable.XmlTableNameElement, + AnalyticsNameTable.gAnalyticsPrefix, + AnalyticsNameTable.gAnalyticsNamspace, + value) + { + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/blogger/Blogger.csproj gdata-sharp-1.7.0.1/src/blogger/Blogger.csproj --- gdata-sharp-1.4.0.2/src/blogger/Blogger.csproj 2008-12-12 15:10:21.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/blogger/Blogger.csproj 2009-10-21 14:06:48.000000000 +0000 @@ -1,8 +1,7 @@ - + Debug AnyCPU - 8.0.50727 2.0 {BE48B106-7766-494C-B0F1-00989ACF2480} Library @@ -11,6 +10,11 @@ Google.GData.Blogger true blogger.sn + + + 2.0 + + true diff -Nru gdata-sharp-1.4.0.2/src/core/abstractentry.cs gdata-sharp-1.7.0.1/src/core/abstractentry.cs --- gdata-sharp-1.4.0.2/src/core/abstractentry.cs 2009-01-28 14:44:32.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/abstractentry.cs 2009-08-17 13:40:32.000000000 +0000 @@ -48,6 +48,7 @@ } private MediaSource mediaSource; + /// /// base implementation, as with the abstract feed, we are adding /// the gnamespace @@ -207,6 +208,30 @@ } + protected void SetStringValue(string value, string elementName, string ns) where T : SimpleElement, new() + { + T v = null; + if (String.IsNullOrEmpty(value) == false) + { + v = new T(); + v.Value = value; + } + + ReplaceExtension(elementName, ns, v); + } + + + protected string GetStringValue(string elementName, string ns) where T : SimpleElement + { + T e = FindExtension(elementName, ns) as T; + if (e!= null) + { + return e.Value; + } + return null; + } + + } } ///////////////////////////////////////////////////////////////////////////// diff -Nru gdata-sharp-1.4.0.2/src/core/asyncDataHandler.cs gdata-sharp-1.7.0.1/src/core/asyncDataHandler.cs --- gdata-sharp-1.4.0.2/src/core/asyncDataHandler.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/asyncDataHandler.cs 2010-01-25 15:37:38.000000000 +0000 @@ -0,0 +1,650 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +#region Using directives + +#define USE_TRACING + +using System; +using System.IO; +using System.IO.Compression; +using System.Net; +using System.Collections.Generic; +using System.Globalization; +using System.ComponentModel; +using System.Threading; +using System.Collections.Specialized; + +#endregion + + +///////////////////////////////////////////////////////////////////// +// contains support classes to handle async up/download and +// delegation. Used for the resumable upload and the service object +// +//////////////////////////////////////////////////////////////////// +namespace Google.GData.Client +{ + +#if WindowsCE || PocketPC + public class AsyncData : Object + { + } + public class AsyncSendData : AsyncData + { + } + public class AsyncQueryData : AsyncData + { + } + public class AsyncDataHandler : Object + { } + + ////////////////////////////////////////////////////////////////////// + /// async functionallity of the Service implementation + /// + ////////////////////////////////////////////////////////////////////// + public partial class Service : IService, IVersionAware + { + private void InitDelegates() + { + } + } +} + +#else + + /// + /// EventArgument class for async events, this one is used + /// when the operation is completed. + /// + public class AsyncOperationCompletedEventArgs : AsyncCompletedEventArgs + { + private AtomFeed feedObject; + private Stream stream; + private AtomEntry entryObject; + + /// + /// constructor. takes the async data blob + /// + /// async data to constructor + internal AsyncOperationCompletedEventArgs(AsyncData data) + : base(data.Exception, false, data.UserData) + { + feedObject = data.Feed; + stream = data.DataStream; + + AsyncSendData sData = data as AsyncSendData; + if (sData != null) + { + entryObject = sData.Entry; + } + + } + + internal AsyncOperationCompletedEventArgs(AsyncData data, bool cancelled) + : base(data.Exception, cancelled, data.UserData) + { + } + + + ////////////////////////////////////////////////////////////////////// + /// the feed that was created. If NULL, a stream or entry was returned + /// + ////////////////////////////////////////////////////////////////////// + public AtomFeed Feed + { + get { return this.feedObject; } + } + //////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////// + /// the entry that was created. If NULL, a stream or feed was returned + /// + ////////////////////////////////////////////////////////////////////// + public AtomEntry Entry + { + get { return this.entryObject; } + } + //////////////////////////////////////////////////////////////////////// + + + ////////////////////////////////////////////////////////////////////// + /// the stream that was created. If NULL, a feed or entry was returned + /// + ////////////////////////////////////////////////////////////////////// + public Stream ResponseStream + { + get { return this.stream; } + } + //////////////////////////////////////////////////////////////////////// + + } + /// Delegate declaration for the feed creation in a service + public delegate void AsyncOperationCompletedEventHandler(object sender, AsyncOperationCompletedEventArgs e); + + + /// + /// EventArgument class for async operation progress reports + /// + public class AsyncOperationProgressEventArgs : ProgressChangedEventArgs + { + private long completeSize; + private long currentPosition; + private Uri uri; + private string httpVerb; + + + /// + /// constructor. Takes the URI and the service this event applies to + /// + /// the completesize of the request + /// the current position in the upload/download + /// progress percentage + /// The userdata identifying the request + public AsyncOperationProgressEventArgs(long completeSize, long currentPosition, int percentage, + Uri targetUri, string httpVerb, + object userData) + : base(percentage, userData) + { + this.completeSize = completeSize; + this.currentPosition = currentPosition; + this.uri = targetUri; + this.httpVerb = httpVerb; + + } + + ////////////////////////////////////////////////////////////////////// + /// the complete upload size + /// + ////////////////////////////////////////////////////////////////////// + public long CompleteSize + { + get { return this.completeSize; } + } + //////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////// + /// the current position in the upload process + /// + ////////////////////////////////////////////////////////////////////// + public long Position + { + get { return this.currentPosition; } + } + //////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////// + /// the Uri that was used + /// + ////////////////////////////////////////////////////////////////////// + public Uri Uri + { + get { return this.uri; } + } + //////////////////////////////////////////////////////////////////////// + + /// + /// returns the http verb that is executed + /// + public string HttpVerb + { + get { return this.httpVerb; } + } + + } + + + /// Delegate declaration for the feed creation in a service + public delegate void AsyncOperationProgressEventHandler(object sender, AsyncOperationProgressEventArgs e); + + + public class AsyncData + { + private Uri uriToUse; + private object userData; + private string httpVerb; + private AsyncOperation op; + private Exception e; + private AtomFeed feed; + private Stream stream; + private SendOrPostCallback onProgressReportDelegate; + private AsyncDataHandler handler; + + public AsyncData(Uri uri, AsyncOperation op, object userData, SendOrPostCallback callback, bool parseFeed) + { + this.uriToUse = uri; + this.op = op; + this.userData = userData; + this.onProgressReportDelegate = callback; + this.ParseFeed = parseFeed; + } + + public AsyncData(Uri uri, AsyncOperation op, object userData, SendOrPostCallback callback) + : this(uri, op, userData, callback, false) + { + } + + public AsyncData(Uri uri, object userData, SendOrPostCallback callback) + : this(uri, null, userData, callback) + { + } + + /// + /// the uri to use + /// + public Uri UriToUse + { + get + { + return this.uriToUse; + } + set + { + this.uriToUse = value; + } + } + + public string HttpVerb + { + get + { + return this.httpVerb; + } + set + { + this.httpVerb = value; + } + } + + + public AsyncDataHandler DataHandler + { + get + { + return this.handler; + } + set + { + this.handler = value; + } + } + + public object UserData + { + get + { + return this.userData; + } + } + + public AtomFeed Feed + { + get + { + return this.feed; + } + set + { + this.feed = value; + } + } + + public AsyncOperation Operation + { + get + { + return this.op; + } + set + { + this.op = value; + } + } + + public SendOrPostCallback Delegate + { + get + { + return this.onProgressReportDelegate; + } + } + + public Exception Exception + { + get + { + return this.e; + } + set + { + this.e = value; + } + } + + public Stream DataStream + { + get + { + return this.stream; + } + set + { + this.stream = value; + } + } + + /// + /// indicates if the async operation should try to + /// parse the server returned stream, or just return the stream + /// + /// + public bool ParseFeed { get; private set; } + } + + + + + + /// + /// internal class for the data to pass to the async worker thread + /// + public class AsyncQueryData : AsyncData + { + private DateTime ifModifiedDate; + bool fParseFeed; + + public AsyncQueryData(Uri uri, DateTime timeStamp, bool doParse, + AsyncOperation op, object userData, SendOrPostCallback callback) + : base(uri, op, userData, callback, doParse) + { + this.ifModifiedDate = timeStamp; + this.fParseFeed = doParse; + } + + /// + /// the date for the ifModified timestamp + /// + public DateTime Modified + { + get + { + return this.ifModifiedDate; + } + set + { + this.ifModifiedDate = value; + } + } + } + + + public abstract class AsyncDataHandler + { + + /// eventhandler, fired when an async operation is completed + public event AsyncOperationCompletedEventHandler AsyncOperationCompleted; + + /// eventhandler, fired when an async operation reports progress + public event AsyncOperationProgressEventHandler AsyncOperationProgress; + + protected delegate void WorkerQueryEventHandler(AsyncQueryData data, AsyncOperation asyncOp, + SendOrPostCallback completionMethodDelegate); + + + + private SendOrPostCallback onProgressReportDelegate; + private SendOrPostCallback onCompletedDelegate; + private SendOrPostCallback completionMethodDelegate; + + + private HybridDictionary userStateToLifetime = + new HybridDictionary(); + + + + public AsyncDataHandler() + { + this.onProgressReportDelegate = new SendOrPostCallback(OnAsyncReportProgress); + this.onCompletedDelegate = new SendOrPostCallback(OnAsyncCompleted); + this.completionMethodDelegate = new SendOrPostCallback(OnAsyncCompletionMethod); + } + + + /// + /// this method cancels the corresponding async operation. + /// It sends still a completed event, but that event will then + /// have the cancel property set to true + /// + /// your identifier for the operation to be cancelled + public void CancelAsync(object userData) + { + lock (this.userStateToLifetime.SyncRoot) + { + object obj = this.userStateToLifetime[userData]; + if (obj != null) + { + + this.userStateToLifetime.Remove(userData); + + AsyncOperation asyncOp = obj as AsyncOperation; + // The asyncOp object is responsible for + // marshaling the call to the proper + // thread or context. + + AsyncData data = new AsyncData(null, userData, this.onProgressReportDelegate); + AsyncOperationCompletedEventArgs args = + new AsyncOperationCompletedEventArgs(data, true); + + asyncOp.PostOperationCompleted(this.onCompletedDelegate, args); + } + } + } + + protected SendOrPostCallback ProgressReportDelegate + { + get + { + return this.onProgressReportDelegate; + } + } + + protected SendOrPostCallback CompletionMethodDelegate + { + get + { + return this.completionMethodDelegate; + } + } + + protected SendOrPostCallback OnCompletedDelegate + { + get + { + return this.onCompletedDelegate; + } + } + + protected void AddUserDataToDictionary(Object userData, AsyncOperation asyncOp) + { + // Multiple threads will access the task dictionary, + // so it must be locked to serialize access. + lock (this.userStateToLifetime.SyncRoot) + { + if (this.userStateToLifetime.Contains(userData)) + { + throw new ArgumentException( + "UserData parameter must be unique", + "userData"); + } + + this.userStateToLifetime[userData] = asyncOp; + } + } + + protected bool CheckIfOperationIsCancelled(Object userData) + { + lock (userStateToLifetime.SyncRoot) + { + if (userStateToLifetime.Contains(userData) == false) + { + return true; + } + } + return false; + } + + + + + // This method is invoked via the AsyncOperation object, + // so it is guaranteed to be executed on the correct thread. + private void OnAsyncReportProgress(object state) + { + AsyncOperationProgressEventArgs e = + state as AsyncOperationProgressEventArgs; + + if (this.AsyncOperationProgress != null) + { + this.AsyncOperationProgress(this, e); + } + } + + private void OnAsyncCompleted(Object obj) + { + if (this.AsyncOperationCompleted != null) + { + AsyncOperationCompletedEventArgs args = obj as AsyncOperationCompletedEventArgs; + this.AsyncOperationCompleted(this, args); + } + } + + // This is the method that the underlying, free-threaded + // asynchronous behavior will invoke. This will happen on + // an arbitrary thread. + private void OnAsyncCompletionMethod(object operationState) + { + AsyncData data = operationState as AsyncData; + + AsyncOperation asyncOp = data.Operation; + + AsyncOperationCompletedEventArgs args = + new AsyncOperationCompletedEventArgs(data); + + // In this case, don't allow cancellation, as the method + // is about to raise the completed event. + lock (this.userStateToLifetime.SyncRoot) + { + if (userStateToLifetime.Contains(data.UserData) == false) + { + asyncOp = null; + } + else + { + this.userStateToLifetime.Remove(asyncOp.UserSuppliedState); + } + } + + // The asyncOp object is responsible for marshaling + // the call. + if (asyncOp != null) + asyncOp.PostOperationCompleted(this.onCompletedDelegate, args); + + // Note that after the call to OperationCompleted, + // asyncOp is no longer usable, and any attempt to use it + // will cause an exception to be thrown. + } + + /// + /// handles the response stream + /// copies it into the memory stream, or parses it into a feed. + /// + /// + /// + /// + /// + protected virtual void HandleResponseStream(AsyncData data, Stream responseStream, long contentLength) + { + data.DataStream = CopyResponseToMemory(data, responseStream, contentLength); + } + + + private MemoryStream CopyResponseToMemory(AsyncData data, Stream responseStream, long contentLength) + { + MemoryStream memStream = null; + if (responseStream != null) + { + // read the stream into memory. That's the only way to satisfy the "main work + // on the other thread requirement + memStream = new MemoryStream(); + const int size = 4096; + var bytes = new byte[size]; + + int numBytes; + + double current = 0; + long bytesWritten = 0; + + while ((numBytes = responseStream.Read(bytes, 0, size)) > 0) + { + memStream.Write(bytes, 0, numBytes); + if (data == null || data.Delegate == null) + { + continue; + } + bytesWritten += numBytes; + + if (contentLength > size) + { + current = bytesWritten * 100d / contentLength; + } + + + + // see if we are still in the list... + // Multiple threads will access the task dictionary, + // so it must be locked to serialize access. + if (CheckIfOperationIsCancelled(data.UserData) == true) + { + throw new ArgumentException("Operation was cancelled"); + } + + var args = new AsyncOperationProgressEventArgs(contentLength, bytesWritten, (int)current, + data.UriToUse, + data.HttpVerb, + data.UserData); + data.Operation.Post(data.Delegate, args); + } + + memStream.Seek(0, SeekOrigin.Begin); + } + + return memStream; + } + + + internal bool SendProgressData(AsyncData data, AsyncOperationProgressEventArgs args) + { + // In this case, don't allow cancellation, as the method + // is about to raise the completed event. + bool ret = !CheckIfOperationIsCancelled(data.UserData); + if (ret == true) + { + data.Operation.Post(data.Delegate, args); + } + return ret; + } + + } +} +#endif \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/src/core/asyncservice.cs gdata-sharp-1.7.0.1/src/core/asyncservice.cs --- gdata-sharp-1.4.0.2/src/core/asyncservice.cs 2009-02-09 16:07:39.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/asyncservice.cs 2010-05-26 08:26:14.000000000 +0000 @@ -34,322 +34,48 @@ //////////////////////////////////////////////////////////////////// namespace Google.GData.Client { - #if WindowsCE || PocketPC - internal class AsyncData : Object - { - } - internal class AsyncSendData : AsyncData - { - } - - ////////////////////////////////////////////////////////////////////// - /// async functionallity of the Service implementation - /// - ////////////////////////////////////////////////////////////////////// - public partial class Service : IService, IVersionAware - { - private void InitDelegates() - { - } - } - #else + - /// - /// EventArgument class for async events, this one is used - /// when the operation is completed. - /// - public class AsyncOperationCompletedEventArgs : AsyncCompletedEventArgs - { - private AtomFeed feedObject; - private Stream stream; - private Uri uri; - private AtomEntry entryObject; - - - /// - /// constructor. takes the async data blog - /// - /// async data to constructor - internal AsyncOperationCompletedEventArgs(AsyncData data) : base(data.Exception, false, data.UserData) - { - AsyncQueryData qData = data as AsyncQueryData; - AsyncSendData sData = data as AsyncSendData; - - this.uri = data.UriToUse; - - if (qData != null) - { - this.feedObject = qData.Feed; - this.stream = qData.DataStream; - } - if (sData != null) - { - this.entryObject = sData.Entry; - } - } - - internal AsyncOperationCompletedEventArgs(AsyncData data, bool cancelled) - : base(data.Exception, cancelled, data.UserData) - { - } - - - ////////////////////////////////////////////////////////////////////// - /// the feed that was created. If NULL, a stream or entry was returned - /// - ////////////////////////////////////////////////////////////////////// - public AtomFeed Feed - { - get { return this.feedObject; } - } - //////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////// - /// the entry that was created. If NULL, a stream or feed was returned - /// - ////////////////////////////////////////////////////////////////////// - public AtomEntry Entry - { - get { return this.entryObject; } - } - //////////////////////////////////////////////////////////////////////// - - - ////////////////////////////////////////////////////////////////////// - /// the stream that was created. If NULL, a feed or entry was returned - /// - ////////////////////////////////////////////////////////////////////// - public Stream ResponseStream - { - get { return this.stream; } - } - //////////////////////////////////////////////////////////////////////// - - - ////////////////////////////////////////////////////////////////////// - /// the Uri to be used - /// - ////////////////////////////////////////////////////////////////////// - public Uri Uri - { - get { return this.uri; } - } - //////////////////////////////////////////////////////////////////////// - } - /// Delegate declaration for the feed creation in a service - public delegate void AsyncOperationCompletedEventHandler(object sender, AsyncOperationCompletedEventArgs e); - - - /// - /// EventArgument class for async operation progress reports - /// - public class AsyncOperationProgressEventArgs : ProgressChangedEventArgs - { - private long completeSize; - private long currentPosition; - - /// - /// constructor. Takes the URI and the service this event applies to - /// - /// the completesize of the request - /// the current position in the upload/download - /// progress percentage - /// The userdata identifying the request - public AsyncOperationProgressEventArgs(long completeSize, long currentPosition, int percentage, - object userData) : base(percentage, userData) - { - this.completeSize = completeSize; - this.currentPosition = currentPosition; - } - - ////////////////////////////////////////////////////////////////////// - /// the complete upload size - /// - ////////////////////////////////////////////////////////////////////// - public long CompleteSize - { - get { return this.completeSize; } - } - //////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////// - /// the current position in the upload process - /// - ////////////////////////////////////////////////////////////////////// - public long Position - { - get { return this.currentPosition; } - } - //////////////////////////////////////////////////////////////////////// - - } - - - /// Delegate declaration for the feed creation in a service - public delegate void AsyncOperationProgressEventHandler(object sender, AsyncOperationProgressEventArgs e); - - - internal class AsyncData - { - private Uri uriToUse; - private object userData; - private AsyncOperation op; - private Exception e; - private AtomFeed feed; - private Stream stream; - private SendOrPostCallback onProgressReportDelegate; - private Service service; - - public AsyncData(Uri uri, AsyncOperation op, object userData, SendOrPostCallback callback) - { - this.uriToUse = uri; - this.userData = userData; - this.op = op; - this.onProgressReportDelegate = callback; - } - - public AsyncData(Uri uri, object userData, SendOrPostCallback callback) - { - this.uriToUse = uri; - this.userData = userData; - this.onProgressReportDelegate = callback; - } - - /// - /// the uri to use - /// - public Uri UriToUse - { - get - { - return this.uriToUse; - } - set - { - this.uriToUse = value; - } - } - - public Service Service - { - get - { - return this.service; - } - set - { - this.service = value; - } - } - - - - - public object UserData - { - get - { - return this.userData; - } - } - - - public AtomFeed Feed - { - get - { - return this.feed; - } - set - { - this.feed = value; - } - } - public AsyncOperation Operation - { - get - { - return this.op; - } - set - { - this.op = value; - } - } - - public SendOrPostCallback Delegate - { - get - { - return this.onProgressReportDelegate; - } - } - - public Exception Exception - { - get - { - return this.e; - } - set - { - this.e= value; - } - } - - public Stream DataStream - { - get - { - return this.stream; - } - set - { - this.stream = value; - } - } - } - - internal class AsyncSendData : AsyncData + public class AsyncSendData : AsyncData { - private AtomEntry entry; + private AtomEntry entry; private GDataRequestType type; private string contentType; private string slugHeader; - public AsyncSendData(Service service, AtomEntry entry, SendOrPostCallback callback, object userData) - : base(null, userData, callback) + private AsyncSendData(AsyncDataHandler handler, Uri uriToUse, AtomEntry entry, AtomFeed feed, SendOrPostCallback callback, object userData, bool parseFeed) + : base(uriToUse, null, userData, callback, parseFeed) { + this.DataHandler = handler; this.entry = entry; - this.Service = service; + this.Feed = feed; } - public AsyncSendData(Service service, Uri uriToUse, AtomEntry entry, SendOrPostCallback callback, object userData) - : base(uriToUse, userData, callback) + public AsyncSendData(AsyncDataHandler handler, Uri uriToUse, AtomEntry entry, SendOrPostCallback callback, object userData) + : this(handler, uriToUse, entry, null, callback, userData, false) { - this.entry = entry; - this.Service = service; } - public AsyncSendData(Service service, Uri uriToUse, AtomFeed feed, SendOrPostCallback callback, object userData) - : base(uriToUse, userData, callback) + public AsyncSendData(AsyncDataHandler handler, AtomEntry entry, SendOrPostCallback callback, object userData) + : this(handler, null, entry, null, callback, userData, false) { - this.Feed = feed; - this.Service = service; } + public AsyncSendData(AsyncDataHandler handler, Uri uriToUse, AtomFeed feed, SendOrPostCallback callback, object userData) + : this(handler, uriToUse, null, feed, callback, userData, false) + { + } - public AsyncSendData(Service service, Uri uriToUse, Stream stream, GDataRequestType type, - string contentType, string slugHeader, SendOrPostCallback callback, object userData) - : base(uriToUse, userData, callback) + public AsyncSendData(AsyncDataHandler handler, Uri uriToUse, Stream stream, GDataRequestType type, + string contentType, string slugHeader, SendOrPostCallback callback, object userData, bool parseFeed) + : this(handler, uriToUse, null, null, callback, userData, parseFeed) { this.DataStream = stream; this.type = type; this.contentType = contentType; this.slugHeader = slugHeader; - this.Service = service; } public AtomEntry Entry @@ -358,7 +84,7 @@ { return this.entry; } - set + set { this.entry = value; } @@ -387,95 +113,52 @@ return this.type; } } + } - /// - /// internal class for the data to pass to the async worker thread - /// - internal class AsyncQueryData : AsyncData + public class AsyncDeleteData : AsyncData { - private DateTime ifModifiedDate; - bool fParseFeed; + private readonly AtomEntry _entry; + private readonly bool _permanentDelete; - public AsyncQueryData(Uri uri, DateTime timeStamp, bool doParse, - AsyncOperation op, object userData, SendOrPostCallback callback) - : base(uri, op, userData, callback) + public AsyncDeleteData(AtomEntry entry, bool permanentDelete, object userData, SendOrPostCallback callback) + : base(null, userData, callback) { - this.ifModifiedDate = timeStamp; - this.fParseFeed = doParse; + _entry = entry; + _permanentDelete = permanentDelete; } - - /// - /// the date for the ifModified timestamp - /// - public DateTime Modified + public bool PermanentDelete { get { - return this.ifModifiedDate; - } - set - { - this.ifModifiedDate = value; + return _permanentDelete; } } - /// - /// indicates if the async operation should try to - /// parse the server returned stream, or just return the stream - /// - /// - public bool ParseFeed + public AtomEntry Entry { - get - { - return this.fParseFeed; - } - set + get { - this.fParseFeed = value; + return _entry; } } - - } - + ////////////////////////////////////////////////////////////////////// /// async functionallity of the Service implementation /// ////////////////////////////////////////////////////////////////////// - public partial class Service : IService, IVersionAware + public partial class Service : AsyncDataHandler, IService, IVersionAware { - /// eventhandler, fired when an async operation is completed - public event AsyncOperationCompletedEventHandler AsyncOperationCompleted; - - /// eventhandler, fired when an async operation reports progress - public event AsyncOperationProgressEventHandler AsyncOperationProgress; - - private delegate void WorkerQueryEventHandler(AsyncQueryData data, AsyncOperation asyncOp, - SendOrPostCallback completionMethodDelegate); private delegate void WorkerSendEventHandler(AsyncSendData data, AsyncOperation asyncOp, - SendOrPostCallback completionMethodDelegate); - - - - private SendOrPostCallback onProgressReportDelegate; - private SendOrPostCallback onCompletedDelegate; - private SendOrPostCallback completionMethodDelegate; - - - private HybridDictionary userStateToLifetime = - new HybridDictionary(); - - - - - - + SendOrPostCallback completionMethodDelegate); + private delegate void WorkerDeleteEventHandler(AsyncDeleteData data, AsyncOperation asyncOp, + SendOrPostCallback completionMethodDelegate); + /// /// the basic interface as an async version. This call will return directly /// and you need to rely on the events fired to figure out what happened. @@ -518,40 +201,22 @@ private void QueryAsync(Uri queryUri, DateTime ifModifiedSince, bool doParse, Object userData) { AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(userData); - AsyncQueryData data = new AsyncQueryData(queryUri, ifModifiedSince, doParse, asyncOp, userData, this.onProgressReportDelegate); - - // Multiple threads will access the task dictionary, - // so it must be locked to serialize access. - lock (this.userStateToLifetime.SyncRoot) - { - if (userStateToLifetime.Contains(userData)) - { - throw new ArgumentException( - "UserData parameter must be unique", - "userData"); - } - - this.userStateToLifetime[userData] = asyncOp; - } - + AsyncQueryData data = new AsyncQueryData(queryUri, ifModifiedSince, doParse, asyncOp, userData, this.ProgressReportDelegate); + AddUserDataToDictionary(userData, asyncOp); // Start the asynchronous operation. WorkerQueryEventHandler workerDelegate = new WorkerQueryEventHandler(AsyncQueryWorker); workerDelegate.BeginInvoke( data, asyncOp, - completionMethodDelegate, + this.CompletionMethodDelegate, null, null); } - - - - /// /// worker method for the query case /// @@ -559,152 +224,26 @@ /// /// /// - private void AsyncQueryWorker(AsyncQueryData data, - AsyncOperation asyncOp, - SendOrPostCallback completionMethodDelegate) - + private void AsyncQueryWorker(AsyncQueryData data, AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate) { - Stream responseStream = null; try { long contentLength; - responseStream = this.Query(data.UriToUse, data.Modified, null, out contentLength); - AtomFeed feed = null; - MemoryStream memStream = null; - - if (responseStream != null) + using (var responseStream = Query(data.UriToUse, data.Modified, null, out contentLength)) { - // read the stream into memory. That's the only way to satisfy the "main work - // on the other thread requirement - memStream = new MemoryStream(); - const int size = 4096; - byte[] bytes = new byte[4096]; - - int numBytes; - - double current = 0; - long bytesWritten = 0; - - while ((numBytes = responseStream.Read(bytes, 0, size)) > 0) - { - memStream.Write(bytes, 0, numBytes); - bytesWritten += numBytes; - if (data != null && data.Delegate != null) - { - AsyncOperationProgressEventArgs args; - if (contentLength > size) - { - current = (double)bytesWritten * 100 / (double)contentLength; - } - // see if we are still in the list... - // Multiple threads will access the task dictionary, - // so it must be locked to serialize access. - lock (this.userStateToLifetime.SyncRoot) - { - if (userStateToLifetime.Contains(data.UserData) == false) - { - throw new ArgumentException("Operation was cancelled"); - } - } - args = new AsyncOperationProgressEventArgs(contentLength, bytesWritten, (int)current, data.UserData); - data.Operation.Post(data.Delegate, args); - } - } - memStream.Seek(0, SeekOrigin.Begin); - } - - if (data.ParseFeed == true && responseStream != null) - { - Tracing.TraceCall("Using Atom always.... "); - feed = CreateFeed(data.UriToUse); - - feed.NewAtomEntry += new FeedParserEventHandler(this.OnParsedNewEntry); - feed.NewExtensionElement += new ExtensionElementEventHandler(this.OnNewExtensionElement); - feed.Parse(memStream, AlternativeFormat.Atom); - memStream.Close(); - memStream = null; + HandleResponseStream(data, responseStream, contentLength); } - data.Feed = feed; - data.DataStream = memStream; } catch (Exception e) { data.Exception = e; } - finally - { - if (responseStream != null) - responseStream.Close(); - } completionMethodDelegate(data); } - // This method is invoked via the AsyncOperation object, - // so it is guaranteed to be executed on the correct thread. - private void AsyncReportProgress(object state) - { - AsyncOperationProgressEventArgs e = - state as AsyncOperationProgressEventArgs; - - if (this.AsyncOperationProgress != null) - { - this.AsyncOperationProgress(this, e); - } - } - - - - - - // This is the method that the underlying, free-threaded - // asynchronous behavior will invoke. This will happen on - // an arbitrary thread. - private void AsyncCompletionMethod(object operationState) - { - AsyncData data = operationState as AsyncData; - - AsyncOperation asyncOp = data.Operation; - - AsyncOperationCompletedEventArgs args = - new AsyncOperationCompletedEventArgs(data); - - // In this case, don't allow cancellation, as the method - // is about to raise the completed event. - lock (this.userStateToLifetime.SyncRoot) - { - if (userStateToLifetime.Contains(data.UserData) == false) - { - asyncOp = null; - } - else - { - this.userStateToLifetime.Remove(asyncOp.UserSuppliedState); - } - } - - // The asyncOp object is responsible for marshaling - // the call. - if (asyncOp != null) - asyncOp.PostOperationCompleted(onCompletedDelegate, args); - - // Note that after the call to OperationCompleted, - // asyncOp is no longer usable, and any attempt to use it - // will cause an exception to be thrown. - } - - - private void OnAsyncCompleted(Object obj) - { - if (this.AsyncOperationCompleted != null) - { - AsyncOperationCompletedEventArgs args = obj as AsyncOperationCompletedEventArgs; - this.AsyncOperationCompleted(this, args); - } - } - - - + + /// /// updates the entry asynchronous, you need to supply a valid and unique /// token. Events will be send to the async delegates you setup on the service @@ -715,7 +254,7 @@ /// public void UpdateAsync(AtomEntry entry, Object userData) { - AsyncSendData data = new AsyncSendData(this, entry, this.onProgressReportDelegate, userData); + AsyncSendData data = new AsyncSendData(this, entry, this.ProgressReportDelegate, userData); WorkerSendEventHandler workerDelegate = new WorkerSendEventHandler(AsyncUpdateWorker); this.AsyncStarter(data, workerDelegate, userData); } @@ -732,7 +271,7 @@ /// public void InsertAsync(Uri feedUri, AtomEntry entry, Object userData) { - AsyncSendData data = new AsyncSendData(this, feedUri, entry, this.onProgressReportDelegate, userData); + AsyncSendData data = new AsyncSendData(this, feedUri, entry, this.ProgressReportDelegate, userData); WorkerSendEventHandler workerDelegate = new WorkerSendEventHandler(AsyncInsertWorker); this.AsyncStarter(data, workerDelegate, userData); } @@ -746,15 +285,16 @@ /// the URI to user /// the userdata identifying this request /// - public void BatchAsync(AtomFeed feed, Uri batchUri, Object userData) + public void BatchAsync(AtomFeed feed, Uri batchUri, Object userData) { - AsyncSendData data = new AsyncSendData(this, batchUri, feed,this.onProgressReportDelegate, userData); + AsyncSendData data = new AsyncSendData(this, batchUri, feed, this.ProgressReportDelegate, userData); WorkerSendEventHandler workerDelegate = new WorkerSendEventHandler(AsyncBatchWorker); this.AsyncStarter(data, workerDelegate, userData); } /// /// this is a helper function for to send binary data asyncronous to a resource + /// The async returned object will contain the output Feed /// /// /// @@ -763,58 +303,82 @@ /// the slugHeader to use in the request, if NULL is passed, factory default is used /// a unique identifier to associate this request with /// - public void StreamSendAsync(Uri targetUri, - Stream inputStream, - GDataRequestType type, + public void StreamSendFeedAsync(Uri targetUri, + Stream inputStream, + GDataRequestType type, string contentType, string slugHeader, object userData) { - AsyncSendData data = new AsyncSendData(this, targetUri, inputStream, type, contentType, slugHeader, - this.onProgressReportDelegate, userData); - WorkerSendEventHandler workerDelegate = new WorkerSendEventHandler(AsyncStreamSendWorker); - this.AsyncStarter(data, workerDelegate, userData); + StreamSendAsync(targetUri, inputStream, type, contentType, slugHeader, userData, true); } + /// + /// this is a helper function for to send binary data asyncronous to a resource + /// The async returned object will contain the output stream + /// + /// + /// + /// + /// the contenttype to use in the request, if NULL is passed, factory default is used + /// the slugHeader to use in the request, if NULL is passed, factory default is used + /// a unique identifier to associate this request with + /// + public void StreamSendStreamAsync(Uri targetUri, + Stream inputStream, + GDataRequestType type, + string contentType, + string slugHeader, + object userData) + { + StreamSendAsync(targetUri, inputStream, type, contentType, slugHeader, userData, false); + } + /// + /// this is a helper function for to send binary data asyncronous to a resource + /// + /// + /// + /// + /// the contenttype to use in the request, if NULL is passed, factory default is used + /// the slugHeader to use in the request, if NULL is passed, factory default is used + /// a unique identifier to associate this request with + /// indicates if the async operation should try to parse the server returned stream, or just return the stream + /// + private void StreamSendAsync(Uri targetUri, + Stream inputStream, + GDataRequestType type, + string contentType, + string slugHeader, + object userData, bool parseFeed) + { + AsyncSendData data = new AsyncSendData(this, targetUri, inputStream, type, contentType, slugHeader, + this.ProgressReportDelegate, userData, parseFeed); + WorkerSendEventHandler workerDelegate = new WorkerSendEventHandler(AsyncStreamSendWorker); + this.AsyncStarter(data, workerDelegate, userData); + } /// - /// starts the async job for several send methods + /// handles the response stream + /// copies it into the memory stream, or parses it into a feed. /// /// - /// - /// + /// + /// /// - private void AsyncStarter(AsyncSendData data, WorkerSendEventHandler workerDelegate, Object userData) + protected override void HandleResponseStream(AsyncData data, Stream responseStream, long contentLength) { - AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(userData); - - data.Operation = asyncOp; - - // Multiple threads will access the task dictionary, - // so it must be locked to serialize access. - lock (this.userStateToLifetime.SyncRoot) + if (data.ParseFeed) { - if (userStateToLifetime.Contains(userData)) - { - throw new ArgumentException( - "UserData parameter must be unique", - "userData"); - } - - this.userStateToLifetime[userData] = asyncOp; + data.Feed = CreateAndParseFeed(responseStream, data.UriToUse); + data.DataStream = null; + } + else + { + base.HandleResponseStream(data, responseStream, contentLength); } - // Start the asynchronous operation. - workerDelegate.BeginInvoke( - data, - asyncOp, - this.completionMethodDelegate, - null, - null); } - - - + /// /// worker method for the update case /// @@ -822,15 +386,15 @@ /// /// /// - private void AsyncUpdateWorker(AsyncSendData data, + private void AsyncUpdateWorker(AsyncSendData data, AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate) - { try { data.Entry = this.Update(data.Entry, data); - } catch (Exception e) + } + catch (Exception e) { data.Exception = e; } @@ -838,21 +402,21 @@ } /// - /// worker method for the update case + /// worker method for the Insert case /// /// /// /// /// - private void AsyncInsertWorker(AsyncSendData data, + private void AsyncInsertWorker(AsyncSendData data, AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate) - { try { data.Entry = this.Insert(data.UriToUse, data.Entry, data); - } catch (Exception e) + } + catch (Exception e) { data.Exception = e; } @@ -866,16 +430,16 @@ /// /// /// - private void AsyncBatchWorker(AsyncSendData data, + private void AsyncBatchWorker(AsyncSendData data, AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate) - { try { - data.Feed = this.Batch(data.Feed, data.UriToUse, data); + data.Feed = this.Batch(data.Feed, data.UriToUse, data); - } catch (Exception e) + } + catch (Exception e) { data.Exception = e; } @@ -889,85 +453,81 @@ /// /// /// - private void AsyncStreamSendWorker(AsyncSendData data, - AsyncOperation asyncOp, - SendOrPostCallback completionMethodDelegate) - + private void AsyncStreamSendWorker(AsyncSendData data, AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate) { try { - data.DataStream = this.StreamSend(data.UriToUse, data.DataStream, data.Type, - data.ContentType, data.SlugHeader, null, data); - - } catch (Exception e) - { - data.Exception = e; - } - completionMethodDelegate(data); - } - - internal bool SendProgressData(AsyncData data, AsyncOperationProgressEventArgs args) - { - bool ret = true; - // In this case, don't allow cancellation, as the method - // is about to raise the completed event. - lock (this.userStateToLifetime.SyncRoot) - { - if (userStateToLifetime.Contains(data.UserData) == false) + using (var responseStream = StreamSend(data.UriToUse, data.DataStream, data.Type, data.ContentType, data.SlugHeader, null, data)) { - ret = false; + HandleResponseStream(data, responseStream, -1); } } - if (ret == true) + catch (Exception e) { - data.Operation.Post(data.Delegate, args); + data.Exception = e; } - return ret; - } - + completionMethodDelegate(data); + } /// - /// this method cancels the corresponding async operation. - /// It sends still a completed event, but that event will then - /// have the cancel property set to true + /// starts the async job /// - /// your identifier for the operation to be cancelled - public void CancelAsync(object userData) + /// + /// + /// + /// + private void AsyncStarter(AsyncSendData data, WorkerSendEventHandler workerDelegate, Object userData) { - lock (this.userStateToLifetime.SyncRoot) - { - object obj = this.userStateToLifetime[userData]; - if (obj != null) - { + AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(userData); - this.userStateToLifetime.Remove(userData); + data.Operation = asyncOp; - AsyncOperation asyncOp = obj as AsyncOperation; - // The asyncOp object is responsible for - // marshaling the call to the proper - // thread or context. - - AsyncData data = new AsyncData(null, userData, this.onProgressReportDelegate); - AsyncOperationCompletedEventArgs args = - new AsyncOperationCompletedEventArgs(data, true); - - asyncOp.PostOperationCompleted(this.onCompletedDelegate, args); - } - } + AddUserDataToDictionary(userData, asyncOp); + + + // Start the asynchronous operation. + workerDelegate.BeginInvoke( + data, + asyncOp, + this.CompletionMethodDelegate, + null, + null); } - - private void InitDelegates() + + public void DeleteAsync(AtomEntry entry, bool permanentDelete, Object userData) { - this.onProgressReportDelegate = new SendOrPostCallback(AsyncReportProgress); - this.onCompletedDelegate = new SendOrPostCallback(OnAsyncCompleted); - this.completionMethodDelegate= new SendOrPostCallback(AsyncCompletionMethod); + AsyncDeleteData data = new AsyncDeleteData(entry, permanentDelete, userData, ProgressReportDelegate); + AsyncStarter(data, AsyncDeleteWorker, userData); } - } - ///////////////////////////////////////////////////////////////////////////// + private void AsyncStarter(AsyncDeleteData data, WorkerDeleteEventHandler workerDelegate, Object userData) + { + AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(userData); + data.Operation = asyncOp; + AddUserDataToDictionary(userData, asyncOp); -#endif + // Start the asynchronous operation. + workerDelegate.BeginInvoke(data, asyncOp, CompletionMethodDelegate, null, null); + } + private void AsyncDeleteWorker(AsyncDeleteData data, AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate) + { + try + { + Delete(data.Entry, data.PermanentDelete); + } + catch (Exception e) + { + data.Exception = e; + } + + completionMethodDelegate(data); + } + } + ////////////////////////////////////////////////////////////////////////// +#endif } ///////////////////////////////////////////////////////////////////////////// + + diff -Nru gdata-sharp-1.4.0.2/src/core/atombase.cs gdata-sharp-1.7.0.1/src/core/atombase.cs --- gdata-sharp-1.4.0.2/src/core/atombase.cs 2009-02-16 17:39:06.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/atombase.cs 2009-11-25 14:22:39.000000000 +0000 @@ -365,7 +365,7 @@ /// Primary use of this is to find XML nodes /// /// the xml local name of the element to find - /// the namespace of the elementToPersist + /// the namespace of the element to find /// Object public IExtensionElementFactory FindExtension(string localName, string ns) { @@ -377,7 +377,7 @@ /// extension factories list and calling CreateInstance for the right one /// /// the xml local name of the element to find - /// the namespace of the elementToPersist + /// the namespace of the element to find /// Object public IExtensionElementFactory CreateExtension(string localName, string ns) { @@ -396,7 +396,7 @@ /// Finds the extension factory for a given name/namespace /// /// the xml local name of the element to find - /// the namespace of the elementToPersist + /// the namespace of the element to find /// Object public IExtensionElementFactory FindExtensionFactory(string localName, string ns) { @@ -424,7 +424,7 @@ /// Primary use of this is to find XML nodes /// /// the xml local name of the element to find - /// the namespace of the elementToPersist + /// the namespace of the element to find /// Object public ExtensionList FindExtensions(string localName, string ns) { @@ -439,7 +439,7 @@ /// Primary use of this is to find XML nodes /// /// the xml local name of the element to find - /// the namespace of the elementToPersist + /// the namespace of the element to find /// the array to fill /// none public ExtensionList FindExtensions(string localName, string ns, ExtensionList arr) @@ -457,7 +457,7 @@ /// Primary use of this is to find XML nodes /// /// the xml local name of the element to find - /// the namespace of the elementToPersist + /// the namespace of the element to findt /// none public List FindExtensions(string localName, string ns) where T : IExtensionElementFactory { @@ -654,7 +654,6 @@ if (IsPersistable()) { WriteElementStart(writer, this.XmlName); - AddOtherNamespaces(writer); SaveXmlAttributes(writer); SaveInnerXml(writer); writer.WriteEndElement(); @@ -697,37 +696,39 @@ writer.WriteAttributeString(BaseNameTable.gDataPrefix, BaseNameTable.XmlEtagAttribute, BaseNameTable.gNamespace, se.Etag); } - foreach (object ob in this.ExtensionElements) + + // first go over all attributes + foreach (IExtensionElementFactory ele in this.ExtensionElements) { - // this code can be removed when the generics are introduced. - XmlNode node = ob as XmlNode; - if (node != null) + XmlExtension x = ele as XmlExtension; + // what we need to do here is: + // go over all the attributes. look at all attributes that are namespace related + // if the attribute is another default atomnamespace declaration, change it to some rnd prefix + + if (x != null) { - if (SkipNode(node)) + if (x.Node.NodeType == XmlNodeType.Attribute) { - continue; + ele.Save(writer); } - Tracing.TraceInfo("Saving out additonal attributes..." + node.Name); - node.WriteTo(writer); } - else + } + AddOtherNamespaces(writer); + + // now just the non attributes + foreach (IExtensionElementFactory ele in this.ExtensionElements) + { + XmlExtension x = ele as XmlExtension; + if (x != null) { - IExtensionElementFactory ele = ob as IExtensionElementFactory; - XmlExtension x = ele as XmlExtension; - if (x != null) + if (x.Node.NodeType == XmlNodeType.Attribute) { - if (SkipNode(x.Node)) - { - continue; - } - } - if (ele != null) - { - ele.Save(writer); - } + // skip the guy + continue; + } } + ele.Save(writer); } - } ///////////////////////////////////////////////////////////////////////////// @@ -746,21 +747,57 @@ return false; } + private bool IsAtomDefaultNamespace(XmlWriter writer) + { + string prefix = writer.LookupPrefix(BaseNameTable.NSAtom); + if (prefix == null) + { + // if it is not defined, we need to make a choice + // go over all attributes + foreach (IExtensionElementFactory ele in this.ExtensionElements) + { + XmlExtension x = ele as XmlExtension; + // what we need to do here is: + // go over all the attributes. look at all attributes that are namespace related + // if the attribute is another default atomnamespace declaration, change it to some rnd prefix + + if (x != null) + { + if (x.Node.NodeType == XmlNodeType.Attribute && + (String.Compare(x.Node.Name, "xmlns") == 0) && + (String.Compare(x.Node.Value, BaseNameTable.NSAtom) != 0)) + return false; + } + } + + return true; + } + if (prefix.Length > 0) + return false; + return true; + } + ////////////////////////////////////////////////////////////////////// /// protected WriteElementStart(XmlWriter writer) /// the xmlwriter to use /// the elementToPersist to use ////////////////////////////////////////////////////////////////////// - static protected void WriteElementStart(XmlWriter writer, string elementName) + protected void WriteElementStart(XmlWriter writer, string elementName) { Tracing.Assert(writer != null, "writer should not be null"); if (writer == null) { throw new ArgumentNullException("writer"); } - writer.WriteStartElement(elementName); - Utilities.EnsureAtomNamespace(writer); + if (IsAtomDefaultNamespace(writer) == false) + { + writer.WriteStartElement("atom", elementName, BaseNameTable.NSAtom); + } + else + { + writer.WriteStartElement(elementName); + } } ///////////////////////////////////////////////////////////////////////////// @@ -784,7 +821,7 @@ /// the elementToPersist to use /// the localDateTime to convert and persist ////////////////////////////////////////////////////////////////////// - static protected void WriteLocalDateTimeElement(XmlWriter writer, string elementName, DateTime dateTime) + protected void WriteLocalDateTimeElement(XmlWriter writer, string elementName, DateTime dateTime) { Tracing.Assert(writer != null, "writer should not be null"); if (writer == null) diff -Nru gdata-sharp-1.4.0.2/src/core/atomcategory.cs gdata-sharp-1.7.0.1/src/core/atomcategory.cs --- gdata-sharp-1.4.0.2/src/core/atomcategory.cs 2006-07-27 10:16:06.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/atomcategory.cs 2009-11-24 11:09:57.000000000 +0000 @@ -49,7 +49,7 @@ /// } /// ////////////////////////////////////////////////////////////////////// - public class AtomCategory : AtomBase + public class AtomCategory : AtomBase, IEquatable { /// holds the term private string term; @@ -90,6 +90,21 @@ } ///////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// + /// Category constructor + /// the term of the category + /// the scheme of the category + /// the label for the category + ////////////////////////////////////////////////////////////////////// + public AtomCategory(string term, AtomUri scheme, string label) + { + this.Term = term; + this.Scheme = scheme; + this.label = label; + } + ///////////////////////////////////////////////////////////////////////////// + + #region overloaded for persistence ////////////////////////////////////////////////////////////////////// @@ -108,10 +123,11 @@ ////////////////////////////////////////////////////////////////////// protected override void SaveXmlAttributes(XmlWriter writer) { - base.SaveXmlAttributes(writer); WriteEncodedAttributeString(writer, AtomParserNameTable.XmlAttributeTerm, this.Term); WriteEncodedAttributeString(writer, AtomParserNameTable.XmlAttributeScheme, this.Scheme); WriteEncodedAttributeString(writer, AtomParserNameTable.XmlAttributeLabel, this.Label); + // call base later as base takes care of writing out extension elements that might close the attribute list + base.SaveXmlAttributes(writer); } ///////////////////////////////////////////////////////////////////////////// @@ -192,7 +208,49 @@ } } ///////////////////////////////////////////////////////////////////////////// - + + #region added by Noam Gal (ATGardner gmail.com) + + public bool Equals(AtomCategory other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + if (ReferenceEquals(this, other)) + { + return true; + } + return Equals(other.term, this.term) && (other.scheme == null || this.scheme == null || Equals(other.scheme, this.scheme)); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + if (ReferenceEquals(this, obj)) + { + return true; + } + if (obj.GetType() != typeof(AtomCategory)) + { + return false; + } + return Equals((AtomCategory)obj); + } + + public override int GetHashCode() + { + unchecked + { + return ((this.term != null ? this.term.GetHashCode() : 0) * 397) ^ (this.scheme != null ? this.scheme.GetHashCode() : 0); + } + } + + #endregion + } ///////////////////////////////////////////////////////////////////////////// } diff -Nru gdata-sharp-1.4.0.2/src/core/atomcontent.cs gdata-sharp-1.7.0.1/src/core/atomcontent.cs --- gdata-sharp-1.4.0.2/src/core/atomcontent.cs 2008-08-25 14:34:13.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/atomcontent.cs 2009-11-24 11:09:57.000000000 +0000 @@ -156,9 +156,10 @@ ////////////////////////////////////////////////////////////////////// protected override void SaveXmlAttributes(XmlWriter writer) { - base.SaveXmlAttributes(writer); WriteEncodedAttributeString(writer, AtomParserNameTable.XmlAttributeSrc, this.Src); WriteEncodedAttributeString(writer, AtomParserNameTable.XmlAttributeType, this.Type); + // call base later, as base will save out extension elements that might create subelements + base.SaveXmlAttributes(writer); } ///////////////////////////////////////////////////////////////////////////// diff -Nru gdata-sharp-1.4.0.2/src/core/atomfeed.cs gdata-sharp-1.7.0.1/src/core/atomfeed.cs --- gdata-sharp-1.4.0.2/src/core/atomfeed.cs 2008-11-27 14:44:21.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/atomfeed.cs 2009-12-08 13:43:41.000000000 +0000 @@ -613,6 +613,12 @@ Tracing.TraceCall("parsing stream -> Start:" + format.ToString()); BaseFeedParser feedParser= null; + // make sure we reset our collections + this.Authors.Clear(); + this.Contributors.Clear(); + this.Links.Clear(); + this.Categories.Clear(); + feedParser = new AtomFeedParser(this); // create a new delegate for the parser diff -Nru gdata-sharp-1.4.0.2/src/core/atomFeedgenerator.cs gdata-sharp-1.7.0.1/src/core/atomFeedgenerator.cs --- gdata-sharp-1.4.0.2/src/core/atomFeedgenerator.cs 2007-01-09 10:06:30.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/atomFeedgenerator.cs 2009-11-24 11:09:57.000000000 +0000 @@ -121,9 +121,10 @@ ////////////////////////////////////////////////////////////////////// protected override void SaveXmlAttributes(XmlWriter writer) { - base.SaveXmlAttributes(writer); WriteEncodedAttributeString(writer, AtomParserNameTable.XmlUriElement, this.Uri); WriteEncodedAttributeString(writer, AtomParserNameTable.XmlAttributeVersion, this.Version); + // call base later as base takes care of writing out extension elements that might close the attribute list + base.SaveXmlAttributes(writer); } ///////////////////////////////////////////////////////////////////////////// diff -Nru gdata-sharp-1.4.0.2/src/core/atomfeedparser.cs gdata-sharp-1.7.0.1/src/core/atomfeedparser.cs --- gdata-sharp-1.4.0.2/src/core/atomfeedparser.cs 2009-02-16 17:39:06.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/atomfeedparser.cs 2009-11-30 10:16:11.000000000 +0000 @@ -753,8 +753,7 @@ while (NextChildElement(reader, ref depth)) { localname = reader.LocalName; - bool fSkip = true; - + if (IsCurrentNameSpace(reader, BaseNameTable.NSAtom)) { if (localname.Equals(this.nameTable.Id)) @@ -797,7 +796,7 @@ } else if (localname.Equals(this.nameTable.Content)) { - entry.Content = ParseContent(reader, entry, out fSkip); + entry.Content = ParseContent(reader, entry); } else if (localname.Equals(this.nameTable.Source)) { @@ -808,13 +807,8 @@ { entry.Title = ParseTextConstruct(reader, entry); } - // this will either move the reader to the end of an element, or, - // if at the end, to the start of a new one. some methods use readInnerXm - // and might therefore already be at the start of the next - if (fSkip) - // note: we want to get rid of fskip and move the logic into the parsing methods - // ParseXXX should just come back with a clearly defined state - reader.Read(); + // all parse methods should leave the reader at the end of their element + reader.Read(); } else if (IsCurrentNameSpace(reader, BaseNameTable.gBatchNamespace)) { @@ -1090,10 +1084,9 @@ /// creates an AtomContent object by parsing an xml stream /// a XMLReader positioned correctly /// the container element - /// a boolen indicating if the node needs to be skipped, or not /// null or an AtomContent object ////////////////////////////////////////////////////////////////////// - protected AtomContent ParseContent(XmlReader reader, AtomBase owner, out bool skipNode) + protected AtomContent ParseContent(XmlReader reader, AtomBase owner) { Tracing.Assert(reader != null, "reader should not be null"); if (reader == null) @@ -1107,9 +1100,6 @@ } - // by default, skip to the next node after this routine - skipNode = true; - AtomContent content = owner.CreateAtomSubElement(reader, this) as AtomContent; Tracing.TraceCall(); if (content != null) @@ -1136,21 +1126,37 @@ if (MoveToStartElement(reader) == true) { - // using readInnerXml has disadvantages, even for HTML/XHTML. in .NET 1.1 - // decoding will happen and text like "this & that" will come back - // as "this & that" - if (content.Type.Equals("xhtml")) - { - // ReadInnerXml moves to the next node - skipNode = false; - content.Content = reader.ReadInnerXml(); - } - else + if (content.Type.Equals("text") || + content.Type.Equals("html") || + content.Type.StartsWith("text/")) { - // anything NOT xhtml get's just the string treatment. No + // if it's text it get's just the string treatment. No // subelements are allowed here content.Content = Utilities.DecodedValue(reader.ReadString()); } + else if (content.Type.Equals("xhtml") || + content.Type.Contains("/xml") || + content.Type.Contains("+xml")) + { + // do not get childlists if the element is empty. That would skip to the next element + if (reader.IsEmptyElement == false) + { + // everything else will be nodes in the extension element list + // different media type. Create extension elements + int lvl = -1; + while (NextChildElement(reader, ref lvl)) + { + ParseExtensionElements(reader, content); + } + } + } + else + { + // everything else SHOULD be base 64 encoded, so one big string + // i know the if statement could be combined with the text handling + // but i consider it clearer to make a 3 cases statement than combine them + content.Content = Utilities.DecodedValue(reader.ReadString()); + } } } return content; diff -Nru gdata-sharp-1.4.0.2/src/core/atomlink.cs gdata-sharp-1.7.0.1/src/core/atomlink.cs --- gdata-sharp-1.4.0.2/src/core/atomlink.cs 2008-08-29 16:49:04.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/atomlink.cs 2009-11-24 11:09:57.000000000 +0000 @@ -1,261 +1,261 @@ -/* Copyright (c) 2006 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ -#region Using directives - -#define USE_TRACING - -using System; -using System.Xml; -using System.Globalization; - -#endregion - -////////////////////////////////////////////////////////////////////// -// Contains AtomLink, an object to represent the atom:link -// element. -////////////////////////////////////////////////////////////////////// -namespace Google.GData.Client -{ - - ////////////////////////////////////////////////////////////////////// - /// AtomLink represents an atom:link element - /// atomLink = element atom:link { - /// atomCommonAttributes, - /// attribute href { atomUri }, - /// attribute rel { atomNCName | atomUri }?, - /// attribute type { atomMediaType }?, - /// attribute hreflang { atomLanguageTag }?, - /// attribute title { text }?, - /// attribute length { text }?, - /// empty - /// - ////////////////////////////////////////////////////////////////////// - public class AtomLink : AtomBase - { - /// property holder exposed over get/set - private AtomUri href; - /// property holder exposed over get/set - private string rel; - /// property holder exposed over get/set - private string type; - /// property holder exposed over get/set - private string hreflang; - /// property holder exposed over get/set - private string title; - /// property holder exposed over get/set - private int length; - - - /// HTML Link Type - public const string HTML_TYPE = "text/html"; - - /// ATOM Link Type - public const string ATOM_TYPE = "application/atom+xml"; - - ////////////////////////////////////////////////////////////////////// - /// default empty constructor - ////////////////////////////////////////////////////////////////////// - public AtomLink() - { - } - ///////////////////////////////////////////////////////////////////////////// - - - ////////////////////////////////////////////////////////////////////// - /// public AtomLink(string uri) - /// the uri for the link - ////////////////////////////////////////////////////////////////////// - public AtomLink(string link) - { - this.HRef = new AtomUri(link); - } - /// - /// constructor used in atomfeed to create new links - /// - /// the type of link to create - /// the rel value - public AtomLink(string type, string rel) - { - this.Type = type; - this.Rel = rel; - } - - ////////////////////////////////////////////////////////////////////// - /// accessor method public Uri HRef - /// - ////////////////////////////////////////////////////////////////////// - public AtomUri HRef - { - get {return this.href;} - set {this.Dirty = true; this.href = value;} - } - ///////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////// - /// public string AbsoluteUri - ////////////////////////////////////////////////////////////////////// - public string AbsoluteUri - { - get - { - if (this.HRef != null) +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +#region Using directives + +#define USE_TRACING + +using System; +using System.Xml; +using System.Globalization; + +#endregion + +////////////////////////////////////////////////////////////////////// +// Contains AtomLink, an object to represent the atom:link +// element. +////////////////////////////////////////////////////////////////////// +namespace Google.GData.Client +{ + + ////////////////////////////////////////////////////////////////////// + /// AtomLink represents an atom:link element + /// atomLink = element atom:link { + /// atomCommonAttributes, + /// attribute href { atomUri }, + /// attribute rel { atomNCName | atomUri }?, + /// attribute type { atomMediaType }?, + /// attribute hreflang { atomLanguageTag }?, + /// attribute title { text }?, + /// attribute length { text }?, + /// empty + /// + ////////////////////////////////////////////////////////////////////// + public class AtomLink : AtomBase + { + /// property holder exposed over get/set + private AtomUri href; + /// property holder exposed over get/set + private string rel; + /// property holder exposed over get/set + private string type; + /// property holder exposed over get/set + private string hreflang; + /// property holder exposed over get/set + private string title; + /// property holder exposed over get/set + private int length; + + + /// HTML Link Type + public const string HTML_TYPE = "text/html"; + + /// ATOM Link Type + public const string ATOM_TYPE = "application/atom+xml"; + + ////////////////////////////////////////////////////////////////////// + /// default empty constructor + ////////////////////////////////////////////////////////////////////// + public AtomLink() + { + } + ///////////////////////////////////////////////////////////////////////////// + + + ////////////////////////////////////////////////////////////////////// + /// public AtomLink(string uri) + /// the uri for the link + ////////////////////////////////////////////////////////////////////// + public AtomLink(string link) + { + this.HRef = new AtomUri(link); + } + /// + /// constructor used in atomfeed to create new links + /// + /// the type of link to create + /// the rel value + public AtomLink(string type, string rel) + { + this.Type = type; + this.Rel = rel; + } + + ////////////////////////////////////////////////////////////////////// + /// accessor method public Uri HRef + /// + ////////////////////////////////////////////////////////////////////// + public AtomUri HRef + { + get {return this.href;} + set {this.Dirty = true; this.href = value;} + } + ///////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////// + /// public string AbsoluteUri + ////////////////////////////////////////////////////////////////////// + public string AbsoluteUri + { + get + { + if (this.HRef != null) return GetAbsoluteUri(this.HRef.ToString()); - return null; - } - } - ///////////////////////////////////////////////////////////////////////////// - - - - ////////////////////////////////////////////////////////////////////// - /// accessor method public string Rel - /// - ////////////////////////////////////////////////////////////////////// - public string Rel - { - get {return this.rel;} - set {this.Dirty = true; this.rel = value;} - } - ///////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////// - /// accessor method public string Type - /// - ////////////////////////////////////////////////////////////////////// - public string Type - { - get {return this.type;} - set {this.Dirty = true; this.type = value;} - } - ///////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////// - /// accessor method public string HrefLang - /// - ////////////////////////////////////////////////////////////////////// - public string HRefLang - { - get {return this.hreflang;} - set {this.Dirty = true; this.hreflang = value;} - } - ///////////////////////////////////////////////////////////////////////////// - - - ////////////////////////////////////////////////////////////////////// - /// accessor method public int Lenght - /// - ////////////////////////////////////////////////////////////////////// - public int Length - { - get {return this.length;} - set {this.Dirty = true; this.length = value;} - } - ///////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////// - /// accessor method public string Title - /// - ////////////////////////////////////////////////////////////////////// - public string Title - { - get {return this.title;} - set {this.Dirty = true; this.title = value;} - } - ///////////////////////////////////////////////////////////////////////////// - - - #region Persistence overloads - ////////////////////////////////////////////////////////////////////// - /// Returns the constant representing this XML element. - ////////////////////////////////////////////////////////////////////// - public override string XmlName - { - get { return AtomParserNameTable.XmlLinkElement; } - } - ///////////////////////////////////////////////////////////////////////////// - - - ////////////////////////////////////////////////////////////////////// - /// overridden to save attributes for this(XmlWriter writer) - /// the xmlwriter to save into - ////////////////////////////////////////////////////////////////////// - protected override void SaveXmlAttributes(XmlWriter writer) - { - WriteEncodedAttributeString(writer, AtomParserNameTable.XmlAttributeHRef, this.HRef); - WriteEncodedAttributeString(writer, AtomParserNameTable.XmlAttributeHRefLang, this.HRefLang); - WriteEncodedAttributeString(writer, AtomParserNameTable.XmlAttributeRel, this.Rel); - WriteEncodedAttributeString(writer, AtomParserNameTable.XmlAttributeType, this.Type); - - if (this.length > 0) - { - WriteEncodedAttributeString(writer, AtomParserNameTable.XmlAttributeLength, this.Length.ToString(CultureInfo.InvariantCulture)); - } - WriteEncodedAttributeString(writer, AtomParserNameTable.XmlTitleElement, this.Title); - base.SaveXmlAttributes(writer); - - } - ///////////////////////////////////////////////////////////////////////////// - - - ////////////////////////////////////////////////////////////////////// - /// figures out if this object should be persisted - /// true, if it's worth saving - ////////////////////////////////////////////////////////////////////// - public override bool ShouldBePersisted() - { - if (base.ShouldBePersisted() == true) - { - return true; - } - if (Utilities.IsPersistable(this.href)) - { - return true; - } - if (Utilities.IsPersistable(this.hreflang)) - { - return true; - } - if (Utilities.IsPersistable(this.rel)) - { - return true; - } - if (Utilities.IsPersistable(this.type)) - { - return true; - } - if (Utilities.IsPersistable(this.Length)) - { - return true; - } - - if (Utilities.IsPersistable(this.title)) - { - return true; - } - return false; - } - ///////////////////////////////////////////////////////////////////////////// - - - #endregion - - - - - } - ///////////////////////////////////////////////////////////////////////////// - -} ///////////////////////////////////////////////////////////////////////////// - + return null; + } + } + ///////////////////////////////////////////////////////////////////////////// + + + + ////////////////////////////////////////////////////////////////////// + /// accessor method public string Rel + /// + ////////////////////////////////////////////////////////////////////// + public string Rel + { + get {return this.rel;} + set {this.Dirty = true; this.rel = value;} + } + ///////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////// + /// accessor method public string Type + /// + ////////////////////////////////////////////////////////////////////// + public string Type + { + get {return this.type;} + set {this.Dirty = true; this.type = value;} + } + ///////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////// + /// accessor method public string HrefLang + /// + ////////////////////////////////////////////////////////////////////// + public string HRefLang + { + get {return this.hreflang;} + set {this.Dirty = true; this.hreflang = value;} + } + ///////////////////////////////////////////////////////////////////////////// + + + ////////////////////////////////////////////////////////////////////// + /// accessor method public int Lenght + /// + ////////////////////////////////////////////////////////////////////// + public int Length + { + get {return this.length;} + set {this.Dirty = true; this.length = value;} + } + ///////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////// + /// accessor method public string Title + /// + ////////////////////////////////////////////////////////////////////// + public string Title + { + get {return this.title;} + set {this.Dirty = true; this.title = value;} + } + ///////////////////////////////////////////////////////////////////////////// + + + #region Persistence overloads + ////////////////////////////////////////////////////////////////////// + /// Returns the constant representing this XML element. + ////////////////////////////////////////////////////////////////////// + public override string XmlName + { + get { return AtomParserNameTable.XmlLinkElement; } + } + ///////////////////////////////////////////////////////////////////////////// + + + ////////////////////////////////////////////////////////////////////// + /// overridden to save attributes for this(XmlWriter writer) + /// the xmlwriter to save into + ////////////////////////////////////////////////////////////////////// + protected override void SaveXmlAttributes(XmlWriter writer) + { + WriteEncodedAttributeString(writer, AtomParserNameTable.XmlAttributeHRef, this.HRef); + WriteEncodedAttributeString(writer, AtomParserNameTable.XmlAttributeHRefLang, this.HRefLang); + WriteEncodedAttributeString(writer, AtomParserNameTable.XmlAttributeRel, this.Rel); + WriteEncodedAttributeString(writer, AtomParserNameTable.XmlAttributeType, this.Type); + + if (this.length > 0) + { + WriteEncodedAttributeString(writer, AtomParserNameTable.XmlAttributeLength, this.Length.ToString(CultureInfo.InvariantCulture)); + } + WriteEncodedAttributeString(writer, AtomParserNameTable.XmlTitleElement, this.Title); + // call base later as base takes care of writing out extension elements that might close the attribute list + base.SaveXmlAttributes(writer); + } + ///////////////////////////////////////////////////////////////////////////// + + + ////////////////////////////////////////////////////////////////////// + /// figures out if this object should be persisted + /// true, if it's worth saving + ////////////////////////////////////////////////////////////////////// + public override bool ShouldBePersisted() + { + if (base.ShouldBePersisted() == true) + { + return true; + } + if (Utilities.IsPersistable(this.href)) + { + return true; + } + if (Utilities.IsPersistable(this.hreflang)) + { + return true; + } + if (Utilities.IsPersistable(this.rel)) + { + return true; + } + if (Utilities.IsPersistable(this.type)) + { + return true; + } + if (Utilities.IsPersistable(this.Length)) + { + return true; + } + + if (Utilities.IsPersistable(this.title)) + { + return true; + } + return false; + } + ///////////////////////////////////////////////////////////////////////////// + + + #endregion + + + + + } + ///////////////////////////////////////////////////////////////////////////// + +} ///////////////////////////////////////////////////////////////////////////// + diff -Nru gdata-sharp-1.4.0.2/src/core/atomtextconstruct.cs gdata-sharp-1.7.0.1/src/core/atomtextconstruct.cs --- gdata-sharp-1.4.0.2/src/core/atomtextconstruct.cs 2008-06-10 10:23:24.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/atomtextconstruct.cs 2009-11-24 11:09:57.000000000 +0000 @@ -209,8 +209,9 @@ ////////////////////////////////////////////////////////////////////// protected override void SaveXmlAttributes(XmlWriter writer) { - base.SaveXmlAttributes(writer); WriteEncodedAttributeString(writer, AtomParserNameTable.XmlAttributeType, this.Type.ToString()); + // call base later as base takes care of writing out extension elements that might close the attribute list + base.SaveXmlAttributes(writer); } ///////////////////////////////////////////////////////////////////////////// diff -Nru gdata-sharp-1.4.0.2/src/core/authentication.cs gdata-sharp-1.7.0.1/src/core/authentication.cs --- gdata-sharp-1.4.0.2/src/core/authentication.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/authentication.cs 2010-06-28 13:31:33.000000000 +0000 @@ -0,0 +1,598 @@ + /* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + + +using System; +using System.IO; +using System.Collections; +using System.Text; +using System.Net; +using Google.GData.Client; +using Google.GData.Extensions; +using System.Collections.Generic; +using System.Security.Cryptography; + + +namespace Google.GData.Client +{ + + public interface ICreateHttpRequest + { + HttpWebRequest Create(Uri target); + + } + + + public class HttpRequestFactory : ICreateHttpRequest + { + public HttpWebRequest Create(Uri target) + { + return WebRequest.Create(target) as HttpWebRequest; + } + } + + /// + /// this is the static collection of all google service names + /// + public static class ServiceNames + { + public static string YouTube = "youtube"; + public static string Calendar = "cl"; + public static string Documents = "writely"; + } + + /// + /// Base authentication class. Takes credentials and applicationname + /// and is able to create a HttpWebRequest augmented with the right + /// authentication + /// + /// + public abstract class Authenticator + { + private string applicationName; + private string developerKey; + private ICreateHttpRequest requestFactory; + + /// + /// an unauthenticated use case + /// + /// + /// + public Authenticator(string applicationName) + { + this.applicationName = applicationName; + this.requestFactory = new HttpRequestFactory(); + } + + + public ICreateHttpRequest RequestFactory + { + get + { + return this.requestFactory; + } + set + { + this.requestFactory = value; + } + } + + + /// + /// Creates a HttpWebRequest object that can be used against a given service. + /// for a RequestSetting object that is using client login, this might call + /// to get an authentication token from the service, if it is not already set. + /// + /// if this uses client login, and you need to use a proxy, set the application wide + /// proxy first using the GlobalProxySelection + /// + /// + /// + /// + /// + public HttpWebRequest CreateHttpWebRequest(string httpMethod, Uri targetUri) + { + Uri uriResult = ApplyAuthenticationToUri(targetUri); + + if (this.requestFactory != null) + { + HttpWebRequest request = this.requestFactory.Create(uriResult); + // turn off autoredirect + request.AllowAutoRedirect = false; + request.Method = httpMethod; + ApplyAuthenticationToRequest(request); + return request; + } + return null; + } + + /// + /// returns the application name + /// + /// + public string Application + { + get + { + return this.applicationName; + } + } + + /// + /// primarily for YouTube. allows you to set the developer key used + /// + public string DeveloperKey + { + get + { + return this.developerKey; + } + set + { + this.developerKey = value; + } + } + + + + /// + /// Takes an existing httpwebrequest and modifies it's headers according to + /// the authentication system used. + /// + /// + /// + public virtual void ApplyAuthenticationToRequest(HttpWebRequest request) + { + /// adds the developer key if present + if (this.DeveloperKey != null) + { + string strHeader = GoogleAuthentication.YouTubeDevKey + this.DeveloperKey; + request.Headers.Add(strHeader); + } + } + + /// + /// Takes an existing httpwebrequest and modifies it's uri according to + /// the authentication system used. Only overridden in 2leggedoauth case + /// + /// the original uri + /// + public virtual Uri ApplyAuthenticationToUri(Uri source) + { + return source; + } + + } + + + public class ClientLoginAuthenticator : Authenticator + { + private GDataCredentials credentials; + private Uri loginHandler; + private string serviceName; + + /// + /// a constructor for client login use cases + /// + /// + /// + /// + /// + public ClientLoginAuthenticator(string applicationName, string serviceName, string userName, string passWord) : + this(applicationName, serviceName, new GDataCredentials(userName, passWord)) + { + } + + + /// + /// a constructor for client login use cases + /// + /// The name of the application + /// the user credentials + /// + public ClientLoginAuthenticator(string applicationName, string serviceName, + GDataCredentials credentials) + : this(applicationName, serviceName, credentials, null) + { + } + + /// + /// a constructor for client login use cases + /// + /// The name of the application + /// the user credentials + /// + public ClientLoginAuthenticator(string applicationName, + string serviceName, + GDataCredentials credentials, + Uri clientLoginHandler) + : base(applicationName) + { + this.credentials = credentials; + this.serviceName = serviceName; + this.loginHandler = clientLoginHandler == null ? + new Uri(GoogleAuthentication.UriHandler) : clientLoginHandler; + } + + + /// + /// returns the Credentials in case of a client login scenario + /// + /// + public GDataCredentials Credentials + { + get + { + return this.credentials; + } + } + + /// + /// returns the service this authenticator is working against + /// + /// + public string Service + { + get + { + return this.serviceName; + } + } + + /// + /// returns the loginhandler that is used to aquire the token from + /// + /// + public Uri LoginHandler + { + get + { + return this.loginHandler; + } + } + + /// + /// Takes an existing httpwebrequest and modifies it's headers according to + /// the authentication system used. + /// + /// + /// + public override void ApplyAuthenticationToRequest(HttpWebRequest request) + { + base.ApplyAuthenticationToRequest(request); + EnsureClientLoginCredentials(request); + if (!String.IsNullOrEmpty(this.Credentials.ClientToken)) + { + string strHeader = GoogleAuthentication.Header + this.Credentials.ClientToken; + request.Headers.Add(strHeader); + } + } + + + private void EnsureClientLoginCredentials(HttpWebRequest request) + { + if (String.IsNullOrEmpty(this.Credentials.ClientToken)) + { + this.Credentials.ClientToken = Utilities.QueryClientLoginToken(this.Credentials, + this.Service, + this.Application, + false, + this.LoginHandler); + } + + } + } + +#if WindowsCE || PocketPC +#else + public class AuthSubAuthenticator : Authenticator + { + private string authSubToken; + private AsymmetricAlgorithm privateKey; + + /// + /// a constructor for a web application authentication scenario + /// + /// + /// + /// + public AuthSubAuthenticator(string applicationName, string authSubToken) + : this(applicationName, authSubToken, null) + { + } + + /// + /// a constructor for a web application authentication scenario + /// + /// + /// + /// + /// + public AuthSubAuthenticator(string applicationName, + string authSubToken, + AsymmetricAlgorithm privateKey) : base(applicationName) + { + this.privateKey = privateKey; + this.authSubToken = authSubToken; + } + + /// + /// returns the authsub token to use for a webapplication scenario + /// + /// + public string Token + { + get + { + return this.authSubToken; + } + } + + /// + /// returns the private key used for authsub authentication + /// + /// + public AsymmetricAlgorithm PrivateKey + { + get + { + return this.privateKey; + } + } + + + /// + /// Takes an existing httpwebrequest and modifies it's headers according to + /// the authentication system used. + /// + /// + /// + public override void ApplyAuthenticationToRequest(HttpWebRequest request) + { + base.ApplyAuthenticationToRequest(request); + + string header = AuthSubUtil.formAuthorizationHeader(this.Token, + this.PrivateKey, + request.RequestUri, + request.Method); + request.Headers.Add(header); + } + } + + public abstract class OAuthAuthenticator : Authenticator + { + private string consumerKey; + private string consumerSecret; + + public OAuthAuthenticator(string applicationName, + string consumerKey, + string consumerSecret) : base(applicationName) + { + this.consumerKey = consumerKey; + this.consumerSecret = consumerSecret; + } + + /// + /// returns the ConsumerKey + /// + /// + public string ConsumerKey + { + get + { + return this.consumerKey; + } + } + + /// + /// returns the ConsumerSecret + /// + /// + public string ConsumerSecret + { + get + { + return this.consumerSecret; + } + } + + + + } + + public class OAuth2LeggedAuthenticator : OAuthAuthenticator + { + private string oAuthUser; + private string oAuthDomain; + + public static string OAuthParameter = "xoauth_requestor_id"; + + /// + /// a constructor for OpenAuthentication login use cases + /// + /// The name of the application + /// the consumerKey to use + /// the consumerSecret to use + /// the username to use + /// the domain to use + /// + public OAuth2LeggedAuthenticator(string applicationName, string consumerKey, + string consumerSecret, + string user, + string domain) : base(applicationName, consumerKey, consumerSecret) + { + this.oAuthUser = user; + this.oAuthDomain = domain; + } + + /// + /// returns the OAuth User + /// + /// + public string OAuthUser + { + get + { + return this.oAuthUser; + } + } + + /// + /// returns the OAuth Domain + /// + /// + public string OAuthDomain + { + get + { + return this.oAuthDomain; + } + } + + + /// + /// Takes an existing httpwebrequest and modifies it's headers according to + /// the authentication system used. + /// + /// + /// + public override void ApplyAuthenticationToRequest(HttpWebRequest request) + { + base.ApplyAuthenticationToRequest(request); + + string oauthHeader = OAuthUtil.GenerateHeader(request.RequestUri, + this.ConsumerKey, + this.ConsumerSecret, + null, + null, + request.Method); + request.Headers.Add(oauthHeader); + } + + /// + /// Takes an existing httpwebrequest and modifies it's uri according to + /// the authentication system used. Only overridden in 2leggedoauth case + /// Here we need to add the xoauthrequestor parameter + /// + /// the original uri + /// + public override Uri ApplyAuthenticationToUri(Uri source) + { + UriBuilder builder = new UriBuilder(source); + string queryToAppend = OAuth2LeggedAuthenticator.OAuthParameter + "=" + this.oAuthUser + "%40" + this.OAuthDomain; + + if (builder.Query != null && builder.Query.Length > 1) + builder.Query = builder.Query + "&" + queryToAppend; + else + builder.Query = queryToAppend; + + return builder.Uri; + } + } + + public class OAuth3LeggedAuthenticator : OAuthAuthenticator + { + private string token; + private string tokenSecret; + + /// + /// a constructor for OpenAuthentication login use cases using 3 legged oAuth + /// + /// The name of the application + /// the consumerKey to use + /// the consumerSecret to use + /// The token to be used + /// The tokenSecret to be used + /// + public OAuth3LeggedAuthenticator(string applicationName, + string consumerKey, string consumerSecret, + string token, string tokenSecret) + : base(applicationName, consumerKey, consumerSecret) + { + this.token = token; + this.tokenSecret = tokenSecret; + } + + /// + /// returns the Token for oAuth + /// + /// + public string Token + { + get + { + return this.token; + } + } + + /// + /// returns the TokenSecret for oAuth + /// + /// + public string TokenSecret + { + get + { + return this.tokenSecret; + } + } + + /// + /// Takes an existing httpwebrequest and modifies it's headers according to + /// the authentication system used. + /// + /// + /// + public override void ApplyAuthenticationToRequest(HttpWebRequest request) + { + base.ApplyAuthenticationToRequest(request); + + string oauthHeader = OAuthUtil.GenerateHeader(request.RequestUri, + this.ConsumerKey, + this.ConsumerSecret, + this.Token, + this.TokenSecret, + request.Method); + request.Headers.Add(oauthHeader); + } + } + + +#endif + +} + + + + + + + + + + + + + + + + + + + + + + + diff -Nru gdata-sharp-1.4.0.2/src/core/authsubutil.cs gdata-sharp-1.7.0.1/src/core/authsubutil.cs --- gdata-sharp-1.4.0.2/src/core/authsubutil.cs 2008-12-01 15:16:30.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/authsubutil.cs 2010-03-18 19:54:24.000000000 +0000 @@ -95,8 +95,8 @@ bool session) { - return getRequestUrl(DEFAULT_PROTOCOL, hostedDomain, continueUrl, scope, - secure, session); + return getRequestUrl(hostedDomain, DEFAULT_PROTOCOL, DEFAULT_DOMAIN, DEFAULT_HANDLER, + continueUrl, scope, secure, session); } @@ -109,7 +109,7 @@ /// /// the protocol to use to communicate with the /// server - /// the domain at which the authentication server + /// the domain at which the authentication server /// exists /// the URL to redirect to on successful /// token retrieval @@ -120,14 +120,14 @@ /// the URL to be used to retrieve the AuthSub token ////////////////////////////////////////////////////////////////////// public static string getRequestUrl(string protocol, - string domain, + string authenticationDomain, string continueUrl, string scope, bool secure, bool session) { - return getRequestUrl(null, protocol, domain, DEFAULT_HANDLER, continueUrl, - scope, secure, session); + return getRequestUrl(null, protocol, authenticationDomain, DEFAULT_HANDLER, + continueUrl, scope, secure, session); } ////////////////////////////////////////////////////////////////////// @@ -138,7 +138,7 @@ /// /// the protocol to use to communicate with the /// server - /// the domain at which the authentication server + /// the domain at which the authentication server /// exists /// the location of the authentication handler /// (defaults to "/accounts/AuthSubRequest". @@ -151,7 +151,7 @@ /// the URL to be used to retrieve the AuthSub token ////////////////////////////////////////////////////////////////////// public static string getRequestUrl(string protocol, - string domain, + string authenticationDomain, string handler, string continueUrl, string scope, @@ -159,7 +159,7 @@ bool session) { - return getRequestUrl(null, protocol, domain, handler, continueUrl, + return getRequestUrl(null, protocol, authenticationDomain, handler, continueUrl, scope, secure, session); } @@ -173,7 +173,7 @@ /// like www.myexample.com /// the protocol to use to communicate with the /// server - /// the domain at which the authentication server + /// the domain at which the authentication server /// exists /// the location of the authentication handler /// (defaults to "/accounts/AuthSubRequest". @@ -187,7 +187,7 @@ ////////////////////////////////////////////////////////////////////// public static string getRequestUrl(string hostedDomain, string protocol, - string domain, + string authenticationDomain, string handler, string continueUrl, string scope, @@ -197,7 +197,7 @@ StringBuilder url = new StringBuilder(protocol); url.Append("://"); - url.Append(domain); + url.Append(authenticationDomain); url.Append(handler); url.Append("?"); @@ -624,7 +624,7 @@ { continue; } - x.Insert(i, Convert.ToInt16(randomNumber[i], CultureInfo.InvariantCulture).ToString()[0]); + x.Append(Convert.ToInt16(randomNumber[i], CultureInfo.InvariantCulture).ToString()[0]); } return x.ToString(); } diff -Nru gdata-sharp-1.4.0.2/src/core/collections.cs gdata-sharp-1.7.0.1/src/core/collections.cs --- gdata-sharp-1.4.0.2/src/core/collections.cs 2009-02-25 13:10:33.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/collections.cs 2010-04-26 14:03:09.000000000 +0000 @@ -171,21 +171,6 @@ ////////////////////////////////////////////////////////////////////// public class AtomLinkCollection : AtomCollectionBase { - /// standard typed accessor method - public override void Add(AtomLink value) - { - if (value == null) - { - throw new ArgumentNullException("value"); - } - // Remove link with same relation to avoid duplication. - AtomLink oldLink = FindService(value.Rel, value.Type); - if (oldLink != null) - { - Remove(oldLink); - } - base.Add(value); - } ////////////////////////////////////////////////////////////////////// /// public AtomLink FindService(string service,string type) @@ -204,7 +189,7 @@ string linkType = link.Type; if ((service == null || (linkRel != null && linkRel == service)) && - (type == null || (linkType != null && linkType == type))) + (type == null || (linkType != null && linkType.StartsWith(type)))) { return link; @@ -235,9 +220,7 @@ if ((service == null || (linkRel != null && linkRel == service)) && (type == null || (linkType != null && linkType == type))) { - foundLinks.Add(link); - ; } } return foundLinks; diff -Nru gdata-sharp-1.4.0.2/src/core/Core Client.csproj gdata-sharp-1.7.0.1/src/core/Core Client.csproj --- gdata-sharp-1.4.0.2/src/core/Core Client.csproj 2008-12-16 16:52:51.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/Core Client.csproj 2010-01-19 15:26:34.000000000 +0000 @@ -1,7 +1,6 @@ - + Local - 8.0.50727 2.0 {B6F6D938-0D45-42BA-8A67-55D92EF03995} Debug @@ -26,6 +25,7 @@ true + 2.0 bin\Debug\ @@ -99,6 +99,7 @@ System + System.Web @@ -137,6 +138,7 @@ + @@ -150,7 +152,6 @@ - @@ -168,6 +169,9 @@ + + + diff -Nru gdata-sharp-1.4.0.2/src/core/extcollections.cs gdata-sharp-1.7.0.1/src/core/extcollections.cs --- gdata-sharp-1.4.0.2/src/core/extcollections.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/extcollections.cs 2009-05-25 14:22:32.000000000 +0000 @@ -0,0 +1,301 @@ +/* Copyright (c) 2006-2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* Change history +* Oct 13 2008 Joe Feser joseph.feser@gmail.com +* Converted ArrayLists and other .NET 1.1 collections to use Generics +* Combined IExtensionElement and IExtensionElementFactory interfaces +* +*/ +#region Using directives + +#define USE_TRACING + +using System; +using System.Collections; +using Google.GData.Client; +using System.Collections.Generic; + +#endregion + +////////////////////////////////////////////////////////////////////// +// contains typed collections based on the 1.1 .NET framework +// using typed collections has the benefit of additional code reliability +// and using them in the collection editor +// +////////////////////////////////////////////////////////////////////// +namespace Google.GData.Extensions +{ + + /// + /// base class to take an object pointer with extension information + /// and expose a localname/namespace subset as a collection + /// that still works on the original + /// + public class ExtensionCollection : IList where T : class, IExtensionElementFactory, new() + { + /// holds the owning feed + private IExtensionContainer container; + private List _items = new List(); + + private static Dictionary _cache = new Dictionary(); + + /// + /// Get the XmlName for the Type + /// + /// + private static string CtorXmlName() + { + IExtensionElementFactory val; + Type t = typeof(T); + if (!_cache.TryGetValue(t, out val)) + { + val = new T(); + _cache[t] = val; + } + return val.XmlName; + } + + /// + /// Get the Xml Namespace for the Type + /// + /// + private static string CtorXmlNS() + { + IExtensionElementFactory val; + Type t = typeof(T); + if (!_cache.TryGetValue(t, out val)) + { + val = new T(); + _cache[t] = val; + } + return val.XmlNameSpace; + } + + /// + /// protected default constructor, not usable by outside + /// + public ExtensionCollection() + { + } + + /// + /// takes the base object, and the localname/ns combo to look for + /// will copy objects to an internal array for caching. Note that when the external + /// ExtensionList is modified, this will have no effect on this copy + /// + /// the base element holding the extension list + public ExtensionCollection(IExtensionContainer containerElement) + : this(containerElement, CtorXmlName(), CtorXmlNS()) + { + } + + /// + /// takes the base object, and the localname/ns combo to look for + /// will copy objects to an internal array for caching. Note that when the external + /// ExtensionList is modified, this will have no effect on this copy + /// + /// the base element holding the extension list + /// the local name of the extension + /// the namespace + public ExtensionCollection(IExtensionContainer containerElement, string localName, string ns) + : base() + { + this.container = containerElement; + if (this.container != null) + { + ExtensionList arr = this.container.FindExtensions(localName, ns); + foreach (T o in arr) + { + _items.Add(o); + } + } + } + + /// standard typed accessor method + public T this[int index] + { + get + { + return ((T)_items[index]); + } + set + { + setItem(index, value); + } + } + + /// + /// useful for subclasses that want to overload the set method + /// + /// the index in the array + /// the item to set + protected void setItem(int index, T item) + { + if (_items[index] != null) + { + if (this.container != null) + { + this.container.ExtensionElements.Remove(_items[index]); + } + } + _items[index] = item; + if (item != null && this.container != null) + { + this.container.ExtensionElements.Add(item); + } + } + + + /// + /// default untyped add implementation. Adds the object as well to the parent + /// object ExtensionList + /// + /// + /// + public int Add(T value) + { + if (this.container != null) + { + this.container.ExtensionElements.Add(value); + } + _items.Add(value); + return _items.Count - 1; + } + + /// + /// inserts an element into the collection by index + /// + /// + /// + public void Insert(int index, T value) + { + if (this.container != null && this.container.ExtensionElements.Contains(value)) + { + this.container.ExtensionElements.Remove(value); + } + this.container.ExtensionElements.Add(value); + _items.Insert(index, value); + } + + /// + /// removes an element at a given index + /// + /// + public void Remove(T value) + { + _items.Remove(value); + if (this.container != null) + { + this.container.ExtensionElements.Remove(value); + } + } + + /// standard typed indexOf method + public int IndexOf(T value) + { + return (_items.IndexOf(value)); + } + + /// standard typed Contains method + public bool Contains(T value) + { + // If value is not of type AtomEntry, this will return false. + return (_items.Contains(value)); + } + + /// standard override OnClear, to remove the objects from the extension list + protected void OnClear() + { + if (this.container != null) + { + for (int i = 0; i < this.Count; i++) + { + this.container.ExtensionElements.Remove(_items[i]); + } + } + } + + #region IList Members + + + public void RemoveAt(int index) + { + T item = _items[index]; + _items.RemoveAt(index); + Remove(item); + } + + #endregion + + #region ICollection Members + + void ICollection.Add(T item) + { + _items.Add(item); + } + + public void Clear() + { + OnClear(); + _items.Clear(); + } + + public void CopyTo(T[] array, int arrayIndex) + { + _items.ToArray().CopyTo(array, arrayIndex); + } + + public int Count + { + get + { + return _items.Count; + } + } + + public bool IsReadOnly + { + get + { + return false; + } + } + + bool ICollection.Remove(T item) + { + return _items.Remove(item); + } + + #endregion + + #region IEnumerable Members + + public IEnumerator GetEnumerator() + { + return _items.GetEnumerator(); + } + + #endregion + + #region IEnumerable Members + + IEnumerator IEnumerable.GetEnumerator() + { + return _items.GetEnumerator(); + } + + #endregion + } +} diff -Nru gdata-sharp-1.4.0.2/src/core/extensionbase.cs gdata-sharp-1.7.0.1/src/core/extensionbase.cs --- gdata-sharp-1.4.0.2/src/core/extensionbase.cs 2009-02-26 11:44:40.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/extensionbase.cs 2009-11-23 14:21:18.000000000 +0000 @@ -293,6 +293,8 @@ protected void InitInstance(ExtensionBase factory) { this.attributes = null; + this.attributeNamespaces = null; + this.unknownChildren = null; for (int i=0; i < factory.getAttributes().Count; i++) { string name = factory.getAttributes().GetKey(i) as string; diff -Nru gdata-sharp-1.4.0.2/src/core/feedmodel.cs gdata-sharp-1.7.0.1/src/core/feedmodel.cs --- gdata-sharp-1.4.0.2/src/core/feedmodel.cs 2009-02-27 14:38:35.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/feedmodel.cs 2010-04-27 13:01:48.000000000 +0000 @@ -23,6 +23,12 @@ using Google.GData.Extensions; using System.Collections.Generic; using Google.GData.Extensions.AppControl; +using System.Security.Cryptography; +#if WindowsCE || PocketPC +#else +using System.ComponentModel; +#endif + namespace Google.GData.Client @@ -38,7 +44,8 @@ int maximum = -1; int numberRetrieved=0; Service service; - FeedQuery query; + FeedQuery query; + RequestSettings settings; /// @@ -80,6 +87,7 @@ } } + /// /// if set to true will cause the feed to add more data when you iterate over it's entries /// @@ -165,6 +173,22 @@ } } + /// + /// accessor for the RequestSettings used to construct the feed. Needed to + /// construct a query that takes auth into account + /// + internal RequestSettings Settings + { + get + { + return this.settings; + } + set + { + this.settings = value; + } + } + /** @@ -178,7 +202,7 @@ until the server reports no more rows available. Note that you should cache the entries returned in a list of your own if you want to access them more than once, as this one does no caching on - it's own. + it's own. The following code illustrates a possible use of @@ -197,15 +221,12 @@ get { bool looping; - - // if we have iterated once before, we need to reset - if (this.numberRetrieved > 0 && this.paging == false && this.service != null) - { - this.af = null; - } + if (this.AtomFeed == null) yield break; + AtomFeed originalFeed = this.AtomFeed; + this.numberRetrieved = 0; do @@ -228,9 +249,13 @@ if (looping) { FeedQuery q = new FeedQuery(this.AtomFeed.NextChunk); + FeedQuery.PrepareQuery(q, this.settings); this.af = this.AtomFeed.Service.Query(q); } } while (looping); + + // we are done, reset the feed to the start + this.af = originalFeed; } } } @@ -247,8 +272,7 @@ private AtomEntry e; /// - /// default public constructor, needed for generics. You should not use that one, but use the - /// CreateInstance method for the entry you want to create + /// default public constructor, needed for generics. /// /// public Entry() @@ -271,6 +295,11 @@ /// the original AtomEntry object that this object is standing in for /// /// +#if WindowsCE || PocketPC +#else + [Category("Basic Entry Data"), + Description("The original AtomEntry object that this object is standing in for")] +#endif public AtomEntry AtomEntry { get @@ -286,6 +315,11 @@ /// /// returns the Id of an entry /// +#if WindowsCE || PocketPC +#else + [Category("Basic Entry Data"), + Description("The unique Id of the entry")] +#endif public string Id { get @@ -304,6 +338,11 @@ /// returns the value of the self uri as a string /// /// +#if WindowsCE || PocketPC +#else + [Category("Basic Entry Data"), + Description("The value of the self uri as a string")] +#endif public string Self { get @@ -322,6 +361,11 @@ /// the title of the Entry. /// /// +#if WindowsCE || PocketPC +#else + [Category("Basic Entry Data"), + Description("Specifies the title of the entry.")] +#endif public virtual string Title { get @@ -339,6 +383,11 @@ /// /// returns the appControl sublement /// +#if WindowsCE || PocketPC +#else + [Category("Basic Entry Data"), + Description("The AppControl subobject.")] +#endif public AppControl AppControl { get @@ -357,6 +406,11 @@ /// /// returns the appControl sublement /// +#if WindowsCE || PocketPC +#else + [Category("Basic Entry Data"), + Description("Specifies if the entry is considered a draft entry.")] +#endif public bool IsDraft { get @@ -369,6 +423,11 @@ /// /// returns true, if the entry has an edit link /// +#if WindowsCE || PocketPC +#else + [Category("Basic Entry Data"), + Description("If then entry has no edit uri, it is considered read only.")] +#endif public bool ReadOnly { get @@ -383,6 +442,11 @@ /// returns the first author name in the atom.entry.authors collection /// /// +#if WindowsCE || PocketPC +#else + [Category("Basic Entry Data"), + Description("returns the first author name in the atom.entry.authors collection.")] +#endif public string Author { get @@ -415,6 +479,11 @@ /// returns the string representation of the atom.content element /// /// +#if WindowsCE || PocketPC +#else + [Category("Basic Entry Data"), + Description("returns the string representation of the atom.content element.")] +#endif public string Content { get @@ -433,6 +502,11 @@ /// returns the string representation of the atom.Summary element /// /// +#if WindowsCE || PocketPC +#else + [Category("Basic Entry Data"), + Description("returns the string representation of the atom.Summary element.")] +#endif public string Summary { get @@ -451,6 +525,11 @@ /// just a thin layer on top of the existing updated of the /// underlying atomentry /// +#if WindowsCE || PocketPC +#else + [Category("Basic Entry Data"), + Description("The datetime at which the entry was updated the last time.")] +#endif public DateTime Updated { get @@ -470,6 +549,11 @@ /// this returns the batch data for the inner atom object /// /// +#if WindowsCE || PocketPC +#else + [Category("Basic Entry Data"), + Description("The batchdata subobject.")] +#endif public GDataBatchEntryData BatchData { get @@ -484,6 +568,96 @@ } } + /// + /// returns the categories for the entry + /// + /// +#if WindowsCE || PocketPC +#else + [Category("Basic Entry Data"), + Description("The Categories collection.")] +#endif + public AtomCategoryCollection Categories + { + get + { + EnsureInnerObject(); + return this.e.Categories; + } + } + + ////////////////////////////////////////////////////////////////////// + /// access the associated media element. Note, that setting this + /// WILL cause subsequent updates to be done using MIME multipart posts + /// + /// + ////////////////////////////////////////////////////////////////////// +#if WindowsCE || PocketPC +#else + [Category("Media Data"), + Description("The Mediasource subobject.")] +#endif + public MediaSource MediaSource + { + get + { + EnsureInnerObject(); + AbstractEntry ae = this.e as AbstractEntry; + + if (ae != null) + return ae.MediaSource; + + return null; + } + set + { + EnsureInnerObject(); + AbstractEntry ae = this.e as AbstractEntry; + + if (ae != null) + ae.MediaSource = value; + else + throw new InvalidOperationException("The AtomEntry contained does not support Media operations"); + } + } + // end of accessor public MediaSource Media + + + ////////////////////////////////////////////////////////////////////// + /// access the associated media element. Note, that setting this + /// WILL cause subsequent updates to be done using MIME multipart posts + /// + /// + ////////////////////////////////////////////////////////////////////// +#if WindowsCE || PocketPC +#else + [Category("State Data"), + Description("The etag information.")] +#endif + public string ETag + { + get + { + EnsureInnerObject(); + AbstractEntry ae = this.e as AbstractEntry; + + if (ae != null) + return ae.Etag; + + return null; + } + set + { + EnsureInnerObject(); + AbstractEntry ae = this.e as AbstractEntry; + + if (ae != null) + ae.Etag = value; + else + throw new InvalidOperationException("The AtomEntry contained does not support ETags operations"); + } + } + // end of accessor public MediaSource Media } @@ -495,6 +669,15 @@ /// public class RequestSettings { + public enum AuthenticationType + { + none, + clientLogin, + authSub, + oAuth + } + + private AuthenticationType authType = AuthenticationType.none; private string applicationName; private GDataCredentials credentials; private string authSubToken; @@ -502,6 +685,16 @@ private int max = -1; private bool autoPage; private int timeout = -1; + private string consumerKey; + private string consumerSecret; + private string oAuthUser; + private string oAuthDomain; + private string token; + private string tokenSecret; + private AsymmetricAlgorithm privateKey; + private Uri clientLoginHandler; + private bool useSSL; + /// /// an unauthenticated use case @@ -520,13 +713,57 @@ /// the user name /// the password /// - public RequestSettings(string applicationName, string userName, string passWord) + public RequestSettings(string applicationName, string userName, string passWord) : + this(applicationName, new GDataCredentials(userName, passWord)) { - this.applicationName = applicationName; - this.credentials = new GDataCredentials(userName, passWord); } /// + /// a constructor for OpenAuthentication login use cases + /// + /// The name of the application + /// the consumerKey to use + /// the consumerSecret to use + /// the username to use + /// the domain to use + /// + public RequestSettings(string applicationName, string consumerKey, + string consumerSecret, + string user, + string domain) : this(applicationName) + { + this.authType = AuthenticationType.oAuth; + this.consumerKey = consumerKey; + this.consumerSecret = consumerSecret; + this.oAuthUser = user; + this.oAuthDomain = domain; + } + + /// + /// a constructor for OpenAuthentication login use cases using 2 or 3 legged oAuth + /// + /// The name of the application + /// the consumerKey to use + /// the consumerSecret to use + /// The token to be used + /// The tokenSecret to be used + /// the username to use + /// the domain to use + /// + public RequestSettings(string applicationName, + string consumerKey, string consumerSecret, + string token, string tokenSecret, + string user, string domain) + : this(applicationName, consumerKey, consumerSecret, + user, domain) + { + this.token = token; + this.tokenSecret = tokenSecret; + } + + + + /// /// a constructor for client login use cases /// /// The name of the application @@ -534,6 +771,7 @@ /// public RequestSettings(string applicationName, GDataCredentials credentials) { + this.authType = AuthenticationType.clientLogin; this.applicationName = applicationName; this.credentials = credentials; } @@ -545,9 +783,26 @@ /// /// /// - public RequestSettings(string applicationName, string authSubToken) + public RequestSettings(string applicationName, string authSubToken) + : this(applicationName) { - this.applicationName = applicationName; + this.authType = AuthenticationType.authSub; + this.authSubToken = authSubToken; + } + + /// + /// a constructor for a web application authentication scenario + /// + /// + /// + /// + /// + public RequestSettings(string applicationName, + string authSubToken, + AsymmetricAlgorithm privateKey) : this(applicationName) + { + this.authType = AuthenticationType.authSub; + this.privateKey = privateKey; this.authSubToken = authSubToken; } @@ -577,6 +832,18 @@ } /// + /// returns the private key used for authsub authentication + /// + /// + public AsymmetricAlgorithm PrivateKey + { + get + { + return this.privateKey; + } + } + + /// /// returns the application name /// /// @@ -589,6 +856,78 @@ } /// + /// returns the ConsumerKey + /// + /// + public string ConsumerKey + { + get + { + return this.consumerKey; + } + } + + /// + /// returns the ConsumerSecret + /// + /// + public string ConsumerSecret + { + get + { + return this.consumerSecret; + } + } + + /// + /// returns the Token for oAuth + /// + /// + public string Token + { + get + { + return this.token; + } + } + + /// + /// returns the TokenSecret for oAuth + /// + /// + public string TokenSecret + { + get + { + return this.tokenSecret; + } + } + + /// + /// returns the OAuth User + /// + /// + public string OAuthUser + { + get + { + return this.oAuthUser; + } + } + + /// + /// returns the OAuth Domain + /// + /// + public string OAuthDomain + { + get + { + return this.oAuthDomain; + } + } + + /// /// the pagesize specifies how many entries should be retrieved per call. If not set, /// the server default will be used. Set it either to -1 (for default) or any value > 0 /// to set the pagesize to something the server should honor. Note, that this set's the @@ -702,6 +1041,135 @@ this.timeout = value; } } + + + /// get's and set's the SSL property used for the created + /// HTTPRequestObject. If true, all requests done will use https + /// The default is false . + /// + /// The following code illustrates a possible use of + /// the Timeout property: + /// + /// YouTubeRequestSettings settings = new YouTubeRequestSettings("yourApp", "yourClient", "yourKey", "username", "pwd"); + /// settings.UseSSL = true; + /// + /// + /// + public bool UseSSL + { + get + { + return this.useSSL; + } + set + { + this.useSSL = value; + } + } + + ////////////////////////////////////////////////////////////////////// + /// ClientLoginHandler - this is the URI that is used to + /// retrieve a client login authentication token + /// + /// + ////////////////////////////////////////////////////////////////////// + public Uri ClientLoginHandler + { + get { + + return this.clientLoginHandler!=null ? + this.clientLoginHandler : new Uri(GoogleAuthentication.UriHandler); + } + set {this.clientLoginHandler = value;} + } + ///////////////////////////////////////////////////////////////////////////// + + + + + /// + /// Creates a HttpWebRequest object that can be used against a given service. + /// for a RequestSetting object that is using client login, this might call + /// to get an authentication token from the service, if it is not already set. + /// + /// if this uses client login, and you need to use a proxy, set the application wide + /// proxy first using the GlobalProxySelection + /// + /// + /// + /// + /// + public HttpWebRequest CreateHttpWebRequest(string serviceName, string httpMethod, Uri targetUri) + { + + if (this.UseSSL == true && (targetUri.Scheme.ToLower().Equals("https") == false)) + { + targetUri = new Uri("https://" + targetUri.Host + targetUri.PathAndQuery); + } + + HttpWebRequest request = WebRequest.Create(targetUri) as HttpWebRequest; + if (request == null) + { + throw new ArgumentException("targetUri does not resolve to an http request"); + } + if (this.authType == AuthenticationType.clientLogin) + { + EnsureClientLoginCredentials(request, serviceName); + } +#if WindowsCE || PocketPC +#else + if (this.authType == AuthenticationType.authSub) + { + EnsureAuthSubCredentials(request); + } + if (this.authType == AuthenticationType.oAuth) + { + EnsureOAuthCredentials(request); + } +#endif + return request; + + } + + private void EnsureClientLoginCredentials(HttpWebRequest request, string serviceName) + { + if (String.IsNullOrEmpty(this.Credentials.ClientToken)) + { + this.Credentials.ClientToken = Utilities.QueryClientLoginToken(this.Credentials, + serviceName, + this.Application, + false, + this.ClientLoginHandler); + } + if (!String.IsNullOrEmpty(this.Credentials.ClientToken)) + { + string strHeader = GoogleAuthentication.Header + this.Credentials.ClientToken; + request.Headers.Add(strHeader); + } + } +#if WindowsCE || PocketPC +#else + private void EnsureAuthSubCredentials(HttpWebRequest request) + { + string header = AuthSubUtil.formAuthorizationHeader(this.Token, + this.PrivateKey, + request.RequestUri, + request.Method); + request.Headers.Add(header); + } + + + private void EnsureOAuthCredentials(HttpWebRequest request) + { + string oauthHeader = OAuthUtil.GenerateHeader(request.RequestUri, + this.ConsumerKey, + this.ConsumerSecret, + this.Token, + this.TokenSecret, + request.Method); + request.Headers.Add(oauthHeader); + } +#endif } @@ -714,7 +1182,7 @@ /// returns the next feed chunk if there is more data /// Next, - /// + /// /// returns the previous feed chunk if there is data before /// Prev, @@ -771,8 +1239,21 @@ GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory(s.ServiceIdentifier, settings.Application); authFactory.UserAgent = authFactory.UserAgent + "--IEnumerable"; authFactory.Token = settings.AuthSubToken; + authFactory.PrivateKey = settings.PrivateKey; s.RequestFactory = authFactory; } + else if (settings.ConsumerKey != null) + { + // let's create an oauth factory + GOAuthRequestFactory authFactory = new GOAuthRequestFactory(s.ServiceIdentifier, settings.Application); + authFactory.ConsumerKey = settings.ConsumerKey; + authFactory.ConsumerSecret = settings.ConsumerSecret; + authFactory.Token = settings.Token; + authFactory.TokenSecret = settings.TokenSecret; + s.RequestFactory = authFactory; + + + } else { GDataGAuthRequestFactory authFactory = s.RequestFactory as GDataGAuthRequestFactory; @@ -790,6 +1271,9 @@ f.Timeout = settings.Timeout; } } + + s.RequestFactory.UseSSL = settings.UseSSL; + #endif } @@ -814,10 +1298,34 @@ /// protected void PrepareQuery(FeedQuery q) { - if (this.settings.PageSize != -1) + FeedQuery.PrepareQuery(q, this.settings); + } + + + /// + /// should be used in subclasses to create URIs from strings, so that the OAuth parameters can be + /// attached + /// + /// + /// + protected Uri CreateUri(string location) + { + #if WindowsCE || PocketPC + return new Uri(location); + #else + + Uri retUri = null; + + if (this.settings.OAuthUser != null && location.IndexOf(OAuthUri.OAuthParameter) != 0) { - q.NumberToRetrieve = this.settings.PageSize; + retUri = new OAuthUri(location, this.settings.OAuthUser, this.settings.OAuthDomain); } + else + { + retUri = new Uri(location); + } + return retUri; + #endif } /// @@ -828,14 +1336,25 @@ /// protected virtual Feed PrepareFeed(FeedQuery q) where Y : Entry, new() { - // AtomFeed feed = this.atomService.Query(q); - // Feed f = new Feed(feed); - Feed f = new Feed(this.atomService, q); + Feed f = CreateFeed(q); + f.Settings = this.settings; f.AutoPaging = this.settings.AutoPaging; f.Maximum = this.settings.Maximum; return f; } + + /// + /// the virtual creator function for feeds, so that we can create feedsubclasses in + /// in subclasses of the request + /// + /// + /// + protected virtual Feed CreateFeed(FeedQuery q) where Y : Entry, new() + { + return new Feed(this.atomService, q); + } + /// /// gets a feed object of type T /// @@ -861,6 +1380,60 @@ /// + /// sets the proxy on the service to be used. + /// + /// + public IWebProxy Proxy + { + get + { + GDataRequestFactory x= this.atomService.RequestFactory as GDataRequestFactory; + if (x != null) + { + return x.Proxy; + } + return null; + } + set + { + GDataRequestFactory x= this.atomService.RequestFactory as GDataRequestFactory; + if (x != null) + { + x.Proxy = value; + OnSetOtherProxies(value); + } + else + { + throw new ArgumentException("Can not set a proxy on this service"); + } + } + } + + /// + /// called to set additonal proxies if required. Overloaded on the document service + /// + /// + /// + protected virtual void OnSetOtherProxies(IWebProxy proxy) + { + + } + + /// + /// + /// + /// + protected Service AtomService + { + get + { + return this.atomService; + } + } + + + + /// /// returns a new feed based on the operation passed in. This is useful if you either do not use /// autopaging, or want to move to previous parts of the feed, or get a refresh of the current feed /// @@ -921,6 +1494,41 @@ return f; } + + /// + /// takes an existing stream and creates Feed of entries out of it + /// + /// + /// + /// + /// + public Feed Parse(Stream inputStream, Uri targetUri) where Y : Entry, new() + { + if (targetUri == null) + throw new ArgumentNullException("targetUri can not be null"); + if (inputStream == null) + throw new ArgumentNullException("inputStream can not be null"); + + AtomFeed feed = this.Service.CreateAndParseFeed(inputStream, targetUri); + return new Feed(feed); + } + + /// + /// takes an existing stream and creates just one entry (the first in the stream) + /// + /// + /// + /// + public Y ParseEntry(Stream inputStream, Uri targetUri) where Y : Entry, new() + { + Feed f = Parse(inputStream, targetUri); + foreach (Y y in f.Entries) + { + return y; + } + return null; + } + /// /// performs a batch operation. /// @@ -963,6 +1571,7 @@ /// /// the batch endpoint of the service /// List of entries of type Y, that are to be batched + /// The default operation to be used for all entries /// public Feed Batch(List entries, Uri batchUri, GDataBatchOperationType defaultOperation) where Y: Entry, new() { @@ -975,7 +1584,10 @@ { batchFeed.Entries.Add(e.AtomEntry); } - AtomFeed resultFeed = this.Service.Batch(batchFeed, batchUri); + + FeedQuery q = PrepareQuery(batchUri.AbsoluteUri); + + AtomFeed resultFeed = this.Service.Batch(batchFeed, q.Uri); Feed f = new Feed(resultFeed); return f; } @@ -1044,9 +1656,8 @@ } /// - /// returns a the entry the Uri pointed to + /// returns the entry the Uri pointed to /// - /// /// the Uri of the entry /// public Y Retrieve(Uri entryUri) where Y : Entry, new() @@ -1093,7 +1704,10 @@ throw new ArgumentNullException("Entry.AtomEntry was null"); Y r = null; - AtomEntry ae = this.Service.Update(entry.AtomEntry); + + FeedQuery q = PrepareQuery(entry.AtomEntry.EditUri.ToString()); + Stream s = this.Service.EntrySend(q.Uri, entry.AtomEntry, GDataRequestType.Update, null); + AtomEntry ae = this.Service.CreateAndParseEntry(s, new Uri(entry.AtomEntry.EditUri.ToString())); if (ae != null) { @@ -1113,8 +1727,14 @@ if (entry.AtomEntry == null) throw new ArgumentNullException("Entry.AtomEntry was null"); + FeedQuery q = PrepareQuery(entry.AtomEntry.EditUri.ToString()); + this.Service.Delete(q.Uri, entry.ETag); + } - entry.AtomEntry.Delete(); + public void Delete(Uri targetUrl, string eTag) + { + FeedQuery q = PrepareQuery(targetUrl.AbsoluteUri); + this.Service.Delete(q.Uri, eTag); } /// @@ -1160,7 +1780,9 @@ throw new ArgumentNullException("Feed was null"); Y r = null; - AtomEntry ae = this.Service.Insert(feed.AtomFeed, entry.AtomEntry); + FeedQuery q = PrepareQuery(feed.AtomFeed.Post); + + AtomEntry ae = this.Service.Insert(q.Uri, entry.AtomEntry); if (ae != null) { r = new Y(); diff -Nru gdata-sharp-1.4.0.2/src/core/feedquery.cs gdata-sharp-1.7.0.1/src/core/feedquery.cs --- gdata-sharp-1.4.0.2/src/core/feedquery.cs 2009-02-16 17:39:06.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/feedquery.cs 2010-05-26 08:15:11.000000000 +0000 @@ -239,6 +239,28 @@ } + /// + /// helper method to setup a query object with some parameters + /// based on a requestsettings + /// + /// + /// + internal static void PrepareQuery(FeedQuery q, RequestSettings settings) + { + if (settings.PageSize != -1) + { + q.NumberToRetrieve = settings.PageSize; + } + if (settings.OAuthUser != null) + { + q.OAuthRequestorId = settings.OAuthUser; + if (settings.OAuthDomain != null) + { + q.OAuthRequestorId += "@" + settings.OAuthDomain; + } + } + } + ////////////////////////////////////////////////////////////////////// @@ -307,6 +329,7 @@ /// or the other way round. This is mostly relevant for hosted domains. /// /// + [Obsolete("This is deprecated and replaced by UseSSL on the service and the requestsettings")] public bool UseSSL { get { return this.defaultSSL; } @@ -489,7 +512,7 @@ /// the start-index query parameter, a 1-based index /// indicating the first result to be retrieved. ////////////////////////////////////////////////////////////////////// - public int StartIndex + public virtual int StartIndex { get {return this.startIndex;} set {this.startIndex = value; } @@ -500,7 +523,7 @@ /// Accessor method public int NumberToRetrieve. /// the number of entries to retrieve ////////////////////////////////////////////////////////////////////// - public int NumberToRetrieve + public virtual int NumberToRetrieve { get {return this.numToRetrieve;} set {this.numToRetrieve = value; } @@ -882,7 +905,7 @@ if (builder == null) throw new ArgumentNullException("builder"); - if (builder.ToString().IndexOf(connect+parameterName) == -1) + if (builder.ToString().IndexOf(parameterName + "=") == -1) { if (Utilities.IsPersistable(value)) { @@ -895,7 +918,7 @@ } /// - /// helper to format an inteer parameter into the query + /// helper to format an integer parameter into the query /// /// /// default value @@ -908,7 +931,7 @@ if (builder == null) throw new ArgumentNullException("builder"); - if (builder.ToString().IndexOf(connect+parameterName) == -1) + if (builder.ToString().IndexOf(parameterName + "=") == -1) { if (value != defValue) { @@ -921,7 +944,7 @@ } /// - /// helper to format an inteer parameter into the query + /// helper to format an unsigned integer parameter into the query /// /// /// default value @@ -935,7 +958,10 @@ if (builder == null) throw new ArgumentNullException("builder"); - if (builder.ToString().IndexOf(connect+parameterName) == -1) + // this used to check for connect + parameterName, i do not recall why + // using just the parametername should catch cases where the parameter to be + // appended is already in the URI as the first parameter + if (builder.ToString().IndexOf(parameterName+"=") == -1) { if (value != defValue) { @@ -960,7 +986,7 @@ if (builder == null) throw new ArgumentNullException("builder"); - if (builder.ToString().IndexOf(connect+parameterName) == -1) + if (builder.ToString().IndexOf(parameterName + "=") == -1) { if (Utilities.IsPersistable(value)) { diff -Nru gdata-sharp-1.4.0.2/src/core/gauthrequest.cs gdata-sharp-1.7.0.1/src/core/gauthrequest.cs --- gdata-sharp-1.4.0.2/src/core/gauthrequest.cs 2008-11-11 14:15:40.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/gauthrequest.cs 2010-11-02 13:47:58.000000000 +0000 @@ -114,19 +114,29 @@ private string captchaAnswer; // indicates the captcha Answer in a challenge private string captchaToken; // indicates the captchaToken in a challenge - + private const int RetryCount = 3; // default retry count for failed requests ////////////////////////////////////////////////////////////////////// /// default constructor ////////////////////////////////////////////////////////////////////// - public GDataGAuthRequestFactory(string service, string applicationName) : base(applicationName) + public GDataGAuthRequestFactory(string service, string applicationName) + : this(service, applicationName, RetryCount) { - this.Service = service; - this.ApplicationName = applicationName; } ///////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// + /// overloaded constructor + ////////////////////////////////////////////////////////////////////// + public GDataGAuthRequestFactory(string service, string applicationName, int numberOfRetries) + : base(applicationName) { + this.Service = service; + this.ApplicationName = applicationName; + this.NumberOfRetries = numberOfRetries; + } + ///////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// /// default constructor ////////////////////////////////////////////////////////////////////// @@ -234,7 +244,7 @@ /// /// property accessor to set the account type that is used during - /// authentication. Defaults, if not set, to GOOGLE_OR_HOSTED + /// authentication. Defaults, if not set, to HOSTED_OR_GOOGLE /// public string AccountType { @@ -314,11 +324,6 @@ this.versionInfo.ProtocolMinor = value; } } - - - - - } ///////////////////////////////////////////////////////////////////////////// @@ -459,7 +464,10 @@ { http.Headers.Remove(GDataGAuthRequestFactory.GDataVersion); - http.Headers.Remove(GoogleAuthentication.Override); + + // as we are doublebuffering due to redirect issues anyhow, + // disallow the default buffering + http.AllowWriteStreamBuffering = false; IVersionAware v = this.factory as IVersionAware; if (v != null) @@ -475,6 +483,9 @@ http.Method != HttpMethods.Get && http.Method != HttpMethods.Post) { + // remove it, if it is already there. + http.Headers.Remove(GoogleAuthentication.Override); + // cache the method, because Mono will complain if we try // to open the request stream with a DELETE method. string currentMethod = http.Method; @@ -504,13 +515,16 @@ ////////////////////////////////////////////////////////////////////// internal string QueryAuthToken(GDataCredentials gc) { - Tracing.Assert(gc != null, "Do not call QueryAuthToken with no network credentials"); - if (gc == null) - { - throw new System.ArgumentNullException("nc", "No credentials supplied"); - } - // Create a new request to the authentication URL. Uri authHandler = null; + + // need to copy this to a new object to avoid that people mix and match + // the old (factory) and the new (requestsettings) and get screwed. So + // copy the settings from the gc passed in and mix with the settings from the factory + GDataCredentials gdc = new GDataCredentials(gc.Username, gc.getPassword()); + gdc.CaptchaToken = this.factory.CaptchaToken; + gdc.CaptchaAnswer = this.factory.CaptchaAnswer; + gdc.AccountType = this.factory.AccountType; + try { authHandler = new Uri(this.factory.Handler); @@ -518,161 +532,16 @@ catch { throw new GDataRequestException("Invalid authentication handler URI given"); - } - - WebRequest authRequest = WebRequest.Create(authHandler); - string accountType = GoogleAuthentication.AccountType; - if (this.factory.AccountType != null) - { - accountType += this.factory.AccountType; - } - else - { - accountType += GoogleAuthentication.AccountTypeDefault; - } - if (this.factory.Proxy != null) - { - authRequest.Proxy = this.factory.Proxy; - } - HttpWebRequest web = authRequest as HttpWebRequest; - if (web != null) - { - web.KeepAlive = this.factory.KeepAlive; - } - WebResponse authResponse = null; - - string authToken = null; - try - { - authRequest.ContentType = HttpFormPost.Encoding; - authRequest.Method = HttpMethods.Post; - ASCIIEncoding encoder = new ASCIIEncoding(); - - string user = gc.Username == null ? "" : gc.Username; - string pwd = gc.getPassword() == null ? "" : gc.getPassword(); - - // now enter the data in the stream - string postData = GoogleAuthentication.Email + "=" + Utilities.UriEncodeUnsafe(user) + "&"; - postData += GoogleAuthentication.Password + "=" + Utilities.UriEncodeUnsafe(pwd) + "&"; - postData += GoogleAuthentication.Source + "=" + Utilities.UriEncodeUnsafe(this.factory.ApplicationName) + "&"; - postData += GoogleAuthentication.Service + "=" + Utilities.UriEncodeUnsafe(this.factory.Service) + "&"; - if (this.factory.CaptchaAnswer != null) - { - postData += GoogleAuthentication.CaptchaAnswer + "=" + Utilities.UriEncodeUnsafe(this.factory.CaptchaAnswer) + "&"; - } - if (this.factory.CaptchaToken != null) - { - postData += GoogleAuthentication.CaptchaToken + "=" + Utilities.UriEncodeUnsafe(this.factory.CaptchaToken) + "&"; - } - postData += accountType; - - byte[] encodedData = encoder.GetBytes(postData); - authRequest.ContentLength = encodedData.Length; - - Stream requestStream = authRequest.GetRequestStream() ; - requestStream.Write(encodedData, 0, encodedData.Length); - requestStream.Close(); - authResponse = authRequest.GetResponse(); - - } - catch (WebException e) - { - Tracing.TraceMsg("QueryAuthtoken failed " + e.Status + " " + e.Message); - authResponse = e.Response; - } - HttpWebResponse response = authResponse as HttpWebResponse; - if (response != null) - { - // check the content type, it must be text - if (!response.ContentType.StartsWith(HttpFormPost.ReturnContentType)) - { - throw new GDataRequestException("Execution of authentication request returned unexpected content type: " + response.ContentType, response); - } - TokenCollection tokens = Utilities.ParseStreamInTokenCollection(response.GetResponseStream()); - authToken = Utilities.FindToken(tokens, GoogleAuthentication.AuthToken); + } - if (authToken == null) - { - throw getAuthException(tokens, response); - } - // failsafe. if getAuthException did not catch an error... - int code= (int)response.StatusCode; - if (code != 200) - { - throw new GDataRequestException("Execution of authentication request returned unexpected result: " +code, response); - } - - } - Tracing.Assert(authToken != null, "did not find an auth token in QueryAuthToken"); - if (authResponse != null) - { - authResponse.Close(); - } - - return authToken; + return Utilities.QueryClientLoginToken(gdc, + this.factory.Service, + this.factory.ApplicationName, + this.factory.KeepAlive, + authHandler); } ///////////////////////////////////////////////////////////////////////////// - /// - /// Returns the respective GDataAuthenticationException given the return - /// values from the login URI handler. - /// - /// The tokencollection of the parsed return form - /// the webresponse - /// AuthenticationException - private static LoggedException getAuthException(TokenCollection tokens, HttpWebResponse response) - { - String errorName = Utilities.FindToken(tokens, "Error"); - int code= (int)response.StatusCode; - if (errorName == null || errorName.Length == 0) - { - // no error given by Gaia, return a standard GDataRequestException - throw new GDataRequestException("Execution of authentication request returned unexpected result: " +code, response); - } - if ("BadAuthentication".Equals(errorName)) - { - return new InvalidCredentialsException("Invalid credentials"); - } - else if ("AccountDeleted".Equals(errorName)) - { - return new AccountDeletedException("Account deleted"); - } - else if ("AccountDisabled".Equals(errorName)) - { - return new AccountDisabledException("Account disabled"); - } - else if ("NotVerified".Equals(errorName)) - { - return new NotVerifiedException("Not verified"); - } - else if ("TermsNotAgreed".Equals(errorName)) - { - return new TermsNotAgreedException("Terms not agreed"); - } - else if ("ServiceUnavailable".Equals(errorName)) - { - return new ServiceUnavailableException("Service unavailable"); - } - else if ("CaptchaRequired".Equals(errorName)) - { - String captchaPath = Utilities.FindToken(tokens, "CaptchaUrl"); - String captchaToken = Utilities.FindToken(tokens, "CaptchaToken"); - - StringBuilder captchaUrl = new StringBuilder(); - captchaUrl.Append(GoogleAuthentication.DefaultProtocol).Append("://"); - captchaUrl.Append(GoogleAuthentication.DefaultDomain); - captchaUrl.Append(GoogleAuthentication.AccountPrefix); - captchaUrl.Append('/').Append(captchaPath); - return new CaptchaRequiredException("Captcha required", - captchaUrl.ToString(), - captchaToken); - - } - else - { - return new AuthenticationException("Error authenticating (check service name): " + errorName); - } - } ////////////////////////////////////////////////////////////////////// /// Executes the request and prepares the response stream. Also @@ -749,7 +618,7 @@ { if (retryCounter > this.factory.NumberOfRetries) { - Tracing.TraceMsg("Got no response object"); + Tracing.TraceMsg("Number of retries exceeded"); throw; } Tracing.TraceMsg("Let's retry this"); @@ -803,6 +672,13 @@ } + // 3 lines of debug code + // this.requestCopy.Seek(0, SeekOrigin.Begin); + + // StreamReader reader = new StreamReader( this.requestCopy ); + // string text = reader.ReadToEnd(); + + this.requestCopy.Seek(0, SeekOrigin.Begin); #if WindowsCE || PocketPC @@ -818,14 +694,17 @@ #else bytesWritten += numBytes; if (this.asyncData != null && this.asyncData.Delegate != null && - this.asyncData.Service != null) + this.asyncData.DataHandler != null) { AsyncOperationProgressEventArgs args; - args = new AsyncOperationProgressEventArgs(this.requestCopy.Length, bytesWritten, (int)current, this.asyncData.UserData); - - if (this.asyncData.Service.SendProgressData(asyncData, args) == false) - break; + args = new AsyncOperationProgressEventArgs(this.requestCopy.Length, + bytesWritten, (int)current, + this.Request.RequestUri, + this.Request.Method, + this.asyncData.UserData); current += oneLoop; + if (this.asyncData.DataHandler.SendProgressData(asyncData, args) == false) + break; } #endif } diff -Nru gdata-sharp-1.4.0.2/src/core/goauthrequest.cs gdata-sharp-1.7.0.1/src/core/goauthrequest.cs --- gdata-sharp-1.4.0.2/src/core/goauthrequest.cs 2008-11-26 07:51:06.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/goauthrequest.cs 2009-11-03 14:16:15.000000000 +0000 @@ -31,6 +31,8 @@ /// this factory's agent public const string GDataGAuthSubAgent = "GOAuthRequestFactory-CS/1.0.0"; + private String tokenSecret; + private String token; private String consumerSecret; private String consumerKey; @@ -75,7 +77,27 @@ } // end of accessor public string ConsumerKey + ////////////////////////////////////////////////////////////////////// + /// accessor method public string TokenSecret + /// the TokenSecret for the oauth request + ////////////////////////////////////////////////////////////////////// + public string TokenSecret + { + get { return this.tokenSecret; } + set { this.tokenSecret = value; } + } + // end of accessor public string ConsumerSecret + ////////////////////////////////////////////////////////////////////// + /// accessor method public string TokenSecret + /// the Token for the oauth request + ////////////////////////////////////////////////////////////////////// + public string Token + { + get { return this.token; } + set { this.token = value; } + } + // end of accessor public string ConsumerSecret } ///////////////////////////////////////////////////////////////////////////// @@ -113,7 +135,12 @@ throw new GDataRequestException("ConsumerKey and ConsumerSecret must be provided to use GOAuthRequestFactory"); } - string oauthHeader = OAuthUtil.GenerateHeader(http.RequestUri, this.factory.ConsumerKey, this.factory.ConsumerSecret, http.Method); + string oauthHeader = OAuthUtil.GenerateHeader(http.RequestUri, + this.factory.ConsumerKey, + this.factory.ConsumerSecret, + this.factory.Token, + this.factory.TokenSecret, + http.Method); this.Request.Headers.Remove("Authorization"); // needed? this.Request.Headers.Add(oauthHeader); } diff -Nru gdata-sharp-1.4.0.2/src/core/gzipstream.cs gdata-sharp-1.7.0.1/src/core/gzipstream.cs --- gdata-sharp-1.4.0.2/src/core/gzipstream.cs 2008-05-15 16:26:06.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/gzipstream.cs 1970-01-01 00:00:00.000000000 +0000 @@ -1,311 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; - -namespace Google.GData.Client -{ - /// Type of compression to use for the GZipStream. Currently only Decompress is supported. - public enum CompressionMode - { - /// Compresses the underlying stream. - Compress, - /// Decompresses the underlying stream. - Decompress, - } - - /// Provides methods and properties used to compress and decompress streams. - public class GZipStream : Stream - { - #region Native const, structs, and defs - private const string ZLibVersion = "1.2.3"; - - private enum ZLibReturnCode - { - Ok = 0, - StreamEnd = 1, - NeedDictionary = 2, - Errno = -1, - StreamError = -2, - DataError = -3, - MemoryError = -4, - BufferError = -5, - VersionError = -6 - } - - private enum ZLibFlush - { - NoFlush = 0, - PartialFlush = 1, - SyncFlush = 2, - FullFlush = 3, - Finish = 4 - } - - private enum ZLibCompressionLevel - { - NoCompression = 0, - BestSpeed = 1, - BestCompression = 2, - DefaultCompression = 3 - } - - private enum ZLibCompressionStrategy - { - Filtered = 1, - HuffmanOnly = 2, - DefaultStrategy = 0 - } - - private enum ZLibCompressionMethod - { - Delated = 8 - } - - private enum ZLibDataType - { - Binary = 0, - Ascii = 1, - Unknown = 2, - } - - private enum ZLibOpenType - { - ZLib = 15, - GZip = 15 + 16, - Both = 15 + 32, - } - - - [StructLayoutAttribute(LayoutKind.Sequential)] - private struct z_stream - { - public IntPtr next_in; /* next input byte */ - public uint avail_in; /* number of bytes available at next_in */ - public uint total_in; /* total nb of input bytes read so far */ - - public IntPtr next_out; /* next output byte should be put there */ - public uint avail_out; /* remaining free space at next_out */ - public uint total_out; /* total nb of bytes output so far */ - - public IntPtr msg; /* last error message, NULL if no error */ - public IntPtr state; /* not visible by applications */ - - public IntPtr zalloc; /* used to allocate the internal state */ - public IntPtr zfree; /* used to free the internal state */ - public IntPtr opaque; /* private data object passed to zalloc and zfree */ - - public ZLibDataType data_type; /* best guess about the data type: ascii or binary */ - public uint adler; /* adler32 value of the uncompressed data */ - public uint reserved; /* reserved for future use */ - }; - #endregion - - #region P/Invoke -#if WindowsCE || PocketPC - [DllImport("zlib.arm.dll", EntryPoint = "inflateInit2_", CharSet = CharSet.Auto)] -#else - [DllImport("zlib.x86.dll", EntryPoint = "inflateInit2_", CharSet = CharSet.Ansi)] -#endif - private static extern ZLibReturnCode inflateInit2(ref z_stream strm, ZLibOpenType windowBits, string version, int stream_size); - -#if WindowsCE || PocketPC - [DllImport("zlib.arm.dll", CharSet = CharSet.Auto)] -#else - [DllImport("zlib.x86.dll", CharSet = CharSet.Ansi)] -#endif - private static extern ZLibReturnCode inflate(ref z_stream strm, ZLibFlush flush); - -#if WindowsCE || PocketPC - [DllImport("zlib.arm.dll", CharSet = CharSet.Auto)] -#else - [DllImport("zlib.x86.dll", CharSet = CharSet.Ansi)] -#endif - private static extern ZLibReturnCode inflateEnd(ref z_stream strm); - #endregion - - private const int BufferSize = 16384; - - private Stream compressedStream; - private CompressionMode mode; - - private z_stream zstream = new z_stream(); - - private byte[] inputBuffer = new byte[BufferSize]; - private GCHandle inputBufferHandle; - - /// Initializes a new instance of the GZipStream class using the specified stream and CompressionMode value. - /// The stream to compress or decompress. - /// One of the CompressionMode values that indicates the action to take. - public GZipStream(Stream stream, CompressionMode mode) - { - if (mode != CompressionMode.Decompress) - throw new NotImplementedException("Compression is not implemented."); - - this.compressedStream = stream; - this.mode = mode; - - this.zstream.zalloc = IntPtr.Zero; - this.zstream.zfree = IntPtr.Zero; - this.zstream.opaque = IntPtr.Zero; - - ZLibReturnCode ret = inflateInit2(ref this.zstream, ZLibOpenType.Both, ZLibVersion, Marshal.SizeOf(typeof(z_stream))); - - if (ret != ZLibReturnCode.Ok) - throw new ArgumentException("Unable to init ZLib. Return code: " + ret.ToString()); - - this.inputBufferHandle = GCHandle.Alloc(inputBuffer, GCHandleType.Pinned); - } - - /// GZipStream destructor. Cleans all allocated resources. - ~GZipStream() - { - Dispose(false); - } - - ////////////////////////////////////////////////////////////////////// - /// Handle Dispose since Stream implements IDisposable - /// indicates if dispose called it or finalize - ////////////////////////////////////////////////////////////////////// - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); - - if (inputBufferHandle.IsAllocated) - { - inputBufferHandle.Free(); - inflateEnd(ref this.zstream); - } - } - - - /// Reads a number of decompressed bytes into the specified byte array. - /// The array used to store decompressed bytes. - /// The location in the array to begin reading. - /// The number of bytes decompressed. - /// The number of bytes that were decompressed into the byte array. If the end of the stream has been reached, zero or the number of bytes read is returned. - public override int Read(byte[] buffer, int offset, int count) - { - if (this.mode == CompressionMode.Compress) - throw new NotSupportedException("Can't read on a compress stream!"); - - bool exitLoop = false; - - byte[] tmpOutputBuffer = new byte[count]; - GCHandle tmpOutpuBufferHandle = GCHandle.Alloc(tmpOutputBuffer, GCHandleType.Pinned); - - this.zstream.next_out = tmpOutpuBufferHandle.AddrOfPinnedObject(); - this.zstream.avail_out = (uint)tmpOutputBuffer.Length; - - try - { - while (this.zstream.avail_out > 0 && exitLoop == false) - { - if (this.zstream.avail_in == 0) - { - int readLength = this.compressedStream.Read(inputBuffer, 0, inputBuffer.Length); - this.zstream.avail_in = (uint)readLength; - this.zstream.next_in = this.inputBufferHandle.AddrOfPinnedObject(); - } - ZLibReturnCode result = inflate(ref zstream, ZLibFlush.NoFlush); - switch (result) - { - case ZLibReturnCode.StreamEnd: - exitLoop = true; - Array.Copy(tmpOutputBuffer, 0, buffer, offset, count - (int)this.zstream.avail_out); - break; - case ZLibReturnCode.Ok: - Array.Copy(tmpOutputBuffer, 0, buffer, offset, count - (int)this.zstream.avail_out); - break; - case ZLibReturnCode.MemoryError: - throw new OutOfMemoryException("ZLib return code: " + result.ToString()); - default: - throw new Exception("ZLib return code: " + result.ToString()); - } - } - - return (count - (int)this.zstream.avail_out); - } - finally - { - tmpOutpuBufferHandle.Free(); - } - } - - /// Closes the current stream and releases any resources (such as sockets and file handles) associated with the current stream. - public override void Close() - { - this.compressedStream.Close(); - base.Close(); - } - - /// Gets a value indicating whether the stream supports reading while decompressing a file. - public override bool CanRead - { - get { return (this.mode == CompressionMode.Decompress ? true : false); } - } - - /// Gets a value indicating whether the stream supports writing. - public override bool CanWrite - { - get { return (this.mode == CompressionMode.Compress ? true : false); } - } - - /// Gets a value indicating whether the stream supports seeking. - public override bool CanSeek - { - get { return (false); } - } - - /// Gets a reference to the underlying stream. - public Stream BaseStream - { - get { return (this.compressedStream); } - } - - #region Not yet supported - /// Flushes the contents of the internal buffer of the current GZipStream object to the underlying stream. - public override void Flush() - { - throw new NotSupportedException("The method or operation is not implemented."); - } - - /// This property is not supported and always throws a NotSupportedException. - /// The location in the stream. - /// One of the SeekOrigin values. - /// A long value. - public override long Seek(long offset, SeekOrigin origin) - { - throw new NotSupportedException(); - } - - /// This property is not supported and always throws a NotSupportedException. - /// The length of the stream. - public override void SetLength(long value) - { - throw new NotSupportedException(); - } - - /// This property is not supported and always throws a NotSupportedException. - /// The array used to store compressed bytes. - /// The location in the array to begin reading. - /// The number of bytes compressed. - public override void Write(byte[] buffer, int offset, int count) - { - throw new NotSupportedException("Not yet supported!"); - } - - /// This property is not supported and always throws a NotSupportedException. - public override long Length - { - get { throw new NotSupportedException(); } - } - - /// This property is not supported and always throws a NotSupportedException. - public override long Position - { - get { throw new NotSupportedException(); } - set { throw new NotSupportedException(); } - } - #endregion - } -} diff -Nru gdata-sharp-1.4.0.2/src/core/HttpUtility.cs gdata-sharp-1.7.0.1/src/core/HttpUtility.cs --- gdata-sharp-1.4.0.2/src/core/HttpUtility.cs 2007-01-09 10:06:30.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/HttpUtility.cs 2009-12-08 11:37:27.000000000 +0000 @@ -1,969 +1,969 @@ #if WindowsCE || PocketPC -// -// System.Web.HttpUtility -// -// Authors: -// Patrik Torstensson (Patrik.Torstensson@labs2.com) -// Wictor Wilén (decode/encode functions) (wictor@ibizkit.se) -// Tim Coleman (tim@timcoleman.com) -// Gonzalo Paniagua Javier (gonzalo@ximian.com) -// -// Copyright (C) 2005 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System.Collections; -using System.Collections.Specialized; -using System.Globalization; -using System.IO; -using System.Security.Permissions; -using System.Text; - -namespace System.Web { - - public sealed class HttpUtility { - - #region Fields - - static Hashtable entities; - static object lock_ = new object (); - - #endregion // Fields - - static Hashtable Entities { - get { - lock (lock_) { - if (entities == null) - InitEntities (); - - return entities; - } - } - } - - #region Constructors - - static void InitEntities () - { - // Build the hash table of HTML entity references. This list comes - // from the HTML 4.01 W3C recommendation. - entities = new Hashtable (); - entities.Add ("nbsp", '\u00A0'); - entities.Add ("iexcl", '\u00A1'); - entities.Add ("cent", '\u00A2'); - entities.Add ("pound", '\u00A3'); - entities.Add ("curren", '\u00A4'); - entities.Add ("yen", '\u00A5'); - entities.Add ("brvbar", '\u00A6'); - entities.Add ("sect", '\u00A7'); - entities.Add ("uml", '\u00A8'); - entities.Add ("copy", '\u00A9'); - entities.Add ("ordf", '\u00AA'); - entities.Add ("laquo", '\u00AB'); - entities.Add ("not", '\u00AC'); - entities.Add ("shy", '\u00AD'); - entities.Add ("reg", '\u00AE'); - entities.Add ("macr", '\u00AF'); - entities.Add ("deg", '\u00B0'); - entities.Add ("plusmn", '\u00B1'); - entities.Add ("sup2", '\u00B2'); - entities.Add ("sup3", '\u00B3'); - entities.Add ("acute", '\u00B4'); - entities.Add ("micro", '\u00B5'); - entities.Add ("para", '\u00B6'); - entities.Add ("middot", '\u00B7'); - entities.Add ("cedil", '\u00B8'); - entities.Add ("sup1", '\u00B9'); - entities.Add ("ordm", '\u00BA'); - entities.Add ("raquo", '\u00BB'); - entities.Add ("frac14", '\u00BC'); - entities.Add ("frac12", '\u00BD'); - entities.Add ("frac34", '\u00BE'); - entities.Add ("iquest", '\u00BF'); - entities.Add ("Agrave", '\u00C0'); - entities.Add ("Aacute", '\u00C1'); - entities.Add ("Acirc", '\u00C2'); - entities.Add ("Atilde", '\u00C3'); - entities.Add ("Auml", '\u00C4'); - entities.Add ("Aring", '\u00C5'); - entities.Add ("AElig", '\u00C6'); - entities.Add ("Ccedil", '\u00C7'); - entities.Add ("Egrave", '\u00C8'); - entities.Add ("Eacute", '\u00C9'); - entities.Add ("Ecirc", '\u00CA'); - entities.Add ("Euml", '\u00CB'); - entities.Add ("Igrave", '\u00CC'); - entities.Add ("Iacute", '\u00CD'); - entities.Add ("Icirc", '\u00CE'); - entities.Add ("Iuml", '\u00CF'); - entities.Add ("ETH", '\u00D0'); - entities.Add ("Ntilde", '\u00D1'); - entities.Add ("Ograve", '\u00D2'); - entities.Add ("Oacute", '\u00D3'); - entities.Add ("Ocirc", '\u00D4'); - entities.Add ("Otilde", '\u00D5'); - entities.Add ("Ouml", '\u00D6'); - entities.Add ("times", '\u00D7'); - entities.Add ("Oslash", '\u00D8'); - entities.Add ("Ugrave", '\u00D9'); - entities.Add ("Uacute", '\u00DA'); - entities.Add ("Ucirc", '\u00DB'); - entities.Add ("Uuml", '\u00DC'); - entities.Add ("Yacute", '\u00DD'); - entities.Add ("THORN", '\u00DE'); - entities.Add ("szlig", '\u00DF'); - entities.Add ("agrave", '\u00E0'); - entities.Add ("aacute", '\u00E1'); - entities.Add ("acirc", '\u00E2'); - entities.Add ("atilde", '\u00E3'); - entities.Add ("auml", '\u00E4'); - entities.Add ("aring", '\u00E5'); - entities.Add ("aelig", '\u00E6'); - entities.Add ("ccedil", '\u00E7'); - entities.Add ("egrave", '\u00E8'); - entities.Add ("eacute", '\u00E9'); - entities.Add ("ecirc", '\u00EA'); - entities.Add ("euml", '\u00EB'); - entities.Add ("igrave", '\u00EC'); - entities.Add ("iacute", '\u00ED'); - entities.Add ("icirc", '\u00EE'); - entities.Add ("iuml", '\u00EF'); - entities.Add ("eth", '\u00F0'); - entities.Add ("ntilde", '\u00F1'); - entities.Add ("ograve", '\u00F2'); - entities.Add ("oacute", '\u00F3'); - entities.Add ("ocirc", '\u00F4'); - entities.Add ("otilde", '\u00F5'); - entities.Add ("ouml", '\u00F6'); - entities.Add ("divide", '\u00F7'); - entities.Add ("oslash", '\u00F8'); - entities.Add ("ugrave", '\u00F9'); - entities.Add ("uacute", '\u00FA'); - entities.Add ("ucirc", '\u00FB'); - entities.Add ("uuml", '\u00FC'); - entities.Add ("yacute", '\u00FD'); - entities.Add ("thorn", '\u00FE'); - entities.Add ("yuml", '\u00FF'); - entities.Add ("fnof", '\u0192'); - entities.Add ("Alpha", '\u0391'); - entities.Add ("Beta", '\u0392'); - entities.Add ("Gamma", '\u0393'); - entities.Add ("Delta", '\u0394'); - entities.Add ("Epsilon", '\u0395'); - entities.Add ("Zeta", '\u0396'); - entities.Add ("Eta", '\u0397'); - entities.Add ("Theta", '\u0398'); - entities.Add ("Iota", '\u0399'); - entities.Add ("Kappa", '\u039A'); - entities.Add ("Lambda", '\u039B'); - entities.Add ("Mu", '\u039C'); - entities.Add ("Nu", '\u039D'); - entities.Add ("Xi", '\u039E'); - entities.Add ("Omicron", '\u039F'); - entities.Add ("Pi", '\u03A0'); - entities.Add ("Rho", '\u03A1'); - entities.Add ("Sigma", '\u03A3'); - entities.Add ("Tau", '\u03A4'); - entities.Add ("Upsilon", '\u03A5'); - entities.Add ("Phi", '\u03A6'); - entities.Add ("Chi", '\u03A7'); - entities.Add ("Psi", '\u03A8'); - entities.Add ("Omega", '\u03A9'); - entities.Add ("alpha", '\u03B1'); - entities.Add ("beta", '\u03B2'); - entities.Add ("gamma", '\u03B3'); - entities.Add ("delta", '\u03B4'); - entities.Add ("epsilon", '\u03B5'); - entities.Add ("zeta", '\u03B6'); - entities.Add ("eta", '\u03B7'); - entities.Add ("theta", '\u03B8'); - entities.Add ("iota", '\u03B9'); - entities.Add ("kappa", '\u03BA'); - entities.Add ("lambda", '\u03BB'); - entities.Add ("mu", '\u03BC'); - entities.Add ("nu", '\u03BD'); - entities.Add ("xi", '\u03BE'); - entities.Add ("omicron", '\u03BF'); - entities.Add ("pi", '\u03C0'); - entities.Add ("rho", '\u03C1'); - entities.Add ("sigmaf", '\u03C2'); - entities.Add ("sigma", '\u03C3'); - entities.Add ("tau", '\u03C4'); - entities.Add ("upsilon", '\u03C5'); - entities.Add ("phi", '\u03C6'); - entities.Add ("chi", '\u03C7'); - entities.Add ("psi", '\u03C8'); - entities.Add ("omega", '\u03C9'); - entities.Add ("thetasym", '\u03D1'); - entities.Add ("upsih", '\u03D2'); - entities.Add ("piv", '\u03D6'); - entities.Add ("bull", '\u2022'); - entities.Add ("hellip", '\u2026'); - entities.Add ("prime", '\u2032'); - entities.Add ("Prime", '\u2033'); - entities.Add ("oline", '\u203E'); - entities.Add ("frasl", '\u2044'); - entities.Add ("weierp", '\u2118'); - entities.Add ("image", '\u2111'); - entities.Add ("real", '\u211C'); - entities.Add ("trade", '\u2122'); - entities.Add ("alefsym", '\u2135'); - entities.Add ("larr", '\u2190'); - entities.Add ("uarr", '\u2191'); - entities.Add ("rarr", '\u2192'); - entities.Add ("darr", '\u2193'); - entities.Add ("harr", '\u2194'); - entities.Add ("crarr", '\u21B5'); - entities.Add ("lArr", '\u21D0'); - entities.Add ("uArr", '\u21D1'); - entities.Add ("rArr", '\u21D2'); - entities.Add ("dArr", '\u21D3'); - entities.Add ("hArr", '\u21D4'); - entities.Add ("forall", '\u2200'); - entities.Add ("part", '\u2202'); - entities.Add ("exist", '\u2203'); - entities.Add ("empty", '\u2205'); - entities.Add ("nabla", '\u2207'); - entities.Add ("isin", '\u2208'); - entities.Add ("notin", '\u2209'); - entities.Add ("ni", '\u220B'); - entities.Add ("prod", '\u220F'); - entities.Add ("sum", '\u2211'); - entities.Add ("minus", '\u2212'); - entities.Add ("lowast", '\u2217'); - entities.Add ("radic", '\u221A'); - entities.Add ("prop", '\u221D'); - entities.Add ("infin", '\u221E'); - entities.Add ("ang", '\u2220'); - entities.Add ("and", '\u2227'); - entities.Add ("or", '\u2228'); - entities.Add ("cap", '\u2229'); - entities.Add ("cup", '\u222A'); - entities.Add ("int", '\u222B'); - entities.Add ("there4", '\u2234'); - entities.Add ("sim", '\u223C'); - entities.Add ("cong", '\u2245'); - entities.Add ("asymp", '\u2248'); - entities.Add ("ne", '\u2260'); - entities.Add ("equiv", '\u2261'); - entities.Add ("le", '\u2264'); - entities.Add ("ge", '\u2265'); - entities.Add ("sub", '\u2282'); - entities.Add ("sup", '\u2283'); - entities.Add ("nsub", '\u2284'); - entities.Add ("sube", '\u2286'); - entities.Add ("supe", '\u2287'); - entities.Add ("oplus", '\u2295'); - entities.Add ("otimes", '\u2297'); - entities.Add ("perp", '\u22A5'); - entities.Add ("sdot", '\u22C5'); - entities.Add ("lceil", '\u2308'); - entities.Add ("rceil", '\u2309'); - entities.Add ("lfloor", '\u230A'); - entities.Add ("rfloor", '\u230B'); - entities.Add ("lang", '\u2329'); - entities.Add ("rang", '\u232A'); - entities.Add ("loz", '\u25CA'); - entities.Add ("spades", '\u2660'); - entities.Add ("clubs", '\u2663'); - entities.Add ("hearts", '\u2665'); - entities.Add ("diams", '\u2666'); - entities.Add ("quot", '\u0022'); - entities.Add ("amp", '\u0026'); - entities.Add ("lt", '\u003C'); - entities.Add ("gt", '\u003E'); - entities.Add ("OElig", '\u0152'); - entities.Add ("oelig", '\u0153'); - entities.Add ("Scaron", '\u0160'); - entities.Add ("scaron", '\u0161'); - entities.Add ("Yuml", '\u0178'); - entities.Add ("circ", '\u02C6'); - entities.Add ("tilde", '\u02DC'); - entities.Add ("ensp", '\u2002'); - entities.Add ("emsp", '\u2003'); - entities.Add ("thinsp", '\u2009'); - entities.Add ("zwnj", '\u200C'); - entities.Add ("zwj", '\u200D'); - entities.Add ("lrm", '\u200E'); - entities.Add ("rlm", '\u200F'); - entities.Add ("ndash", '\u2013'); - entities.Add ("mdash", '\u2014'); - entities.Add ("lsquo", '\u2018'); - entities.Add ("rsquo", '\u2019'); - entities.Add ("sbquo", '\u201A'); - entities.Add ("ldquo", '\u201C'); - entities.Add ("rdquo", '\u201D'); - entities.Add ("bdquo", '\u201E'); - entities.Add ("dagger", '\u2020'); - entities.Add ("Dagger", '\u2021'); - entities.Add ("permil", '\u2030'); - entities.Add ("lsaquo", '\u2039'); - entities.Add ("rsaquo", '\u203A'); - entities.Add ("euro", '\u20AC'); - } - - public HttpUtility () - { - } - - #endregion // Constructors - - #region Methods - - public static void HtmlAttributeEncode (string s, TextWriter output) - { - output.Write(HtmlAttributeEncode(s)); - } - - public static string HtmlAttributeEncode (string s) - { - if (null == s) - return null; - - if (s.IndexOf ('&') == -1 && s.IndexOf ('"') == -1) - return s; - - StringBuilder output = new StringBuilder (); - foreach (char c in s) - switch (c) { - case '&' : - output.Append ("&"); - break; - case '"' : - output.Append ("""); - break; - default: - output.Append (c); - break; - } - - return output.ToString(); - } - - public static string UrlDecode (string str) - { - return UrlDecode(str, Encoding.UTF8); - } - - private static char [] GetChars (MemoryStream b, Encoding e) - { - return e.GetChars (b.GetBuffer (), 0, (int) b.Length); - } - - public static string UrlDecode (string s, Encoding e) - { - if (null == s) - return null; - - if (s.IndexOf ('%') == -1 && s.IndexOf ('+') == -1) - return s; - - if (e == null) - e = Encoding.UTF8; - - StringBuilder output = new StringBuilder (); - long len = s.Length; - MemoryStream bytes = new MemoryStream (); - int xchar; - - for (int i = 0; i < len; i++) { - if (s [i] == '%' && i + 2 < len && s [i + 1] != '%') { - if (s [i + 1] == 'u' && i + 5 < len) { - if (bytes.Length > 0) { - output.Append (GetChars (bytes, e)); - bytes.SetLength (0); - } - - xchar = GetChar (s, i + 2, 4); - if (xchar != -1) { - output.Append ((char) xchar); - i += 5; - } else { - output.Append ('%'); - } - } else if ((xchar = GetChar (s, i + 1, 2)) != -1) { - bytes.WriteByte ((byte) xchar); - i += 2; - } else { - output.Append ('%'); - } - continue; - } - - if (bytes.Length > 0) { - output.Append (GetChars (bytes, e)); - bytes.SetLength (0); - } - - if (s [i] == '+') { - output.Append (' '); - } else { - output.Append (s [i]); - } - } - - if (bytes.Length > 0) { - output.Append (GetChars (bytes, e)); - } - - bytes = null; - return output.ToString (); - } - - public static string UrlDecode (byte [] bytes, Encoding e) - { - if (bytes == null) - return null; - - return UrlDecode (bytes, 0, bytes.Length, e); - } - - private static int GetInt (byte b) - { - char c = (char) b; - if (c >= '0' && c <= '9') - return c - '0'; - - if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - - if (c >= 'A' && c <= 'F') - return c - 'A' + 10; - - return -1; - } - - private static int GetChar (byte [] bytes, int offset, int length) - { - int value = 0; - int end = length + offset; - for (int i = offset; i < end; i++) { - int current = GetInt (bytes [i]); - if (current == -1) - return -1; - value = (value << 4) + current; - } - - return value; - } - - private static int GetChar (string str, int offset, int length) - { - int val = 0; - int end = length + offset; - for (int i = offset; i < end; i++) { - char c = str [i]; - if (c > 127) - return -1; - - int current = GetInt ((byte) c); - if (current == -1) - return -1; - val = (val << 4) + current; - } - - return val; - } - - public static string UrlDecode (byte [] bytes, int offset, int count, Encoding e) - { - if (bytes == null) - return null; - if (count == 0) - return String.Empty; - - if (bytes == null) - throw new ArgumentNullException ("bytes"); - - if (offset < 0 || offset > bytes.Length) - throw new ArgumentOutOfRangeException ("offset"); - - if (count < 0 || offset + count > bytes.Length) - throw new ArgumentOutOfRangeException ("count"); - - StringBuilder output = new StringBuilder (); - MemoryStream acc = new MemoryStream (); - - int end = count + offset; - int xchar; - for (int i = offset; i < end; i++) { - if (bytes [i] == '%' && i + 2 < count && bytes [i + 1] != '%') { - if (bytes [i + 1] == (byte) 'u' && i + 5 < end) { - if (acc.Length > 0) { - output.Append (GetChars (acc, e)); - acc.SetLength (0); - } - xchar = GetChar (bytes, i + 2, 4); - if (xchar != -1) { - output.Append ((char) xchar); - i += 5; - continue; - } - } else if ((xchar = GetChar (bytes, i + 1, 2)) != -1) { - acc.WriteByte ((byte) xchar); - i += 2; - continue; - } - } - - if (acc.Length > 0) { - output.Append (GetChars (acc, e)); - acc.SetLength (0); - } - - if (bytes [i] == '+') { - output.Append (' '); - } else { - output.Append ((char) bytes [i]); - } - } - - if (acc.Length > 0) { - output.Append (GetChars (acc, e)); - } - - acc = null; - return output.ToString (); - } - - public static byte [] UrlDecodeToBytes (byte [] bytes) - { - if (bytes == null) - return null; - - return UrlDecodeToBytes (bytes, 0, bytes.Length); - } - - public static byte [] UrlDecodeToBytes (string str) - { - return UrlDecodeToBytes (str, Encoding.UTF8); - } - - public static byte [] UrlDecodeToBytes (string str, Encoding e) - { - if (str == null) - return null; - - if (e == null) - throw new ArgumentNullException ("e"); - - return UrlDecodeToBytes (e.GetBytes (str)); - } - - public static byte [] UrlDecodeToBytes (byte [] bytes, int offset, int count) - { - if (bytes == null) - return null; - if (count == 0) - return new byte [0]; - - int len = bytes.Length; - if (offset < 0 || offset >= len) - throw new ArgumentOutOfRangeException("offset"); - - if (count < 0 || offset > len - count) - throw new ArgumentOutOfRangeException("count"); - - MemoryStream result = new MemoryStream (); - int end = offset + count; - for (int i = offset; i < end; i++){ - char c = (char) bytes [i]; - if (c == '+') { - c = ' '; - } else if (c == '%' && i < end - 2) { - int xchar = GetChar (bytes, i + 1, 2); - if (xchar != -1) { - c = (char) xchar; - i += 2; - } - } - result.WriteByte ((byte) c); - } - - return result.ToArray (); - } - - static char [] hexChars = "0123456789abcdef".ToCharArray (); - const string notEncoded = "!'()*-._"; - - static void UrlEncodeChar (char c, Stream result, bool isUnicode) { - if (c > 255) { - //FIXME: what happens when there is an internal error? - //if (!isUnicode) - // throw new ArgumentOutOfRangeException ("c", c, "c must be less than 256"); - int idx; - int i = (int) c; - - result.WriteByte ((byte)'%'); - result.WriteByte ((byte)'u'); - idx = i >> 12; - result.WriteByte ((byte)hexChars [idx]); - idx = (i >> 8) & 0x0F; - result.WriteByte ((byte)hexChars [idx]); - idx = (i >> 4) & 0x0F; - result.WriteByte ((byte)hexChars [idx]); - idx = i & 0x0F; - result.WriteByte ((byte)hexChars [idx]); - return; - } - - if (c>' ' && notEncoded.IndexOf (c)!=-1) { - result.WriteByte ((byte)c); - return; - } - if (c==' ') { - result.WriteByte ((byte)'+'); - return; - } - if ( (c < '0') || - (c < 'A' && c > '9') || - (c > 'Z' && c < 'a') || - (c > 'z')) { - if (isUnicode && c > 127) { - result.WriteByte ((byte)'%'); - result.WriteByte ((byte)'u'); - result.WriteByte ((byte)'0'); - result.WriteByte ((byte)'0'); - } - else - result.WriteByte ((byte)'%'); - - int idx = ((int) c) >> 4; - result.WriteByte ((byte)hexChars [idx]); - idx = ((int) c) & 0x0F; - result.WriteByte ((byte)hexChars [idx]); - } - else - result.WriteByte ((byte)c); - } - - public static byte [] UrlEncodeToBytes (byte [] bytes, int offset, int count) - { - if (bytes == null) - return null; - - int len = bytes.Length; - if (len == 0) - return new byte [0]; - - if (offset < 0 || offset >= len) - throw new ArgumentOutOfRangeException("offset"); - - if (count < 0 || count > len - offset) - throw new ArgumentOutOfRangeException("count"); - - MemoryStream result = new MemoryStream (count); - int end = offset + count; - for (int i = offset; i < end; i++) - UrlEncodeChar ((char)bytes [i], result, false); - - return result.ToArray(); - } - - - public static byte [] UrlEncodeUnicodeToBytes (string str) - { - if (str == null) - return null; - - if (str == "") - return new byte [0]; - - MemoryStream result = new MemoryStream (str.Length); - foreach (char c in str){ - UrlEncodeChar (c, result, true); - } - return result.ToArray (); - } - - /// - /// Decodes an HTML-encoded string and returns the decoded string. - /// - /// The HTML string to decode. - /// The decoded text. - public static string HtmlDecode (string s) - { - if (s == null) - throw new ArgumentNullException ("s"); - - if (s.IndexOf ('&') == -1) - return s; - - StringBuilder entity = new StringBuilder (); - StringBuilder output = new StringBuilder (); - int len = s.Length; - // 0 -> nothing, - // 1 -> right after '&' - // 2 -> between '&' and ';' but no '#' - // 3 -> '#' found after '&' and getting numbers - int state = 0; - int number = 0; - bool have_trailing_digits = false; - - for (int i = 0; i < len; i++) { - char c = s [i]; - if (state == 0) { - if (c == '&') { - entity.Append (c); - state = 1; - } else { - output.Append (c); - } - continue; - } - - if (c == '&') { - state = 1; - if (have_trailing_digits) { - entity.Append (number.ToString (CultureInfo.InvariantCulture)); - have_trailing_digits = false; - } - - output.Append (entity.ToString ()); - entity.Length = 0; - entity.Append ('&'); - continue; - } - - if (state == 1) { - if (c == ';') { - state = 0; - output.Append (entity.ToString ()); - output.Append (c); - entity.Length = 0; - } else { - number = 0; - if (c != '#') { - state = 2; - } else { - state = 3; - } - entity.Append (c); - } - } else if (state == 2) { - entity.Append (c); - if (c == ';') { - string key = entity.ToString (); - if (key.Length > 1 && Entities.ContainsKey (key.Substring (1, key.Length - 2))) - key = Entities [key.Substring (1, key.Length - 2)].ToString (); - - output.Append (key); - state = 0; - entity.Length = 0; - } - } else if (state == 3) { - if (c == ';') { - if (number > 65535) { - output.Append ("&#"); - output.Append (number.ToString (CultureInfo.InvariantCulture)); - output.Append (";"); - } else { - output.Append ((char) number); - } - state = 0; - entity.Length = 0; - have_trailing_digits = false; - } else if (Char.IsDigit (c)) { - number = number * 10 + ((int) c - '0'); - have_trailing_digits = true; - } else { - state = 2; - if (have_trailing_digits) { - entity.Append (number.ToString (CultureInfo.InvariantCulture)); - have_trailing_digits = false; - } - entity.Append (c); - } - } - } - - if (entity.Length > 0) { - output.Append (entity.ToString ()); - } else if (have_trailing_digits) { - output.Append (number.ToString (CultureInfo.InvariantCulture)); - } - return output.ToString (); - } - - /// - /// Decodes an HTML-encoded string and sends the resulting output to a TextWriter output stream. - /// - /// The HTML string to decode - /// The TextWriter output stream containing the decoded string. - public static void HtmlDecode(string s, TextWriter output) - { - if (s != null) - output.Write (HtmlDecode (s)); - } - - /// - /// HTML-encodes a string and returns the encoded string. - /// - /// The text string to encode. - /// The HTML-encoded text. - public static string HtmlEncode (string s) - { - if (s == null) - return null; - - StringBuilder output = new StringBuilder (); - - foreach (char c in s) - switch (c) { - case '&' : - output.Append ("&"); - break; - case '>' : - output.Append (">"); - break; - case '<' : - output.Append ("<"); - break; - case '"' : - output.Append ("""); - break; - default: - // MS starts encoding with &# from 160 and stops at 255. - // We don't do that. One reason is the 65308/65310 unicode - // characters that look like '<' and '>'. - if (c > 159) { - output.Append ("&#"); - output.Append (((int) c).ToString (CultureInfo.InvariantCulture)); - output.Append (";"); - } else { - output.Append (c); - } - break; - } - return output.ToString (); - } - - /// - /// HTML-encodes a string and sends the resulting output to a TextWriter output stream. - /// - /// The string to encode. - /// The TextWriter output stream containing the encoded string. - public static void HtmlEncode(string s, TextWriter output) - { - if (s != null) - output.Write (HtmlEncode (s)); - } - -#if NET_1_1 - public static string UrlPathEncode (string s) - { - if (s == null || s.Length == 0) - return s; - - MemoryStream result = new MemoryStream (); - int length = s.Length; - for (int i = 0; i < length; i++) { - UrlPathEncodeChar (s [i], result); - } - return Encoding.ASCII.GetString (result.ToArray ()); - } - - static void UrlPathEncodeChar (char c, Stream result) { - if (c > 127) { - byte [] bIn = Encoding.UTF8.GetBytes (c.ToString ()); - for (int i = 0; i < bIn.Length; i++) { - result.WriteByte ((byte) '%'); - int idx = ((int) bIn [i]) >> 4; - result.WriteByte ((byte) hexChars [idx]); - idx = ((int) bIn [i]) & 0x0F; - result.WriteByte ((byte) hexChars [idx]); - } - } - else if (c == ' ') { - result.WriteByte ((byte) '%'); - result.WriteByte ((byte) '2'); - result.WriteByte ((byte) '0'); - } - else - result.WriteByte ((byte) c); - } -#endif - -#if NET_2_0 - public static NameValueCollection ParseQueryString (string query) - { - return ParseQueryString (query, Encoding.UTF8); - } - - public static NameValueCollection ParseQueryString (string query, Encoding encoding) - { - if (query == null) - throw new ArgumentNullException ("query"); - if (encoding == null) - throw new ArgumentNullException ("encoding"); - if (query.Length == 0 || (query.Length == 1 && query[0] == '?')) - return new NameValueCollection (); - if (query[0] == '?') - query = query.Substring (1); - - NameValueCollection result = new NameValueCollection (); - ParseQueryString (query, encoding, result); - return result; - } -#endif - - internal static void ParseQueryString (string query, Encoding encoding, NameValueCollection result) - { - if (query.Length == 0) - return; - - int namePos = 0; - while (namePos <= query.Length) { - int valuePos = -1, valueEnd = -1; - for (int q = namePos; q < query.Length; q++) { - if (valuePos == -1 && query[q] == '=') { - valuePos = q + 1; - } else if (query[q] == '&') { - valueEnd = q; - break; - } - } - - string name, value; - if (valuePos == -1) { - name = null; - valuePos = namePos; - } else { - name = UrlDecode (query.Substring (namePos, valuePos - namePos - 1), encoding); - } - if (valueEnd < 0) { - namePos = -1; - valueEnd = query.Length; - } else { - namePos = valueEnd + 1; - } - value = UrlDecode (query.Substring (valuePos, valueEnd - valuePos), encoding); - - result.Add (name, value); - if (namePos == -1) break; - } - } - #endregion // Methods - } +// +// System.Web.HttpUtility +// +// Authors: +// Patrik Torstensson (Patrik.Torstensson@labs2.com) +// Wictor Wilén (decode/encode functions) (wictor@ibizkit.se) +// Tim Coleman (tim@timcoleman.com) +// Gonzalo Paniagua Javier (gonzalo@ximian.com) +// +// Copyright (C) 2005 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.Collections; +using System.Collections.Specialized; +using System.Globalization; +using System.IO; +using System.Security.Permissions; +using System.Text; + +namespace System.Web { + + public sealed class HttpUtility { + + #region Fields + + static Hashtable entities; + static object lock_ = new object (); + + #endregion // Fields + + static Hashtable Entities { + get { + lock (lock_) { + if (entities == null) + InitEntities (); + + return entities; + } + } + } + + #region Constructors + + static void InitEntities () + { + // Build the hash table of HTML entity references. This list comes + // from the HTML 4.01 W3C recommendation. + entities = new Hashtable (); + entities.Add ("nbsp", '\u00A0'); + entities.Add ("iexcl", '\u00A1'); + entities.Add ("cent", '\u00A2'); + entities.Add ("pound", '\u00A3'); + entities.Add ("curren", '\u00A4'); + entities.Add ("yen", '\u00A5'); + entities.Add ("brvbar", '\u00A6'); + entities.Add ("sect", '\u00A7'); + entities.Add ("uml", '\u00A8'); + entities.Add ("copy", '\u00A9'); + entities.Add ("ordf", '\u00AA'); + entities.Add ("laquo", '\u00AB'); + entities.Add ("not", '\u00AC'); + entities.Add ("shy", '\u00AD'); + entities.Add ("reg", '\u00AE'); + entities.Add ("macr", '\u00AF'); + entities.Add ("deg", '\u00B0'); + entities.Add ("plusmn", '\u00B1'); + entities.Add ("sup2", '\u00B2'); + entities.Add ("sup3", '\u00B3'); + entities.Add ("acute", '\u00B4'); + entities.Add ("micro", '\u00B5'); + entities.Add ("para", '\u00B6'); + entities.Add ("middot", '\u00B7'); + entities.Add ("cedil", '\u00B8'); + entities.Add ("sup1", '\u00B9'); + entities.Add ("ordm", '\u00BA'); + entities.Add ("raquo", '\u00BB'); + entities.Add ("frac14", '\u00BC'); + entities.Add ("frac12", '\u00BD'); + entities.Add ("frac34", '\u00BE'); + entities.Add ("iquest", '\u00BF'); + entities.Add ("Agrave", '\u00C0'); + entities.Add ("Aacute", '\u00C1'); + entities.Add ("Acirc", '\u00C2'); + entities.Add ("Atilde", '\u00C3'); + entities.Add ("Auml", '\u00C4'); + entities.Add ("Aring", '\u00C5'); + entities.Add ("AElig", '\u00C6'); + entities.Add ("Ccedil", '\u00C7'); + entities.Add ("Egrave", '\u00C8'); + entities.Add ("Eacute", '\u00C9'); + entities.Add ("Ecirc", '\u00CA'); + entities.Add ("Euml", '\u00CB'); + entities.Add ("Igrave", '\u00CC'); + entities.Add ("Iacute", '\u00CD'); + entities.Add ("Icirc", '\u00CE'); + entities.Add ("Iuml", '\u00CF'); + entities.Add ("ETH", '\u00D0'); + entities.Add ("Ntilde", '\u00D1'); + entities.Add ("Ograve", '\u00D2'); + entities.Add ("Oacute", '\u00D3'); + entities.Add ("Ocirc", '\u00D4'); + entities.Add ("Otilde", '\u00D5'); + entities.Add ("Ouml", '\u00D6'); + entities.Add ("times", '\u00D7'); + entities.Add ("Oslash", '\u00D8'); + entities.Add ("Ugrave", '\u00D9'); + entities.Add ("Uacute", '\u00DA'); + entities.Add ("Ucirc", '\u00DB'); + entities.Add ("Uuml", '\u00DC'); + entities.Add ("Yacute", '\u00DD'); + entities.Add ("THORN", '\u00DE'); + entities.Add ("szlig", '\u00DF'); + entities.Add ("agrave", '\u00E0'); + entities.Add ("aacute", '\u00E1'); + entities.Add ("acirc", '\u00E2'); + entities.Add ("atilde", '\u00E3'); + entities.Add ("auml", '\u00E4'); + entities.Add ("aring", '\u00E5'); + entities.Add ("aelig", '\u00E6'); + entities.Add ("ccedil", '\u00E7'); + entities.Add ("egrave", '\u00E8'); + entities.Add ("eacute", '\u00E9'); + entities.Add ("ecirc", '\u00EA'); + entities.Add ("euml", '\u00EB'); + entities.Add ("igrave", '\u00EC'); + entities.Add ("iacute", '\u00ED'); + entities.Add ("icirc", '\u00EE'); + entities.Add ("iuml", '\u00EF'); + entities.Add ("eth", '\u00F0'); + entities.Add ("ntilde", '\u00F1'); + entities.Add ("ograve", '\u00F2'); + entities.Add ("oacute", '\u00F3'); + entities.Add ("ocirc", '\u00F4'); + entities.Add ("otilde", '\u00F5'); + entities.Add ("ouml", '\u00F6'); + entities.Add ("divide", '\u00F7'); + entities.Add ("oslash", '\u00F8'); + entities.Add ("ugrave", '\u00F9'); + entities.Add ("uacute", '\u00FA'); + entities.Add ("ucirc", '\u00FB'); + entities.Add ("uuml", '\u00FC'); + entities.Add ("yacute", '\u00FD'); + entities.Add ("thorn", '\u00FE'); + entities.Add ("yuml", '\u00FF'); + entities.Add ("fnof", '\u0192'); + entities.Add ("Alpha", '\u0391'); + entities.Add ("Beta", '\u0392'); + entities.Add ("Gamma", '\u0393'); + entities.Add ("Delta", '\u0394'); + entities.Add ("Epsilon", '\u0395'); + entities.Add ("Zeta", '\u0396'); + entities.Add ("Eta", '\u0397'); + entities.Add ("Theta", '\u0398'); + entities.Add ("Iota", '\u0399'); + entities.Add ("Kappa", '\u039A'); + entities.Add ("Lambda", '\u039B'); + entities.Add ("Mu", '\u039C'); + entities.Add ("Nu", '\u039D'); + entities.Add ("Xi", '\u039E'); + entities.Add ("Omicron", '\u039F'); + entities.Add ("Pi", '\u03A0'); + entities.Add ("Rho", '\u03A1'); + entities.Add ("Sigma", '\u03A3'); + entities.Add ("Tau", '\u03A4'); + entities.Add ("Upsilon", '\u03A5'); + entities.Add ("Phi", '\u03A6'); + entities.Add ("Chi", '\u03A7'); + entities.Add ("Psi", '\u03A8'); + entities.Add ("Omega", '\u03A9'); + entities.Add ("alpha", '\u03B1'); + entities.Add ("beta", '\u03B2'); + entities.Add ("gamma", '\u03B3'); + entities.Add ("delta", '\u03B4'); + entities.Add ("epsilon", '\u03B5'); + entities.Add ("zeta", '\u03B6'); + entities.Add ("eta", '\u03B7'); + entities.Add ("theta", '\u03B8'); + entities.Add ("iota", '\u03B9'); + entities.Add ("kappa", '\u03BA'); + entities.Add ("lambda", '\u03BB'); + entities.Add ("mu", '\u03BC'); + entities.Add ("nu", '\u03BD'); + entities.Add ("xi", '\u03BE'); + entities.Add ("omicron", '\u03BF'); + entities.Add ("pi", '\u03C0'); + entities.Add ("rho", '\u03C1'); + entities.Add ("sigmaf", '\u03C2'); + entities.Add ("sigma", '\u03C3'); + entities.Add ("tau", '\u03C4'); + entities.Add ("upsilon", '\u03C5'); + entities.Add ("phi", '\u03C6'); + entities.Add ("chi", '\u03C7'); + entities.Add ("psi", '\u03C8'); + entities.Add ("omega", '\u03C9'); + entities.Add ("thetasym", '\u03D1'); + entities.Add ("upsih", '\u03D2'); + entities.Add ("piv", '\u03D6'); + entities.Add ("bull", '\u2022'); + entities.Add ("hellip", '\u2026'); + entities.Add ("prime", '\u2032'); + entities.Add ("Prime", '\u2033'); + entities.Add ("oline", '\u203E'); + entities.Add ("frasl", '\u2044'); + entities.Add ("weierp", '\u2118'); + entities.Add ("image", '\u2111'); + entities.Add ("real", '\u211C'); + entities.Add ("trade", '\u2122'); + entities.Add ("alefsym", '\u2135'); + entities.Add ("larr", '\u2190'); + entities.Add ("uarr", '\u2191'); + entities.Add ("rarr", '\u2192'); + entities.Add ("darr", '\u2193'); + entities.Add ("harr", '\u2194'); + entities.Add ("crarr", '\u21B5'); + entities.Add ("lArr", '\u21D0'); + entities.Add ("uArr", '\u21D1'); + entities.Add ("rArr", '\u21D2'); + entities.Add ("dArr", '\u21D3'); + entities.Add ("hArr", '\u21D4'); + entities.Add ("forall", '\u2200'); + entities.Add ("part", '\u2202'); + entities.Add ("exist", '\u2203'); + entities.Add ("empty", '\u2205'); + entities.Add ("nabla", '\u2207'); + entities.Add ("isin", '\u2208'); + entities.Add ("notin", '\u2209'); + entities.Add ("ni", '\u220B'); + entities.Add ("prod", '\u220F'); + entities.Add ("sum", '\u2211'); + entities.Add ("minus", '\u2212'); + entities.Add ("lowast", '\u2217'); + entities.Add ("radic", '\u221A'); + entities.Add ("prop", '\u221D'); + entities.Add ("infin", '\u221E'); + entities.Add ("ang", '\u2220'); + entities.Add ("and", '\u2227'); + entities.Add ("or", '\u2228'); + entities.Add ("cap", '\u2229'); + entities.Add ("cup", '\u222A'); + entities.Add ("int", '\u222B'); + entities.Add ("there4", '\u2234'); + entities.Add ("sim", '\u223C'); + entities.Add ("cong", '\u2245'); + entities.Add ("asymp", '\u2248'); + entities.Add ("ne", '\u2260'); + entities.Add ("equiv", '\u2261'); + entities.Add ("le", '\u2264'); + entities.Add ("ge", '\u2265'); + entities.Add ("sub", '\u2282'); + entities.Add ("sup", '\u2283'); + entities.Add ("nsub", '\u2284'); + entities.Add ("sube", '\u2286'); + entities.Add ("supe", '\u2287'); + entities.Add ("oplus", '\u2295'); + entities.Add ("otimes", '\u2297'); + entities.Add ("perp", '\u22A5'); + entities.Add ("sdot", '\u22C5'); + entities.Add ("lceil", '\u2308'); + entities.Add ("rceil", '\u2309'); + entities.Add ("lfloor", '\u230A'); + entities.Add ("rfloor", '\u230B'); + entities.Add ("lang", '\u2329'); + entities.Add ("rang", '\u232A'); + entities.Add ("loz", '\u25CA'); + entities.Add ("spades", '\u2660'); + entities.Add ("clubs", '\u2663'); + entities.Add ("hearts", '\u2665'); + entities.Add ("diams", '\u2666'); + entities.Add ("quot", '\u0022'); + entities.Add ("amp", '\u0026'); + entities.Add ("lt", '\u003C'); + entities.Add ("gt", '\u003E'); + entities.Add ("OElig", '\u0152'); + entities.Add ("oelig", '\u0153'); + entities.Add ("Scaron", '\u0160'); + entities.Add ("scaron", '\u0161'); + entities.Add ("Yuml", '\u0178'); + entities.Add ("circ", '\u02C6'); + entities.Add ("tilde", '\u02DC'); + entities.Add ("ensp", '\u2002'); + entities.Add ("emsp", '\u2003'); + entities.Add ("thinsp", '\u2009'); + entities.Add ("zwnj", '\u200C'); + entities.Add ("zwj", '\u200D'); + entities.Add ("lrm", '\u200E'); + entities.Add ("rlm", '\u200F'); + entities.Add ("ndash", '\u2013'); + entities.Add ("mdash", '\u2014'); + entities.Add ("lsquo", '\u2018'); + entities.Add ("rsquo", '\u2019'); + entities.Add ("sbquo", '\u201A'); + entities.Add ("ldquo", '\u201C'); + entities.Add ("rdquo", '\u201D'); + entities.Add ("bdquo", '\u201E'); + entities.Add ("dagger", '\u2020'); + entities.Add ("Dagger", '\u2021'); + entities.Add ("permil", '\u2030'); + entities.Add ("lsaquo", '\u2039'); + entities.Add ("rsaquo", '\u203A'); + entities.Add ("euro", '\u20AC'); + } + + public HttpUtility () + { + } + + #endregion // Constructors + + #region Methods + + public static void HtmlAttributeEncode (string s, TextWriter output) + { + output.Write(HtmlAttributeEncode(s)); + } + + public static string HtmlAttributeEncode (string s) + { + if (null == s) + return null; + + if (s.IndexOf ('&') == -1 && s.IndexOf ('"') == -1) + return s; + + StringBuilder output = new StringBuilder (); + foreach (char c in s) + switch (c) { + case '&' : + output.Append ("&"); + break; + case '"' : + output.Append ("""); + break; + default: + output.Append (c); + break; + } + + return output.ToString(); + } + + public static string UrlDecode (string str) + { + return UrlDecode(str, Encoding.UTF8); + } + + private static char [] GetChars (MemoryStream b, Encoding e) + { + return e.GetChars (b.GetBuffer (), 0, (int) b.Length); + } + + public static string UrlDecode (string s, Encoding e) + { + if (null == s) + return null; + + if (s.IndexOf ('%') == -1 && s.IndexOf ('+') == -1) + return s; + + if (e == null) + e = Encoding.UTF8; + + StringBuilder output = new StringBuilder (); + long len = s.Length; + MemoryStream bytes = new MemoryStream (); + int xchar; + + for (int i = 0; i < len; i++) { + if (s [i] == '%' && i + 2 < len && s [i + 1] != '%') { + if (s [i + 1] == 'u' && i + 5 < len) { + if (bytes.Length > 0) { + output.Append (GetChars (bytes, e)); + bytes.SetLength (0); + } + + xchar = GetChar (s, i + 2, 4); + if (xchar != -1) { + output.Append ((char) xchar); + i += 5; + } else { + output.Append ('%'); + } + } else if ((xchar = GetChar (s, i + 1, 2)) != -1) { + bytes.WriteByte ((byte) xchar); + i += 2; + } else { + output.Append ('%'); + } + continue; + } + + if (bytes.Length > 0) { + output.Append (GetChars (bytes, e)); + bytes.SetLength (0); + } + + if (s [i] == '+') { + output.Append (' '); + } else { + output.Append (s [i]); + } + } + + if (bytes.Length > 0) { + output.Append (GetChars (bytes, e)); + } + + bytes = null; + return output.ToString (); + } + + public static string UrlDecode (byte [] bytes, Encoding e) + { + if (bytes == null) + return null; + + return UrlDecode (bytes, 0, bytes.Length, e); + } + + private static int GetInt (byte b) + { + char c = (char) b; + if (c >= '0' && c <= '9') + return c - '0'; + + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + + return -1; + } + + private static int GetChar (byte [] bytes, int offset, int length) + { + int value = 0; + int end = length + offset; + for (int i = offset; i < end; i++) { + int current = GetInt (bytes [i]); + if (current == -1) + return -1; + value = (value << 4) + current; + } + + return value; + } + + private static int GetChar (string str, int offset, int length) + { + int val = 0; + int end = length + offset; + for (int i = offset; i < end; i++) { + char c = str [i]; + if (c > 127) + return -1; + + int current = GetInt ((byte) c); + if (current == -1) + return -1; + val = (val << 4) + current; + } + + return val; + } + + public static string UrlDecode (byte [] bytes, int offset, int count, Encoding e) + { + if (bytes == null) + return null; + if (count == 0) + return String.Empty; + + if (bytes == null) + throw new ArgumentNullException ("bytes"); + + if (offset < 0 || offset > bytes.Length) + throw new ArgumentOutOfRangeException ("offset"); + + if (count < 0 || offset + count > bytes.Length) + throw new ArgumentOutOfRangeException ("count"); + + StringBuilder output = new StringBuilder (); + MemoryStream acc = new MemoryStream (); + + int end = count + offset; + int xchar; + for (int i = offset; i < end; i++) { + if (bytes [i] == '%' && i + 2 < count && bytes [i + 1] != '%') { + if (bytes [i + 1] == (byte) 'u' && i + 5 < end) { + if (acc.Length > 0) { + output.Append (GetChars (acc, e)); + acc.SetLength (0); + } + xchar = GetChar (bytes, i + 2, 4); + if (xchar != -1) { + output.Append ((char) xchar); + i += 5; + continue; + } + } else if ((xchar = GetChar (bytes, i + 1, 2)) != -1) { + acc.WriteByte ((byte) xchar); + i += 2; + continue; + } + } + + if (acc.Length > 0) { + output.Append (GetChars (acc, e)); + acc.SetLength (0); + } + + if (bytes [i] == '+') { + output.Append (' '); + } else { + output.Append ((char) bytes [i]); + } + } + + if (acc.Length > 0) { + output.Append (GetChars (acc, e)); + } + + acc = null; + return output.ToString (); + } + + public static byte [] UrlDecodeToBytes (byte [] bytes) + { + if (bytes == null) + return null; + + return UrlDecodeToBytes (bytes, 0, bytes.Length); + } + + public static byte [] UrlDecodeToBytes (string str) + { + return UrlDecodeToBytes (str, Encoding.UTF8); + } + + public static byte [] UrlDecodeToBytes (string str, Encoding e) + { + if (str == null) + return null; + + if (e == null) + throw new ArgumentNullException ("e"); + + return UrlDecodeToBytes (e.GetBytes (str)); + } + + public static byte [] UrlDecodeToBytes (byte [] bytes, int offset, int count) + { + if (bytes == null) + return null; + if (count == 0) + return new byte [0]; + + int len = bytes.Length; + if (offset < 0 || offset >= len) + throw new ArgumentOutOfRangeException("offset"); + + if (count < 0 || offset > len - count) + throw new ArgumentOutOfRangeException("count"); + + MemoryStream result = new MemoryStream (); + int end = offset + count; + for (int i = offset; i < end; i++){ + char c = (char) bytes [i]; + if (c == '+') { + c = ' '; + } else if (c == '%' && i < end - 2) { + int xchar = GetChar (bytes, i + 1, 2); + if (xchar != -1) { + c = (char) xchar; + i += 2; + } + } + result.WriteByte ((byte) c); + } + + return result.ToArray (); + } + + static char [] hexChars = "0123456789abcdef".ToCharArray (); + const string notEncoded = "!'()*-._"; + + static void UrlEncodeChar (char c, Stream result, bool isUnicode) { + if (c > 255) { + //FIXME: what happens when there is an internal error? + //if (!isUnicode) + // throw new ArgumentOutOfRangeException ("c", c, "c must be less than 256"); + int idx; + int i = (int) c; + + result.WriteByte ((byte)'%'); + result.WriteByte ((byte)'u'); + idx = i >> 12; + result.WriteByte ((byte)hexChars [idx]); + idx = (i >> 8) & 0x0F; + result.WriteByte ((byte)hexChars [idx]); + idx = (i >> 4) & 0x0F; + result.WriteByte ((byte)hexChars [idx]); + idx = i & 0x0F; + result.WriteByte ((byte)hexChars [idx]); + return; + } + + if (c>' ' && notEncoded.IndexOf (c)!=-1) { + result.WriteByte ((byte)c); + return; + } + if (c==' ') { + result.WriteByte ((byte)'+'); + return; + } + if ( (c < '0') || + (c < 'A' && c > '9') || + (c > 'Z' && c < 'a') || + (c > 'z')) { + if (isUnicode && c > 127) { + result.WriteByte ((byte)'%'); + result.WriteByte ((byte)'u'); + result.WriteByte ((byte)'0'); + result.WriteByte ((byte)'0'); + } + else + result.WriteByte ((byte)'%'); + + int idx = ((int) c) >> 4; + result.WriteByte ((byte)hexChars [idx]); + idx = ((int) c) & 0x0F; + result.WriteByte ((byte)hexChars [idx]); + } + else + result.WriteByte ((byte)c); + } + + public static byte [] UrlEncodeToBytes (byte [] bytes, int offset, int count) + { + if (bytes == null) + return null; + + int len = bytes.Length; + if (len == 0) + return new byte [0]; + + if (offset < 0 || offset >= len) + throw new ArgumentOutOfRangeException("offset"); + + if (count < 0 || count > len - offset) + throw new ArgumentOutOfRangeException("count"); + + MemoryStream result = new MemoryStream (count); + int end = offset + count; + for (int i = offset; i < end; i++) + UrlEncodeChar ((char)bytes [i], result, false); + + return result.ToArray(); + } + + + public static byte [] UrlEncodeUnicodeToBytes (string str) + { + if (str == null) + return null; + + if (str == "") + return new byte [0]; + + MemoryStream result = new MemoryStream (str.Length); + foreach (char c in str){ + UrlEncodeChar (c, result, true); + } + return result.ToArray (); + } + + /// + /// Decodes an HTML-encoded string and returns the decoded string. + /// + /// The HTML string to decode. + /// The decoded text. + public static string HtmlDecode (string s) + { + if (s == null) + throw new ArgumentNullException ("s"); + + if (s.IndexOf ('&') == -1) + return s; + + StringBuilder entity = new StringBuilder (); + StringBuilder output = new StringBuilder (); + int len = s.Length; + // 0 -> nothing, + // 1 -> right after '&' + // 2 -> between '&' and ';' but no '#' + // 3 -> '#' found after '&' and getting numbers + int state = 0; + int number = 0; + bool have_trailing_digits = false; + + for (int i = 0; i < len; i++) { + char c = s [i]; + if (state == 0) { + if (c == '&') { + entity.Append (c); + state = 1; + } else { + output.Append (c); + } + continue; + } + + if (c == '&') { + state = 1; + if (have_trailing_digits) { + entity.Append (number.ToString (CultureInfo.InvariantCulture)); + have_trailing_digits = false; + } + + output.Append (entity.ToString ()); + entity.Length = 0; + entity.Append ('&'); + continue; + } + + if (state == 1) { + if (c == ';') { + state = 0; + output.Append (entity.ToString ()); + output.Append (c); + entity.Length = 0; + } else { + number = 0; + if (c != '#') { + state = 2; + } else { + state = 3; + } + entity.Append (c); + } + } else if (state == 2) { + entity.Append (c); + if (c == ';') { + string key = entity.ToString (); + if (key.Length > 1 && Entities.ContainsKey (key.Substring (1, key.Length - 2))) + key = Entities [key.Substring (1, key.Length - 2)].ToString (); + + output.Append (key); + state = 0; + entity.Length = 0; + } + } else if (state == 3) { + if (c == ';') { + if (number > 65535) { + output.Append ("&#"); + output.Append (number.ToString (CultureInfo.InvariantCulture)); + output.Append (";"); + } else { + output.Append ((char) number); + } + state = 0; + entity.Length = 0; + have_trailing_digits = false; + } else if (Char.IsDigit (c)) { + number = number * 10 + ((int) c - '0'); + have_trailing_digits = true; + } else { + state = 2; + if (have_trailing_digits) { + entity.Append (number.ToString (CultureInfo.InvariantCulture)); + have_trailing_digits = false; + } + entity.Append (c); + } + } + } + + if (entity.Length > 0) { + output.Append (entity.ToString ()); + } else if (have_trailing_digits) { + output.Append (number.ToString (CultureInfo.InvariantCulture)); + } + return output.ToString (); + } + + /// + /// Decodes an HTML-encoded string and sends the resulting output to a TextWriter output stream. + /// + /// The HTML string to decode + /// The TextWriter output stream containing the decoded string. + public static void HtmlDecode(string s, TextWriter output) + { + if (s != null) + output.Write (HtmlDecode (s)); + } + + /// + /// HTML-encodes a string and returns the encoded string. + /// + /// The text string to encode. + /// The HTML-encoded text. + public static string HtmlEncode (string s) + { + if (s == null) + return null; + + StringBuilder output = new StringBuilder (); + + foreach (char c in s) + switch (c) { + case '&' : + output.Append ("&"); + break; + case '>' : + output.Append (">"); + break; + case '<' : + output.Append ("<"); + break; + case '"' : + output.Append ("""); + break; + default: + // MS starts encoding with &# from 160 and stops at 255. + // We don't do that. One reason is the 65308/65310 unicode + // characters that look like '<' and '>'. + if (c > 159) { + output.Append ("&#"); + output.Append (((int) c).ToString (CultureInfo.InvariantCulture)); + output.Append (";"); + } else { + output.Append (c); + } + break; + } + return output.ToString (); + } + + /// + /// HTML-encodes a string and sends the resulting output to a TextWriter output stream. + /// + /// The string to encode. + /// The TextWriter output stream containing the encoded string. + public static void HtmlEncode(string s, TextWriter output) + { + if (s != null) + output.Write (HtmlEncode (s)); + } + +#if NET_1_1 + public static string UrlPathEncode (string s) + { + if (s == null || s.Length == 0) + return s; + + MemoryStream result = new MemoryStream (); + int length = s.Length; + for (int i = 0; i < length; i++) { + UrlPathEncodeChar (s [i], result); + } + return Encoding.ASCII.GetString (result.ToArray ()); + } + + static void UrlPathEncodeChar (char c, Stream result) { + if (c > 127) { + byte [] bIn = Encoding.UTF8.GetBytes (c.ToString ()); + for (int i = 0; i < bIn.Length; i++) { + result.WriteByte ((byte) '%'); + int idx = ((int) bIn [i]) >> 4; + result.WriteByte ((byte) hexChars [idx]); + idx = ((int) bIn [i]) & 0x0F; + result.WriteByte ((byte) hexChars [idx]); + } + } + else if (c == ' ') { + result.WriteByte ((byte) '%'); + result.WriteByte ((byte) '2'); + result.WriteByte ((byte) '0'); + } + else + result.WriteByte ((byte) c); + } +#endif + +#if NET_2_0 + public static NameValueCollection ParseQueryString (string query) + { + return ParseQueryString (query, Encoding.UTF8); + } + + public static NameValueCollection ParseQueryString (string query, Encoding encoding) + { + if (query == null) + throw new ArgumentNullException ("query"); + if (encoding == null) + throw new ArgumentNullException ("encoding"); + if (query.Length == 0 || (query.Length == 1 && query[0] == '?')) + return new NameValueCollection (); + if (query[0] == '?') + query = query.Substring (1); + + NameValueCollection result = new NameValueCollection (); + ParseQueryString (query, encoding, result); + return result; + } +#endif + + internal static void ParseQueryString (string query, Encoding encoding, NameValueCollection result) + { + if (query.Length == 0) + return; + + int namePos = 0; + while (namePos <= query.Length) { + int valuePos = -1, valueEnd = -1; + for (int q = namePos; q < query.Length; q++) { + if (valuePos == -1 && query[q] == '=') { + valuePos = q + 1; + } else if (query[q] == '&') { + valueEnd = q; + break; + } + } + + string name, value; + if (valuePos == -1) { + name = null; + valuePos = namePos; + } else { + name = UrlDecode (query.Substring (namePos, valuePos - namePos - 1), encoding); + } + if (valueEnd < 0) { + namePos = -1; + valueEnd = query.Length; + } else { + namePos = valueEnd + 1; + } + value = UrlDecode (query.Substring (valuePos, valueEnd - valuePos), encoding); + + result.Add (name, value); + if (namePos == -1) break; + } + } + #endregion // Methods + } } #endif diff -Nru gdata-sharp-1.4.0.2/src/core/mediaservice.cs gdata-sharp-1.7.0.1/src/core/mediaservice.cs --- gdata-sharp-1.4.0.2/src/core/mediaservice.cs 2008-11-11 14:15:40.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/mediaservice.cs 2010-03-23 16:40:45.000000000 +0000 @@ -128,7 +128,7 @@ outputStream = request.GetRequestStream(); - inputStream = entry.MediaSource.Data; + inputStream = entry.MediaSource.GetDataStream(); StreamWriter w = new StreamWriter(outputStream); w.WriteLine("Media multipart posting"); diff -Nru gdata-sharp-1.4.0.2/src/core/mediasource.cs gdata-sharp-1.7.0.1/src/core/mediasource.cs --- gdata-sharp-1.4.0.2/src/core/mediasource.cs 2008-06-10 10:23:24.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/mediasource.cs 2010-03-23 16:40:45.000000000 +0000 @@ -107,10 +107,17 @@ /// returns a stream of the actual content that is base64 encoded /// /// + [Obsolete("That name was misleading. Use GetDataStream() instead")] public abstract Stream Data { get; } + + /// + /// returns a stream of the actual content that is base64 encoded + /// + /// + public abstract Stream GetDataStream(); } @@ -153,6 +160,29 @@ this.stream = data; } + + /// + /// tries to get a contenttype for a filename by using the classesRoot + /// in the registry. Will FAIL if that filetype is not registered with a + /// contenttype + /// + /// + /// NULL or the registered contenttype + public static string GetContentTypeForFileName(string fileName) + { + string ext = System.IO.Path.GetExtension(fileName).ToLower(); + + using (Microsoft.Win32.RegistryKey registryKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext)) + { + if (registryKey != null && registryKey.GetValue("Content Type") != null) + { + return registryKey.GetValue("Content Type").ToString(); + } + } + return null; + } + + /// /// returns the content lenght of the file /// @@ -160,8 +190,22 @@ public override long ContentLength { get - { - return 0; + { + long result; + + try + { + + Stream s = this.GetDataStream(); + result = s.Length; + s.Close(); + } + catch (NotSupportedException e) + { + result = -1; + } + + return result; } } @@ -170,17 +214,29 @@ /// note, the caller has to release the resource /// /// + [Obsolete("That name was misleading. Use GetDataStream() instead")] public override Stream Data { get { - if (String.IsNullOrEmpty(this.file) == false) - { - FileStream f = File.OpenRead(this.file); - return f; - } - return this.stream; + return GetDataStream(); + } + } + + + /// + /// returns the stream for the file. The file will be opened in readonly mode + /// note, the caller has to release the resource + /// + /// + public override Stream GetDataStream() + { + if (String.IsNullOrEmpty(this.file) == false) + { + FileStream f = File.OpenRead(this.file); + return f; } + return this.stream; } } } diff -Nru gdata-sharp-1.4.0.2/src/core/oauthbase.cs gdata-sharp-1.7.0.1/src/core/oauthbase.cs --- gdata-sharp-1.4.0.2/src/core/oauthbase.cs 2008-11-26 07:51:06.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/oauthbase.cs 2010-05-26 08:04:54.000000000 +0000 @@ -83,7 +83,7 @@ protected Random random = new Random(); - protected string unreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~"; + protected static string unreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~"; /// /// Helper function to compute a hash value @@ -91,7 +91,8 @@ /// The hashing algoirhtm used. If that algorithm needs some initialization, like HMAC and its derivatives, they should be initialized prior to passing it to this function /// The data to hash /// a Base64 string of the hash value - private string ComputeHash(HashAlgorithm hashAlgorithm, string data) { + private static string ComputeHash(HashAlgorithm hashAlgorithm, string data) + { if (hashAlgorithm == null) { throw new ArgumentNullException("hashAlgorithm"); } @@ -111,7 +112,7 @@ /// /// The query string part of the Url /// A list of QueryParameter each containing the parameter name and value - private List GetQueryParameters(string parameters) { + private static List GetQueryParameters(string parameters) { if (parameters.StartsWith("?")) { parameters = parameters.Remove(0, 1); } @@ -124,9 +125,14 @@ if (!string.IsNullOrEmpty(s) && !s.StartsWith(OAuthParameterPrefix)) { if (s.IndexOf('=') > -1) { string[] temp = s.Split('='); - result.Add(new QueryParameter(temp[0], temp[1])); + // now temp[1], the value, might contain encoded data, that would be double encoded later. + // also it MIGHT contain encoding of the lowercase kind, which throws OAUTH off + // the same is true for the name + string name = Utilities.UrlDecodedValue(temp[0]); + string value = Utilities.UrlDecodedValue(temp[1]); + result.Add(new QueryParameter(name, value)); } else { - result.Add(new QueryParameter(s, string.Empty)); + result.Add(new QueryParameter(Utilities.UrlDecodedValue(s), string.Empty)); } } } @@ -136,12 +142,15 @@ } /// - /// This is a different Url Encode implementation since the default .NET one outputs the percent encoding in lower case. - /// While this is not a problem with the percent encoding spec, it is used in upper case throughout OAuth + /// All parameter names and values are escaped using the [RFC3986] + /// percent-encoding (%xx) mechanism. Characters not in the unreserved character + /// MUST be encoded. Characters in the unreserved character set MUST NOT be encoded. + /// Hexadecimal characters in encodings MUST be upper case. Text names and values MUST be + /// encoded as UTF-8 octets before percent-encoding them per [RFC3629] /// /// The value to Url encode /// Returns a Url encoded string - protected string UrlEncode(string value) { + public static string EncodingPerRFC3986(string value) { StringBuilder result = new StringBuilder(); foreach (char symbol in value) { @@ -156,16 +165,18 @@ } /// - /// Normalizes the request parameters according to the spec + /// Normalizes the request parameters according to the spec for the signature generation. /// /// The list of parameters already sorted /// a string representing the normalized parameters - protected string NormalizeRequestParameters(IList parameters) { + protected static string NormalizeRequestParameters(IList parameters) { StringBuilder sb = new StringBuilder(); QueryParameter p = null; for (int i = 0; i < parameters.Count; i++) { p = parameters[i]; - sb.AppendFormat(CultureInfo.InvariantCulture, "{0}={1}", p.Name, p.Value); + sb.AppendFormat(CultureInfo.InvariantCulture, "{0}={1}", + EncodingPerRFC3986(p.Name), + EncodingPerRFC3986(p.Value)); if (i < parameters.Count - 1) { sb.Append("&"); @@ -185,7 +196,8 @@ /// The http method used. Must be a valid HTTP method verb (POST,GET,PUT, etc) /// The signature type. To use the default values use OAuthBase.SignatureTypes. /// The signature base - public string GenerateSignatureBase(Uri url, string consumerKey, string token, string tokenSecret, string httpMethod, string timeStamp, string nonce, string signatureType, out string normalizedUrl, out string normalizedRequestParameters) { + public static string GenerateSignatureBase(Uri url, string consumerKey, string token, string tokenSecret, + string httpMethod, string timeStamp, string nonce, string signatureType) { if (token == null) { token = string.Empty; } @@ -206,8 +218,8 @@ throw new ArgumentNullException("signatureType"); } - normalizedUrl = null; - normalizedRequestParameters = null; + string normalizedUrl = null; + string normalizedRequestParameters = null; List parameters = GetQueryParameters(url.Query); parameters.Add(new QueryParameter(OAuthVersionKey, OAuthVersion)); @@ -219,7 +231,7 @@ if (!string.IsNullOrEmpty(token)) { parameters.Add(new QueryParameter(OAuthTokenKey, token)); } - + parameters.Sort(new QueryParameterComparer()); normalizedUrl = string.Format("{0}://{1}", url.Scheme, url.Host); @@ -232,8 +244,8 @@ StringBuilder signatureBase = new StringBuilder(); signatureBase.AppendFormat(CultureInfo.InvariantCulture, "{0}&", httpMethod.ToUpper()); - signatureBase.AppendFormat(CultureInfo.InvariantCulture, "{0}&", UrlEncode(normalizedUrl)); - signatureBase.AppendFormat(CultureInfo.InvariantCulture, "{0}", UrlEncode(normalizedRequestParameters)); + signatureBase.AppendFormat(CultureInfo.InvariantCulture, "{0}&", EncodingPerRFC3986(normalizedUrl)); + signatureBase.AppendFormat(CultureInfo.InvariantCulture, "{0}", EncodingPerRFC3986(normalizedRequestParameters)); return signatureBase.ToString(); } @@ -244,7 +256,7 @@ /// The signature based as produced by the GenerateSignatureBase method or by any other means /// The hash algorithm used to perform the hashing. If the hashing algorithm requires initialization or a key it should be set prior to calling this method /// A base64 string of the hash value - public string GenerateSignatureUsingHash(string signatureBase, HashAlgorithm hash) { + public static string GenerateSignatureUsingHash(string signatureBase, HashAlgorithm hash) { return ComputeHash(hash, signatureBase); } @@ -258,8 +270,8 @@ /// The token secret, if available. If not available pass null or an empty string /// The http method used. Must be a valid HTTP method verb (POST,GET,PUT, etc) /// A base64 string of the hash value - public string GenerateSignature(Uri url, string consumerKey, string consumerSecret, string token, string tokenSecret, string httpMethod, string timeStamp, string nonce, out string normalizedUrl, out string normalizedRequestParameters) { - return GenerateSignature(url, consumerKey, consumerSecret, token, tokenSecret, httpMethod, timeStamp, nonce, SignatureTypes.HMACSHA1, out normalizedUrl, out normalizedRequestParameters); + public string GenerateSignature(Uri url, string consumerKey, string consumerSecret, string token, string tokenSecret, string httpMethod, string timeStamp, string nonce) { + return GenerateSignature(url, consumerKey, consumerSecret, token, tokenSecret, httpMethod, timeStamp, nonce, SignatureTypes.HMACSHA1); } /// @@ -273,18 +285,17 @@ /// The http method used. Must be a valid HTTP method verb (POST,GET,PUT, etc) /// The type of signature to use /// A base64 string of the hash value - public string GenerateSignature(Uri url, string consumerKey, string consumerSecret, string token, string tokenSecret, string httpMethod, string timeStamp, string nonce, SignatureTypes signatureType, out string normalizedUrl, out string normalizedRequestParameters) { - normalizedUrl = null; - normalizedRequestParameters = null; + public static string GenerateSignature(Uri url, string consumerKey, string consumerSecret, string token, string tokenSecret, string httpMethod, string timeStamp, string nonce, SignatureTypes signatureType) { switch (signatureType) { case SignatureTypes.PLAINTEXT: return HttpUtility.UrlEncode(string.Format("{0}&{1}", consumerSecret, tokenSecret)); case SignatureTypes.HMACSHA1: - string signatureBase = GenerateSignatureBase(url, consumerKey, token, tokenSecret, httpMethod, timeStamp, nonce, HMACSHA1SignatureType, out normalizedUrl, out normalizedRequestParameters); + string signatureBase = GenerateSignatureBase(url, consumerKey, token, tokenSecret, httpMethod, timeStamp, + nonce, HMACSHA1SignatureType); HMACSHA1 hmacsha1 = new HMACSHA1(); - hmacsha1.Key = Encoding.ASCII.GetBytes(string.Format("{0}&{1}", UrlEncode(consumerSecret), string.IsNullOrEmpty(tokenSecret) ? "" : UrlEncode(tokenSecret))); + hmacsha1.Key = Encoding.ASCII.GetBytes(GenerateOAuthSignature(consumerSecret, tokenSecret)); return GenerateSignatureUsingHash(signatureBase, hmacsha1); case SignatureTypes.RSASHA1: @@ -294,6 +305,40 @@ } } + + /// + /// oauth_signature is set to the concatenated encoded values of the Consumer Secret and Token Secret, + /// separated by a ‘&’ character (ASCII code 38), even if either secret is empty. This version calls + /// GenerateOAuthSignature and encodes the whole signature again + /// The result MUST be encoded again. + /// + /// + /// + /// + public static string GenerateOAuthSignatureEncoded(string consumerSecret, string tokenSecret) + { + return EncodingPerRFC3986( + GenerateOAuthSignature(consumerSecret, tokenSecret)); + } + + + /// + /// oauth_signature is set to the concatenated encoded values of the Consumer Secret and Token Secret, + /// separated by a ‘&’ character (ASCII code 38), even if either secret is empty. + /// The result MUST be encoded again. + /// + /// + /// + /// + public static string GenerateOAuthSignature(string consumerSecret, string tokenSecret) + { + return string.Format("{0}&{1}", + EncodingPerRFC3986(consumerSecret), + string.IsNullOrEmpty(tokenSecret) ? "" : EncodingPerRFC3986(tokenSecret)); + } + + + /// /// Generate the timestamp for the signature /// diff -Nru gdata-sharp-1.4.0.2/src/core/oauthuri.cs gdata-sharp-1.7.0.1/src/core/oauthuri.cs --- gdata-sharp-1.4.0.2/src/core/oauthuri.cs 2008-11-26 07:51:06.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/oauthuri.cs 2009-12-08 13:15:18.000000000 +0000 @@ -24,8 +24,10 @@ /// An implementation of Uri that will create an uri with an /// xoauth_requestor_id query string. /// + [Obsolete("this is going to be removed in the future and replaced with OAuthAuthenticator")] public class OAuthUri : Uri { + public static string OAuthParameter = "xoauth_requestor_id"; /// /// Creates a Uri with a xoauth_requestor_id query string. /// @@ -33,7 +35,7 @@ /// The username for the xoauth_requestor_id /// The domain for the xoauth_requestor_id public OAuthUri(String uriString, String userName, String domain) - : base(uriString + "?xoauth_requestor_id=" + userName + "%40" + domain) + : base(uriString + "?"+OAuthParameter+"=" + userName + "%40" + domain) { } } diff -Nru gdata-sharp-1.4.0.2/src/core/oauthutil.cs gdata-sharp-1.7.0.1/src/core/oauthutil.cs --- gdata-sharp-1.4.0.2/src/core/oauthutil.cs 2008-11-26 07:51:06.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/oauthutil.cs 2010-05-26 08:04:54.000000000 +0000 @@ -18,6 +18,7 @@ using System; using System.Text; +using System.Globalization; namespace Google.GData.Client { @@ -35,7 +36,7 @@ { // Default implementation of UNIX time of the current UTC time TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); - string timeStamp = ts.TotalSeconds.ToString(); + string timeStamp = ts.TotalSeconds.ToString(CultureInfo.InvariantCulture); // remove any fractions of seconds int pointIndex = timeStamp.IndexOf("."); if (pointIndex != -1) @@ -63,22 +64,29 @@ /// The OAuth authorization header public static string GenerateHeader(Uri uri, String consumerKey, String consumerSecret, String httpMethod) { + return GenerateHeader(uri, consumerKey, consumerSecret, string.Empty, string.Empty, httpMethod); + } + + public static string GenerateHeader(Uri uri, String consumerKey, String consumerSecret, String token, String tokenSecret, String httpMethod) + { OAuthUtil oauthUtil = new OAuthUtil(); string timeStamp = oauthUtil.GenerateTimeStamp(); string nonce = oauthUtil.GenerateNonce(); - string normalizedUrl; string normalizedRequestParameters; - - string signature = oauthUtil.GenerateSignature(uri, consumerKey, consumerSecret, string.Empty, string.Empty, - httpMethod.ToUpper(), timeStamp, nonce, out normalizedUrl, out normalizedRequestParameters); - signature = System.Web.HttpUtility.UrlEncode(signature); + string signature = oauthUtil.GenerateSignature(uri, consumerKey, consumerSecret, token, tokenSecret, + httpMethod.ToUpper(), timeStamp, nonce); + StringBuilder sb = new StringBuilder(); - sb.Append("Authorization: OAuth realm=\"\",oauth_version=\"1.0\","); - sb.AppendFormat("oauth_nonce=\"{0}\",", nonce); - sb.AppendFormat("oauth_timestamp=\"{0}\",", timeStamp); - sb.AppendFormat("oauth_consumer_key=\"{0}\",", consumerKey); + sb.Append("Authorization: OAuth oauth_version=\"1.0\","); + sb.AppendFormat("oauth_nonce=\"{0}\",", EncodingPerRFC3986(nonce)); + sb.AppendFormat("oauth_timestamp=\"{0}\",", EncodingPerRFC3986(timeStamp)); + sb.AppendFormat("oauth_consumer_key=\"{0}\",", EncodingPerRFC3986(consumerKey)); + if (!String.IsNullOrEmpty(token)) + { + sb.AppendFormat("oauth_token=\"{0}\",", EncodingPerRFC3986(token)); + } sb.Append("oauth_signature_method=\"HMAC-SHA1\","); - sb.AppendFormat("oauth_signature=\"{0}\"", signature); + sb.AppendFormat("oauth_signature=\"{0}\"", EncodingPerRFC3986(signature)); return sb.ToString(); } diff -Nru gdata-sharp-1.4.0.2/src/core/request.cs gdata-sharp-1.7.0.1/src/core/request.cs --- gdata-sharp-1.4.0.2/src/core/request.cs 2009-02-13 12:50:08.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/request.cs 2010-02-03 12:18:51.000000000 +0000 @@ -18,6 +18,7 @@ using System; using System.IO; +using System.IO.Compression; using System.Net; using System.Collections.Generic; using System.Globalization; @@ -40,7 +41,11 @@ private string passWord; private string userName; private string clientToken; - + private string accountType = GoogleAuthentication.AccountTypeDefault; + + private string captchaAnswer; + private string captchaToken; + /// /// default constructor /// @@ -61,9 +66,8 @@ this.clientToken = clientToken; } - ////////////////////////////////////////////////////////////////////// - /// accessor method public string Username + /// the username used for authentication /// ////////////////////////////////////////////////////////////////////// public string Username @@ -71,6 +75,39 @@ get {return this.userName;} set {this.userName = value;} } + + ////////////////////////////////////////////////////////////////////// + /// the type of Account used + /// + ////////////////////////////////////////////////////////////////////// + public string AccountType + { + get {return this.accountType;} + set {this.accountType = value;} + } + // end of accessor public string Username + + ////////////////////////////////////////////////////////////////////// + /// in case you need to handle catpcha responses for this account + /// + ////////////////////////////////////////////////////////////////////// + public string CaptchaToken + { + get {return this.captchaToken;} + set {this.captchaToken = value;} + } + // end of accessor public string Username + + + ////////////////////////////////////////////////////////////////////// + /// in case you need to handle catpcha responses for this account + /// + ////////////////////////////////////////////////////////////////////// + public string CaptchaAnswer + { + get {return this.captchaAnswer;} + set {this.captchaAnswer = value;} + } // end of accessor public string Username ////////////////////////////////////////////////////////////////////// @@ -99,6 +136,10 @@ { return this.clientToken; } + set + { + this.clientToken = value; + } } /// @@ -111,9 +152,9 @@ return new NetworkCredential(this.userName, this.passWord); } } - } + } + - ////////////////////////////////////////////////////////////////////// /// base GDataRequestFactory implementation ////////////////////////////////////////////////////////////////////// @@ -121,30 +162,35 @@ { /// this factory's agent public const string GDataAgent = "SA"; - + /// /// the default content type for the atom envelope /// public const string DefaultContentType = "application/atom+xml; charset=UTF-8"; /// holds the user-agent private string userAgent; - private List customHeaders; // holds any custom headers to set + private List customHeaders; // holds any custom headers to set private IWebProxy webProxy; // holds an iwebproxy interface private bool keepAlive; // indicates wether or not to keep the connection alive private bool useGZip; + private bool useSSL; // indicate is https should be used private string contentType = DefaultContentType; private string slugHeader; // set to default by default private int timeOut = -1; - + /// Cookie setting header, returned from server public const string SetCookieHeader = "Set-Cookie"; /// Cookie client header - public const string CookieHeader = "Cookie"; + public const string CookieHeader = "Cookie"; /// Slug client header public const string SlugHeader = "Slug"; + /// content override header for resumable upload + public const string ContentOverrideHeader = "X-Upload-Content-Type"; + /// content length header for resumable upload + public const string ContentLengthOverrideHeader = "X-Upload-Content-Length"; /// /// constant for the Etag header @@ -160,7 +206,12 @@ /// constant for the if-None-match header /// public const string IfNoneMatch = "If-None-Match"; - + + + /// + /// constant for the ifmatch value that matches everything + /// + public const string IfMatchAll = "*"; @@ -189,8 +240,8 @@ ////////////////////////////////////////////////////////////////////// public bool UseGZip { - get { return (this.useGZip); } - set { this.useGZip = value; } + get { return(this.useGZip);} + set { this.useGZip = value;} } ////////////////////////////////////////////////////////////////////// @@ -209,8 +260,8 @@ if (this.cookies == null) this.cookies = new CookieContainer(); - return this.cookies; } - set { this.cookies = value; } + return this.cookies;} + set { this.cookies = value;} } ////////////////////////////////////////////////////////////////////// #endif @@ -249,7 +300,7 @@ ////////////////////////////////////////////////////////////////////// public virtual string UserAgent { - get { return this.userAgent; } + get { return this.userAgent;} set {this.userAgent = value;} } ///////////////////////////////////////////////////////////////////////////// @@ -264,7 +315,7 @@ set {this.webProxy = value;} } ///////////////////////////////////////////////////////////////////////////// - + ///////////////////////////////////////////////////////////////////// /// indicates if the connection should be kept alive, default /// is true @@ -272,8 +323,20 @@ ////////////////////////////////////////////////////////////////////// public bool KeepAlive { - get {return this.keepAlive;} - set {this.keepAlive = value;} + get { return this.keepAlive; } + set { this.keepAlive = value; } + } + ///////////////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////////// + /// indicates if the connection should use https + /// is true + /// + ////////////////////////////////////////////////////////////////////// + public bool UseSSL + { + get { return this.useSSL; } + set { this.useSSL = value; } } ///////////////////////////////////////////////////////////////////////////// @@ -307,12 +370,12 @@ public List CustomHeaders { get { - if (this.customHeaders == null) + if (this.customHeaders == null) { this.customHeaders = new List(); } return this.customHeaders; - } + } } // end of accessor public StringArray CustomHeaders } @@ -403,8 +466,8 @@ ////////////////////////////////////////////////////////////////////// public bool UseGZip { - get { return (this.useGZip); } - set { this.useGZip = value; } + get { return(this.useGZip);} + set { this.useGZip = value;} } ////////////////////////////////////////////////////////////////////// @@ -413,8 +476,8 @@ ////////////////////////////////////////////////////////////////////// public DateTime IfModifiedSince { - get { return (this.ifModifiedSince); } - set { this.ifModifiedSince = value; } + get { return(this.ifModifiedSince);} + set { this.ifModifiedSince = value;} } ////////////////////////////////////////////////////////////////////// @@ -451,7 +514,7 @@ ///////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// /// set's and get's the content Type, used for binary transfers /// ////////////////////////////////////////////////////////////////////// @@ -468,8 +531,8 @@ ////////////////////////////////////////////////////////////////////// public string Etag { - get { return this.eTag; } - set { this.eTag = value; } + get { return this.eTag;} + set { this.eTag = value;} } ///////////////////////////////////////////////////////////////////////////// @@ -560,9 +623,13 @@ ////////////////////////////////////////////////////////////////////// protected virtual void EnsureWebRequest() { - if (this.webRequest == null && this.targetUri != null) { + if (this.factory.UseSSL == true && (this.targetUri.Scheme.ToLower().Equals("https") == false)) + { + this.targetUri = new Uri("https://" + this.targetUri.Host + this.targetUri.PathAndQuery); + } + this.webRequest = WebRequest.Create(this.targetUri); this.webResponse = null; @@ -574,7 +641,7 @@ if (web != null) { - switch (this.type) + switch (this.type) { case GDataRequestType.Delete: web.Method = HttpMethods.Delete; @@ -589,27 +656,30 @@ case GDataRequestType.Query: web.Method = HttpMethods.Get; break; - + } if (this.useGZip == true) web.Headers.Add("Accept-Encoding", "gzip"); if (this.Etag != null) { + if (this.Etag != GDataRequestFactory.IfMatchAll) + { web.Headers.Add(GDataRequestFactory.EtagHeader, this.Etag); - switch (this.type) - { - case GDataRequestType.Update: - case GDataRequestType.Delete: - if (Utilities.IsWeakETag(this) == false) - { - web.Headers.Add(GDataRequestFactory.IfMatch, this.Etag); - } - break; - case GDataRequestType.Query: - web.Headers.Add(GDataRequestFactory.IfNoneMatch, this.Etag); - break; - } + } + switch (this.type) + { + case GDataRequestType.Update: + case GDataRequestType.Delete: + if (Utilities.IsWeakETag(this) == false) + { + web.Headers.Add(GDataRequestFactory.IfMatch, this.Etag); + } + break; + case GDataRequestType.Query: + web.Headers.Add(GDataRequestFactory.IfNoneMatch, this.Etag); + break; + } } if (this.IfModifiedSince != DateTime.MinValue) @@ -644,7 +714,7 @@ this.Request.Proxy = this.factory.Proxy; } } - + EnsureCredentials(); } } @@ -667,7 +737,7 @@ - + ////////////////////////////////////////////////////////////////////// /// Log's the request object if overridden in subclass /// the request to log @@ -676,7 +746,7 @@ { } - + ////////////////////////////////////////////////////////////////////// /// Log's the response object if overridden in subclass /// the response to log @@ -691,7 +761,7 @@ ////////////////////////////////////////////////////////////////////// public virtual void Execute() { - try + try { EnsureWebRequest(); // if we ever handed out a stream, we want to close it before doing the real excecution @@ -702,8 +772,7 @@ Tracing.TraceCall("calling the real execution over the webresponse"); LogRequest(this.webRequest); this.webResponse = this.webRequest.GetResponse(); - } - catch (WebException e) + } catch (WebException e) { Tracing.TraceCall("GDataRequest::Execute failed: " + this.targetUri.ToString()); GDataRequestException gde = new GDataRequestException("Execution of request failed: " + this.targetUri.ToString(), e); @@ -735,14 +804,14 @@ // that could imply that we need to reauthenticate Tracing.TraceMsg("need to reauthenticate"); throw new GDataForbiddenException("Execution of request returned HttpStatusCode.Forbidden: " + - this.targetUri.ToString() + response.StatusCode.ToString(), this.webResponse); + this.targetUri.ToString() + response.StatusCode.ToString(), this.webResponse); } if (response.StatusCode == HttpStatusCode.Conflict) { // a put went bad due to a version conflict throw new GDataVersionConflictException("Execution of request returned HttpStatusCode.Conflict: " + - this.targetUri.ToString() + response.StatusCode.ToString(), this.webResponse); + this.targetUri.ToString() + response.StatusCode.ToString(), this.webResponse); } if ((this.IfModifiedSince != DateTime.MinValue @@ -751,7 +820,7 @@ // Throw an exception for conditional GET throw new GDataNotModifiedException("Content not modified: " + this.targetUri.ToString(), this.webResponse); } - + if (response.StatusCode == HttpStatusCode.Redirect || response.StatusCode == HttpStatusCode.Found || response.StatusCode == HttpStatusCode.RedirectKeepVerb) @@ -787,7 +856,7 @@ ////////////////////////////////////////////////////////////////////// public virtual Stream GetResponseStream() { - return (this.responseStream); + return(this.responseStream); } ///////////////////////////////////////////////////////////////////////////// diff -Nru gdata-sharp-1.4.0.2/src/core/resumableupload.cs gdata-sharp-1.7.0.1/src/core/resumableupload.cs --- gdata-sharp-1.4.0.2/src/core/resumableupload.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/resumableupload.cs 2010-11-18 17:29:57.000000000 +0000 @@ -0,0 +1,790 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +#region Using directives + +#define USE_TRACING + +using System; +using System.IO; +using System.IO.Compression; +using System.Net; +using System.Collections.Generic; +using System.Globalization; +using System.ComponentModel; +using System.Threading; +using System.Collections.Specialized; + +#endregion + + +///////////////////////////////////////////////////////////////////// +// contains support classes to work with +// the resumable upload protocol. +// +//////////////////////////////////////////////////////////////////// +namespace Google.GData.Client.ResumableUpload +{ + + internal class AsyncResumableUploadData : AsyncData + { + private Authenticator authenticator; + private string contentType; + private AbstractEntry entry; + private string slug; + + + public AsyncResumableUploadData(AsyncDataHandler handler, + Authenticator authenticator, + Uri uriToUse, + Stream payload, + string contentType, + string slug, + string httpMethod, + SendOrPostCallback callback, + object userData) + : base(uriToUse, null, userData, callback) + { + this.DataHandler = handler; + this.authenticator = authenticator; + this.contentType = contentType; + this.DataStream = payload; + this.slug = slug; + this.HttpVerb = httpMethod; + } + + public AsyncResumableUploadData(AsyncDataHandler handler, + Authenticator authenticator, + AbstractEntry payload, + string httpMethod, + SendOrPostCallback callback, + object userData) + : base(null, null, userData, callback) + { + this.DataHandler = handler; + this.authenticator = authenticator; + this.entry = payload; + this.HttpVerb = httpMethod; + } + + + public string ContentType + { + get + { + return this.contentType; + } + } + + public Authenticator Authentication + { + get + { + return this.authenticator; + } + } + + public AbstractEntry Entry + { + get + { + return this.entry; + } + } + + public string Slug + { + get + { + return this.slug; + } + } + } + + /// + /// this class handles the Resumable Upload protocol + /// + public class ResumableUploader : AsyncDataHandler + { + // chunksize in Megabytes + private int chunkSize; + private long lastChunk = 0; // the index of the last chunk uploaded + private static long MB = 1024000; + + /// + /// The relationship value to be used to find the resumable + /// + public static string CreateMediaRelation = "http://schemas.google.com/g/2005#resumable-create-media"; + public static string EditMediaRelation = "http://schemas.google.com/g/2005#resumable-edit-media"; + + private delegate void WorkerResumableUploadHandler(AsyncResumableUploadData data, AsyncOperation asyncOp, + SendOrPostCallback completionMethodDelegate); + + + /// + /// Default constructor. Uses the default chunksize of 25 megabyte + /// + /// + public ResumableUploader() : this(25) + { + } + + /// + /// ResumableUploader constructor. + /// + /// the upload chunksize in Megabytes, needs to be greater than 0 + /// + public ResumableUploader(int chunkSize) + { + if (chunkSize < 1) + throw new ArgumentException("chunkSize needs to be > 0"); + this.chunkSize = chunkSize; + } + + /// + /// returns the resumable edit media Uri for a given entry + /// + /// + /// + public static Uri GetResumableEditUri(AtomLinkCollection links) + { + // scan the link collection + AtomLink link = links.FindService(EditMediaRelation, null); + return link == null ? null : new Uri(link.AbsoluteUri); + } + + /// + /// returns the resumabled create media Uri for a given entry + /// + /// + /// + public static Uri GetResumableCreateUri(AtomLinkCollection links) + { + // scan the link collection + AtomLink link = links.FindService(CreateMediaRelation, null); + return link == null ? null : new Uri(link.AbsoluteUri); + } + + /// + /// Uploads an entry, including it's media to the uri given inside the entry. + /// + /// The authentication information to be used + /// The entry to be uploaded. This is a complete entry, including the metadata. + /// This will create a new entry on the service + /// + public WebResponse Insert(Authenticator authentication, AbstractEntry payload) + { + return Insert(authentication, payload, null); + } + + /// + /// Uploads just the media media to the uri given. + /// + /// + /// The authentication information to be used + /// The media to uploaded. + /// The type of the content, e.g. text/html + /// + public WebResponse Insert(Authenticator authentication, Uri resumableUploadUri, Stream payload, string contentType, string slug) + { + return Insert(authentication, resumableUploadUri, payload, contentType, slug, null); + } + + + private WebResponse Insert(Authenticator authentication, AbstractEntry payload, AsyncData data) + { + WebResponse r = null; + Uri initialUri = ResumableUploader.GetResumableCreateUri(payload.Links); + if (initialUri == null) + throw new ArgumentException("payload did not contain a resumabled create media Uri"); + + Uri resumeUri = InitiateUpload(initialUri, authentication, payload); + + using (Stream s = payload.MediaSource.GetDataStream()) + { + + r = UploadStream(HttpMethods.Post, resumeUri, authentication, + s, + payload.MediaSource.ContentType, data); + } + return r; + } + + private WebResponse Insert(Authenticator authentication, Uri resumableUploadUri, + Stream payload, string contentType, string slug, AsyncData data) + { + + Uri resumeUri = InitiateUpload(resumableUploadUri, authentication, contentType, null, GetStreamLength(payload)); + return UploadStream(HttpMethods.Post, resumeUri, authentication, payload, contentType, data); + } + + public void InsertAsync(Authenticator authentication, Uri resumableUploadUri, Stream payload, string contentType, string slug, object userData) + { + AsyncResumableUploadData data = new AsyncResumableUploadData(this, + authentication, + resumableUploadUri, + payload, + contentType, + slug, + HttpMethods.Post, + this.ProgressReportDelegate, + userData); + WorkerResumableUploadHandler workerDelegate = new WorkerResumableUploadHandler(AsyncInsertWorker); + this.AsyncStarter(data, workerDelegate, userData); + } + + public void InsertAsync(Authenticator authentication, AbstractEntry payload, object userData) + { + AsyncResumableUploadData data = new AsyncResumableUploadData(this, + authentication, + payload, + HttpMethods.Post, + this.ProgressReportDelegate, + userData); + WorkerResumableUploadHandler workerDelegate = new WorkerResumableUploadHandler(AsyncInsertWorker); + this.AsyncStarter(data, workerDelegate, userData); + } + + + /// + /// askes the server about the current status + /// + /// + /// + /// + public static long QueryStatus(Authenticator authentication, Uri targetUri) + { + HttpWebRequest request = authentication.CreateHttpWebRequest(HttpMethods.Post, targetUri); + long result = -1; + + // add a range header + string contentRange = String.Format("bytes */*"); + request.Headers.Add(HttpRequestHeader.ContentRange, contentRange); + request.ContentLength = 0; + HttpWebResponse response = request.GetResponse() as HttpWebResponse; + + // now parse the header + string range = response.Headers["Range"]; + string []parts = range.Split('-'); + + if (parts.Length > 1 && parts[1] != null) + { + result = long.Parse(parts[1]); + } + + return result; + } + + + /// + /// worker method for the the resumable insert + /// + /// + /// + /// + /// + private void AsyncInsertWorker(AsyncResumableUploadData data, AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate) + { + try + { + if (data.Entry != null) + { + using (var response = Insert(data.Authentication, data.Entry, data)) + { + HandleResponseStream(data, response.GetResponseStream(), -1); + } + } + else + { + using (var response = Insert(data.Authentication, data.UriToUse, data.DataStream, data.ContentType, data.Slug, data)) + { + HandleResponseStream(data, response.GetResponseStream(), -1); + } + } + } + catch (Exception e) + { + data.Exception = e; + } + + this.CompletionMethodDelegate(data); + } + + + /// + /// Uploads an entry, including it's media to the uri given inside the entry + /// + /// + /// The authentication information to be used + /// The entry to be uploaded. This is a complete entry, including the metadata. + /// This will create a new entry on the service + /// + public WebResponse Update(Authenticator authentication, AbstractEntry payload) + { + return Update(authentication, payload, null); + } + + /// + /// Uploads just the media media to the uri given. + /// + /// + /// The authentication information to be used + /// The media to uploaded. + /// The type of the content, e.g. text/html + /// + public WebResponse Update(Authenticator authentication, Uri resumableUploadUri, Stream payload, string contentType) + { + return Update(authentication, resumableUploadUri, payload, contentType, null); + } + + private WebResponse Update(Authenticator authentication, AbstractEntry payload, AsyncData data) + { + WebResponse r = null; + + Uri initialUri = ResumableUploader.GetResumableEditUri(payload.Links); + if (initialUri == null) + throw new ArgumentException("payload did not contain a resumabled edit media Uri"); + + Uri resumeUri = InitiateUpload(initialUri, authentication, payload); + + // get the stream + using (Stream s = payload.MediaSource.GetDataStream()) + { + r = UploadStream(HttpMethods.Put, resumeUri, authentication, s, payload.MediaSource.ContentType, data); + } + return r; + + } + + private WebResponse Update(Authenticator authentication, Uri resumableUploadUri, Stream payload, string contentType, AsyncData data) + { + Uri resumeUri = InitiateUpload(resumableUploadUri, authentication, contentType, null, GetStreamLength(payload)); + return UploadStream(HttpMethods.Put, resumeUri, authentication, payload, contentType, data); + } + + public void UpdateAsync(Authenticator authentication, Uri resumableUploadUri, Stream payload, string contentType, object userData) + { + AsyncResumableUploadData data = new AsyncResumableUploadData(this, + authentication, + resumableUploadUri, + payload, + contentType, + null, + HttpMethods.Put, + this.ProgressReportDelegate, + userData); + WorkerResumableUploadHandler workerDelegate = new WorkerResumableUploadHandler(AsyncUpdateWorker); + this.AsyncStarter(data, workerDelegate, userData); + } + + public void UpdateAsync(Authenticator authentication, AbstractEntry payload, object userData) + { + AsyncResumableUploadData data = new AsyncResumableUploadData(this, + authentication, + payload, + HttpMethods.Put, + this.ProgressReportDelegate, + userData); + WorkerResumableUploadHandler workerDelegate = new WorkerResumableUploadHandler(AsyncUpdateWorker); + this.AsyncStarter(data, workerDelegate, userData); + } + + public WebResponse Resume(Authenticator authentication, Uri resumeUri, String httpMethod, Stream payload, string contentType) + { + return Resume(authentication, resumeUri, httpMethod, payload, contentType, null); + } + + public void ResumeAsync(Authenticator authentication, Uri resumeUri, String httpmethod, Stream payload, string contentType, object userData) + { + AsyncResumableUploadData data = new AsyncResumableUploadData(this, + authentication, + resumeUri, + payload, + contentType, + null, + httpmethod, + this.ProgressReportDelegate, + userData); + WorkerResumableUploadHandler workerDelegate = new WorkerResumableUploadHandler(AsyncResumeWorker); + this.AsyncStarter(data, workerDelegate, userData); + } + + private WebResponse Resume(Authenticator authentication, Uri resumeUri, + String httpmethod, Stream payload, string contentType, + AsyncData data) + { + return UploadStream(httpmethod, resumeUri, authentication, payload, contentType, data); + } + + /// + /// worker method for the resume + /// + /// + /// + /// + /// + private void AsyncResumeWorker(AsyncResumableUploadData data, AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate) + { + try + { + using (var response = Resume(data.Authentication, data.UriToUse, data.HttpVerb, data.DataStream, data.ContentType, data)) + { + HandleResponseStream(data, response.GetResponseStream(), -1); + } + } + catch (Exception e) + { + data.Exception = e; + } + + this.CompletionMethodDelegate(data); + } + + /// + /// worker method for the resumable update + /// + /// + /// + /// + /// + private void AsyncUpdateWorker(AsyncResumableUploadData data, AsyncOperation asyncOp, SendOrPostCallback completionMethodDelegate) + { + try + { + if (data.Entry != null) + { + using (var response = Update(data.Authentication, data.Entry, data)) + { + HandleResponseStream(data, response.GetResponseStream(), -1); + } + } + else + { + using (var response = Update(data.Authentication, data.UriToUse, data.DataStream, data.ContentType, data)) + { + HandleResponseStream(data, response.GetResponseStream(), -1); + } + } + } + catch (Exception e) + { + data.Exception = e; + } + + this.CompletionMethodDelegate(data); + } + + /// + /// Note the URI passed in here, is the session URI obtained by InitiateUpload + /// + /// + /// + /// + /// + public WebResponse UploadStream(string httpMethod, Uri sessionUri, Authenticator authentication, + Stream payload, string mediaType, AsyncData data) + { + HttpWebResponse returnResponse = null; + // upload one part at a time + int index = 0; + bool isDone = false; + + + // if the passed in stream is NOT at the beginning, we assume + // that we are resuming + try + { + // calculate a new index, we will resume in chunk sizes + if (payload.Position != 0) + { + index = (int)((double)payload.Position / (this.chunkSize * ResumableUploader.MB)); + } + } + catch (System.NotSupportedException e) + { + index = 0; + } + + do + { + HttpWebResponse response; + try + { + response = UploadStreamPart(index, httpMethod, sessionUri, authentication, payload, mediaType, data); + if (data != null && CheckIfOperationIsCancelled(data.UserData) == true) + { + break; + } + + index++; + { + int status = (int)response.StatusCode; + switch (status) + { + + case 308: + isDone = false; + break; + case 200: + case 201: + isDone = true; + returnResponse = response; + break; + default: + throw new ApplicationException("Unexpected return code during resumable upload"); + } + + } + } + finally + { + response = null; + } + } while (isDone == false); + return returnResponse; + } + + private HttpWebResponse UploadStreamPart(int partIndex, string httpMethod, Uri sessionUri, + Authenticator authentication, Stream payload, string mediaType, + AsyncData data) + { + HttpWebRequest request = authentication.CreateHttpWebRequest(httpMethod, sessionUri); + request.AllowWriteStreamBuffering = false; + request.Timeout = 600000; + + // write the data + request.ContentType = mediaType; + CopyData(payload, request, partIndex, data); + + HttpWebResponse response = request.GetResponse() as HttpWebResponse; + + return response; + } + + private long GetStreamLength(Stream s) + { + long result; + + try + { + result = s.Length; + } + catch (NotSupportedException e) + { + result = -1; + } + + return result; + + } + + ////////////////////////////////////////////////////////////////////// + /// takes our copy of the stream, and puts it into the request stream + /// returns FALSE when we are done by reaching the end of the input stream + ////////////////////////////////////////////////////////////////////// + protected bool CopyData(Stream input, HttpWebRequest request, int partIndex, AsyncData data) + { + + long chunkCounter = 0; + long chunkStart = lastChunk; + long chunkSizeMb = this.chunkSize * ResumableUploader.MB; + long dataLength; + + dataLength = GetStreamLength(input); + + + // calculate the range + // move the source stream to the correct position + input.Seek(chunkStart, SeekOrigin.Begin); + + // to reduce memory consumption, we read in 256K chunks + const int size = 262144; + byte[] bytes = new byte[size]; + int numBytes; + + // first calculate the contentlength. We can not modify + // headers AFTER we started writing to the stream + // Note: we want to read in chunksize*MB, but it might be less + // if we have smaller files or are at the last chunk + while ((numBytes = input.Read(bytes, 0, size)) > 0) + { + chunkCounter += numBytes; + + if (chunkCounter >= chunkSizeMb) + break; + } + request.ContentLength = chunkCounter; + long chunkEnd = chunkStart + chunkCounter; + + // modify the content-range header + string contentRange = String.Format("bytes {0}-{1}/{2}", chunkStart, chunkEnd - 1, dataLength > 0 ? dataLength.ToString() : "*"); + request.Headers.Add(HttpRequestHeader.ContentRange, contentRange); + + lastChunk = chunkEnd; // save the last start index, need to add 503 error handling to this + + // stream it into the real request stream + using (Stream req = request.GetRequestStream()) + { + // move the source stream to the correct position + input.Seek(chunkStart, SeekOrigin.Begin); + chunkCounter = 0; + + // to reduce memory consumption, we read in 256K chunks + while ((numBytes = input.Read(bytes, 0, size)) > 0) + { + req.Write(bytes, 0, numBytes); + chunkCounter += numBytes; + + // while we are writing along, send notifications out + if (data != null) + { + if (CheckIfOperationIsCancelled(data.UserData) == true) + { + break; + } + else if (data.Delegate != null && + data.DataHandler != null) + { + AsyncOperationProgressEventArgs args; + long position = chunkStart + chunkCounter - 1; + int percentage = (int)((double)position / dataLength * 100); + + args = new AsyncOperationProgressEventArgs(dataLength, + position, + percentage, + request.RequestUri, + request.Method, + data.UserData); + data.DataHandler.SendProgressData(data, args); + } + } + + if (chunkCounter >= request.ContentLength) + break; + + } + } + + return chunkCounter < chunkSizeMb; + + } + ///////////////////////////////////////////////////////////////////////////// + + /// + /// retrieves the resumable URI for the rest of the operation. This will initiate the + /// communication with resumable upload server by posting against the starting URI + /// + /// + /// + /// + /// The uri to be used for the rest of the operation + public Uri InitiateUpload(Uri resumableUploadUri, Authenticator authentication, string contentType, string slug, long contentLength) + { + HttpWebRequest request = PrepareRequest(resumableUploadUri, + authentication, + slug, + contentType, + contentLength); + + WebResponse response = request.GetResponse(); + return new Uri(response.Headers["Location"]); + } + + + /// + /// retrieves the resumable URI for the rest of the operation. This will initiate the + /// communication with resumable upload server by posting against the starting URI + /// + /// + /// + /// + /// The uri to be used for the rest of the operation + public Uri InitiateUpload(Uri resumableUploadUri, Authenticator authentication, AbstractEntry entry) + { + HttpWebRequest request = PrepareRequest(resumableUploadUri, + authentication, + entry.MediaSource.Name, + entry.MediaSource.ContentType, + entry.MediaSource.ContentLength); + + IVersionAware v = entry as IVersionAware; + if (v != null) + { + // need to add the version header to the request + request.Headers.Add(GDataGAuthRequestFactory.GDataVersion, v.ProtocolMajor.ToString() + "." + v.ProtocolMinor.ToString()); + } + + ISupportsEtag e = entry as ISupportsEtag; + if (e != null && Utilities.IsWeakETag(e) == false) + { + request.Headers.Add(GDataRequestFactory.IfMatch, e.Etag); + } + + Stream outputStream = request.GetRequestStream(); + entry.SaveToXml(outputStream); + outputStream.Close(); + + /// this is the contenttype for the xml post + request.ContentType = GDataRequestFactory.DefaultContentType; + + WebResponse response = request.GetResponse(); + return new Uri(response.Headers["Location"]); + } + + private HttpWebRequest PrepareRequest(Uri target, + Authenticator authentication, + string slug, + string contentType, + long contentLength) + { + HttpWebRequest request = authentication.CreateHttpWebRequest(HttpMethods.Post, target); + request.Headers.Add(GDataRequestFactory.SlugHeader + ": " + slug); + request.Headers.Add(GDataRequestFactory.ContentOverrideHeader + ": " + contentType); + if (contentLength != -1) + { + request.Headers.Add(GDataRequestFactory.ContentLengthOverrideHeader + ": " + contentLength); + } + + return request; + + } + + + /// + /// starts the async job + /// + /// + /// + /// + /// + private void AsyncStarter(AsyncResumableUploadData data, WorkerResumableUploadHandler workerDelegate, Object userData) + { + AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(userData); + + data.Operation = asyncOp; + + AddUserDataToDictionary(userData, asyncOp); + + + // Start the asynchronous operation. + workerDelegate.BeginInvoke( + data, + asyncOp, + this.CompletionMethodDelegate, + null, + null); + } + + } +} diff -Nru gdata-sharp-1.4.0.2/src/core/service.cs gdata-sharp-1.7.0.1/src/core/service.cs --- gdata-sharp-1.4.0.2/src/core/service.cs 2009-02-16 17:39:06.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/service.cs 2010-05-26 08:26:14.000000000 +0000 @@ -121,10 +121,9 @@ ////////////////////////////////////////////////////////////////////// /// default constructor, sets the default GDataRequest ////////////////////////////////////////////////////////////////////// - public Service() + public Service() : base() { this.RequestFactory = new GDataRequestFactory(this.GetType().Name); - InitDelegates(); InitVersionInformation(); } ///////////////////////////////////////////////////////////////////////////// @@ -133,12 +132,11 @@ ////////////////////////////////////////////////////////////////////// /// default constructor, sets the default GDataRequest ////////////////////////////////////////////////////////////////////// - public Service(string applicationName) + public Service(string applicationName) : base() { this.RequestFactory = new GDataRequestFactory(applicationName == null ? this.GetType().Name : applicationName); - InitDelegates(); InitVersionInformation(); } ///////////////////////////////////////////////////////////////////////////// @@ -147,11 +145,10 @@ ////////////////////////////////////////////////////////////////////// /// this will trigger the creation of an authenticating service ////////////////////////////////////////////////////////////////////// - public Service(string service, string applicationName) + public Service(string service, string applicationName) : base() { this.RequestFactory = new GDataGAuthRequestFactory(service, applicationName); this.serviceID = service; - InitDelegates(); InitVersionInformation(); } ///////////////////////////////////////////////////////////////////////////// @@ -189,6 +186,8 @@ } } + + /// /// returns the minor protocol version number this element /// is working against. @@ -268,8 +267,11 @@ /// if the service is using a Google Request Factory it will use that /// assuming credentials are set to retrieve the authentication token /// for those credentials + /// + /// Note that this only works for ClientLogin, not for any other type of authentication /// /// string + [Obsolete("the name is confusing. Do not use this, use QueryClientLoginToken instead")] public string QueryAuthenticationToken() { if (this.Credentials != null) @@ -284,6 +286,27 @@ } /// + /// if the service is using a Google Request Factory it will use that + /// assuming credentials are set to retrieve the authentication token + /// for those credentials + /// + /// Note that this only works for ClientLogin, not for any other type of authentication + /// + /// string + public string QueryClientLoginToken() + { + if (this.Credentials != null) + { + GDataGAuthRequestFactory factory = this.factory as GDataGAuthRequestFactory; + if (factory != null) + { + return factory.QueryAuthToken(this.Credentials); + } + } + return null; + } + + /// /// if the service is using a Google Request Factory it will set the passed /// in token to the factory. NET CF does not support authsubtokens here /// @@ -410,7 +433,7 @@ throw; } - + // return the response GDataGAuthRequest gr = request as GDataGAuthRequest; if (gr != null) @@ -718,7 +741,13 @@ } - private AtomFeed CreateAndParseFeed(Stream inputStream, Uri uriToUse) + /// + /// used to create a feed based on a stream + /// + /// + /// + /// + internal AtomFeed CreateAndParseFeed(Stream inputStream, Uri uriToUse) { AtomFeed returnFeed = null; @@ -741,7 +770,7 @@ return returnFeed; } - private AtomEntry CreateAndParseEntry(Stream inputStream, Uri uriTarget) + internal AtomEntry CreateAndParseEntry(Stream inputStream, Uri uriTarget) { AtomFeed returnFeed = CreateAndParseFeed(inputStream, uriTarget); AtomEntry entry=null; @@ -1119,20 +1148,30 @@ ////////////////////////////////////////////////////////////////////// public void Delete(AtomEntry entry) { + Delete(entry, false); + } + + ////////////////////////////////////////////////////////////////////// + /// deletes an Atom entry object + /// The entry to be deleted + /// Should the entry be archived or not + ////////////////////////////////////////////////////////////////////// + public void Delete(AtomEntry entry, bool permanentDelete) + { Tracing.Assert(entry != null, "entry should not be null"); string eTag = null; if (entry == null) { - throw new ArgumentNullException("entry"); + throw new ArgumentNullException("entry"); } if (entry.ReadOnly == true) { - throw new GDataRequestException("Can not update a read-only entry"); + throw new GDataRequestException("Can not update a read-only entry"); } - Tracing.Assert(entry.EditUri != null, "Entry should have a valid edit URI"); + Tracing.Assert(entry.EditUri != null, "Entry should have a valid edit URI"); ISupportsEtag eSource = entry as ISupportsEtag; @@ -1143,13 +1182,15 @@ if (entry.EditUri != null) { - Delete(new Uri(entry.EditUri.ToString()), eTag); + var uriString = entry.EditUri.Content + (permanentDelete ? "?delete=true" : string.Empty); + Delete(new Uri(uriString), eTag); } else { - throw new GDataRequestException("Invalid Entry object (no edit uri) to call Delete on"); + throw new GDataRequestException("Invalid Entry object (no edit uri) to call Delete on"); } } + ///////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// @@ -1190,7 +1231,8 @@ request.Execute(); IDisposable disp = request as IDisposable; disp.Dispose(); - } + } + ////////////////////////////////////////////////////////////////////// diff -Nru gdata-sharp-1.4.0.2/src/core/serviceinterface.cs gdata-sharp-1.7.0.1/src/core/serviceinterface.cs --- gdata-sharp-1.4.0.2/src/core/serviceinterface.cs 2009-02-16 17:39:06.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/serviceinterface.cs 2010-03-19 14:43:08.000000000 +0000 @@ -65,7 +65,7 @@ get; } - /// the minimal Get OpenSearchRssDescription function + /// the minimal Get OpenSearchRssDescription function Stream QueryOpenSearchRssDescription(Uri serviceUri); /// the minimal query implementation @@ -98,7 +98,16 @@ /// creation method for GDatarequests IGDataRequest CreateRequest(GDataRequestType type, Uri uriTarget); /// set wether or not to use gzip for new requests - bool UseGZip + bool UseGZip + { + get; + set; + } + + /// + /// indicates that the service should use SSL exclusively + /// + bool UseSSL { get; set; diff -Nru gdata-sharp-1.4.0.2/src/core/simplecontainer.cs gdata-sharp-1.7.0.1/src/core/simplecontainer.cs --- gdata-sharp-1.4.0.2/src/core/simplecontainer.cs 2008-10-21 10:10:36.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/simplecontainer.cs 2009-11-23 14:21:18.000000000 +0000 @@ -24,6 +24,7 @@ using System.Xml; using Google.GData.Client; using System.Globalization; +using System.Collections.Generic; namespace Google.GData.Extensions { @@ -124,7 +125,7 @@ /// Primary use of this is to find XML nodes /// /// the xml local name of the element to find - /// the namespace of the elementToPersist + /// the namespace of the element to find /// none public ExtensionList FindExtensions(string localName, string ns) { @@ -133,6 +134,24 @@ } + + /// + /// Finds all ExtensionElement based on it's local name + /// and it's namespace. If namespace is NULL, allwhere + /// the localname matches is found. If there are extensionelements that do + /// not implment ExtensionElementFactory, they will not be taken into account + /// Primary use of this is to find XML nodes + /// + /// the xml local name of the element to find + /// the namespace of the element to find + /// none + public List FindExtensions(string localName, string ns) where T : IExtensionElementFactory + { + return Utilities.FindExtensions(this.ExtensionElements, + localName, ns); + + } + /// /// Delete's all Extensions from the Extension list that match /// a localName and a Namespace. @@ -196,6 +215,7 @@ SimpleContainer sc = null; // create a new container sc = this.MemberwiseClone() as SimpleContainer; + sc.InitInstance(this); sc.ProcessAttributes(node); sc.ProcessChildNodes(node, parser); @@ -266,6 +286,30 @@ } } } + + + protected void SetStringValue(string value, string elementName, string ns) where T : SimpleElement, new() + { + T v = null; + if (String.IsNullOrEmpty(value) == false) + { + v = new T(); + v.Value = value; + } + + ReplaceExtension(elementName, ns, v); + } + + + protected string GetStringValue(string elementName, string ns) where T : SimpleElement + { + T e = FindExtension(elementName, ns) as T; + if (e!= null) + { + return e.Value; + } + return null; + } #endregion } } diff -Nru gdata-sharp-1.4.0.2/src/core/simpleelement.cs gdata-sharp-1.7.0.1/src/core/simpleelement.cs --- gdata-sharp-1.4.0.2/src/core/simpleelement.cs 2008-10-15 12:50:39.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/simpleelement.cs 2010-03-24 11:01:14.000000000 +0000 @@ -30,7 +30,8 @@ /// /// Extensible enum type used in many places. /// compared to the base class, this one - /// adds a default values + /// adds a default value which is the text content inside the + /// element node. /// public abstract class SimpleElement : ExtensionBase { @@ -152,11 +153,21 @@ if (node != null) { - e.Value = node.InnerText; + e.ProcessAttributes(node); + if (node.HasChildNodes == true) + { + XmlNode n = node.ChildNodes[0]; + if (n.NodeType == XmlNodeType.Text && node.ChildNodes.Count == 1) + { + e.Value = node.InnerText; + } + else + { + e.ProcessChildNodes(node, parser); + } + } } - e.ProcessAttributes(node); - e.ProcessChildNodes(node, parser); return e; } @@ -229,4 +240,41 @@ // end of accessor public string Value } + /// + /// a simple element with two attribute,called value and name that exposes + /// that value as the value property + /// + public class SimpleNameValueAttribute : SimpleAttribute + { + /// + /// constructor + /// + /// the xml name + /// the xml prefix + /// the xml namespace + protected SimpleNameValueAttribute(string localName, string prefix, string ns) + :base(localName, prefix, ns) + { + this.Attributes.Add(BaseNameTable.XmlName, null); + } + + + ////////////////////////////////////////////////////////////////////// + /// Accessor for "name" attribute. + /// + ////////////////////////////////////////////////////////////////////// + public string Name + { + get { + return this.Attributes[BaseNameTable.XmlName] as string; + } + set + { + this.Attributes[BaseNameTable.XmlName] = value; + } + } + // end of accessor public string Value + } + + } diff -Nru gdata-sharp-1.4.0.2/src/core/utilities.cs gdata-sharp-1.7.0.1/src/core/utilities.cs --- gdata-sharp-1.4.0.2/src/core/utilities.cs 2009-02-16 17:39:06.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/utilities.cs 2010-04-27 13:01:48.000000000 +0000 @@ -53,6 +53,11 @@ /// xsd version of bool:false /// public const string XSDFalse = "false"; + /// + /// default user string + /// + public const string DefaultUser = "default"; + ////////////////////////////////////////////////////////////////////// /// private constructor to prevent the compiler from generating a default one @@ -195,8 +200,7 @@ return returnString.ToString(); } - - + /// /// used as a cover method to hide the actual decoding implementation @@ -562,6 +566,7 @@ } ///////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// /// Sets the gDataBatch namespace, if it's not already set. /// @@ -851,6 +856,172 @@ } return false; } + + ////////////////////////////////////////////////////////////////////// + /// goes to the Google auth service, and gets a new auth token + /// the auth token, or NULL if none received + ////////////////////////////////////////////////////////////////////// + public static string QueryClientLoginToken(GDataCredentials gc, + string serviceName, + string applicationName, + bool fUseKeepAlive, + Uri clientLoginHandler + ) + { + Tracing.Assert(gc != null, "Do not call QueryAuthToken with no network credentials"); + if (gc == null) + { + throw new System.ArgumentNullException("nc", "No credentials supplied"); + } + + HttpWebRequest authRequest = WebRequest.Create(clientLoginHandler) as HttpWebRequest; + + authRequest.KeepAlive = fUseKeepAlive; + + string accountType = GoogleAuthentication.AccountType; + if (!String.IsNullOrEmpty(gc.AccountType)) + { + accountType += gc.AccountType; + } + else + { + accountType += GoogleAuthentication.AccountTypeDefault; + } + + WebResponse authResponse = null; + + string authToken = null; + try + { + authRequest.ContentType = HttpFormPost.Encoding; + authRequest.Method = HttpMethods.Post; + ASCIIEncoding encoder = new ASCIIEncoding(); + + string user = gc.Username == null ? "" : gc.Username; + string pwd = gc.getPassword() == null ? "" : gc.getPassword(); + + // now enter the data in the stream + string postData = GoogleAuthentication.Email + "=" + Utilities.UriEncodeUnsafe(user) + "&"; + postData += GoogleAuthentication.Password + "=" + Utilities.UriEncodeUnsafe(pwd) + "&"; + postData += GoogleAuthentication.Source + "=" + Utilities.UriEncodeUnsafe(applicationName) + "&"; + postData += GoogleAuthentication.Service + "=" + Utilities.UriEncodeUnsafe(serviceName) + "&"; + if (gc.CaptchaAnswer != null) + { + postData += GoogleAuthentication.CaptchaAnswer + "=" + Utilities.UriEncodeUnsafe(gc.CaptchaAnswer) + "&"; + } + if (gc.CaptchaToken != null) + { + postData += GoogleAuthentication.CaptchaToken + "=" + Utilities.UriEncodeUnsafe(gc.CaptchaToken) + "&"; + } + postData += accountType; + + byte[] encodedData = encoder.GetBytes(postData); + authRequest.ContentLength = encodedData.Length; + + Stream requestStream = authRequest.GetRequestStream() ; + requestStream.Write(encodedData, 0, encodedData.Length); + requestStream.Close(); + authResponse = authRequest.GetResponse(); + + } + catch (WebException e) + { + Tracing.TraceMsg("QueryAuthtoken failed " + e.Status + " " + e.Message); + throw; + } + HttpWebResponse response = authResponse as HttpWebResponse; + if (response != null) + { + // check the content type, it must be text + if (!response.ContentType.StartsWith(HttpFormPost.ReturnContentType)) + { + throw new GDataRequestException("Execution of authentication request returned unexpected content type: " + response.ContentType, response); + } + TokenCollection tokens = Utilities.ParseStreamInTokenCollection(response.GetResponseStream()); + authToken = Utilities.FindToken(tokens, GoogleAuthentication.AuthToken); + + if (authToken == null) + { + throw Utilities.getAuthException(tokens, response); + } + // failsafe. if getAuthException did not catch an error... + int code= (int)response.StatusCode; + if (code != 200) + { + throw new GDataRequestException("Execution of authentication request returned unexpected result: " +code, response); + } + + } + Tracing.Assert(authToken != null, "did not find an auth token in QueryAuthToken"); + if (authResponse != null) + { + authResponse.Close(); + } + + return authToken; + } + ///////////////////////////////////////////////////////////////////////////// + /// + /// Returns the respective GDataAuthenticationException given the return + /// values from the login URI handler. + /// + /// The tokencollection of the parsed return form + /// the webresponse + /// AuthenticationException + static LoggedException getAuthException(TokenCollection tokens, HttpWebResponse response) + { + String errorName = Utilities.FindToken(tokens, "Error"); + int code= (int)response.StatusCode; + if (errorName == null || errorName.Length == 0) + { + // no error given by Gaia, return a standard GDataRequestException + throw new GDataRequestException("Execution of authentication request returned unexpected result: " +code, response); + } + if ("BadAuthentication".Equals(errorName)) + { + return new InvalidCredentialsException("Invalid credentials"); + } + else if ("AccountDeleted".Equals(errorName)) + { + return new AccountDeletedException("Account deleted"); + } + else if ("AccountDisabled".Equals(errorName)) + { + return new AccountDisabledException("Account disabled"); + } + else if ("NotVerified".Equals(errorName)) + { + return new NotVerifiedException("Not verified"); + } + else if ("TermsNotAgreed".Equals(errorName)) + { + return new TermsNotAgreedException("Terms not agreed"); + } + else if ("ServiceUnavailable".Equals(errorName)) + { + return new ServiceUnavailableException("Service unavailable"); + } + else if ("CaptchaRequired".Equals(errorName)) + { + String captchaPath = Utilities.FindToken(tokens, "CaptchaUrl"); + String captchaToken = Utilities.FindToken(tokens, "CaptchaToken"); + + StringBuilder captchaUrl = new StringBuilder(); + captchaUrl.Append(GoogleAuthentication.DefaultProtocol).Append("://"); + captchaUrl.Append(GoogleAuthentication.DefaultDomain); + captchaUrl.Append(GoogleAuthentication.AccountPrefix); + captchaUrl.Append('/').Append(captchaPath); + return new CaptchaRequiredException("Captcha required", + captchaUrl.ToString(), + captchaToken); + + } + else + { + return new AuthenticationException("Error authenticating (check service name): " + errorName); + } + } + } ///////////////////////////////////////////////////////////////////////////// diff -Nru gdata-sharp-1.4.0.2/src/core/versioninterface.cs gdata-sharp-1.7.0.1/src/core/versioninterface.cs --- gdata-sharp-1.4.0.2/src/core/versioninterface.cs 2009-02-16 17:39:06.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/core/versioninterface.cs 2009-06-24 15:22:59.000000000 +0000 @@ -61,6 +61,10 @@ /// and versionTwo is a 2 /// public const int VersionTwo = 2; + /// + /// and versionThree is a 3 + /// + public const int VersionThree = 3; } diff -Nru gdata-sharp-1.4.0.2/src/documents3/AssemblyInfo.cs gdata-sharp-1.7.0.1/src/documents3/AssemblyInfo.cs --- gdata-sharp-1.4.0.2/src/documents3/AssemblyInfo.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/documents3/AssemblyInfo.cs 2009-10-21 14:06:48.000000000 +0000 @@ -0,0 +1,22 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +using System.Reflection; +using System.Runtime.CompilerServices; + + +[assembly: AssemblyDelaySign(false)] +[assembly: AssemblyKeyName("")] +[assembly: AssemblyTitle("Google Data API Documents Library")] + diff -Nru gdata-sharp-1.4.0.2/src/documents3/docrequest.cs gdata-sharp-1.7.0.1/src/documents3/docrequest.cs --- gdata-sharp-1.4.0.2/src/documents3/docrequest.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/documents3/docrequest.cs 2010-03-19 14:43:08.000000000 +0000 @@ -0,0 +1,761 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + + +using System; +using System.IO; +using System.Collections; +using System.Text; +using System.Net; +using Google.GData.Client; +using Google.GData.Extensions; +using Google.GData.AccessControl; +using Google.GData.Documents; +using System.Collections.Generic; + +namespace Google.Documents +{ + + /// + /// the base class for all documents in the document service. A document can represent folders, documents, spreadsheets etc. + /// + public class Document : Entry + { + + /// + /// descripes the type of the document entry + /// + public enum DocumentType + { + /// + /// a document + /// + Document, + /// + /// a spreadsheet + /// + Spreadsheet, + /// + /// a pdf file + /// + PDF, + /// + /// a presentation + /// + Presentation, + /// + /// a folder + /// + Folder, + /// + /// a form + /// + Form, + /// + /// something unknown to us + /// + Unknown + } + + /// + /// describes the download type, in what format you want to download the document + /// + public enum DownloadType + { + /// + /// text file + /// + txt, + /// + /// open document format + /// + odt, + /// + /// portable document format PFDF + /// + pdf, + /// + /// html format + /// + html, + /// + /// rich text format + /// + rtf, + /// + /// microsoft word format + /// + doc, + /// + /// portable network graphics format + /// + png, + /// zip format + zip, + /// + /// flash format + /// + swf, + /// + /// Microsoft Powerpoint format + /// + ppt, + /// + /// Microsoft Excel format + /// + xls, + /// + /// commma seperated value format + /// + csv, + /// + /// open document spreadsheet format + /// + ods, + /// + /// tab seperated values format + /// + tsv + } + + /// + /// creates the inner contact object when needed + /// + /// + protected override void EnsureInnerObject() + { + if (this.AtomEntry == null) + { + this.AtomEntry = new DocumentEntry(); + } + } + + + + /// + /// readonly accessor for the DocumentEntry that is underneath this object. + /// + /// + public DocumentEntry DocumentEntry + { + get + { + EnsureInnerObject(); + return this.AtomEntry as DocumentEntry; + } + } + + /// + /// the type of the document entry + /// + /// + public Document.DocumentType Type + { + get + { + EnsureInnerObject(); + if (this.DocumentEntry.IsDocument) + { + return Document.DocumentType.Document; + } + else if (this.DocumentEntry.IsPDF) + { + return Document.DocumentType.PDF; + } + else if (this.DocumentEntry.IsSpreadsheet) + { + return Document.DocumentType.Spreadsheet; + } + else if (this.DocumentEntry.IsFolder) + { + return Document.DocumentType.Folder; + } + else if (this.DocumentEntry.IsPresentation) + { + return Document.DocumentType.Presentation; + } + return Document.DocumentType.Unknown; + } + set + { + EnsureInnerObject(); + switch (value) + { + case Document.DocumentType.Document: + this.DocumentEntry.IsDocument = true; + break; + case Document.DocumentType.Folder: + this.DocumentEntry.IsFolder = true; + break; + case Document.DocumentType.PDF: + this.DocumentEntry.IsPDF = true; + break; + case Document.DocumentType.Presentation: + this.DocumentEntry.IsPresentation = true; + break; + case Document.DocumentType.Spreadsheet: + this.DocumentEntry.IsSpreadsheet = true; + break; + case Document.DocumentType.Unknown: + throw new ArgumentException("Type.Unknown is not allowed to be set"); + } + } + } + + /// + /// returns the href values of the parent link releationships + /// can be used to retrieve the parent folder + /// + /// + public List ParentFolders + { + get + { + EnsureInnerObject(); + List strings = new List(); + foreach (AtomLink l in this.DocumentEntry.ParentFolders) + { + strings.Add(l.HRef.ToString()); + } + return strings; + } + } + + + + + /// + /// returns the document resource id of the object. + /// this uses the gd:resourceId element + /// + /// + public string ResourceId + { + get + { + EnsureInnerObject(); + return this.DocumentEntry.ResourceId; + } + } + + /// + /// returns if colaborators should be able to modify + /// the documents ACL list + /// + /// + public bool WritersCanInvite + { + get + { + EnsureInnerObject(); + return this.DocumentEntry.WritersCanInvite; + } + set + { + + EnsureInnerObject(); + this.DocumentEntry.WritersCanInvite = value; + } + } + + /// + /// Returns the last viewed timestamp + /// + /// + public DateTime LastViewed + { + get + { + EnsureInnerObject(); + return this.DocumentEntry.LastViewed; + } + } + + + /// + /// returns the last modifiedBy subobject, indicating + /// who edited the document last + /// + /// + public LastModifiedBy LastModified + { + get + { + EnsureInnerObject(); + return this.DocumentEntry.LastModified; + } + } + + /// + /// returns the quota used by the object. 0 if not availabe + /// + [CLSCompliant(false)] + public uint QuotaBytesUsed + { + get + { + EnsureInnerObject(); + if (this.DocumentEntry.QuotaUsed != null) + { + return this.DocumentEntry.QuotaUsed.UnsignedIntegerValue; + } + return 0; + } + } + + + /// + /// returns the Uri to the access control list + /// + /// the value of the href attribute for the acl feedlink, or null if not found + public Uri AccessControlList + { + get + { + EnsureInnerObject(); + return this.DocumentEntry.AccessControlList != null ? + new Uri(this.DocumentEntry.AccessControlList) : + null; + } + } + + /// + /// returns the Uri to the revision document + /// + /// The value of the href attribute of the revisions feedlink, or null if not found + public Uri RevisionDocument + { + get + { + EnsureInnerObject(); + return this.DocumentEntry.RevisionDocument != null ? + new Uri(this.DocumentEntry.RevisionDocument) : + null; + } + } + } + + + ////////////////////////////////////////////////////////////////////// + /// + /// The Google Documents List Data API allows client applications + /// to view and update documents (spreadsheets and word processor) + /// using a Google Data API feed. Your client application can request + /// a list of a user's documents, query the content of a + /// user's documents, and upload new documents. + /// + /// + /// The following code illustrates a possible use of + /// the DocumentsRequest object: + /// + /// RequestSettings settings = new RequestSettings("yourApp"); + /// settings.PageSize = 50; + /// settings.AutoPaging = true; + /// DocumentsRequest c = new DocumentsRequest(settings); + /// Feed<Dcouments> feed = c.GetDocuments(); + /// + /// foreach (Document d in feed.Entries) + /// { + /// Console.WriteLine(d.Title); + /// } + /// + /// + ////////////////////////////////////////////////////////////////////// + public class DocumentsRequest : FeedRequest + { + + private string baseUri = DocumentsListQuery.documentsBaseUri; + private Service spreadsheetsService; + /// + /// default constructor for a DocumentsRequest + /// + /// + public DocumentsRequest(RequestSettings settings) : base(settings) + { + this.Service = new DocumentsService(settings.Application); + // we hardcode the service name here to avoid having a dependency + // on the spreadsheet dll for now. + this.spreadsheetsService = new Service("wise", settings.Application); + this.spreadsheetsService.ProtocolMajor = 2; + PrepareService(); + PrepareService(this.spreadsheetsService); + } + + /// + /// the base string to use for queries. Defaults to + /// DocumentsListQuery.documentsBaseUri + /// + /// + public string BaseUri + { + get + { + return this.baseUri; + } + set + { + this.baseUri = value; + } + } + /// + /// called to set additonal proxies if required. Overloaded on the document service + /// + /// + /// + protected override void OnSetOtherProxies(IWebProxy proxy) + { + base.OnSetOtherProxies(proxy); + GDataRequestFactory x= this.spreadsheetsService.RequestFactory as GDataRequestFactory; + if (x != null) + { + x.Proxy = proxy; + } + else + { + throw new ArgumentException("Can not set a proxy on the spreadsheet service"); + } + } + + + /// + /// returns a Feed of all documents and folders for the authorized user + /// + /// a feed of everyting + public Feed GetEverything() + { + DocumentsListQuery q = PrepareQuery(this.BaseUri); + q.ShowFolders = true; + return PrepareFeed(q); + } + + /// + /// returns a Feed of all documents for the authorized user + /// + /// a feed of Documents + public Feed GetDocuments() + { + TextDocumentQuery q = PrepareQuery(this.BaseUri); + return PrepareFeed(q); + } + + /// + /// returns a Feed of all presentations for the authorized user + /// + /// a feed of Documents + public Feed GetPresentations() + { + PresentationsQuery q = PrepareQuery(this.BaseUri); + return PrepareFeed(q); + } + + /// + /// returns a Feed of all spreadsheets for the authorized user + /// + /// a feed of Documents + public Feed GetSpreadsheets() + { + SpreadsheetQuery q = PrepareQuery(this.BaseUri); + return PrepareFeed(q); + } + + /// + /// returns a Feed of all pdf files for the authorized user + /// + /// a feed of Documents + public Feed GetPDFs() + { + PDFsQuery q = PrepareQuery(this.BaseUri); + return PrepareFeed(q); + } + + /// + /// returns a Feed of all files that are owned by the authorized user + /// + /// a feed of Documents + public Feed GetMyDocuments() + { + DocumentsListQuery q = PrepareQuery(this.BaseUri); + q.Categories.Add(DocumentsListQuery.MINE); + return PrepareFeed(q); + } + + + /// + /// returns a Feed of all folders for the authorized user + /// + /// a feed of Documents + public Feed GetFolders() + { + DocumentsListQuery q = PrepareQuery(DocumentsListQuery.allFoldersUri); + return PrepareFeed(q); + } + + /// + /// returns all items the user has viewed recently + /// + /// + public Feed GetViewed() + { + DocumentsListQuery q = PrepareQuery(this.BaseUri); + q.Categories.Add(DocumentsListQuery.VIEWED); + return PrepareFeed(q); + } + + /// + /// returns all forms for the authorized user + /// + /// + public Feed GetForms() + { + DocumentsListQuery q = PrepareQuery(this.BaseUri); + q.Categories.Add(DocumentsListQuery.FORMS); + return PrepareFeed(q); + } + + /// + /// returns a feed of documents for the specified folder + /// + /// + /// + public Feed GetFolderContent(Document folder) + { + if (folder.Type != Document.DocumentType.Folder) + { + throw new ArgumentException("The parameter folder is not a folder"); + } + + string uri = String.Format(DocumentsListQuery.foldersUriTemplate, folder.ResourceId); + DocumentsListQuery q = PrepareQuery(uri); + return PrepareFeed(q); + } + + + + /// + /// this will create an empty document or folder, pending + /// the content of the newDocument parameter + /// + /// + /// the created document from the server + public Document CreateDocument(Document newDocument) + { + return Insert(new Uri(DocumentsListQuery.documentsBaseUri), newDocument); + } + + /// + /// this will create an empty document or folder, pending + /// the content of the newDocument parameter. This will + /// append the convert=false paramter to allow for arbitrary file + /// uploads + /// + /// + /// the created document from the server + public Document CreateFile(Document newDocument) + { + return Insert(new Uri(DocumentsListQuery.documentsBaseUri + "?convert=false"), newDocument); + } + + /// + /// moves a document or a folder into a folder + /// + /// this has to be a folder + /// can be a folder or a document + /// + public Document MoveDocumentTo(Document parent, Document child) + { + if (parent == null || child == null) + { + throw new ArgumentNullException("parent or child can not be null"); + } + if (parent.AtomEntry.Content == null || parent.AtomEntry.Content.AbsoluteUri == null) + { + throw new ArgumentException("parent has no content uri"); + } + if (parent.Type != Document.DocumentType.Folder) + { + throw new ArgumentException("wrong parent type"); + } + + Document payload = new Document(); + payload.DocumentEntry.Id = new AtomId(child.Id); + payload.Type = child.Type; + + // to do that, we just need to post the CHILD + // against the URI of the parent + return Insert(new Uri(parent.AtomEntry.Content.AbsoluteUri), payload); + } + + + /// + /// downloads a document. + /// + /// The document to download. It needs to have the document type set, as well as the id link + /// The output format of the document you want to download + /// + public Stream Download(Document document, Document.DownloadType type) + { + return this.Download(document, type, null, 0); + } + + + + + /// + /// downloads a document. + /// + /// The document to download. It needs to have the document type set, as well as the id link + /// The output format of the document you want to download + /// When requesting a CSV or TSV file you must specify an additional parameter called + /// gid which indicates which grid, or sheet, you wish to get (the index is 0 based, so gid 1 + /// actually refers to the second sheet sheet on a given spreadsheet). + /// if null, default is used. Otherwise needs to specify the domain to download from, ending with a slash + /// + public Stream Download(Document document, Document.DownloadType type, string baseDomain, int sheetNumber) + { + if (document.Type == Document.DocumentType.Unknown) + { + throw new ArgumentException("Document has an unknown type"); + } + + if (document.Type == Document.DocumentType.Folder) + { + throw new ArgumentException("Document is a folder, can not be downloaded"); + } + + // now figure out the parameters + string queryUri = ""; + + Service s = this.Service; + + switch (document.Type) + { + + case Document.DocumentType.Spreadsheet: + // spreadsheet has a different parameter + if (baseDomain == null) + { + baseDomain = "http://spreadsheets.google.com/"; + } + queryUri = baseDomain + "feeds/download/spreadsheets/Export?key=" + document.ResourceId + "&exportFormat="; + s = this.spreadsheetsService; + switch (type) + { + case Document.DownloadType.xls: + queryUri+="xls"; + break; + case Document.DownloadType.csv: + queryUri+="csv&gid="+sheetNumber.ToString(); + break; + case Document.DownloadType.pdf: + queryUri+="pdf"; + break; + case Document.DownloadType.ods: + queryUri+="ods"; + break; + case Document.DownloadType.tsv: + queryUri+="tsv&gid="+sheetNumber.ToString();; + break; + case Document.DownloadType.html: + queryUri+="html"; + break; + default: + throw new ArgumentException("type is invalid for a spreadsheet"); + + } + break; + + case Document.DocumentType.Presentation: + if (baseDomain == null) + { + baseDomain = "http://docs.google.com/"; + } + + queryUri = baseDomain + "feeds/download/presentations/Export?docID=" + document.ResourceId + "&exportFormat="; + switch (type) + { + case Document.DownloadType.swf: + queryUri+="swf"; + break; + case Document.DownloadType.pdf: + queryUri+="pdf"; + break; + case Document.DownloadType.ppt: + queryUri+="ppt"; + break; + default: + throw new ArgumentException("type is invalid for a presentation"); + } + break; + default: + if (baseDomain == null) + { + baseDomain = "http://docs.google.com/"; + } + + queryUri = baseDomain + "feeds/download/documents/Export?docID=" + document.ResourceId + "&exportFormat=" + type.ToString(); + break; + + } + + Uri target = new Uri(queryUri); + return s.Query(target); + } + + + /// + /// Downloads arbitrary documents, where the link to the document is inside the + /// content field. + /// + /// a Document Entry + /// a string for the exportformat parameter or null + /// + public Stream Download(Document document, string exportFormat) + { + if (document == null) + { + throw new ArgumentException("Document should not be null"); + } + if (document.DocumentEntry == null) + { + throw new ArgumentException("document.DocumentEntry should not be null"); + } + if (document.DocumentEntry.Content == null) + { + throw new ArgumentException("document.DocumentEntry.Content should not be null"); + } + string url = document.DocumentEntry.Content.Src.ToString(); + if (String.IsNullOrEmpty(exportFormat) == false) + { + char r = '?'; + if (url.IndexOf('?') != -1) + { + r = '&'; + } + + url += r + "exportFormat=" + exportFormat; + } + + Service s = this.Service; + // figure out if we need to use the spreadsheet service + if (url.IndexOf("spreadsheets.google.com") != -1) + { + s = this.spreadsheetsService; + } + + Uri target = new Uri(url); + return s.Query(target); + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/documents3/documententry.cs gdata-sharp-1.7.0.1/src/documents3/documententry.cs --- gdata-sharp-1.4.0.2/src/documents3/documententry.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/documents3/documententry.cs 2010-01-19 15:26:34.000000000 +0000 @@ -0,0 +1,462 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +#define USE_TRACING + +using System; +using System.Xml; +using System.IO; +using System.Collections.Generic; +using Google.GData.Client; +using Google.GData.Extensions; +using Google.GData.AccessControl; +using System.Globalization; + + +namespace Google.GData.Documents { + + + /// + /// Name Table for string constants used in the Documents list api + /// + public class DocumentslistNametable : GDataParserNameTable + { + /// Document list namespace + public const string NSDocumentslist = "http://schemas.google.com/docs/2007"; + /// Document list prefix + public const string Prefix = "docs"; + /// Writers can invite element + public const string WritersCanInvite = "writersCanInvite"; + } + + + + ////////////////////////////////////////////////////////////////////// + /// + /// Entry API customization class for defining entries in an Event feed. + /// + ////////////////////////////////////////////////////////////////////// + public class DocumentEntry : AbstractEntry + { + + static string PRESENTATION_KIND = DocumentsService.DocumentsNamespace + "#presentation"; + static string DOCUMENT_KIND = DocumentsService.DocumentsNamespace + "#document"; + static string SPREADSHEET_KIND = DocumentsService.DocumentsNamespace + "#spreadsheet"; + static string PDF_KIND = DocumentsService.DocumentsNamespace + "#pdf"; + static string FOLDER_KIND = DocumentsService.DocumentsNamespace + "#folder"; + static string FORM_KIND = DocumentsService.DocumentsNamespace + "#form"; + static string PARENT_FOLDER_REL = DocumentsService.DocumentsNamespace + "#parent"; + + static string STARRED_KIND = BaseNameTable.gLabels + "#starred"; + static string TRASHED_KIND = BaseNameTable.gLabels + "#trashed"; + static string HIDDEN_KIND = BaseNameTable.gLabels + "#hidden"; + static string VIEWED_KIND = BaseNameTable.gLabels + "#viewed"; + static string MINE_KIND = BaseNameTable.gLabels + "#mine"; + static string PRIVATE_KIND = BaseNameTable.gLabels + "#private"; + static string SHARED_KIND = BaseNameTable.gLabels + "#shared-with-domain"; + + + /// + /// a predefined atom category for Documents + /// + public static AtomCategory DOCUMENT_CATEGORY = + new AtomCategory(DOCUMENT_KIND, new AtomUri(BaseNameTable.gKind), "document"); + /// + /// a predefined atom category for Spreadsheets + /// + public static AtomCategory SPREADSHEET_CATEGORY = + new AtomCategory(SPREADSHEET_KIND, new AtomUri(BaseNameTable.gKind), "spreadsheet"); + /// + /// a predefined atom category for PDF + /// + public static AtomCategory PDF_CATEGORY = + new AtomCategory(PDF_KIND, new AtomUri(BaseNameTable.gKind), "pdf"); + /// + /// a predefined atom category for starred documentss + /// + /// + /// a predefined atom category for Presentations + /// + public static AtomCategory PRESENTATION_CATEGORY = + new AtomCategory(PRESENTATION_KIND, new AtomUri(BaseNameTable.gKind), "presentation"); + /// + /// a predefined atom category for folders + /// + public static AtomCategory FOLDER_CATEGORY = + new AtomCategory(FOLDER_KIND, new AtomUri(BaseNameTable.gKind), "folder"); + /// + /// a predefined atom category for forms + /// + public static AtomCategory FORM_CATEGORY = + new AtomCategory(FORM_KIND, new AtomUri(BaseNameTable.gKind), "form"); + + /// + /// a predefined atom category for starred documents + /// + public static AtomCategory STARRED_CATEGORY = + new AtomCategory(STARRED_KIND, new AtomUri(BaseNameTable.gLabels), "starred"); + /// + /// a predefined atom category for trashed documents + /// + public static AtomCategory TRASHED_CATEGORY = + new AtomCategory(TRASHED_KIND, new AtomUri(BaseNameTable.gLabels), "trashed"); + /// + /// a predefined atom category for hidden documents + /// + public static AtomCategory HIDDEN_CATEGORY = + new AtomCategory(HIDDEN_KIND, new AtomUri(BaseNameTable.gLabels), "hidden"); + /// + /// a predefined atom category for VIEWED documents + /// + public static AtomCategory VIEWED_CATEGORY = + new AtomCategory(VIEWED_KIND, new AtomUri(BaseNameTable.gLabels), "viewed"); + /// + /// a predefined atom category for owned by user documents + /// + public static AtomCategory MINE_CATEGORY = + new AtomCategory(MINE_KIND, new AtomUri(BaseNameTable.gLabels), "mine"); + /// + /// a predefined atom category for private documents + /// + public static AtomCategory PRIVATE_CATEGORY = + new AtomCategory(PRIVATE_KIND, new AtomUri(BaseNameTable.gLabels), "private"); + /// + /// a predefined atom category for shared documents + /// + public static AtomCategory SHARED_CATEGORY = + new AtomCategory(SHARED_KIND, new AtomUri(BaseNameTable.gLabels), "shared-with-domain"); + + + + + + + + /// + /// Constructs a new EventEntry instance with the appropriate category + /// to indicate that it is an event. + /// + public DocumentEntry() + : base() + { + this.ProtocolMajor = VersionDefaults.VersionThree; + + Tracing.TraceMsg("Created DocumentEntry"); + this.AddExtension(new FeedLink()); + this.AddExtension(new ResourceId()); + this.AddExtension(new WritersCanInvite()); + this.AddExtension(new LastViewed()); + this.AddExtension(new LastModifiedBy()); + this.AddExtension(new QuotaBytesUsed()); + } + + /// + /// add the documentslist NS + /// + /// The XmlWrite, where we want to add default namespaces to + protected override void AddOtherNamespaces(XmlWriter writer) + { + base.AddOtherNamespaces(writer); + if (writer == null) + { + throw new ArgumentNullException("writer"); + } + string strPrefix = writer.LookupPrefix(DocumentslistNametable.NSDocumentslist); + if (strPrefix == null) + { + writer.WriteAttributeString("xmlns", DocumentslistNametable.Prefix, null, DocumentslistNametable.NSDocumentslist); + } + } + + /// + /// Checks if this is a namespace declaration that we already added + /// + /// XmlNode to check + /// True if this node should be skipped + protected override bool SkipNode(XmlNode node) + { + if (base.SkipNode(node)) + { + return true; + } + + return (node.NodeType == XmlNodeType.Attribute + && node.Name.StartsWith("xmlns") + && String.Compare(node.Value, DocumentslistNametable.NSDocumentslist) == 0); + } + + /// + /// Reflects if this entry is a word processor document + /// + public bool IsDocument + { + get + { + return this.Categories.Contains(DocumentEntry.DOCUMENT_CATEGORY); + } + set + { + this.ToggleCategory(DocumentEntry.DOCUMENT_CATEGORY, value); + } + } + + /// + /// Reflects if this entry is a spreadsheet document + /// + public bool IsSpreadsheet + { + get + { + return this.Categories.Contains(DocumentEntry.SPREADSHEET_CATEGORY); + } + set + { + this.ToggleCategory(DocumentEntry.SPREADSHEET_CATEGORY, value); + } + } + + /// + /// Reflects if this entry is a presentation document + /// + public bool IsPresentation + { + get + { + return this.Categories.Contains(DocumentEntry.PRESENTATION_CATEGORY); + } + set + { + this.ToggleCategory(DocumentEntry.PRESENTATION_CATEGORY, value); + } + } + + /// + /// Reflects if this entry is a form + /// + public bool IsForm + { + get + { + return this.Categories.Contains(DocumentEntry.FORM_CATEGORY); + } + set + { + this.ToggleCategory(DocumentEntry.FORM_CATEGORY, value); + } + } + + /// + /// Reflects if this entry is a PDF document + /// + public bool IsPDF + { + get + { + return this.Categories.Contains(DocumentEntry.PDF_CATEGORY); + } + set + { + this.ToggleCategory(DocumentEntry.PDF_CATEGORY, value); + } + } + + /// + /// Reflects if this entry is starred + /// + public bool IsStarred + { + get + { + return this.Categories.Contains(DocumentEntry.STARRED_CATEGORY); + } + set + { + this.ToggleCategory(DocumentEntry.STARRED_CATEGORY, value); + } + } + + /// + /// returns true if this is a folder + /// + public bool IsFolder + { + get + { + return this.Categories.Contains(DocumentEntry.FOLDER_CATEGORY); + } + set + { + this.ToggleCategory(DocumentEntry.FOLDER_CATEGORY, value); + } + } + + /// + /// returns the string that should represent the Uri to the access control list + /// + /// the value of the hret attribute for the acl feedlink, or null if not found + public string AccessControlList + { + get + { + List list = FindExtensions(GDataParserNameTable.XmlFeedLinkElement, + BaseNameTable.gNamespace); + + foreach (FeedLink fl in list) + { + if (fl.Rel == AclNameTable.LINK_REL_ACCESS_CONTROL_LIST) + { + return fl.Href; + } + } + return null; + } + } + + + /// + /// returns the string that should represent the Uri to the revision document + /// + /// the value of the hret attribute for the revisons feedlink, or null if not found + public string RevisionDocument + { + get + { + List list = FindExtensions(GDataParserNameTable.XmlFeedLinkElement, + BaseNameTable.gNamespace); + + foreach (FeedLink fl in list) + { + if (fl.Rel == DocumentsService.Revisions) + { + return fl.Href; + } + } + return null; + } + } + + /// + /// returns the href value of the parent link releationship + /// + /// + public List ParentFolders + { + get + { + List links = this.Links.FindServiceList(PARENT_FOLDER_REL, AtomLink.ATOM_TYPE); + return links; + } + } + + /// + /// Documents resource Identifier. + /// + /// + public string ResourceId + { + get + { + return GetStringValue(GDataParserNameTable.XmlResourceIdElement, + GDataParserNameTable.gNamespace); + } + } + + /// + /// Identifies if a collaborator can modify the ACLs of the document + /// + /// + public bool WritersCanInvite + { + get + { + String v = GetStringValue(DocumentslistNametable.WritersCanInvite, + DocumentslistNametable.NSDocumentslist); + // v can either be 1/0 or true/false + bool ret = Utilities.XSDTrue == v; + + if (ret == false) + { + ret = "0" == v; + } + return ret; + } + set + { + String v = value == true ? Utilities.XSDTrue : Utilities.XSDFalse; + SetStringValue(v, + DocumentslistNametable.WritersCanInvite, + DocumentslistNametable.NSDocumentslist); + } + } + + /// + /// Returns the last viewed timestamp + /// + /// + public DateTime LastViewed + { + get + { + LastViewed e = FindExtension(GDataParserNameTable.XmlLastViewedElement, GDataParserNameTable.gNamespace) as LastViewed; + if (e!= null && e.Value != null) + { + return DateTime.Parse(e.Value, CultureInfo.InvariantCulture); + } + return DateTime.MinValue; + } + } + + /// + /// returns the last modififiedBy Element + /// + /// + public LastModifiedBy LastModified + { + get + { + return FindExtension(GDataParserNameTable.XmlLastModifiedByElement, GDataParserNameTable.gNamespace) as LastModifiedBy; + } + } + + /// + /// returns the last quotabytesused Element + /// + /// + public QuotaBytesUsed QuotaUsed + { + get + { + return FindExtension(GDataParserNameTable.XmlQuotaBytesUsedElement, GDataParserNameTable.gNamespace) as QuotaBytesUsed; + } + } + + } + + /// + /// Determines if a collaborator can modify a documents ACL + /// + public class WritersCanInvite : SimpleAttribute + { + /// + /// default constructor for gd:resourceid + /// + public WritersCanInvite() + : base(DocumentslistNametable.WritersCanInvite, + DocumentslistNametable.Prefix, + DocumentslistNametable.NSDocumentslist) + { + } + } +} + diff -Nru gdata-sharp-1.4.0.2/src/documents3/documentfeed.cs gdata-sharp-1.7.0.1/src/documents3/documentfeed.cs --- gdata-sharp-1.4.0.2/src/documents3/documentfeed.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/documents3/documentfeed.cs 2009-10-21 14:06:48.000000000 +0000 @@ -0,0 +1,72 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +using System; +using System.Collections; +using System.Text; +using System.Xml; +using Google.GData.Client; +using Google.GData.Extensions; + +namespace Google.GData.Documents { + + + ////////////////////////////////////////////////////////////////////// + /// + /// Google Documents List feed URI takes the following form: + /// http://docs.google.com/feeds/documents/visibility/projection + /// The visibility parameter has two possible values: private and public. + /// In almost all cases, your client should use private. + /// The projection parameter indicates what information is included in the representation. + /// For example, if your client specifies a projection of basic, it's requesting an Atom feed + /// without any GData extension elements. + /// Currently, in the Documents List feed, only the private/full combination + /// for visibility and projection is available. + /// + ////////////////////////////////////////////////////////////////////// + public class DocumentsFeed : AbstractFeed + { + + /// + /// default constructor + /// + /// the base URI of the feedEntry + /// the Service to use + public DocumentsFeed(Uri uriBase, IService iService) : base(uriBase, iService) + { + // todo: add extension elements as appropriate + } + + /// + /// this needs to get implemented by subclasses + /// + /// AtomEntry + public override AtomEntry CreateFeedEntry() + { + return new DocumentEntry(); + } + + /// + /// get's called after we already handled the custom entry, to handle all + /// other potential parsing tasks + /// + /// + /// the atom feed parser used + protected override void HandleExtensionElements(ExtensionElementEventArgs e, AtomFeedParser parser) + { + base.HandleExtensionElements(e, parser); + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/documents3/documentquery.cs gdata-sharp-1.7.0.1/src/documents3/documentquery.cs --- gdata-sharp-1.4.0.2/src/documents3/documentquery.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/documents3/documentquery.cs 2009-12-08 13:15:18.000000000 +0000 @@ -0,0 +1,603 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +using System; +using System.Xml; +using System.Text; +using System.Globalization; +using System.Diagnostics; +using Google.GData.Client; + +namespace Google.GData.Documents { + + ////////////////////////////////////////////////////////////////////// + /// + /// A subclass of FeedQuery, to create an Documents query URI. + /// Provides public properties that describe the different + /// aspects of the URI, as well as a composite URI. + /// + /// Documents List supports the following standard GData query parameters: + /// alt, author, q, start-index, max-results, updated-min, updated-max, /category + /// For more information about the standard parameters, see the GData protocol reference document. + /// In addition to the standard GData query parameters, the Documents List data API uses the following parameters. + /// Parameter Meaning + /// title Specifies the search terms for the title of a document. + /// This parameter used without title-exact will only submit partial queries, not exact queries. + /// + /// title-exact Specifies whether the title query should be taken as an exact string. + /// Meaningless without title. Possible values are true and false. + /// + /// The Documents List data API supports the following categories. + /// Category: Document Type + /// Scheme: http://schemas.google.com/g/2005#kind + /// Term: http://schemas.google.com/docs/2007#type + /// Label: type + /// All documents of the corresponding type in the requesting users document list. + /// Type is currently one of (document|spreadsheet|presentation) + /// Category: Starred Status + /// Scheme: http://schemas.google.com/g/2005/labels + /// Term: starred + /// Label: starred + /// All documents that have been starred by the requesting user + /// Category: Containing Folders + /// Scheme: http://schemas.google.com/docs/2007/folders/user-email + /// Term: folder-id + /// Label: folder-name + /// All documents inside the given folder for the requesting user + /// + ////////////////////////////////////////////////////////////////////// + public class DocumentsListQuery : FeedQuery + { + + + /// + /// document feed base URI + /// + public static string documentsBaseUri = "http://docs.google.com/feeds/default/private/full"; + + + /// + /// document feed base URI with ACLs + /// + public static string documentsAclUri = "http://docs.google.com/feeds/default/private/expandAcl"; + + /// + /// template to construct a folder URI for a folder ID + /// + public static string foldersUriTemplate = "http://docs.google.com/feeds/default/private/full/{0}/contents"; + + /// + /// template to get the ACLs for a resourceID + /// + public static string aclsUriTemplate = "http://docs.google.com/feeds/default/private/full/{0}/acl"; + + /// + /// template to get the media for a resourceID + /// + public static string mediaUriTemplate = "http://docs.google.com/feeds/default/media/{0}"; + + /// + /// uri to get you all folders + /// + public static string allFoldersUri = "http://docs.google.com/feeds/default/private/full/-/folder"; + + /// + /// template to get a revisison for a given resourceID and revisionID + /// + public static string revisionsUriTemplate = "http://docs.google.com/feeds/default/private/full/{0}/revisions/{1}"; + + + /// + /// predefined query category for documents + /// + public static QueryCategory DOCUMENTS = new QueryCategory(new AtomCategory("document")); + + /// + /// predefined query category for spreadsheets + /// + public static QueryCategory SPREADSHEETS = new QueryCategory(new AtomCategory("spreadsheet")); + + /// + /// predefined query category for presentations + /// + public static QueryCategory PRESENTATIONS = new QueryCategory(new AtomCategory("presentation")); + + /// + /// predefined query category for PDFS + /// + public static QueryCategory PDFS = new QueryCategory(new AtomCategory("pdf")); + + /// + /// predefined query category for Forms + /// + public static QueryCategory FORMS = new QueryCategory(new AtomCategory("form")); + + + /// + /// predefined query category for starred documents + /// + public static QueryCategory STARRED = new QueryCategory(new AtomCategory("starred")); + /// + /// predefined query category for starred documents + /// + public static QueryCategory VIEWED = new QueryCategory(new AtomCategory("viewed")); + /// + /// predefined query category for hidden documents + /// + public static QueryCategory HIDDEN = new QueryCategory(new AtomCategory("hidden")); + /// + /// predefined query category for trashed documents + /// + public static QueryCategory TRASHED = new QueryCategory(new AtomCategory("trashed")); + /// + /// predefined query category for user owned documents + /// + public static QueryCategory MINE = new QueryCategory(new AtomCategory("mine")); + /// + /// predefined query category for private documents + /// + public static QueryCategory PRIVATE = new QueryCategory(new AtomCategory("private")); + /// + /// predefined query category for shared documents + /// + public static QueryCategory SHARED = new QueryCategory(new AtomCategory("shared-with-domain")); + + + //Local variable to hold the contents of a title query + private string title; + //Local variable to hold if the title query we are doing should be exact. + private bool titleExact; + + private string owner; + private string writer; + private string reader; + private string targetLanguage; + private string sourceLanguage; + private bool showFolders = false; + private bool showDeleted = false; + private bool ocr = false; + private DateTime editedMin; + private DateTime editedMax; + + + + + /// + /// base constructor + /// + public DocumentsListQuery() + : base(documentsBaseUri) + { + this.CategoryQueriesAsParameter = true; + } + + /// + /// base constructor, with initial queryUri + /// + /// the query to use + public DocumentsListQuery(string queryUri) + : base(queryUri) + { + this.CategoryQueriesAsParameter = true; + } + + + ////////////////////////////////////////////////////////////////////// + /// Doclist does not support index based paging + ////////////////////////////////////////////////////////////////////// + [Obsolete("Index based paging is not supported on DocumentsList")] + public override int StartIndex + { + get { return 0; } + set { } + } + ///////////////////////////////////////////////////////////////////////////// + + + /// + /// Restricts the results to only starred documents + /// + [CLSCompliant(false)] + public bool Starred + { + get + { + return this.Categories.Contains(DocumentsListQuery.STARRED); + } + set + { + if (value) + { + this.Categories.Add(DocumentsListQuery.STARRED); + } + else + { + this.Categories.Remove(DocumentsListQuery.STARRED); + } + } + } + + /// + /// shows folders if true in the result + /// + [CLSCompliant(false)] + public bool ShowFolders + { + get + { + return this.showFolders; + } + set + { + this.showFolders = value; + } + } + + /// + /// Restricts the results to only documents with titles matching a string. + /// + public string Title + { + get + { + return this.title; + } + set + { + this.title = value; + } + } + + /// + /// Restricts the results to only documents matching a string provided + /// by the Title property exactly. (No partial matches.) + /// + public bool TitleExact + { + get + { + return this.titleExact; + } + set + { + this.titleExact = value; + } + } + + /// + /// Searches for documents with a specific owner. Use the email address of the owner + /// + public string Owner + { + get + { + return this.owner; + } + set + { + this.owner = value; + } + } + /// + /// Searches for documents which can be written to by specific users. + /// Use a single email address or a comma separated list of email addresses. + /// + public string Writer + { + get + { + return this.writer; + } + set + { + this.writer = value; + } + } + + /// + /// Searches for documents which can be read by specific users. + /// Use a single email address or a comma separated list of email addresses. + /// + public string Reader + { + get + { + return this.reader; + } + set + { + this.reader = value; + } + } + + /// + /// Specifies whether to attempt OCR on a .jpg, .png, of .gif upload. + /// + public bool Ocr + { + get + { + return this.ocr; + } + set + { + this.ocr = value; + } + } + + /// + /// Specifies whether the query should return documents which are in the trash as well as other documents. + /// + public bool ShowDeleted + { + get + { + return this.showDeleted; + } + set + { + this.showDeleted = value; + } + } + /// + /// Specifies the language to translate a document into. + /// + public string TargetLanguage + { + get + { + return this.targetLanguage; + } + set + { + this.targetLanguage = value; + } + } + + /// + /// Specifies the source langugate to translate a document from. + /// + public string SourceLanguage + { + get + { + return this.sourceLanguage; + } + set + { + this.sourceLanguage = value; + } + } + + ////////////////////////////////////////////////////////////////////// + /// + /// Lower bound on the last time a document was edited by the current user. + /// + ////////////////////////////////////////////////////////////////////// + public DateTime EditedMin + { + get { return this.editedMin; } + set { this.editedMin = value; } + } + ///////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////// + /// Upper bound on the last time a document was edited by the current user. + ////////////////////////////////////////////////////////////////////// + public DateTime EditedMax + { + get { return this.editedMax; } + set { this.editedMax = value; } + } + ///////////////////////////////////////////////////////////////////////////// + + + + +#if WindowsCE || PocketPC +#else + ////////////////////////////////////////////////////////////////////// + /// Parses custom properties out of the incoming URI + /// A URI representing a query on a feed + /// returns the base uri + ////////////////////////////////////////////////////////////////////// + protected override Uri ParseUri(Uri targetUri) + { + base.ParseUri(targetUri); + if (targetUri != null) + { + char[] deli = { '?', '&' }; + + TokenCollection tokens = new TokenCollection(targetUri.Query, deli); + foreach (String token in tokens) + { + if (token.Length > 0) + { + char[] otherDeli = { '=' }; + String[] parameters = token.Split(otherDeli, 2); + switch (parameters[0]) + { + case "title-exact": + this.TitleExact = bool.Parse(parameters[1]); + break; + case "title": + this.Title = parameters[1]; + break; + case "owner": + this.Owner = parameters[1]; + break; + case "reader": + this.Reader = parameters[1]; + break; + case "writer": + this.Writer = parameters[1]; + break; + case "targetLanguage": + this.TargetLanguage = parameters[1]; + break; + case "sourceLanguage": + this.SourceLanguage = parameters[1]; + break; + case "showfolders": + this.ShowFolders = bool.Parse(parameters[1]); + break; + case "ocr": + this.Ocr = bool.Parse(parameters[1]); + break; + case "showDeleted": + this.ShowDeleted = bool.Parse(parameters[1]); + break; + case "edited-min": + this.EditedMin = DateTime.Parse(Utilities.UrlDecodedValue(parameters[1]), CultureInfo.InvariantCulture); + break; + case "edited-max": + this.EditedMax = DateTime.Parse(Utilities.UrlDecodedValue(parameters[1]), CultureInfo.InvariantCulture); + break; + + } + } + } + } + return this.Uri; + } +#endif + ////////////////////////////////////////////////////////////////////// + /// Creates the partial URI query string based on all + /// set properties. + /// A string representing the query part of the URI. + ////////////////////////////////////////////////////////////////////// + protected override string CalculateQuery(string basePath) + { + string path = base.CalculateQuery(basePath); + StringBuilder newPath = new StringBuilder(path, 2048); + char paramInsertion = InsertionParameter(path); + + paramInsertion = AppendQueryPart(this.Title, "title", paramInsertion, newPath); + + if (this.TitleExact == true) + { + paramInsertion = AppendQueryPart("true", "title-exact", paramInsertion, newPath); + } + if (this.ShowFolders == true) + { + paramInsertion = AppendQueryPart("true", "showfolders", paramInsertion, newPath); + } + if (this.Ocr == true) + { + paramInsertion = AppendQueryPart("true", "ocr", paramInsertion, newPath); + } + if (this.ShowDeleted == true) + { + paramInsertion = AppendQueryPart("true", "showDeleted", paramInsertion, newPath); + } + + paramInsertion = AppendQueryPart(this.Owner, "owner", paramInsertion, newPath); + paramInsertion = AppendQueryPart(this.Writer, "writer", paramInsertion, newPath); + paramInsertion = AppendQueryPart(this.Reader, "reader", paramInsertion, newPath); + paramInsertion = AppendQueryPart(this.EditedMin, "edited-min", paramInsertion, newPath); + paramInsertion = AppendQueryPart(this.EditedMax, "edited-max", paramInsertion, newPath); + paramInsertion = AppendQueryPart(this.TargetLanguage, "targetLanguage", paramInsertion, newPath); + paramInsertion = AppendQueryPart(this.SourceLanguage, "sourceLanguage", paramInsertion, newPath); + + return newPath.ToString(); + } + } + + + + /// + /// a subclass setup to just retrieve all word processor documents + /// + public class TextDocumentQuery : DocumentsListQuery + { + + /// + /// base constructor + /// + public TextDocumentQuery() + : base() + { + this.Categories.Add(DocumentsListQuery.DOCUMENTS); + } + } + + + /// + /// a subclass setup to just retrieve all spreadsheets + /// + public class SpreadsheetQuery : DocumentsListQuery + { + + /// + /// base constructor + /// + public SpreadsheetQuery() + : base() + { + this.Categories.Add(DocumentsListQuery.SPREADSHEETS); + } + } + + /// + /// a subclass setup to just retrieve all presentations + /// + public class PresentationsQuery : DocumentsListQuery + { + + /// + /// base constructor + /// + public PresentationsQuery() + : base() + { + this.Categories.Add(DocumentsListQuery.PRESENTATIONS); + } + } + + /// + /// a subclass setup to just retrieve all PDFs + /// + public class PDFsQuery : DocumentsListQuery + { + + /// + /// base constructor + /// + public PDFsQuery() + : base() + { + this.Categories.Add(DocumentsListQuery.PDFS); + } + } + + + /// + /// a subclass setup to just retrieve all Folders + /// + public class FolderQuery : DocumentsListQuery + { + + /// + /// base constructor + /// + public FolderQuery(string folderId) + : base() + { + this.baseUri = String.Format(DocumentsListQuery.foldersUriTemplate, folderId); + this.ShowFolders = true; + } + } + +} diff -Nru gdata-sharp-1.4.0.2/src/documents3/Documents3.csproj gdata-sharp-1.7.0.1/src/documents3/Documents3.csproj --- gdata-sharp-1.4.0.2/src/documents3/Documents3.csproj 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/documents3/Documents3.csproj 2009-10-21 14:06:48.000000000 +0000 @@ -0,0 +1,143 @@ + + + Local + 2.0 + {4E97E7C2-D30C-48ED-9C3D-FFA2127099AA} + Debug + AnyCPU + + + + + Google.GData.Documents + documents.sn + JScript + Grid + IE50 + false + Library + Google.GData.Documents + OnBuildSuccess + + + + + + + true + 2.0 + + + bin\Debug\ + false + 285212672 + false + + + DEBUG;TRACE + + + true + 4096 + false + + + false + false + false + false + 4 + full + prompt + + + bin\Release\ + false + 285212672 + false + + + TRACE + bin\gdocuments.xml + false + 4096 + false + + + true + false + false + false + 4 + none + prompt + + + bin\asp\ + false + 285212672 + false + + + PARTIALLY_TRUSTED + + + false + 4096 + false + + + true + false + false + false + 4 + none + prompt + + + + System + + + System.Data + + + System.XML + + + {B6F6D938-0D45-42BA-8A67-55D92EF03995} + Core Client + + + Common Data Extensions + {21BCB644-F9C3-4ADC-8BE1-4E55C6565011} + {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + {279D35CE-871A-4C76-B823-A73675EDF191} + Access Control + + + + + + + + AssemblyVersion.cs + + + + + + + + + + + + + + + + \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/src/documents3/documentservice.cs gdata-sharp-1.7.0.1/src/documents3/documentservice.cs --- gdata-sharp-1.4.0.2/src/documents3/documentservice.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/documents3/documentservice.cs 2010-02-15 11:26:47.000000000 +0000 @@ -0,0 +1,238 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + + +using System; +using System.IO; +using System.Collections; +using System.Text; +using System.Net; +using Google.GData.Client; +using Google.GData.Extensions; +using Google.GData.AccessControl; + + + +namespace Google.GData.Documents { + + ////////////////////////////////////////////////////////////////////// + /// + /// The Google Documents List data API allows client applications to upload + /// documents to Google Documents and list them in the form of Google data + /// API ("GData") feeds. Your client application can request a list of a user's + /// documents, and query the content in an existing document. + /// Here are some of the things you can do with the Documents List data API: + /// Upload the word processing documents and spreadsheets on + /// your computer to allow you to back them up or + /// collaborate online when editing. + /// Find all of your documents that contain specific keywords. + /// Get a list of spreadsheets which can be accessed through the Google Spreadsheets data API. + /// + ////////////////////////////////////////////////////////////////////// + public class DocumentsService : Service + { + + /// + /// the documents namespace + /// + public const string DocumentsNamespace = "http://schemas.google.com/docs/2007"; + + /// + /// revisions prefix + /// + public const string Revisions = DocumentsNamespace + "/revisions"; + + /// + /// A Hashtable that expresses the allowed content types. + /// + public static Hashtable DocumentTypes; + + /// + /// Static constructor used to initialize GDocumentsAllowedTypes. + /// + static DocumentsService() + { + DocumentTypes = new Hashtable(); + DocumentTypes.Add("CSV", "text/csv"); + DocumentTypes.Add("TAB", "text/tab-separated-values"); + DocumentTypes.Add("TSV", "text/tab-separated-values"); + DocumentTypes.Add("TXT", "text/plain"); + DocumentTypes.Add("HTML", "text/html"); + DocumentTypes.Add("HTM", "text/html"); + DocumentTypes.Add("DOC", "application/msword"); + DocumentTypes.Add("DOCX", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"); + DocumentTypes.Add("ODS", "application/x-vnd.oasis.opendocument.spreadsheet"); + DocumentTypes.Add("ODT", "application/vnd.oasis.opendocument.text"); + DocumentTypes.Add("RTF", "application/rtf"); + DocumentTypes.Add("SXW", "application/vnd.sun.xml.writer"); + DocumentTypes.Add("XLSX", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + DocumentTypes.Add("XLS", "application/vnd.ms-excel"); + DocumentTypes.Add("PPT", "application/vnd.ms-powerpoint"); + DocumentTypes.Add("PPS", "application/vnd.ms-powerpoint"); + DocumentTypes.Add("PDF", "application/pdf"); + } + + /// + /// default constructor + /// + /// the applicationname + public DocumentsService(string applicationName) : base(ServiceNames.Documents, applicationName) + { + this.NewFeed += new ServiceEventHandler(this.OnNewFeed); + } + + /// + /// overloaded to create typed version of Query + /// + /// + /// EventFeed + public DocumentsFeed Query(DocumentsListQuery feedQuery) + { + return base.Query(feedQuery) as DocumentsFeed; + } + + + /// + /// Simple method to upload a document, presentation, or spreadsheet + /// based upon the file extension. + /// + /// The full path to the file. + /// The desired name of the document on the server. + /// A DocumentEntry describing the created document. + public DocumentEntry UploadDocument(string fileName, string documentName) + { + FileInfo fileInfo = new FileInfo(fileName); + //convert the extension to caps and strip the "." off the front + string ext = fileInfo.Extension.ToUpper().Substring(1); + + String contentType = (String)DocumentTypes[ext]; + if (contentType == null) + { + throw new ArgumentException("File extension '" + ext + "' could not be matched to a contentType automatically."); + } + + return this.UploadDocument(fileName, documentName, contentType); + } + + /// + /// Simple method to upload a document, presentation, or spreadsheet + /// + /// The full path to the file. + /// The desired name of the document on the server. + /// The mime type of the document + /// A DocumentEntry describing the created document. + public DocumentEntry UploadDocument(string fileName, string documentName, string contentType) + { + return UploadFile(fileName, documentName, contentType, true); + } + + /// + /// Simple method to upload an arbitrary file. + /// + /// The full path to the file. + /// The desired name of the file on the server. + /// The mime type of the file + /// Indiates if the document should be converted to a known type on the server + /// A DocumentEntry describing the created document. + public DocumentEntry UploadFile(string fileName, string documentName, string contentType, bool convert) + { + DocumentEntry entry = null; + + FileInfo fileInfo = new FileInfo(fileName); + FileStream stream = fileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + + try + { + Uri postUri; + + if (convert == false) + { + postUri = new Uri(DocumentsListQuery.documentsBaseUri + "?convert=false"); + } + else + { + postUri = new Uri(DocumentsListQuery.documentsBaseUri); + } + + + if (documentName == null) + { + documentName = fileInfo.Name; + } + + if (contentType == null) + { + throw new ArgumentException("You need to specify a content type, like text/html"); + } + + entry = this.Insert(postUri, stream, contentType, documentName) as DocumentEntry; + } + finally + { + stream.Close(); + } + + return entry; + } + + + /// + /// by default all services now use version 1 for the protocol. + /// this needs to be overridden by a service to specify otherwise. + /// Documents uses Version 3 + /// + /// + protected override void InitVersionInformation() + { + this.ProtocolMajor = VersionDefaults.VersionThree; + } + + /// + /// overloaded to create typed version of Query + /// + /// + /// EventFeed + public AclFeed Query(AclQuery feedQuery) + { + return base.Query(feedQuery) as AclFeed; + } + + + + + ////////////////////////////////////////////////////////////////////// + /// eventchaining. We catch this by from the base service, which + /// would not by default create an atomFeed + /// the object which send the event + /// FeedParserEventArguments, holds the feedentry + /// + ////////////////////////////////////////////////////////////////////// + protected void OnNewFeed(object sender, ServiceEventArgs e) + { + Tracing.TraceMsg("Created new Documents Feed"); + if (e == null) + { + throw new ArgumentNullException("e"); + } + if (e.Uri.AbsoluteUri.IndexOf("/acl") != -1) + { + e.Feed = new AclFeed(e.Uri, e.Service); + } + else + e.Feed = new DocumentsFeed(e.Uri, e.Service); + } + ///////////////////////////////////////////////////////////////////////////// + } +} Binary files /tmp/UhUzKTrMiD/gdata-sharp-1.4.0.2/src/documents3/documents.sn and /tmp/kt1AG0Pm9_/gdata-sharp-1.7.0.1/src/documents3/documents.sn differ diff -Nru gdata-sharp-1.4.0.2/src/extensions/apps.cs gdata-sharp-1.7.0.1/src/extensions/apps.cs --- gdata-sharp-1.4.0.2/src/extensions/apps.cs 2009-02-13 14:12:59.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/extensions/apps.cs 2010-11-02 15:10:58.000000000 +0000 @@ -302,6 +302,77 @@ } /// + /// Name table for Google Apps extensions specific to the Google Domain Settings API. + /// + public class AppsDomainSettingsNameTable : AppsNameTable + { + public const string AppsAdminSettingsBaseFeedUri = "https://apps-apis.google.com/a/feeds/domain/2.0/"; + /// + /// URL suffixes for the Google Domain Settings tasks + /// + // General Settings + public const string DefaultLanguageUriSuffix = "/general/defaultLanguage"; + public const string OrganizationNameUriSuffix = "/general/organizationName"; + public const string MaximumNumberOfUsersUriSuffix = "/general/maximumNumberOfUsers"; + public const string CurrentNumberOfUsersUriSuffix = "/general/currentNumberOfUsers"; + // Account Information Settings + public const string IsVerifiedUriSuffix = "/accountInformation/isVerified"; + public const string SupportPINUriSuffix = "/accountInformation/supportPIN"; + public const string EditionUriSuffix = "/accountInformation/edition"; + public const string CustomerPINUriSuffix = "/accountInformation/customerPIN"; + public const string CreationTimeUriSuffix = "/accountInformation/creationTime"; + public const string CountryCodeUriSuffix = "/accountInformation/countryCode"; + public const string AdminSecondaryEmailUriSuffix = "/accountInformation/adminSecondaryEmail"; + // Appearance Settings + public const string CustomLogoUriSuffix = "/appearance/customLogo"; + // Verification Settings + public const string CnameUriSuffix = "/verification/cname"; + public const string MxUriSuffix = "/verification/mx"; + // SSO Settings + public const string SsoGeneralUriSuffix = "/sso/general"; + public const string SsoSigningkeyUriSuffix = "/sso/signingkey"; + // Email Settings + public const string MigrationUriSuffix = "/email/migration"; + public const string GatewayUriSuffix = "/email/gateway"; + public const string EmailroutingUriSuffix = "/emailrouting"; + // Properties + public const string DefaultLanguage = "defaultLanguage"; + public const string OrganizationName = "organizationName"; + public const string MaximumNumberOfUsers = "maximumNumberOfUsers"; + public const string CurrentNumberOfUsers = "currentNumberOfUsers"; + public const string IsVerified = "isVerified"; + public const string SupportPIN = "supportPIN"; + public const string Edition = "edition"; + public const string CustomerPIN = "customerPIN"; + public const string CreationTime = "creationTime"; + public const string CountryCode = "countryCode"; + public const string AdminSecondaryEmail = "adminSecondaryEmail"; + public const string LogoImage = "logoImage"; + public const string RecordName = "recordName"; + public const string Verified = "verified"; + public const string VerifiedMethod = "verifiedMethod"; + public const string SamlSignonUri = "samlSignonUri"; + public const string SamlLogoutUri = "samlLogoutUri"; + public const string ChangePasswordUri = "changePasswordUri"; + public const string EnableSSO = "enableSSO"; + public const string SsoWhitelist = "ssoWhitelist"; + public const string UseDomainSpecificIssuer = "useDomainSpecificIssuer"; + public const string SigningKey = "signingKey"; + public const string EnableUserMigration = "enableUserMigration"; + public const string SmartHost = "smartHost"; + public const string SmtpMode = "smtpMode"; + public const string RouteDestination = "routeDestination"; + public const string RouteRewriteTo = "routeRewriteTo"; + public const string RouteEnabled = "routeEnabled"; + public const string BounceNotifications = "bounceNotifications"; + public const string AccountHandling = "accountHandling"; + // AccountHandling possible values + public const string AllAccounts = "allAccounts"; + public const string ProvisionedAccounts = "allAccounts"; + public const string UnknownAccounts = "unknownAccounts"; + } + + /// /// Name table for Google Apps extensions specific to the Groups Provisioning /// public class AppsGroupsNameTable : AppsNameTable @@ -320,6 +391,42 @@ } /// + /// Name table for Google Apps extensions specific to the Organization Units Provisioning + /// + public class AppsOrganizationNameTable : AppsNameTable + { + public const string AppsOrgUnitBaseFeedUri = "https://apps-apis.google.com/a/feeds/orgunit/2.0"; + public const string AppsOrgUserBaseFeedUri = "https://apps-apis.google.com/a/feeds/orguser/2.0"; + public const string AppsCustomerBaseFeedUri = "https://apps-apis.google.com/a/feeds/customer/2.0"; + public const string CustomerId = "customerId"; + public const string Description = "description"; + public const string OrgUnitName = "name"; + public const string BlockInheritance = "blockInheritance"; + public const string UsersToMove = "usersToMove"; + public const string OldOrgUnitPath = "oldOrgUnitPath"; + public const string NewOrgUnitPath = "orgUnitPath"; + public const string ParentOrgUnitPath = "parentOrgUnitPath"; + } + + /// + /// Name table for Google Apps extensions specific to the Multidomain Provisioning + /// + public class AppsMultiDomainNameTable : AppsNameTable { + public const string AppsMultiDomainAliasBaseFeedUri = "https://apps-apis.google.com/a/feeds/alias/2.0"; + public const string AppsMultiDomainUserBaseFeedUri = "https://apps-apis.google.com/a/feeds/user/2.0"; + public const string AliasEmail = "aliasEmail"; + public const string FirstName = "firstName"; + public const string IpWhitelisted = "ipWhitelisted"; + public const string IsAdmin = "isAdmin"; + public const string IsChangePasswordAtNextLogin = "isChangePasswordAtNextLogin"; + public const string IsSuspended = "isSuspended"; + public const string LastName = "lastName"; + public const string NewEmail = "newEmail"; + public const string Password = "password"; + public const string UserEmail = "userEmail"; + } + + /// /// Extension element sed to model a Google Apps email list. /// Has attribute "name". /// diff -Nru gdata-sharp-1.4.0.2/src/extensions/Common Data Extensions.csproj gdata-sharp-1.7.0.1/src/extensions/Common Data Extensions.csproj --- gdata-sharp-1.4.0.2/src/extensions/Common Data Extensions.csproj 2008-12-12 14:12:01.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/extensions/Common Data Extensions.csproj 2010-12-06 13:36:40.000000000 +0000 @@ -1,7 +1,6 @@ - + Local - 8.0.50727 2.0 {21BCB644-F9C3-4ADC-8BE1-4E55C6565011} Debug @@ -26,6 +25,7 @@ true + 2.0 bin\Debug\ @@ -110,12 +110,6 @@ - - {B6F6D938-0D45-42BA-8A67-55D92EF03995} - Core Client - - - AssemblyVersion.cs @@ -126,7 +120,6 @@ - @@ -138,11 +131,18 @@ + + + + {B6F6D938-0D45-42BA-8A67-55D92EF03995} + Core Client + + diff -Nru gdata-sharp-1.4.0.2/src/extensions/contacts.cs gdata-sharp-1.7.0.1/src/extensions/contacts.cs --- gdata-sharp-1.4.0.2/src/extensions/contacts.cs 2009-02-18 12:04:25.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/extensions/contacts.cs 2009-11-09 11:07:33.000000000 +0000 @@ -26,7 +26,7 @@ /// helper to instantiate all factories defined in here and attach /// them to a base object /// - public class ContactsExtensions + public class ContactsKindExtensions { /// /// helper to add all MediaRss extensions to a base object @@ -35,11 +35,11 @@ public static void AddExtension(AtomBase baseObject) { baseObject.AddExtension(new EMail()); - baseObject.AddExtension(new Deleted()); baseObject.AddExtension(new IMAddress()); baseObject.AddExtension(new Organization()); baseObject.AddExtension(new PhoneNumber()); - baseObject.AddExtension(new PostalAddress()); + baseObject.AddExtension(new Name()); + baseObject.AddExtension(new StructuredPostalAddress()); } } @@ -65,66 +65,173 @@ /// /// indicates a home email in the rel field /// - public const string IsHome = "http://schemas.google.com/g/2005#home"; + public const string IsHome = BaseNameTable.gNamespace + "#home"; /// /// indicates an undefined email in the rel field, label might be used to be /// more precise /// - public const string IsOther = "http://schemas.google.com/g/2005#other"; + public const string IsOther = BaseNameTable.gNamespace + "#other"; /// /// indicates a work email in the rel field /// - public const string IsWork = "http://schemas.google.com/g/2005#work"; + public const string IsWork = BaseNameTable.gNamespace + "#work"; /// /// indicates a general value in the rel field /// - public const string IsGeneral = "http://schemas.google.com/g/2005#general"; + public const string IsGeneral = BaseNameTable.gNamespace + "#general"; /// /// indicates a car related value in the rel field /// - public const string IsCar = "http://schemas.google.com/g/2005#car"; + public const string IsCar = BaseNameTable.gNamespace + "#car"; /// /// indicates a fax value in the rel field /// - public const string IsFax = "http://schemas.google.com/g/2005#fax"; + public const string IsFax = BaseNameTable.gNamespace + "#fax"; /// /// indicates a home fax value in the rel field /// - public const string IsHomeFax = "http://schemas.google.com/g/2005#home_fax"; + public const string IsHomeFax = BaseNameTable.gNamespace + "#home_fax"; /// /// indicates a work fax value in the rel field /// - public const string IsWorkFax = "http://schemas.google.com/g/2005#work_fax"; + public const string IsWorkFax = BaseNameTable.gNamespace + "#work_fax"; /// /// indicates an internal extension value in the rel field /// - public const string IsInternalExtension = "http://schemas.google.com/g/2005#internal-extension"; + public const string IsInternalExtension = BaseNameTable.gNamespace + "#internal-extension"; /// /// indicates a mobile number value in the rel field /// - public const string IsMobile = "http://schemas.google.com/g/2005#mobile"; + public const string IsMobile = BaseNameTable.gNamespace + "#mobile"; /// /// indicates a pager value in the rel field /// - public const string IsPager = "http://schemas.google.com/g/2005#pager"; + public const string IsPager = BaseNameTable.gNamespace + "#pager"; /// /// indicates a satellite value in the rel field /// - public const string IsSatellite = "http://schemas.google.com/g/2005#satellite"; + public const string IsSatellite = BaseNameTable.gNamespace + "#satellite"; /// /// indicates a voip value in the rel field /// - public const string IsVoip = "http://schemas.google.com/g/2005#voip"; + public const string IsVoip = BaseNameTable.gNamespace + "#voip"; + + /// + /// Assistant's number + /// + public const string IsAssistant = BaseNameTable.gNamespace + "#assistant"; + + /// + /// Callback number + /// + public const string IsCallback = BaseNameTable.gNamespace + "#callback"; + + /// + /// CompanyMain + /// + public const string IsCompanyMain = BaseNameTable.gNamespace + "#company_main"; + + /// + /// ISDN number + /// + public const string IsISDN = BaseNameTable.gNamespace + "#isdn"; + + /// + /// Main number + /// + public const string IsMain = BaseNameTable.gNamespace + "#main"; + + /// + /// OtherFax number + /// + public const string IsOtherFax = BaseNameTable.gNamespace + "#other_fax"; + + /// + /// Radio number + /// + public const string IsRadio = BaseNameTable.gNamespace + "#radio"; + + /// + /// Telex number + /// + public const string IsTelex = BaseNameTable.gNamespace + "#telex"; + + /// + /// TTY_TDD number + /// + public const string IsTTY_TDD = BaseNameTable.gNamespace + "#tty_tdd"; + + /// + /// WorkMobile number + /// + public const string IsWorkMobile = BaseNameTable.gNamespace + "#work_mobile"; + + /// + /// WorkPager number + /// + public const string IsWorkPager = BaseNameTable.gNamespace + "#work_pager"; + + /// + /// Netmeeting relationship + /// + public const string IsNetmeeting = BaseNameTable.gNamespace + "#netmeeting"; + } + + /// + /// holds static strings indicating several often used protocol + /// values for the contacts API in the IM element + /// + public static class ContactsProtocols + { + /// + /// AOL Instant Messenger protocol + /// + public const string IsAIM = BaseNameTable.gNamespace + "#AIM"; + + /// + /// MSN protocol + /// + public const string IsMSN = BaseNameTable.gNamespace + "#MSN"; + + /// + /// Yahoo protocol + /// + public const string IsYahoo = BaseNameTable.gNamespace + "#YAHOO"; + + /// + /// Skype protocol + /// + public const string IsSkype = BaseNameTable.gNamespace + "#SKYPE"; + + /// + /// QQ protocol + /// + public const string IsQQ = BaseNameTable.gNamespace + "#QQ"; + + /// + /// GoogleTalk protocol + /// + public const string IsGoogleTalk = BaseNameTable.gNamespace + "#GOOGLE_TALK"; + + /// + /// ICQ protocol + /// + public const string IsICQ = BaseNameTable.gNamespace + "#ICQ"; + + /// + /// Jabber protocol + /// + public const string IsJabber = BaseNameTable.gNamespace + "#JABBER"; } @@ -190,6 +297,7 @@ private void addAttributes() { this.Attributes.Add(GDataParserNameTable.XmlAttributeAddress, null); + this.Attributes.Add(GDataParserNameTable.XmlAttributeDisplayName, null); } @@ -298,13 +406,10 @@ } } - - - - /// - /// a base class used for PostalAddress and others. + /// + /// a base class used for several contacts related classes and others. /// - public class CommonAttributesElement : SimpleElement, ICommonAttributes + public class LinkAttributesElement : SimpleElement, ICommonAttributes { /// @@ -313,7 +418,7 @@ /// /// /// - public CommonAttributesElement(string element, string prefix, string ns) : base(element, prefix, ns) + public LinkAttributesElement(string element, string prefix, string ns) : base(element, prefix, ns) { addAttributes(); } @@ -325,7 +430,7 @@ /// /// /// - public CommonAttributesElement(string element, string prefix, string ns, string init) : base(element, prefix, ns, init) + public LinkAttributesElement(string element, string prefix, string ns, string init) : base(element, prefix, ns, init) { addAttributes(); } @@ -382,20 +487,45 @@ this.Attributes[GDataParserNameTable.XmlAttributeLabel] = value; } } + } + + + + + /// + /// a base class used for PostalAddress and others. + /// + public class CommonAttributesElement : LinkAttributesElement + { + /// + /// default constructore with namesapce init + /// + /// + /// + /// + public CommonAttributesElement(string element, string prefix, string ns) : base(element, prefix, ns) + { + } /// + /// default constructor with namespaces and an init value + /// + /// + /// + /// + /// + public CommonAttributesElement(string element, string prefix, string ns, string init) : base(element, prefix, ns, init) + { + } + /// /// returns if the email is the home email address /// public bool Home { get { - if (this.Rel == ContactsRelationships.IsHome) - { - return true; - } - return false; + return IsType(ContactsRelationships.IsHome); } } @@ -405,11 +535,7 @@ public bool Work { get { - if (this.Rel == ContactsRelationships.IsWork) - { - return true; - } - return false; + return IsType(ContactsRelationships.IsWork); } } @@ -420,19 +546,26 @@ { get { - if (this.Rel == ContactsRelationships.IsOther) - { - return true; - } - return false; + return IsType(ContactsRelationships.IsOther); } } + + /// + /// returns true if the element is of the given relationship type + /// + /// + /// + public bool IsType(string relationShip) + { + return this.Rel == relationShip; + } } /// /// gd:PostalAddress element /// + [Obsolete("Use New Version StructuredPostalAddress")] public class PostalAddress : CommonAttributesElement { /// @@ -511,6 +644,10 @@ { this.ExtensionFactories.Add(new OrgName()); this.ExtensionFactories.Add(new OrgTitle()); + this.ExtensionFactories.Add(new OrgDepartment()); + this.ExtensionFactories.Add(new OrgJobDescription()); + this.ExtensionFactories.Add(new OrgSymbol()); + this.ExtensionFactories.Add(new Where()); this.Attributes.Add(GDataParserNameTable.XmlAttributeLabel, null); this.Attributes.Add(GDataParserNameTable.XmlAttributePrimary, null); this.Attributes.Add(GDataParserNameTable.XmlAttributeRel, null); @@ -560,26 +697,13 @@ { get { - OrgName name = FindExtension(GDataParserNameTable.XmlOrgNameElement, - BaseNameTable.gNamespace) as OrgName; - if (name != null) - { - return name.Value; - } - return null; - } + return GetStringValue(GDataParserNameTable.XmlOrgNameElement, + BaseNameTable.gNamespace); + } set { - OrgName name = null; - - if (String.IsNullOrEmpty(value) == false) - { - name = new OrgName(value); - } - - ReplaceExtension(GDataParserNameTable.XmlOrgNameElement, - BaseNameTable.gNamespace, - name); + SetStringValue(value, GDataParserNameTable.XmlOrgNameElement, + BaseNameTable.gNamespace); } } @@ -591,29 +715,97 @@ { get { - OrgTitle title = FindExtension(GDataParserNameTable.XmlOrgTitleElement, - BaseNameTable.gNamespace) as OrgTitle; - if (title != null) - { - return title.Value; - } - return null; + return GetStringValue(GDataParserNameTable.XmlOrgTitleElement, + BaseNameTable.gNamespace); + } + set + { + SetStringValue(value, GDataParserNameTable.XmlOrgTitleElement, + BaseNameTable.gNamespace); + } + } + + /// + /// Symbol of the organization. + /// + /// + public string Symbol + { + get + { + return GetStringValue(GDataParserNameTable.XmlOrgSymbolElement, + BaseNameTable.gNamespace); + } + set + { + SetStringValue(value, GDataParserNameTable.XmlOrgSymbolElement, + BaseNameTable.gNamespace); + } + } + + /// + /// Department of the organization. + /// + /// + public string Department + { + get + { + return GetStringValue(GDataParserNameTable.XmlOrgDepartmentElement, + BaseNameTable.gNamespace); + } + set + { + SetStringValue(value, GDataParserNameTable.XmlOrgDepartmentElement, + BaseNameTable.gNamespace); } + } + + /// + /// Job Description in the organization. + /// + /// + public string JobDescription + { + get + { + return GetStringValue(GDataParserNameTable.XmlOrgJobDescriptionElement, + BaseNameTable.gNamespace); + } set { - OrgTitle title = null; - - if (String.IsNullOrEmpty(value) == false) + SetStringValue(value, GDataParserNameTable.XmlOrgJobDescriptionElement, + BaseNameTable.gNamespace); + } + } + + + /// + /// Location associated with the organization + /// + /// + public String Location + { + get + { + Where w = FindExtension(GDataParserNameTable.XmlWhereElement, BaseNameTable.gNamespace) as Where; + return w != null ? w.ValueString : null; + } + set + { + Where w = null; + if (value != null) { - title = new OrgTitle(value); + w = new Where(null, null, value); } - - ReplaceExtension(GDataParserNameTable.XmlOrgTitleElement, - BaseNameTable.gNamespace, - title); - + ReplaceExtension(GDataParserNameTable.XmlWhereElement, BaseNameTable.gNamespace, w); } } + + + + + ////////////////////////////////////////////////////////////////////// /// accessor method public string Primary /// @@ -706,5 +898,1144 @@ BaseNameTable.gNamespace, initValue) {} } + + /// + /// describes a department within an organization. + /// it's a child of Organization + /// + public class OrgDepartment : SimpleElement + { + /// + /// default constructor for gd:OrgDepartment + /// + public OrgDepartment() + : base(GDataParserNameTable.XmlOrgDepartmentElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace) + {} + + /// + /// default constructor for gd:OrgDepartment with an initial value + /// + /// + public OrgDepartment(string initValue) + : base(GDataParserNameTable.XmlOrgDepartmentElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace, initValue) + {} + } + + /// + /// Describes a job within an organization. + /// it's a child of Organization + /// + public class OrgJobDescription : SimpleElement + { + /// + /// default constructor for gd:XmlOrgJobDescriptionElement + /// + public OrgJobDescription() + : base(GDataParserNameTable.XmlOrgJobDescriptionElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace) + {} + + /// + /// default constructor for gd:XmlOrgJobDescriptionElement with an initial value + /// + /// + public OrgJobDescription(string initValue) + : base(GDataParserNameTable.XmlOrgJobDescriptionElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace, initValue) + {} + } + + /// + /// Provides a symbol of an organization + /// it's a child of Organization + /// + public class OrgSymbol : SimpleElement + { + /// + /// default constructor for OrgSymbol + /// + public OrgSymbol() + : base(GDataParserNameTable.XmlOrgSymbolElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace) + {} + + /// + /// default constructor for OrgSymbol with an initial value + /// + /// + public OrgSymbol(string initValue) + : base(GDataParserNameTable.XmlOrgSymbolElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace, initValue) + {} + } + + +#region Contacts version 3 additions + + /// + /// Phoneticname schema extension + /// + public class PhoneticName : SimpleElement + { + public static string AttributeYomi = "yomi"; + + /// + /// default constructor for PhoneticName + /// + public PhoneticName(string xmlElement, string xmlPrefix, string xmlNamespace) + : base(xmlElement, xmlPrefix, xmlNamespace) + { + this.Attributes.Add(AttributeYomi, null); + } + + /// + /// default constructor for PhoneticName with an initial value + /// + /// + public PhoneticName(string xmlElement, string xmlPrefix, string xmlNamespace, string initValue, string initYomi) + : base(xmlElement, xmlPrefix, xmlNamespace, initValue) + { + this.Attributes.Add(AttributeYomi, initYomi); + } + + + /// + /// Phonetic representation + /// + /// + public string Yomi + { + get + { + return this.Attributes[AttributeYomi] as string; + } + set + { + this.Attributes[AttributeYomi] = value; + } + } + } + + /// + /// GivenName schema extension + /// + public class GivenName : PhoneticName + { + + /// + /// default constructor for GivenName + /// + public GivenName() + : base(GDataParserNameTable.GivenNameElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace) + { + } + + /// + /// default constructor for GivenName with an initial value + /// + /// + public GivenName(string initValue, string initYomi) + : base(GDataParserNameTable.GivenNameElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace, initValue, initYomi) + { + } + } + + /// + /// Allows storing person's name in a structured way. Consists of given name, additional name, family name, prefix, suffix and full name + /// + public class Name : SimpleContainer + { + /// + /// default constructor for Name + /// + public Name() + : base(GDataParserNameTable.NameElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace) + { + this.ExtensionFactories.Add(new GivenName()); + this.ExtensionFactories.Add(new AdditonalName()); + this.ExtensionFactories.Add(new FamilyName()); + this.ExtensionFactories.Add(new NamePrefix()); + this.ExtensionFactories.Add(new NameSuffix()); + this.ExtensionFactories.Add(new FullName()); + } + + + /// + /// Person's given name. + /// + /// + public string GivenName + { + get + { + return GetStringValue(GDataParserNameTable.GivenNameElement, + BaseNameTable.gNamespace); + } + set + { + SetStringValue(value, GDataParserNameTable.GivenNameElement, + BaseNameTable.gNamespace); + + } + } + + /// + /// Person's given name phonetics + /// + /// + public string GivenNamePhonetics + { + get + { + return GetYomiValue(GDataParserNameTable.GivenNameElement, + BaseNameTable.gNamespace); + } + set + { + SetYomiValue(value, GDataParserNameTable.GivenNameElement, + BaseNameTable.gNamespace); + } + } + + + /// + /// Additional name of the person, eg. middle name. + /// + /// + public string AdditonalName + { + get + { + return GetStringValue(GDataParserNameTable.AdditonalNameElement, + BaseNameTable.gNamespace); + + } + set + { + SetStringValue(value, GDataParserNameTable.AdditonalNameElement, + BaseNameTable.gNamespace); + + } + } + + /// + /// Person's additonal name phonetics + /// + /// + public string AdditionalNamePhonetics + { + get + { + return GetYomiValue(GDataParserNameTable.AdditonalNameElement, + BaseNameTable.gNamespace); + } + set + { + SetYomiValue(value, GDataParserNameTable.AdditonalNameElement, + BaseNameTable.gNamespace); + } + } + + + /// + /// Person's family name. + /// + /// + public string FamilyName + { + get + { + return GetStringValue(GDataParserNameTable.FamilyNameElement, + BaseNameTable.gNamespace); + + } + set + { + SetStringValue(value, GDataParserNameTable.FamilyNameElement, + BaseNameTable.gNamespace); + + } + } + + /// + /// FamilyName phonetics + /// + /// + public string FamilyNamePhonetics + { + get + { + return GetYomiValue(GDataParserNameTable.FamilyNameElement, + BaseNameTable.gNamespace); + } + set + { + SetYomiValue(value, GDataParserNameTable.FamilyNameElement, + BaseNameTable.gNamespace); + } + } + + /// + /// Honorific prefix, eg. 'Mr' or 'Mrs'. + /// + /// + public string NamePrefix + { + get + { + return GetStringValue(GDataParserNameTable.NamePrefixElement, + BaseNameTable.gNamespace); + + } + set + { + SetStringValue(value, GDataParserNameTable.NamePrefixElement, + BaseNameTable.gNamespace); + + } + } + + /// + /// Honorific suffix, eg. 'san' or 'III'. + /// + /// + public string NameSuffix + { + get + { + return GetStringValue(GDataParserNameTable.NameSuffixElement, + BaseNameTable.gNamespace); + + } + set + { + SetStringValue(value, GDataParserNameTable.NameSuffixElement, + BaseNameTable.gNamespace); + + } + } + + /// + /// Unstructured representation of the name + /// + /// + public string FullName + { + get + { + return GetStringValue(GDataParserNameTable.FullNameElement, + BaseNameTable.gNamespace); + + } + set + { + SetStringValue(value, GDataParserNameTable.FullNameElement, + BaseNameTable.gNamespace); + + } + } + + private void SetYomiValue(string value, string elementName, string ns) where T : PhoneticName + { + T t = FindExtension(elementName, ns) as T; + + if (t == null) + { + throw new ArgumentException("Can not set phonetics if there is no value itself set"); + } + t.Yomi = value; + } + + + private string GetYomiValue(string elementName, string ns) where T : PhoneticName + { + T t = FindExtension(elementName, ns) as T; + if (t != null) + { + return t.Yomi; + } + return null; + } + } + + + + + /// + /// AdditonalName schema extension + /// + public class AdditonalName : PhoneticName + { + /// + /// default constructor for AdditonalName + /// + public AdditonalName() + : base(GDataParserNameTable.AdditonalNameElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace) + { + } + + /// + /// default constructor for AdditonalName with an initial value + /// + /// + public AdditonalName(string initValue, string initYomi) + : base(GDataParserNameTable.AdditonalNameElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace, initValue, initYomi) + { + } + } + + /// + /// FamilyName schema extension + /// + public class FamilyName : PhoneticName + { + /// + /// default constructor for AdditonalName + /// + public FamilyName() + : base(GDataParserNameTable.FamilyNameElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace) + { + } + + /// + /// default constructor for AdditonalName with an initial value + /// + /// + public FamilyName(string initValue, string initYomi) + : base(GDataParserNameTable.FamilyNameElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace, initValue, initYomi) + { + } + } + + + /// + /// NamePrefix schema extension + /// + public class NamePrefix : SimpleElement + { + /// + /// default constructor for NamePrefix + /// + public NamePrefix() + : base(GDataParserNameTable.NamePrefixElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace) + { + } + + /// + /// default constructor for NamePrefix with an initial value + /// + /// + public NamePrefix(string initValue) + : base(GDataParserNameTable.NamePrefixElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace, initValue) + { + } + } + + /// + /// NameSuffix schema extension + /// + public class NameSuffix : SimpleElement + { + /// + /// default constructor for NameSuffix + /// + public NameSuffix() + : base(GDataParserNameTable.NameSuffixElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace) + { + } + + /// + /// default constructor for NameSuffix with an initial value + /// + /// + public NameSuffix(string initValue) + : base(GDataParserNameTable.NameSuffixElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace, initValue) + { + } + } + + /// + /// FullName schema extension + /// + public class FullName : SimpleElement + { + /// + /// default constructor for FullName + /// + public FullName() + : base(GDataParserNameTable.FullNameElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace) + { + } + + /// + /// default constructor for FullName with an initial value + /// + /// + public FullName(string initValue) + : base(GDataParserNameTable.FullNameElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace, initValue) + { + } + } + + + + /// + /// Postal address split into components. It allows to store the address in locale independent + /// format. The fields can be interpreted and used to generate formatted, locale dependent + /// address. The following elements reperesent parts of the address: agent, house name, street, + /// P.O. box, neighborhood, city, subregion, region, postal code, country. The subregion element + /// is not used for postal addresses, it is provided for extended uses of addresses only. In + /// order to store postal address in an unstructured form formatted address field is provided. + /// + public class StructuredPostalAddress : SimpleContainer, ICommonAttributes + { + /// + /// default constructor for StructuredPostalAddress + /// + public StructuredPostalAddress() + : base(GDataParserNameTable.StructuredPostalAddressElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace) + { + this.Attributes.Add(GDataParserNameTable.XmlAttributeLabel, null); + this.Attributes.Add(GDataParserNameTable.XmlAttributePrimary, null); + this.Attributes.Add(GDataParserNameTable.XmlAttributeRel, null); + + this.Attributes.Add(GDataParserNameTable.XmlAttributeMailClass, null); + this.Attributes.Add(GDataParserNameTable.XmlAttributeUsage, null); + + this.ExtensionFactories.Add(new Agent()); + this.ExtensionFactories.Add(new Housename()); + this.ExtensionFactories.Add(new Street()); + this.ExtensionFactories.Add(new Pobox()); + this.ExtensionFactories.Add(new Neighborhood()); + this.ExtensionFactories.Add(new City()); + this.ExtensionFactories.Add(new Subregion()); + this.ExtensionFactories.Add(new Region()); + this.ExtensionFactories.Add(new Postcode()); + this.ExtensionFactories.Add(new Country()); + this.ExtensionFactories.Add(new FormattedAddress()); + } + + + ////////////////////////////////////////////////////////////////////// + /// accessor method public string Primary + /// + ////////////////////////////////////////////////////////////////////// + public bool Primary + { + get {return ("true" == (this.Attributes[GDataParserNameTable.XmlAttributePrimary] as string));} + set {this.Attributes[GDataParserNameTable.XmlAttributePrimary] = value == true? Utilities.XSDTrue : Utilities.XSDFalse;} + } + + ////////////////////////////////////////////////////////////////////// + /// accessor method for the Rel Value. Note you can only set this + /// or Label, not both + /// + ////////////////////////////////////////////////////////////////////// + public string Rel + { + get {return this.Attributes[GDataParserNameTable.XmlAttributeRel] as string;} + set + { + if (this.Label != null) + { + throw new System.ArgumentException("Label already has a value. You can only set Label or Rel"); + } + this.Attributes[GDataParserNameTable.XmlAttributeRel] = value; + } + } + + ////////////////////////////////////////////////////////////////////// + /// accessor method for the Label value. Note you can only set this or + /// Rel, not both + /// + ////////////////////////////////////////////////////////////////////// + public string Label + { + get {return this.Attributes[GDataParserNameTable.XmlAttributeLabel] as string;} + set + { + if (this.Rel != null) + { + throw new System.ArgumentException("Rel already has a value. You can only set Label or Rel"); + } + this.Attributes[GDataParserNameTable.XmlAttributeLabel] = value; + } + } + + + ////////////////////////////////////////////////////////////////////// + /// The context in which this addess can be used. Local addresses + /// may differ in layout from general addresses, and frequently use local + /// script (as opposed to Latin script) as well, though local script is + /// allowed in general addresses. Unless specified general usage is assumed. + /// + ////////////////////////////////////////////////////////////////////// + public string Usage + { + get {return this.Attributes[GDataParserNameTable.XmlAttributeUsage] as string;} + set {this.Attributes[GDataParserNameTable.XmlAttributeUsage] = value;} + } + + ////////////////////////////////////////////////////////////////////// + /// Classes of mail accepted at the address. + /// Unless specified both is assumed + /// + ////////////////////////////////////////////////////////////////////// + public string MailClass + { + get {return this.Attributes[GDataParserNameTable.XmlAttributeMailClass] as string;} + set {this.Attributes[GDataParserNameTable.XmlAttributeMailClass] = value;} + } + + /// + /// The agent who actually receives the mail. + /// Used in work addresses. Also for 'in care of' or 'c/o'. + /// + /// + public string Agent + { + get + { + return GetStringValue(GDataParserNameTable.AgentElement, + BaseNameTable.gNamespace); + } + set + { + SetStringValue(value, GDataParserNameTable.AgentElement, + BaseNameTable.gNamespace); + } + } + + /// + /// Used in places where houses or buildings have names + /// (and not necessarily numbers), eg. "The Pillars". + /// + /// + public string Housename + { + get + { + return GetStringValue(GDataParserNameTable.HousenameElement, + BaseNameTable.gNamespace); + } + set + { + SetStringValue(value, GDataParserNameTable.HousenameElement, + BaseNameTable.gNamespace); + } + } + + /// + /// Can be street, avenue, road, etc. This element also + /// includes the house number and room/apartment/flat/floor number. + /// + /// + public string Street + { + get + { + return GetStringValue(GDataParserNameTable.StreetElement, + BaseNameTable.gNamespace); + } + set + { + SetStringValue(value, GDataParserNameTable.StreetElement, + BaseNameTable.gNamespace); + } + } + + /// + /// Covers actual P.O. boxes, drawers, locked bags, etc. + /// This is usually but not always mutually exclusive with street. + /// + /// + public string Pobox + { + get + { + return GetStringValue(GDataParserNameTable.PoboxElement, + BaseNameTable.gNamespace); + } + set + { + SetStringValue(value, GDataParserNameTable.PoboxElement, + BaseNameTable.gNamespace); + } + } + + /// + /// This is used to disambiguate a street address when a city contains more + /// than one street with the same name, or to specify a small place whose + /// mail is routed through a larger postal town. In China it could be a + /// county or a minor city. + /// + /// + public string Neighborhood + { + get + { + return GetStringValue(GDataParserNameTable.NeighborhoodElement, + BaseNameTable.gNamespace); + } + set + { + SetStringValue(value, GDataParserNameTable.NeighborhoodElement, + BaseNameTable.gNamespace); + } + } + + /// + /// Can be city, village, town, borough, etc. This is the postal town and not + /// necessarily the place of residence or place of business. + /// + /// + public string City + { + get + { + return GetStringValue(GDataParserNameTable.CityElement, + BaseNameTable.gNamespace); + } + set + { + SetStringValue(value, GDataParserNameTable.CityElement, + BaseNameTable.gNamespace); + } + } + + + /// + /// Handles administrative districts such as U.S. or U.K. counties that are not + /// used for mail addressing purposes. Subregion is not intended for delivery + /// addresses. + /// + /// + public string Subregion + { + get + { + return GetStringValue(GDataParserNameTable.SubregionElement, + BaseNameTable.gNamespace); + } + set + { + SetStringValue(value, GDataParserNameTable.SubregionElement, + BaseNameTable.gNamespace); + } + } + + /// + /// A state, province, county (in Ireland), Land (in Germany), departement + /// (in France), etc. + /// + /// + public string Region + { + get + { + return GetStringValue(GDataParserNameTable.RegionElement, + BaseNameTable.gNamespace); + } + set + { + SetStringValue(value, GDataParserNameTable.RegionElement, + BaseNameTable.gNamespace); + } + } + + /// + /// Postal code. Usually country-wide, but sometimes specific to the city + /// (e.g. "2" in "Dublin 2, Ireland" addresses). + /// + /// + public string Postcode + { + get + { + return GetStringValue(GDataParserNameTable.PostcodeElement, + BaseNameTable.gNamespace); + } + set + { + SetStringValue(value, GDataParserNameTable.PostcodeElement, + BaseNameTable.gNamespace); + } + } + + /// + /// The name or code of the country. + /// + /// + public string Country + { + get + { + return GetStringValue(GDataParserNameTable.CountryElement, + BaseNameTable.gNamespace); + } + set + { + SetStringValue(value, GDataParserNameTable.CountryElement, + BaseNameTable.gNamespace); + } + } + + /// + /// The full, unstructured postal address. + /// + /// + public string FormattedAddress + { + get + { + return GetStringValue(GDataParserNameTable.FormattedAddressElement, + BaseNameTable.gNamespace); + } + set + { + SetStringValue(value, GDataParserNameTable.FormattedAddressElement, + BaseNameTable.gNamespace); + } + } + } + + /// + /// Agent schema extension + /// + public class Agent : SimpleElement + { + /// + /// default constructor for Agent + /// + public Agent() + : base(GDataParserNameTable.AgentElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace) + { + } + + /// + /// default constructor for Agent with an initial value + /// + /// + public Agent(string initValue) + : base(GDataParserNameTable.AgentElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace, initValue) + { + } + } + + /// + /// Housename schema extension + /// + public class Housename : SimpleElement + { + /// + /// default constructor for Housename + /// + public Housename() + : base(GDataParserNameTable.HousenameElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace) + { + } + + /// + /// default constructor for Housename with an initial value + /// + /// + public Housename(string initValue) + : base(GDataParserNameTable.HousenameElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace, initValue) + { + } + } + + /// + /// Street schema extension + /// + public class Street : SimpleElement + { + /// + /// default constructor for Street + /// + public Street() + : base(GDataParserNameTable.StreetElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace) + { + } + + /// + /// default constructor for Street with an initial value + /// + /// + public Street(string initValue) + : base(GDataParserNameTable.StreetElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace, initValue) + { + } + } + + /// + /// Pobox schema extension + /// + public class Pobox : SimpleElement + { + /// + /// default constructor for Pobox + /// + public Pobox() + : base(GDataParserNameTable.PoboxElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace) + { + } + + /// + /// default constructor for Pobox with an initial value + /// + /// + public Pobox(string initValue) + : base(GDataParserNameTable.PoboxElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace, initValue) + { + } + } + + /// + /// Neighborhood schema extension + /// + public class Neighborhood : SimpleElement + { + /// + /// default constructor for Neighborhood + /// + public Neighborhood() + : base(GDataParserNameTable.NeighborhoodElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace) + { + } + + /// + /// default constructor for Neighborhood with an initial value + /// + /// + public Neighborhood(string initValue) + : base(GDataParserNameTable.NeighborhoodElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace, initValue) + { + } + } + + /// + /// City schema extension + /// + public class City : SimpleElement + { + /// + /// default constructor for City + /// + public City() + : base(GDataParserNameTable.CityElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace) + { + } + + /// + /// default constructor for City with an initial value + /// + /// + public City(string initValue) + : base(GDataParserNameTable.CityElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace, initValue) + { + } + } + + /// + /// Subregion schema extension + /// + public class Subregion : SimpleElement + { + /// + /// default constructor for Subregion + /// + public Subregion() + : base(GDataParserNameTable.SubregionElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace) + { + } + + /// + /// default constructor for Subregion with an initial value + /// + /// + public Subregion(string initValue) + : base(GDataParserNameTable.SubregionElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace, initValue) + { + } + } + + /// + /// Region schema extension + /// + public class Region : SimpleElement + { + /// + /// default constructor for Region + /// + public Region() + : base(GDataParserNameTable.RegionElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace) + { + } + + /// + /// default constructor for Region with an initial value + /// + /// + public Region(string initValue) + : base(GDataParserNameTable.RegionElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace, initValue) + { + } + } + + /// + /// Postcode schema extension + /// + public class Postcode : SimpleElement + { + /// + /// default constructor for Postcode + /// + public Postcode() + : base(GDataParserNameTable.PostcodeElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace) + { + } + + /// + /// default constructor for Postcode with an initial value + /// + /// + public Postcode(string initValue) + : base(GDataParserNameTable.PostcodeElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace, initValue) + { + } + } + + /// + /// Country schema extension + /// + public class Country : SimpleElement + { + /// + /// default constructor for Country + /// + public Country() + : base(GDataParserNameTable.CountryElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace) + { + } + + /// + /// default constructor for Country with an initial value + /// + /// + public Country(string initValue) + : base(GDataParserNameTable.CountryElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace, initValue) + { + } + } + + /// + /// FormattedAddress schema extension + /// + public class FormattedAddress : SimpleElement + { + /// + /// default constructor for FormattedAddress + /// + public FormattedAddress() + : base(GDataParserNameTable.FormattedAddressElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace) + { + } + + /// + /// default constructor for FormattedAddress with an initial value + /// + /// + public FormattedAddress(string initValue) + : base(GDataParserNameTable.FormattedAddressElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace, initValue) + { + } + } + + + + + +#endregion } diff -Nru gdata-sharp-1.4.0.2/src/extensions/extcollections.cs gdata-sharp-1.7.0.1/src/extensions/extcollections.cs --- gdata-sharp-1.4.0.2/src/extensions/extcollections.cs 2008-10-15 12:50:39.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/extensions/extcollections.cs 1970-01-01 00:00:00.000000000 +0000 @@ -1,302 +0,0 @@ -/* Copyright (c) 2006-2008 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ -/* Change history -* Oct 13 2008 Joe Feser joseph.feser@gmail.com -* Converted ArrayLists and other .NET 1.1 collections to use Generics -* Combined IExtensionElement and IExtensionElementFactory interfaces -* -*/ -#region Using directives - -#define USE_TRACING - -using System; -using System.Collections; -using Google.GData.Client; -using Google.GData.Extensions.MediaRss; -using System.Collections.Generic; - -#endregion - -////////////////////////////////////////////////////////////////////// -// contains typed collections based on the 1.1 .NET framework -// using typed collections has the benefit of additional code reliability -// and using them in the collection editor -// -////////////////////////////////////////////////////////////////////// -namespace Google.GData.Extensions -{ - - /// - /// base class to take an object pointer with extension information - /// and expose a localname/namespace subset as a collection - /// that still works on the original - /// - public class ExtensionCollection : IList where T : class, IExtensionElementFactory, new() - { - /// holds the owning feed - private IExtensionContainer container; - private List _items = new List(); - - private static Dictionary _cache = new Dictionary(); - - /// - /// Get the XmlName for the Type - /// - /// - private static string CtorXmlName() - { - IExtensionElementFactory val; - Type t = typeof(T); - if (!_cache.TryGetValue(t, out val)) - { - val = new T(); - _cache[t] = val; - } - return val.XmlName; - } - - /// - /// Get the Xml Namespace for the Type - /// - /// - private static string CtorXmlNS() - { - IExtensionElementFactory val; - Type t = typeof(T); - if (!_cache.TryGetValue(t, out val)) - { - val = new T(); - _cache[t] = val; - } - return val.XmlNameSpace; - } - - /// - /// protected default constructor, not usable by outside - /// - public ExtensionCollection() - { - } - - /// - /// takes the base object, and the localname/ns combo to look for - /// will copy objects to an internal array for caching. Note that when the external - /// ExtensionList is modified, this will have no effect on this copy - /// - /// the base element holding the extension list - public ExtensionCollection(IExtensionContainer containerElement) - : this(containerElement, CtorXmlName(), CtorXmlNS()) - { - } - - /// - /// takes the base object, and the localname/ns combo to look for - /// will copy objects to an internal array for caching. Note that when the external - /// ExtensionList is modified, this will have no effect on this copy - /// - /// the base element holding the extension list - /// the local name of the extension - /// the namespace - public ExtensionCollection(IExtensionContainer containerElement, string localName, string ns) - : base() - { - this.container = containerElement; - if (this.container != null) - { - ExtensionList arr = this.container.FindExtensions(localName, ns); - foreach (T o in arr) - { - _items.Add(o); - } - } - } - - /// standard typed accessor method - public T this[int index] - { - get - { - return ((T)_items[index]); - } - set - { - setItem(index, value); - } - } - - /// - /// useful for subclasses that want to overload the set method - /// - /// the index in the array - /// the item to set - protected void setItem(int index, T item) - { - if (_items[index] != null) - { - if (this.container != null) - { - this.container.ExtensionElements.Remove(_items[index]); - } - } - _items[index] = item; - if (item != null && this.container != null) - { - this.container.ExtensionElements.Add(item); - } - } - - - /// - /// default untyped add implementation. Adds the object as well to the parent - /// object ExtensionList - /// - /// - /// - public int Add(T value) - { - if (this.container != null) - { - this.container.ExtensionElements.Add(value); - } - _items.Add(value); - return _items.Count - 1; - } - - /// - /// inserts an element into the collection by index - /// - /// - /// - public void Insert(int index, T value) - { - if (this.container != null && this.container.ExtensionElements.Contains(value)) - { - this.container.ExtensionElements.Remove(value); - } - this.container.ExtensionElements.Add(value); - _items.Insert(index, value); - } - - /// - /// removes an element at a given index - /// - /// - public void Remove(T value) - { - _items.Remove(value); - if (this.container != null) - { - this.container.ExtensionElements.Remove(value); - } - } - - /// standard typed indexOf method - public int IndexOf(T value) - { - return (_items.IndexOf(value)); - } - - /// standard typed Contains method - public bool Contains(T value) - { - // If value is not of type AtomEntry, this will return false. - return (_items.Contains(value)); - } - - /// standard override OnClear, to remove the objects from the extension list - protected void OnClear() - { - if (this.container != null) - { - for (int i = 0; i < this.Count; i++) - { - this.container.ExtensionElements.Remove(_items[i]); - } - } - } - - #region IList Members - - - public void RemoveAt(int index) - { - T item = _items[index]; - _items.RemoveAt(index); - Remove(item); - } - - #endregion - - #region ICollection Members - - void ICollection.Add(T item) - { - _items.Add(item); - } - - public void Clear() - { - OnClear(); - _items.Clear(); - } - - public void CopyTo(T[] array, int arrayIndex) - { - _items.ToArray().CopyTo(array, arrayIndex); - } - - public int Count - { - get - { - return _items.Count; - } - } - - public bool IsReadOnly - { - get - { - return false; - } - } - - bool ICollection.Remove(T item) - { - return _items.Remove(item); - } - - #endregion - - #region IEnumerable Members - - public IEnumerator GetEnumerator() - { - return _items.GetEnumerator(); - } - - #endregion - - #region IEnumerable Members - - IEnumerator IEnumerable.GetEnumerator() - { - return _items.GetEnumerator(); - } - - #endregion - } -} diff -Nru gdata-sharp-1.4.0.2/src/extensions/extended.cs gdata-sharp-1.7.0.1/src/extensions/extended.cs --- gdata-sharp-1.4.0.2/src/extensions/extended.cs 2008-05-21 19:17:39.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/extensions/extended.cs 2009-05-25 13:03:43.000000000 +0000 @@ -25,7 +25,7 @@ /// /// GData schema extension describing an extended property/value pair /// - public class ExtendedProperty : SimpleAttribute + public class ExtendedProperty : SimpleNameValueAttribute { /// @@ -35,7 +35,6 @@ BaseNameTable.gDataPrefix, BaseNameTable.gNamespace) { - this.Attributes.Add(AtomParserNameTable.XmlName, null); } /// @@ -44,10 +43,9 @@ /// public ExtendedProperty(string initValue) : base(GDataParserNameTable.XmlExtendedPropertyElement, BaseNameTable.gDataPrefix, - BaseNameTable.gNamespace, - initValue) + BaseNameTable.gNamespace) { - this.Attributes.Add(AtomParserNameTable.XmlName, null); + this.Value = initValue; } /// @@ -57,26 +55,10 @@ /// name for the key public ExtendedProperty(string initValue, string initName) : base(GDataParserNameTable.XmlExtendedPropertyElement, BaseNameTable.gDataPrefix, - BaseNameTable.gNamespace, - initValue) - { - this.Attributes.Add(AtomParserNameTable.XmlName, initName); - } - - - ////////////////////////////////////////////////////////////////////// - /// Accessor for "value" attribute. - /// - ////////////////////////////////////////////////////////////////////// - public string Name + BaseNameTable.gNamespace) { - get { - return this.Attributes[AtomParserNameTable.XmlName] as string; - } - set - { - this.Attributes[AtomParserNameTable.XmlName] = value; - } + this.Value = initValue; + this.Name = initName; } } } diff -Nru gdata-sharp-1.4.0.2/src/extensions/gdatanametable.cs gdata-sharp-1.7.0.1/src/extensions/gdatanametable.cs --- gdata-sharp-1.4.0.2/src/extensions/gdatanametable.cs 2009-02-03 15:10:46.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/extensions/gdatanametable.cs 2010-02-15 11:26:47.000000000 +0000 @@ -108,9 +108,18 @@ public const string XmlDeletedElement = "deleted"; /// static string for parsing the organization name element in a contacts public const string XmlOrgNameElement = "orgName"; + /// static string for parsing the organization symbol element in a contacts + public const string XmlOrgSymbolElement = "orgSymbol"; + /// static string for parsing the organization job description element in a contacts + public const string XmlOrgJobDescriptionElement = "orgJobDescription"; + /// static string for parsing the organization department element in a contacts + public const string XmlOrgDepartmentElement = "orgDepartment"; /// static string for parsing the organization title element in a contacts public const string XmlOrgTitleElement = "orgTitle"; + /// static string for parsing the quotaBytesUsed element + public const string XmlQuotaBytesUsedElement = "quotaBytesUsed"; + /// xmlelement for gd:rating public const string XmlRatingElement = "rating"; @@ -171,6 +180,27 @@ public const string XmlAttributeProtocol= "protocol"; /// static string for parsing the uri attribute public const string XmlAttributeUri = "uri"; + /// static string for parsing the displayname attribute + public const string XmlAttributeDisplayName = "displayName"; + + /// + /// a resource id + /// + public const string XmlResourceIdElement = "resourceId"; + + /// + /// lastviewed constant + /// + /// + public const string XmlLastViewedElement = "lastViewed"; + + /// + /// lastviewed constant + /// + /// + public const string XmlLastModifiedByElement = "lastModifiedBy"; + + #endregion @@ -183,6 +213,8 @@ public const string XmlExtendedPropertyElement = "extendedProperty"; /// static string for the url attribute public const string XmlAttributeUrl = "url"; + /// static string for the display attribute + public const string XmlAttributeDisplay = "display"; /// static string for the width attribute public const string XmlAttributeWidth= "width"; /// static string for the height attribute @@ -193,6 +225,97 @@ public const string XmlQuickAddElement = "quickadd"; #endregion +#region Contacts specific + /// + /// Allows storing person's name in a structured way. Consists of given name, additional name, family name, prefix, suffix and full name. + /// + public const string NameElement = "name"; + /// + /// Person's given name + /// + public const string GivenNameElement = "givenName"; + /// + /// Additonal name of the person, e.g. middle name + /// + public const string AdditonalNameElement = "additonalName"; + /// + /// Person's family Name + /// + public const string FamilyNameElement = "familyName"; + /// + /// honorific prefix, eg. Mr or Mrs + /// + public const string NamePrefixElement = "namePrefix"; + /// + /// Honorific suffix, eg. san + /// + public const string NameSuffixElement = "nameSuffix"; + /// + /// Unstructured representation of the name + /// + public const string FullNameElement = "fullName"; + /// + /// Postal address split into components. It allows to store the address in locale independent format. + /// The fields can be interpreted and used to generate formatted, locale dependent address. + /// + public const string StructuredPostalAddressElement = "structuredPostalAddress"; + /// + /// The agent who actually receives the mail. + /// + public const string AgentElement = "agent"; + /// + /// Used in places where houses have names + /// + public const string HousenameElement = "housename"; + /// + /// Can be stree, avenue, road, etc + /// + public const string StreetElement = "street"; + /// + /// Covers actual P.O. Boxes, drawers, locked bags etc + /// + public const string PoboxElement = "pobox"; + /// + /// This is used to disambiguate a street address when a city contains + /// more than one street with the same name, or to specify a small place whose + /// mail is routed through a larger postal town. + /// In China it could be a county or a minor city. + /// + public const string NeighborhoodElement = "neighborhood"; + /// + /// Can be City, village etc + /// + public const string CityElement = "city"; + /// + /// Administrative districts + /// + public const string SubregionElement = "subregion"; + /// + /// A state, province etc + /// + public const string RegionElement = "region"; + /// + /// Postal code + /// + public const string PostcodeElement = "postcode"; + /// + /// The name or code of the country + /// + public const string CountryElement = "country"; + /// + /// The full, unstructured postal address + /// + public const string FormattedAddressElement = "formattedAddress"; + /// + /// The full, unstructured postal address + /// + public const string XmlAttributeMailClass = "mailClass"; + /// + /// The full, unstructured postal address + /// + public const string XmlAttributeUsage = "usage"; +#endregion + } ///////////////////////////////////////////////////////////////////////////// @@ -200,3 +323,4 @@ ///////////////////////////////////////////////////////////////////////////// + diff -Nru gdata-sharp-1.4.0.2/src/extensions/mediarss.cs gdata-sharp-1.7.0.1/src/extensions/mediarss.cs --- gdata-sharp-1.4.0.2/src/extensions/mediarss.cs 2009-02-27 14:55:17.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/extensions/mediarss.cs 2009-04-14 13:28:31.000000000 +0000 @@ -610,11 +610,11 @@ { get { - return this.Attributes[MediaRssNameTable.AttributeDuration] as string; + return this.Attributes[MediaRssNameTable.AttributeType] as string; } set { - this.Attributes[MediaRssNameTable.AttributeDuration] = value; + this.Attributes[MediaRssNameTable.AttributeType] = value; } } @@ -626,11 +626,11 @@ { get { - return this.Attributes[MediaRssNameTable.AttributeType] as string; + return this.Attributes[MediaRssNameTable.AttributeDuration] as string; } set { - this.Attributes[MediaRssNameTable.AttributeType] = value; + this.Attributes[MediaRssNameTable.AttributeDuration] = value; } } diff -Nru gdata-sharp-1.4.0.2/src/extensions/misc.cs gdata-sharp-1.7.0.1/src/extensions/misc.cs --- gdata-sharp-1.4.0.2/src/extensions/misc.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/extensions/misc.cs 2009-11-04 10:46:31.000000000 +0000 @@ -0,0 +1,157 @@ +/* Copyright (c) 2006-2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* Change history +* Oct 13 2008 Joe Feser joseph.feser@gmail.com +* Converted ArrayLists and other .NET 1.1 collections to use Generics +* Combined IExtensionElement and IExtensionElementFactory interfaces +* +*/ +using System; +using System.Xml; +using System.Collections; +using System.Text; +using System.Globalization; +using Google.GData.Client; + +namespace Google.GData.Extensions { + + /// + /// The resource ID is an identifier for a resource that an entry might + /// be refering to + /// + public class ResourceId : SimpleElement + { + /// + /// default constructor for gd:resourceid + /// + public ResourceId() + : base(GDataParserNameTable.XmlResourceIdElement, + GDataParserNameTable.gDataPrefix, + GDataParserNameTable.gNamespace) + { + } + } + + /// + /// Identifies when an entry was last viewed + /// + public class LastViewed : SimpleElement + { + /// + /// default constructor for gd:resourceid + /// + public LastViewed() + : base(GDataParserNameTable.XmlLastViewedElement, + GDataParserNameTable.gDataPrefix, + GDataParserNameTable.gNamespace) + { + } + } + + + /// + /// identifies the person who last modified an entry + /// + /// + public class LastModifiedBy : SimpleContainer + { + /// + /// default constructor for media:group + /// + public LastModifiedBy() + : base(GDataParserNameTable.XmlLastModifiedByElement, + GDataParserNameTable.gDataPrefix, + GDataParserNameTable.gNamespace) + { + this.ExtensionFactories.Add(new LastModifiedByName()); + this.ExtensionFactories.Add(new LastModifiedByEMail()); + } + + /// + /// the name portion of the element + /// + /// + public string Name + { + + get + { + return GetStringValue(GDataParserNameTable.XmlName, + GDataParserNameTable.NSAtom); + } + } + + /// + /// the email portion of the element + /// + /// + public string EMail + { + get + { + return GetStringValue(GDataParserNameTable.XmlEmailElement, + GDataParserNameTable.NSAtom); + } + } + } + + /// + /// simple subclass to hold the name subportion for the lastmodifed container + /// + public class LastModifiedByName : SimpleElement + { + /// + /// default constructor for a name subobject + /// + public LastModifiedByName() + : base(GDataParserNameTable.XmlName, + GDataParserNameTable.AtomPrefix, + GDataParserNameTable.NSAtom) + { + } + } + + /// + /// simple sublcass to hold the email subportion of the lastmodified container + /// + public class LastModifiedByEMail : SimpleElement + { + /// + /// default constructor for a email subobject + /// + public LastModifiedByEMail() + : base(GDataParserNameTable.XmlEmailElement, + GDataParserNameTable.AtomPrefix, + GDataParserNameTable.NSAtom) + { + } + } + + /// + /// The amount of quota consumed by the entry. + /// + public class QuotaBytesUsed : SimpleElement + { + /// + /// default constructor for gd:resourceid + /// + public QuotaBytesUsed() + : base(GDataParserNameTable.XmlQuotaBytesUsedElement, + GDataParserNameTable.gDataPrefix, + GDataParserNameTable.gNamespace) + { + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/extensions/recurexception.cs gdata-sharp-1.7.0.1/src/extensions/recurexception.cs --- gdata-sharp-1.4.0.2/src/extensions/recurexception.cs 2008-10-15 12:50:39.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/extensions/recurexception.cs 2010-06-07 14:40:22.000000000 +0000 @@ -29,139 +29,73 @@ /// /// GData schema extension describing an RFC 2445 recurrence rule. /// - public class RecurrenceException : IExtensionElementFactory + public class RecurrenceException : SimpleContainer { - /// optional nested entry - private EntryLink entryLink; - /// specialized exception or not - private bool isSpecialized; - - /// - /// Nested entry (optional). - /// - public EntryLink EntryLink + public RecurrenceException() : + base(GDataParserNameTable.XmlRecurrenceExceptionElement, + BaseNameTable.gDataPrefix, + BaseNameTable.gNamespace) { - get { return entryLink; } - set { entryLink = value; } + this.ExtensionFactories.Add(new OriginalEvent()); + this.ExtensionFactories.Add(new EntryLink()); + this.Attributes.Add(GDataParserNameTable.XmlAttributeSpecialized, null); } + ////////////////////////////////////////////////////////////////////// - // Date: 7/3/2006 - /// accessor method public bool Specialized + /// Accessor for "specialized" attribute. /// ////////////////////////////////////////////////////////////////////// - public bool Specialized + public bool Specialized { - get {return this.isSpecialized;} - set {this.isSpecialized = value;} + get + { + return bool.Parse(this.Attributes[GDataParserNameTable.XmlAttributeSpecialized] as string); + } + set + { + this.Attributes[GDataParserNameTable.XmlAttributeSpecialized] = value; + } } - /// holds the value property - private string value; + /// - /// Accessor method for the Value property + /// exposes the EntryLink element for this exception /// - public string Value - { - get { return value; } - set { this.value = value; } - } - - - #region overloaded from IExtensionElementFactory - ////////////////////////////////////////////////////////////////////// - /// Parses an xml node to create a Where object. - /// the node to parse node - /// the xml parser to use if we need to dive deeper - /// the created Where object - ////////////////////////////////////////////////////////////////////// - public IExtensionElementFactory CreateInstance(XmlNode node, AtomFeedParser parser) + /// + public EntryLink EntryLink { - Tracing.TraceCall(); - RecurrenceException exception = null; - - if (node != null) + get { - object localname = node.LocalName; - if (localname.Equals(this.XmlName) == false || - node.NamespaceURI.Equals(this.XmlNameSpace) == false) - { - return null; - } - } - - exception = new RecurrenceException(); - - if (node != null) - { - if (node.Attributes != null) - { - if (node.Attributes[GDataParserNameTable.XmlAttributeSpecialized] != null) - { - exception.Specialized = bool.Parse(node.Attributes[GDataParserNameTable.XmlAttributeSpecialized].Value); - } - } - - if (node.HasChildNodes) - { - XmlNode childNode = node.FirstChild; - while (childNode != null && childNode is XmlElement) - { - if (childNode.LocalName == GDataParserNameTable.XmlEntryLinkElement) - { - exception.EntryLink = EntryLink.ParseEntryLink(childNode, parser); - } - childNode = childNode.NextSibling; - } - } - if (exception.EntryLink == null) - { - throw new ArgumentException("g:recurringException/entryLink is required."); - } + return FindExtension(GDataParserNameTable.XmlEntryLinkElement, + BaseNameTable.gNamespace) as EntryLink; + } + set + { + ReplaceExtension(GDataParserNameTable.XmlEntryLinkElement, + BaseNameTable.gNamespace, + value); } - - return exception; - } - - - - #endregion - - #region overloaded for persistence - ////////////////////////////////////////////////////////////////////// - /// Returns the constant representing this XML element. - ////////////////////////////////////////////////////////////////////// - public string XmlName - { - get { return GDataParserNameTable.XmlRecurrenceExceptionElement; } - } - - ////////////////////////////////////////////////////////////////////// - /// Returns the constant representing this XML element. - ////////////////////////////////////////////////////////////////////// - public string XmlNameSpace - { - get { return BaseNameTable.gNamespace; } - } - - ////////////////////////////////////////////////////////////////////// - /// Returns the constant representing this XML element. - ////////////////////////////////////////////////////////////////////// - public string XmlPrefix - { - get { return BaseNameTable.gDataPrefix; } } - /// - /// Persistence method for the RecurrenceException object + /// exposes the OriginalEvent element for this exception /// - /// the xmlwriter to write into - public void Save(XmlWriter writer) + /// + public OriginalEvent OriginalEvent { - writer.WriteStartElement(BaseNameTable.gDataPrefix, XmlName, BaseNameTable.gNamespace); - writer.WriteEndElement(); + get + { + return FindExtension(GDataParserNameTable.XmlOriginalEventElement, + BaseNameTable.gNamespace) as OriginalEvent; + } + set + { + ReplaceExtension(GDataParserNameTable.XmlOriginalEventElement, + BaseNameTable.gNamespace, + value); + } } - #endregion - } + + } } diff -Nru gdata-sharp-1.4.0.2/src/extensions/where.cs gdata-sharp-1.7.0.1/src/extensions/where.cs --- gdata-sharp-1.4.0.2/src/extensions/where.cs 2008-10-15 12:50:39.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/extensions/where.cs 2009-07-02 10:35:15.000000000 +0000 @@ -84,8 +84,8 @@ /// label property value /// default for the Rel property value public Where(String rel, - String label, - String value) + String label, + String value) { this.Rel = rel; this.Label = label; diff -Nru gdata-sharp-1.4.0.2/src/gacl/Access Control.csproj gdata-sharp-1.7.0.1/src/gacl/Access Control.csproj --- gdata-sharp-1.4.0.2/src/gacl/Access Control.csproj 2008-12-12 15:10:21.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gacl/Access Control.csproj 2009-12-14 12:18:56.000000000 +0000 @@ -1,7 +1,6 @@ - + Local - 8.0.50727 2.0 {279D35CE-871A-4C76-B823-A73675EDF191} Debug @@ -26,6 +25,7 @@ true + 2.0 bin\Debug\ @@ -124,6 +124,7 @@ + diff -Nru gdata-sharp-1.4.0.2/src/gacl/aclmodel.cs gdata-sharp-1.7.0.1/src/gacl/aclmodel.cs --- gdata-sharp-1.4.0.2/src/gacl/aclmodel.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gacl/aclmodel.cs 2009-12-14 12:18:56.000000000 +0000 @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Google.GData.Client; +using Google.GData.Extensions; +using Google.GData.AccessControl; + +namespace Google.AccessControl +{ + public class Acl : Entry + { + /// + /// creates the inner contact object when needed + /// + /// + protected override void EnsureInnerObject() + { + if (this.AtomEntry == null) + { + this.AtomEntry = new AclEntry(); + } + } + + /// + /// readonly accessor for the AclEntry that is underneath this object. + /// + /// + public AclEntry AclEntry + { + get + { + EnsureInnerObject(); + return this.AtomEntry as AclEntry; + } + } + + public string Role + { + get + { + EnsureInnerObject(); + if (this.AclEntry.Role != null) + return this.AclEntry.Role.Value; + return null; + } + + set + { + EnsureInnerObject(); + this.AclEntry.Role = new AclRole(value); + } + } + + + public AclScope Scope + { + get + { + EnsureInnerObject(); + return this.AclEntry.Scope; + } + + set + { + EnsureInnerObject(); + this.AclEntry.Scope = value; + } + } + + + + } + +} diff -Nru gdata-sharp-1.4.0.2/src/gacl/aclscope.cs gdata-sharp-1.7.0.1/src/gacl/aclscope.cs --- gdata-sharp-1.4.0.2/src/gacl/aclscope.cs 2008-05-21 19:17:39.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gacl/aclscope.cs 2009-12-09 11:25:39.000000000 +0000 @@ -39,33 +39,24 @@ /// /// default constructor /// - public AclScope() : base(AclNameTable.XmlAclScopeElement, - AclNameTable.gAclAlias, - AclNameTable.gAclNamespace) - { - this.Attributes.Add(AclNameTable.XmlAttributeType, null); - } + public AclScope() : this(null, null) + {} /// /// default constructor with an init value /// /// - public AclScope(string initValue) : base(GDataParserNameTable.XmlExtendedPropertyElement, - BaseNameTable.gDataPrefix, - BaseNameTable.gNamespace, - initValue) - { - this.Attributes.Add(AclNameTable.XmlAttributeType, null); - } + public AclScope(string initValue) : this(initValue, null) + {} /// /// constructor taking an initial value and a name /// /// /// - public AclScope(string initValue, string initName) : base(GDataParserNameTable.XmlExtendedPropertyElement, - BaseNameTable.gDataPrefix, - BaseNameTable.gNamespace, + public AclScope(string initValue, string initName) : base(AclNameTable.XmlAclScopeElement, + AclNameTable.gAclAlias, + AclNameTable.gAclNamespace, initValue) { this.Attributes.Add(AclNameTable.XmlAttributeType, initName); diff -Nru gdata-sharp-1.4.0.2/src/gapps/adminsettingsentry.cs gdata-sharp-1.7.0.1/src/gapps/adminsettingsentry.cs --- gdata-sharp-1.4.0.2/src/gapps/adminsettingsentry.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gapps/adminsettingsentry.cs 2010-03-25 12:08:16.000000000 +0000 @@ -0,0 +1,470 @@ +/* Copyright (c) 2007 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +using System; +using System.Xml; +using System.IO; +using System.Collections; +using Google.GData.Apps; +using Google.GData.Client; +using Google.GData.Extensions.Apps; + +namespace Google.GData.Apps.AdminSettings +{ + /// + /// A Google Apps Google Admin Settings entry. + /// + public class AdminSettingsEntry : AppsExtendedEntry + { + /// + /// Constructs a new AdminSettingsEntry object. + /// + public AdminSettingsEntry() + : base() + { + } + + /// + /// typed override of the Update method + /// + /// AdminSettingsEntry + public new AdminSettingsEntry Update() + { + return base.Update() as AdminSettingsEntry; + } + + /// + /// DefaultLanguage Property accessor + /// + public string DefaultLanguage + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.DefaultLanguage); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.DefaultLanguage).Value = value; } + } + + /// + /// OrganizationName Property accessor + /// + public string OrganizationName + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.OrganizationName); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.OrganizationName).Value = value; } + } + + /// + /// MaximumNumberOfUsers Property accessor + /// + public string MaximumNumberOfUsers + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.MaximumNumberOfUsers); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.MaximumNumberOfUsers).Value = value; } + } + + /// + /// MaximumNumberOfUsers Property accessor + /// + public string CurrentNumberOfUsers + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.CurrentNumberOfUsers); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.CurrentNumberOfUsers).Value = value; } + } + + /// + /// IsVerified Property accessor + /// + public string IsVerified + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.IsVerified); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.IsVerified).Value = value; } + } + + /// + /// SupportPIN Property accessor + /// + public string SupportPIN + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.SupportPIN); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.SupportPIN).Value = value; } + } + + /// + /// Edition Property accessor + /// + public string Edition + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.Edition); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.Edition).Value = value; } + } + + /// + /// CustomerPIN Property accessor + /// + public string CustomerPIN + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.CustomerPIN); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.CustomerPIN).Value = value; } + } + + /// + /// CreationTime Property accessor + /// + public string CreationTime + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.CreationTime); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.CreationTime).Value = value; } + } + + /// + /// CountryCode Property accessor + /// + public string CountryCode + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.CountryCode); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.CountryCode).Value = value; } + } + + /// + /// AdminSecondaryEmail Property accessor + /// + public string AdminSecondaryEmail + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.AdminSecondaryEmail); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.AdminSecondaryEmail).Value = value; } + } + + /// + /// LogoImage Property accessor + /// + public string LogoImage + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.LogoImage); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.LogoImage).Value = value; } + } + + /// + /// RecordName Property accessor + /// + public string RecordName + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.RecordName); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.RecordName).Value = value; } + } + + /// + /// Verified Property accessor + /// + public string Verified + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.Verified); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.Verified).Value = value; } + } + + /// + /// VerifiedMethod Property accessor + /// + public string VerifiedMethod + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.VerifiedMethod); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.VerifiedMethod).Value = value; } + } + + /// + /// MaximumNumberOfUsers Property accessor + /// + public string SamlSignonUri + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.SamlSignonUri); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.SamlSignonUri).Value = value; } + } + + /// + /// SamlLogoutUri Property accessor + /// + public string SamlLogoutUri + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.SamlLogoutUri); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.SamlLogoutUri).Value = value; } + } + + /// + /// ChangePasswordUri Property accessor + /// + public string ChangePasswordUri + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.ChangePasswordUri); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.ChangePasswordUri).Value = value; } + } + + /// + /// EnableSSO Property accessor + /// + public string EnableSSO + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.EnableSSO); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.EnableSSO).Value = value; } + } + + + /// + /// SsoWhitelist Property accessor + /// + public string SsoWhitelist + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.SsoWhitelist); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.SsoWhitelist).Value = value; } + } + + /// + /// UseDomainSpecificIssuer Property accessor + /// + public string UseDomainSpecificIssuer + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.UseDomainSpecificIssuer); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.UseDomainSpecificIssuer).Value = value; } + } + + /// + /// SigningKey Property accessor + /// + public string SigningKey + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.SigningKey); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.SigningKey).Value = value; } + } + + /// + /// EnableUserMigration Property accessor + /// + public string EnableUserMigration + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.EnableUserMigration); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.EnableUserMigration).Value = value; } + } + + /// + /// SmartHost Property accessor + /// + public string SmartHost + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.SmartHost); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.SmartHost).Value = value; } + } + + /// + /// SmtpMode Property accessor + /// + public string SmtpMode + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.SmtpMode); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.SmtpMode).Value = value; } + } + + /// + /// RouteDestination Property accessor + /// + public string RouteDestination + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.RouteDestination); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.RouteDestination).Value = value; } + } + + /// + /// RouteRewriteTo Property accessor + /// + public string RouteRewriteTo + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.RouteRewriteTo); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.RouteRewriteTo).Value = value; } + } + + + /// + /// RouteEnabled Property accessor + /// + public string RouteEnabled + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.RouteEnabled); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.RouteEnabled).Value = value; } + } + + /// + /// BounceNotifications Property accessor + /// + public string BounceNotifications + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.BounceNotifications); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.BounceNotifications).Value = value; } + } + + /// + /// AccountHandling Property accessor + /// + public string AccountHandling + { + get + { + PropertyElement property = + this.getPropertyByName(AppsDomainSettingsNameTable.AccountHandling); + return property != null ? property.Value : null; + } + set { this.getPropertyByName(AppsDomainSettingsNameTable.AccountHandling).Value = value; } + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/gapps/adminsettingsfeed.cs gdata-sharp-1.7.0.1/src/gapps/adminsettingsfeed.cs --- gdata-sharp-1.4.0.2/src/gapps/adminsettingsfeed.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gapps/adminsettingsfeed.cs 2010-03-25 12:08:16.000000000 +0000 @@ -0,0 +1,51 @@ +/* Copyright (c) 2007 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +using System; +using System.Text; +using System.Xml; +using Google.GData.Apps; +using Google.GData.Client; +using Google.GData.Extensions; +using Google.GData.Extensions.Apps; + +namespace Google.GData.Apps.AdminSettings +{ + /// + /// Feed API customization class for defining the Google + /// Admin Settings feed. + /// + public class AdminSettingsFeed : AppsExtendedFeed + { + /// + /// Constructor + /// + /// The uri for the migration feed. + /// The GoogleMailSettings service. + public AdminSettingsFeed(Uri uriBase, IService iService) + : base(uriBase, iService) + { + } + + /// + /// Overridden. Returns a new AdminSettingsEntry. + /// + /// the new new AdminSettingtEntry + public override AtomEntry CreateFeedEntry() + { + return new AdminSettingsEntry(); + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/gapps/adminsettingsservice.cs gdata-sharp-1.7.0.1/src/gapps/adminsettingsservice.cs --- gdata-sharp-1.4.0.2/src/gapps/adminsettingsservice.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gapps/adminsettingsservice.cs 2010-03-25 12:08:16.000000000 +0000 @@ -0,0 +1,503 @@ +/* Copyright (c) 2007 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +using System; +using System.IO; +using System.Net; +using System.Text; +using Google.GData.Client; +using Google.GData.Extensions.Apps; + +namespace Google.GData.Apps.AdminSettings +{ + /// + /// Base service for accessing Google Admin Settings item feeds from the + /// Google Apps Google Domain Settings API. + /// + public class AdminSettingsService : Service + { + private string domain; + + /// + /// Constructor + /// + /// The hosted domain in which the Google Mail Settings are + /// being set up + /// The name of the client application + /// using this service. + public AdminSettingsService(string domain, string applicationName) + : base(AppsNameTable.GAppsService, applicationName) + { + this.domain = domain; + this.NewAtomEntry += new FeedParserEventHandler(this.OnParsedNewGoogleMailSettingsItemEntry); + this.NewFeed += new ServiceEventHandler(this.OnNewFeed); + // You can set factory.methodOverride = true if you are behind a + // proxy that filters out HTTP methods such as PUT and DELETE. + } + + /// + /// Accessor for Domain property. + /// + public string Domain + { + get { return domain; } + set { this.domain = value; } + } + + /// + /// Gets the domain's default language + /// + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry GetDefaultLanguage() + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.DefaultLanguageUriSuffix; + return Get(uri) as AdminSettingsEntry; + } + + /// + /// Updates the domain's default language + /// + /// the new default language for the domain + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry UpdateDefaultLanguage(string defaultLanguage) + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.DefaultLanguageUriSuffix; + AdminSettingsEntry entry = new AdminSettingsEntry(); + entry.EditUri = uri; + entry.Properties.Add(new PropertyElement(AppsDomainSettingsNameTable.DefaultLanguage, defaultLanguage)); + return base.Update(entry); + } + + /// + /// Gets the domain's organization name + /// + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry GetOrganizationName() + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.OrganizationNameUriSuffix; + return Get(uri) as AdminSettingsEntry; + } + + /// + /// Updates the domain's organization name + /// + /// the new organization name for the domain + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry UpdateOrganizationName(string organizationName) + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.OrganizationNameUriSuffix; + AdminSettingsEntry entry = new AdminSettingsEntry(); + entry.EditUri = uri; + entry.Properties.Add(new PropertyElement(AppsDomainSettingsNameTable.OrganizationName, organizationName)); + return base.Update(entry); + } + + /// + /// Gets the domain's Maximum Number Of Users + /// + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry GetMaximumNumberOfUsers() + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.MaximumNumberOfUsersUriSuffix; + return Get(uri) as AdminSettingsEntry; + } + + /// + /// Gets the domain's Current Number Of Users + /// + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry GetCurrentNumberOfUsers() + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.CurrentNumberOfUsersUriSuffix; + return Get(uri) as AdminSettingsEntry; + } + + /// + /// Gets the domain's verification status + /// + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry GetIsVerified() + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.IsVerifiedUriSuffix; + return Get(uri) as AdminSettingsEntry; + } + + /// + /// Gets the domain's Support PIN + /// + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry GetSupportPIN() + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.SupportPINUriSuffix; + return Get(uri) as AdminSettingsEntry; + } + + /// + /// Gets the domain's Google Apps Edition + /// + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry GetDomainEdition() + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.EditionUriSuffix; + return Get(uri) as AdminSettingsEntry; + } + + /// + /// Gets the domain's Customers PIN + /// + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry GetCustomerPIN() + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.CustomerPINUriSuffix; + return Get(uri) as AdminSettingsEntry; + } + + /// + /// Gets the domain's Creation Time + /// + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry GetCreationTime() + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.CreationTimeUriSuffix; + return Get(uri) as AdminSettingsEntry; + } + + /// + /// Gets the domain's Country Code + /// + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry GetCountryCode() + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.CountryCodeUriSuffix; + return Get(uri) as AdminSettingsEntry; + } + + /// + /// Gets the domain's Administrator Secondary Email address + /// + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry GetAdminSecondaryEmail() + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.AdminSecondaryEmailUriSuffix; + return Get(uri) as AdminSettingsEntry; + } + + /// + /// Updates the domain's Administrator Secondary Email address + /// + /// the new domain's admin Secondary Email domain + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry UpdateAdminSecondaryEmail(string adminSecondaryEmail) + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.AdminSecondaryEmailUriSuffix; + AdminSettingsEntry entry = new AdminSettingsEntry(); + entry.EditUri = uri; + entry.Properties.Add( + new PropertyElement(AppsDomainSettingsNameTable.AdminSecondaryEmail, adminSecondaryEmail)); + return base.Update(entry); + } + + /// + /// Updates the domain's Custom Logo + /// + /// base 64 encoded binary data of logo image + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry UpdateCustomLogo(string base64EncodedLogoImage) + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.CustomLogoUriSuffix; + AdminSettingsEntry entry = new AdminSettingsEntry(); + entry.EditUri = uri; + entry.Properties.Add(new PropertyElement(AppsDomainSettingsNameTable.LogoImage, base64EncodedLogoImage)); + return base.Update(entry); + } + + public string FileToBase64(string path) + { + string base64String = ""; + FileStream fs = new FileStream(path, System.IO.FileMode.Open, FileAccess.Read); + byte[] binaryData = new Byte[fs.Length]; + long bytesRead = fs.Read(binaryData, 0, (int)fs.Length); + fs.Close(); + base64String = System.Convert.ToBase64String(binaryData, 0, binaryData.Length); + return base64String; + } + + public string UrlToBase64(Uri uri) + { + string base64String = ""; + WebClient webClient = new WebClient(); + byte[] binaryData = webClient.DownloadData(uri); + base64String = System.Convert.ToBase64String(binaryData, 0, binaryData.Length); + webClient.Dispose(); + return base64String; + } + + /// + /// Gets the domain's CNAME verification status + /// + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry GetCnameVerificationStatus() + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.CnameUriSuffix; + return Get(uri) as AdminSettingsEntry; + } + + /// + /// Updates the domain's CNAME verification status + /// + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry UpdateCnameVerificationStatus() + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.CnameUriSuffix; + AdminSettingsEntry entry = new AdminSettingsEntry(); + entry.EditUri = uri; + entry.Properties.Add(new PropertyElement(AppsDomainSettingsNameTable.Verified, Boolean.TrueString)); + return base.Update(entry); + } + + /// + /// Gets the domain's MX verification status + /// + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry GetMxVerificationStatus() + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.MxUriSuffix; + return Get(uri) as AdminSettingsEntry; + } + + /// + /// Updates the domain's MX verification status + /// + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry UpdateMxVerificationStatus() + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.MxUriSuffix; + AdminSettingsEntry entry = new AdminSettingsEntry(); + entry.EditUri = uri; + entry.Properties.Add(new PropertyElement(AppsDomainSettingsNameTable.Verified, Boolean.TrueString)); + return base.Update(entry); + } + + /// + /// Gets the domain's SSO settings + /// + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry GetSsoSettings() + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.SsoGeneralUriSuffix; + return Get(uri) as AdminSettingsEntry; + } + + /// + /// Updates the domain's SSO settings + /// + /// Enable or Disable SSO for the domain + /// http://www.example.com/sso/signon + /// http://www.example.com/sso/logout + /// http://www.example.com/sso/changepassword + /// CIDR formated IP address + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry UpdateSsoSettings( Boolean enableSSO, String samlSignonUri, + String samlLogoutUri, String changePasswordUri, String ssoWhitelist, Boolean useDomainSpecificIssuer) + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.SsoGeneralUriSuffix; + AdminSettingsEntry entry = new AdminSettingsEntry(); + entry.EditUri = uri; + entry.Properties.Add(new PropertyElement(AppsDomainSettingsNameTable.EnableSSO, enableSSO.ToString())); + entry.Properties.Add(new PropertyElement(AppsDomainSettingsNameTable.SamlSignonUri, samlSignonUri)); + entry.Properties.Add(new PropertyElement(AppsDomainSettingsNameTable.SamlLogoutUri, samlLogoutUri)); + entry.Properties.Add(new PropertyElement(AppsDomainSettingsNameTable.ChangePasswordUri, changePasswordUri)); + entry.Properties.Add(new PropertyElement(AppsDomainSettingsNameTable.SsoWhitelist, ssoWhitelist)); + entry.Properties.Add(new PropertyElement(AppsDomainSettingsNameTable.UseDomainSpecificIssuer, useDomainSpecificIssuer.ToString())); + return base.Update(entry); + } + + /// + /// Gets the domain's SSO Signing Key + /// + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry GetSsoSigningkey() + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.SsoSigningkeyUriSuffix; + return Get(uri) as AdminSettingsEntry; + } + + /// + /// Updates the domain's SSO Signing Key + /// + /// yourBase64EncodedPublicKey + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry UpdateSsoSigningkey(string base64EncodedSigningKey) + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.SsoSigningkeyUriSuffix; + AdminSettingsEntry entry = new AdminSettingsEntry(); + entry.EditUri = uri; + entry.Properties.Add(new PropertyElement(AppsDomainSettingsNameTable.SigningKey, base64EncodedSigningKey)); + return base.Update(entry); + } + + /// + /// Gets the domain's Migration Access settings + /// + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry GetMigrationAccess() + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.MigrationUriSuffix; + return Get(uri) as AdminSettingsEntry; + } + + /// + /// Updates the domain's Migration Access settings + /// + /// Enable or Disable User migration for the domain + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry UpdateMigrationAccess(Boolean enableUserMigration) + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.MigrationUriSuffix; + AdminSettingsEntry entry = new AdminSettingsEntry(); + entry.EditUri = uri; + entry.Properties.Add(new PropertyElement(AppsDomainSettingsNameTable.EnableUserMigration, enableUserMigration.ToString())); + return base.Update(entry); + } + + /// + /// Gets the domain's Email Gateway settings + /// + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry GetEmailGateway() + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.GatewayUriSuffix; + return Get(uri) as AdminSettingsEntry; + } + + /// + /// Updates the domain's Email Gateway settings + /// + /// Either the IP address or hostname of your SMTP server. + /// Google Apps routes outgoing mail to this server. + /// The default value is SMTP. Another value, SMTP_TLS, + /// secures a connection with TLS when delivering the message. + /// a AdminSettingsEntry containing the results of the + /// operation + public AdminSettingsEntry UpdateEmailGateway(string smartHost, string smtpMode) + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.GatewayUriSuffix; + AdminSettingsEntry entry = new AdminSettingsEntry(); + entry.EditUri = uri; + entry.Properties.Add(new PropertyElement(AppsDomainSettingsNameTable.SmartHost, smartHost)); + entry.Properties.Add(new PropertyElement(AppsDomainSettingsNameTable.SmtpMode, smtpMode)); + return base.Update(entry); + } + + /// + /// Gets the domain's Email Routing settings + /// + /// a AdminSettingsFeed containing the results of the + /// operation + public AdminSettingsFeed GetEmailRouting() + { + string uri = AppsDomainSettingsNameTable.AppsAdminSettingsBaseFeedUri + + domain + AppsDomainSettingsNameTable.EmailroutingUriSuffix; + FeedQuery feedQuery = new FeedQuery(uri); + return Query(feedQuery) as AdminSettingsFeed; + } + + /// + /// Event handler. Called when a new Google Domain Settings entry is parsed. + /// + /// the object that's sending the evet + /// FeedParserEventArguments, holds the feedentry + protected void OnParsedNewGoogleMailSettingsItemEntry(object sender, FeedParserEventArgs e) + { + if (e == null) + { + throw new ArgumentNullException("e"); + } + if (e.CreatingEntry == true) + { + e.Entry = new AdminSettingsEntry(); + } + } + + /// + /// Overridden so that new feeds are returned as AppsExtendedFeeds + /// instead of base AtomFeeds. + /// + /// the object which sent the event + /// FeedParserEventArguments, holds the FeedEntry + protected void OnNewFeed(object sender, ServiceEventArgs e) + { + Tracing.TraceMsg("Created new Google Mail Settings Item Feed"); + if (e == null) + { + throw new ArgumentNullException("e"); + } + e.Feed = new AdminSettingsFeed(e.Uri, e.Service); + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/gapps/Applications.csproj gdata-sharp-1.7.0.1/src/gapps/Applications.csproj --- gdata-sharp-1.4.0.2/src/gapps/Applications.csproj 2008-12-12 15:10:21.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gapps/Applications.csproj 2010-11-02 15:10:58.000000000 +0000 @@ -1,7 +1,6 @@ - + Local - 8.0.50727 2.0 {96CCB33A-3B32-480E-B83D-93F0309F7DD2} Debug @@ -26,6 +25,7 @@ true + 2.0 bin\Debug\ @@ -102,6 +102,7 @@ System.Data + System.XML @@ -125,8 +126,12 @@ + + + + @@ -142,10 +147,12 @@ + + diff -Nru gdata-sharp-1.4.0.2/src/gapps/appsextendedentry.cs gdata-sharp-1.7.0.1/src/gapps/appsextendedentry.cs --- gdata-sharp-1.4.0.2/src/gapps/appsextendedentry.cs 2008-12-08 12:13:37.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gapps/appsextendedentry.cs 2009-11-03 14:06:38.000000000 +0000 @@ -56,6 +56,19 @@ this.Properties = value; } } + /// + /// Gets a the Value of a PropertyElement by its Name + /// + /// a string containing the results of the execution + [Obsolete("this method was mispelled. Please use getPropertyValueByName from now on")] + public string getPropetyValueByName(string name) + { + PropertyElement property = this.getPropertyByName(name); + if (property != null) + return property.Value; + else + return null; + } /// /// Gets a PropertyElement by its Name @@ -78,7 +91,7 @@ /// Gets a the Value of a PropertyElement by its Name /// /// a string containing the results of the execution - public string getPropetyValueByName(string name) + public string getPropertyValueByName(string name) { PropertyElement property = this.getPropertyByName(name); if (property != null) diff -Nru gdata-sharp-1.4.0.2/src/gapps/appspropertyservice.cs gdata-sharp-1.7.0.1/src/gapps/appspropertyservice.cs --- gdata-sharp-1.4.0.2/src/gapps/appspropertyservice.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gapps/appspropertyservice.cs 2010-11-02 11:46:11.000000000 +0000 @@ -0,0 +1,135 @@ +/* Copyright (c) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using Google.GData.Client; +using Google.GData.Extensions.Apps; +using System.IO; + +namespace Google.GData.Apps +{ + /// + /// A base Service for all property(name-value) based services. + /// + /// AppsPropertyService works with AppsExtendedFeed and + /// AppsExtendedEntry + /// + public class AppsPropertyService : Service + { + public AppsPropertyService(string domain, string applicationName) + : base(AppsNameTable.GAppsService, applicationName) + { + this.domain = domain; + this.NewAtomEntry += new FeedParserEventHandler(this.OnParsedNewPropertyEntry); + this.NewFeed += new ServiceEventHandler(this.OnNewFeed); + // You can set factory.methodOverride = true if you are behind a + // proxy that filters out HTTP methods such as PUT and DELETE. + } + + private string domain; + + /// + /// Accessor for Domain property. + /// + public string DomainName + { + get { return domain; } + } + + /// + /// Event handler. Called when a new AppsExtendedEntry is parsed. + /// + /// the object that's sending the event + /// FeedParserEventArguments, holds the feedentry + protected void OnParsedNewPropertyEntry(object sender, FeedParserEventArgs e) + { + if (e == null) + { + throw new ArgumentNullException("e"); + } + if (e.CreatingEntry) + { + e.Entry = new AppsExtendedEntry(); + } + } + + /// + /// Returns a single page of the feed at the specified URI. + /// + /// the URI of the feed + /// + public AppsExtendedFeed QueryExtendedFeed(Uri uri) + { + //By default, get a single page + return QueryExtendedFeed(uri, false); + } + + /// + /// Returns the feed at the end URI specified. + /// + /// the URI of the feed + /// if true, returns all the pages + /// + public AppsExtendedFeed QueryExtendedFeed(Uri uri, Boolean shouldGetAllPages) + { + try + { + Stream feedStream = base.Query(uri); + AppsExtendedFeed feed = new AppsExtendedFeed(uri, this); + feed.Parse(feedStream, AlternativeFormat.Atom); + feedStream.Close(); + if (shouldGetAllPages) + { + if (true) + { + AtomLink next, prev = null; + while ((next = feed.Links.FindService("next", null)) != null + && next != prev) + { + feedStream = base.Query(new Uri(next.HRef.ToString())); + feed.Parse(feedStream, AlternativeFormat.Atom); + feedStream.Close(); + prev = next; + } + } + } + return feed; + } + catch (GDataRequestException e) + { + AppsException a = AppsException.ParseAppsException(e); + throw (a == null ? e : a); + } + } + + /// + /// Overridden so that new feeds are returned as AppsExtendedFeeds + /// instead of base AtomFeeds. + /// + /// the object which sent the event + /// FeedParserEventArguments, holds the FeedEntry + protected void OnNewFeed(object sender, ServiceEventArgs e) + { + Tracing.TraceMsg("Created new AppsExtendedFeed"); + if (e == null) + { + throw new ArgumentNullException("e"); + } + e.Feed = new AppsExtendedFeed(e.Uri, e.Service); + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/gapps/appsservice.cs gdata-sharp-1.7.0.1/src/gapps/appsservice.cs --- gdata-sharp-1.4.0.2/src/gapps/appsservice.cs 2008-12-08 12:13:37.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gapps/appsservice.cs 2010-03-23 16:40:45.000000000 +0000 @@ -117,7 +117,7 @@ { Service service = new Service(AppsNameTable.GAppsService,"apps-"+domain); service.setUserCredentials(adminEmailAddress, adminPassword); - return service.QueryAuthenticationToken(); + return service.QueryClientLoginToken(); } /// @@ -325,6 +325,7 @@ emailListService.RequestFactory = factory; nicknameService.RequestFactory = factory; userAccountService.RequestFactory = factory; + groupsService.RequestFactory = factory; } diff -Nru gdata-sharp-1.4.0.2/src/gapps/googlemailsettingsentry.cs gdata-sharp-1.7.0.1/src/gapps/googlemailsettingsentry.cs --- gdata-sharp-1.4.0.2/src/gapps/googlemailsettingsentry.cs 2008-12-08 12:13:37.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gapps/googlemailsettingsentry.cs 2009-11-03 14:06:38.000000000 +0000 @@ -78,6 +78,7 @@ /// Gets a the Value of a PropertyElement by its Name /// /// a string containing the results of the execution + [Obsolete("this method was mispelled. Please use getPropertyValueByName from now on")] public string getPropetyValueByName(string name) { PropertyElement property = this.getPropertyByName(name); @@ -88,6 +89,18 @@ } /// + /// Gets a the Value of a PropertyElement by its Name + /// + /// a string containing the results of the execution + public string getPropertyValueByName(string name) + { + PropertyElement property = this.getPropertyByName(name); + if (property != null) + return property.Value; + else + return null; + } + /// /// Updates this GoogleMailSettingsEntry. /// /// the updated GoogleMailSettingsEntry diff -Nru gdata-sharp-1.4.0.2/src/gapps/groupsservice.cs gdata-sharp-1.7.0.1/src/gapps/groupsservice.cs --- gdata-sharp-1.4.0.2/src/gapps/groupsservice.cs 2009-01-27 16:18:31.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gapps/groupsservice.cs 2010-06-15 12:25:34.000000000 +0000 @@ -56,9 +56,12 @@ /// /// Accessor for Domain property. /// + /// The hosted domain in which the Google Groups are + /// being set up public String Domain { get { return domain; } + set { domain = value; } } /// @@ -240,17 +243,29 @@ } /// - /// Retrieves all members of the group + /// Retrieves all non-suspened members of the group /// /// Groups's id - /// When set to false, will return only direct/immediate - /// members, as opposed to all transitive members. /// a AppsExtendedFeed containing all the AppsExtendedEntry /// from the Domain public AppsExtendedFeed RetrieveAllMembers(String groupId) { + return RetrieveAllMembers(groupId, false); + } + + /// + /// Retrieves all members of the group + /// + /// Groups's id + /// When set to true, will also return suspended users that + /// are members of the group. + /// a AppsExtendedFeed containing all the AppsExtendedEntry + /// from the Domain + public AppsExtendedFeed RetrieveAllMembers(String groupId, Boolean includeSuspendedUsers) + { Uri getGroupMembersUri = new Uri(AppsGroupsNameTable.AppsGoogleGroupsBaseFeedUri + "/" - + domain + "/" + groupId + "/" + memberUriSuffix); + + domain + "/" + groupId + "/" + memberUriSuffix + "?includeSuspendedUsers=" + + includeSuspendedUsers); return QueryGroups(getGroupMembersUri); } diff -Nru gdata-sharp-1.4.0.2/src/gapps/multidomainmanagementservice.cs gdata-sharp-1.7.0.1/src/gapps/multidomainmanagementservice.cs --- gdata-sharp-1.4.0.2/src/gapps/multidomainmanagementservice.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gapps/multidomainmanagementservice.cs 2010-11-02 15:10:58.000000000 +0000 @@ -0,0 +1,244 @@ +using System; +using System.Collections.Generic; +using System.Web; +using Google.GData.Extensions.Apps; + +namespace Google.GData.Apps +{ + /// + /// Service class for managing multiple domains within Google Apps. + /// + public class MultiDomainManagementService : AppsPropertyService + { + public enum MultiDomainUserProperty + { + AliasEmail, FirstName, IpWhitelisted, IsAdmin, IsChangePasswordAtNextLogin, IsSuspended, LastName, NewEmail, Password, UserEmail + } + + public MultiDomainManagementService(String domain, String applicationName) + : base(domain, applicationName) + { + } + + /// + /// Creates a new user for the specified domain. + /// + /// The domain to use to create the user + /// The user's email address + /// The user's password + /// The user's first name + /// The user's last name + /// Whether the user is an administrator for the domain + /// The created user + public AppsExtendedEntry CreateDomainUser(String domain, String userEmail, String password, + String firstName, String lastName, bool isAdmin) + { + Uri userUri = new Uri(String.Format("{0}/{1}", + AppsMultiDomainNameTable.AppsMultiDomainUserBaseFeedUri, domain)); + + AppsExtendedEntry entry = new AppsExtendedEntry(); + entry.Properties.Add(new PropertyElement(AppsMultiDomainNameTable.UserEmail, userEmail)); + entry.Properties.Add(new PropertyElement(AppsMultiDomainNameTable.Password, password)); + entry.Properties.Add(new PropertyElement(AppsMultiDomainNameTable.FirstName, firstName)); + entry.Properties.Add(new PropertyElement(AppsMultiDomainNameTable.LastName, lastName)); + entry.Properties.Add(new PropertyElement(AppsMultiDomainNameTable.IsAdmin, isAdmin.ToString())); + return Insert(userUri, entry); + } + + /// + /// Updates the given user + /// + /// The user's domain + /// The user's email address + /// The set of attributes to update + /// The updated user + public AppsExtendedEntry UpdateDomainUser(String domain, String userEmail, IDictionary attributes) + { + AppsExtendedEntry entry = new AppsExtendedEntry(); + String uri = String.Format("{0}/{1}/{2}", + AppsMultiDomainNameTable.AppsMultiDomainUserBaseFeedUri, domain, userEmail); + entry.EditUri = new Uri(uri); + + foreach (KeyValuePair mapEntry in attributes) + { + String value = mapEntry.Value; + if (string.IsNullOrEmpty(value)) + { + continue; + } + + switch (mapEntry.Key) + { + case MultiDomainUserProperty.FirstName: + entry.Properties.Add(new PropertyElement(AppsMultiDomainNameTable.FirstName, value)); + break; + case MultiDomainUserProperty.IpWhitelisted: + entry.Properties.Add(new PropertyElement(AppsMultiDomainNameTable.IpWhitelisted, value)); + break; + case MultiDomainUserProperty.IsAdmin: + entry.Properties.Add(new PropertyElement(AppsMultiDomainNameTable.IsAdmin, value)); + break; + case MultiDomainUserProperty.IsChangePasswordAtNextLogin: + entry.Properties.Add(new PropertyElement(AppsMultiDomainNameTable.IsChangePasswordAtNextLogin, value)); + break; + case MultiDomainUserProperty.IsSuspended: + entry.Properties.Add(new PropertyElement(AppsMultiDomainNameTable.IsSuspended, value)); + break; + case MultiDomainUserProperty.LastName: + entry.Properties.Add(new PropertyElement(AppsMultiDomainNameTable.LastName, value)); + break; + case MultiDomainUserProperty.NewEmail: + entry.Properties.Add(new PropertyElement(AppsMultiDomainNameTable.NewEmail, value)); + break; + case MultiDomainUserProperty.Password: + entry.Properties.Add(new PropertyElement(AppsMultiDomainNameTable.Password, value)); + break; + case MultiDomainUserProperty.UserEmail: + entry.Properties.Add(new PropertyElement(AppsMultiDomainNameTable.UserEmail, value)); + break; + default: + break; + } + } + return Update(entry); + } + + /// + /// Renames an existing user + /// + /// The user's domain + /// Current user's email address + /// New user's email address + /// The renamed user + public AppsExtendedEntry RenameDomainUser(String domain, String userEmail, String newEmail) + { + AppsExtendedEntry entry = new AppsExtendedEntry(); + String uri = String.Format("{0}/{1}/{2}", + AppsMultiDomainNameTable.AppsMultiDomainUserBaseFeedUri, domain, userEmail); + entry.EditUri = new Uri(uri); + entry.Properties.Add(new PropertyElement(AppsMultiDomainNameTable.NewEmail, newEmail)); + return Update(entry); + } + + /// + /// Retrieves an user from the domain + /// + /// The user's domain + /// The user's email address + /// The user identified by the given email address + public AppsExtendedEntry RetrieveDomainUser(String domain, String userEmail) + { + String uri = String.Format("{0}/{1}/{2}", + AppsMultiDomainNameTable.AppsMultiDomainUserBaseFeedUri, + domain, userEmail); + + return Get(uri) as AppsExtendedEntry; + } + + /// + /// Retrieves all users from the domain + /// + /// The users' domain + /// Feed containing all domain users + public AppsExtendedFeed RetrieveAllDomainUsers(String domain) + { + String uri = String.Format("{0}/{1}", + AppsMultiDomainNameTable.AppsMultiDomainUserBaseFeedUri, + domain); + + return QueryExtendedFeed(new Uri(uri), true); + } + + /// + /// Deletes an user from the domain + /// + /// The user's domain + /// The user's email address + public void DeleteDomainUser(String domain, String userEmail) + { + String uri = String.Format("{0}/{1}/{2}", + AppsMultiDomainNameTable.AppsMultiDomainUserBaseFeedUri, + domain, + userEmail); + Delete(new Uri(uri)); + } + + /// + /// Creates an alias for an user in the domain + /// + /// The user's domain + /// The user's email address + /// The alias to be added to the user + /// The created alias + public AppsExtendedEntry CreateDomainUserAlias(String domain, String userEmail, String aliasEmail) + { + Uri userUri = new Uri(String.Format("{0}/{1}", + AppsMultiDomainNameTable.AppsMultiDomainAliasBaseFeedUri, domain)); + + AppsExtendedEntry entry = new AppsExtendedEntry(); + entry.Properties.Add(new PropertyElement(AppsMultiDomainNameTable.UserEmail, userEmail)); + entry.Properties.Add(new PropertyElement(AppsMultiDomainNameTable.AliasEmail, aliasEmail)); + return Insert(userUri, entry); + } + + /// + /// Retrieves an alias for the user in the domain + /// + /// The user alias's domain or the domain in the user's primary email address + /// The alias's email address + /// The alias identified by the email address + public AppsExtendedEntry RetrieveDomainUserAlias(String domain, String aliasEmail) + { + String uri = String.Format("{0}/{1}/{2}", + AppsMultiDomainNameTable.AppsMultiDomainAliasBaseFeedUri, + domain, aliasEmail); + + return Get(uri) as AppsExtendedEntry; + } + + /// + /// Retrieves all aliases from the domain + /// + /// The aliases' domain or a user's primary email address domain + /// Feed containing all aliases for the domain + public AppsExtendedFeed RetrieveAllDomainUserAlias(String domain) + { + String uri = String.Format("{0}/{1}", + AppsMultiDomainNameTable.AppsMultiDomainAliasBaseFeedUri, + domain); + + return QueryExtendedFeed(new Uri(uri), true); + } + + /// + /// Retrieves all aliases from the domain for an user + /// + /// The alias's domain or the user's primary email address domain + /// The user's email address + /// Feed containing all aliases for the domain user + public AppsExtendedFeed RetrieveAllDomainUserAliasForUser(String domain, String userEmail) + { + String uri = String.Format("{0}/{1}?userEmail={2}", + AppsMultiDomainNameTable.AppsMultiDomainAliasBaseFeedUri, + domain, + userEmail); + + return QueryExtendedFeed(new Uri(uri), true); + } + + /// + /// Deletes an alias from a domain user + /// + /// The alias's domain or the user's primary email address domain + /// The user's email address + public void DeleteDomainUserAlias(String domain, String userEmail) + { + String uri = String.Format("{0}/{1}/{2}", + AppsMultiDomainNameTable.AppsMultiDomainAliasBaseFeedUri, + domain, + userEmail); + Delete(new Uri(uri)); + } + } +} + \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/src/gapps/orgmanagementservice.cs gdata-sharp-1.7.0.1/src/gapps/orgmanagementservice.cs --- gdata-sharp-1.4.0.2/src/gapps/orgmanagementservice.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gapps/orgmanagementservice.cs 2010-11-02 11:46:11.000000000 +0000 @@ -0,0 +1,293 @@ +using System; +using System.Collections.Generic; +using System.Web; +using Google.GData.Extensions.Apps; + +namespace Google.GData.Apps +{ + /// + /// Service class for managing organization units and users within Google Apps. + /// + /// An OrgUnit path is the URL-encoding (e.g., using HttpUtility.UrlPathEncode) of an OrgUnit's lineage, + /// concatenated together with the slash ('/') character. + /// + public class OrganizationService : AppsPropertyService + { + public enum OrgUnitProperty + { + Name, Description, ParentOrgUnitPath, BlockInheritance, UsersToMove + } + + public OrganizationService(String domain, String applicationName) + : base(domain, applicationName) + { + } + + /// + /// Retrieves the customer Id that will be used for all other operations. + /// + /// the customer domain + /// + public AppsExtendedEntry RetrieveCustomerId(string domain) + { + String customerIdUri = String.Format("{0}/{1}", + AppsOrganizationNameTable.AppsCustomerBaseFeedUri, AppsOrganizationNameTable.CustomerId); + return Get(customerIdUri) as AppsExtendedEntry; + } + + /// + /// Create a new organization unit under the given parent. + /// + /// The unique Id of the customer retrieved through customer feed. + /// The new organization name. + /// The path of the parent organization unit where + /// '/' denotes the root of the organization hierarchy. + /// For any OrgUnits to be created directly under root, specify '/' as parent path. + /// A description for the organization unit created. + /// If true, blocks inheritance of policies from + /// parent units. + /// + public AppsExtendedEntry CreateOrganizationUnit(String customerId, String orgUnitName, + String parentOrgUnitPath, String description, bool blockInheritance) + { + Uri orgUnitUri = new Uri(String.Format("{0}/{1}", + AppsOrganizationNameTable.AppsOrgUnitBaseFeedUri, customerId)); + + AppsExtendedEntry entry = new AppsExtendedEntry(); + entry.Properties.Add(new PropertyElement(AppsOrganizationNameTable.ParentOrgUnitPath, parentOrgUnitPath)); + entry.Properties.Add(new PropertyElement(AppsOrganizationNameTable.Description, description)); + entry.Properties.Add(new PropertyElement(AppsOrganizationNameTable.OrgUnitName, orgUnitName)); + entry.Properties.Add(new PropertyElement(AppsOrganizationNameTable.BlockInheritance, blockInheritance.ToString())); + return Insert(orgUnitUri, entry); ; + } + + + /// + /// Retrieves an organization unit from the customer's domain. + /// + /// The path of the unit to be retrieved for e.g /corp + /// + public AppsExtendedEntry RetrieveOrganizationUnit(String customerId, String orgUnitPath) + { + String uri = String.Format("{0}/{1}/{2}", + AppsOrganizationNameTable.AppsOrgUnitBaseFeedUri, + customerId, orgUnitPath); + + return Get(uri) as AppsExtendedEntry; + + } + + /// + /// Retrieves all organization units for the given customer account. + /// + /// The unique Id of the customer retrieved through customer feed. + /// + public AppsExtendedFeed RetrieveAllOrganizationUnits(String customerId) + { + String uri = String.Format("{0}/{1}?get=all", AppsOrganizationNameTable.AppsOrgUnitBaseFeedUri, customerId); + return QueryExtendedFeed(new Uri(uri), true); + } + + /// + /// Retrieves all the child units of the given organization unit. + /// + /// The unique Id of the customer retrieved through customer feed. + /// The path of the unit to be retrieved for e.g /corp + /// + public AppsExtendedFeed RetrieveChildOrganizationUnits(String customerId, String orgUnitPath) + { + String uri = String.Format("{0}/{1}?get=children&orgUnitPath={2}", + AppsOrganizationNameTable.AppsOrgUnitBaseFeedUri, customerId, + HttpUtility.UrlPathEncode(orgUnitPath)); + return QueryExtendedFeed(new Uri(uri), true); + } + + /// + /// Deletes the given organization unit. The unit must not have any OrgUsers or any + /// child OrgUnits for it to be deleted + /// + /// The unique Id of the customer retrieved through customer feed. + /// The path of the unit to be retrieved for e.g /corp + public void DeleteOrganizationUnit(String customerId, String orgUnitPath) + { + String uri = String.Format("{0}/{1}/{2}", AppsOrganizationNameTable.AppsOrgUnitBaseFeedUri, customerId, + orgUnitPath); + Delete(new Uri(uri)); + } + + /// + /// Updates the given organization attributes. + /// attributes.USERS_TO_MOVE is a comma separated list of email addresses that are to be moved across orgUnits. + /// + /// The unique Id of the customer retrieved through customer feed. + /// The path of the unit to be retrieved for e.g /corp + /// A dictionary of OrgUnitProperty and values to be updated. + /// + public AppsExtendedEntry UpdateOrganizationUnit(String customerId, String orgUnitPath, IDictionary attributes) + { + AppsExtendedEntry entry = new AppsExtendedEntry(); + String uri = String.Format("{0}/{1}/{2}", + AppsOrganizationNameTable.AppsOrgUnitBaseFeedUri, customerId, + orgUnitPath); + entry.EditUri = new Uri(uri); + foreach (KeyValuePair mapEntry in attributes) + { + String value = mapEntry.Value; + if (string.IsNullOrEmpty(value)) + { + continue; + } + switch (mapEntry.Key) + { + case OrgUnitProperty.Name: + entry.Properties.Add(new PropertyElement(AppsOrganizationNameTable.OrgUnitName, value)); + break; + case OrgUnitProperty.ParentOrgUnitPath: + entry.Properties.Add(new PropertyElement(AppsOrganizationNameTable.ParentOrgUnitPath, value)); + + break; + case OrgUnitProperty.Description: + entry.Properties.Add(new PropertyElement(AppsOrganizationNameTable.Description, value)); + break; + case OrgUnitProperty.BlockInheritance: + entry.Properties.Add(new PropertyElement(AppsOrganizationNameTable.BlockInheritance, value)); + break; + case OrgUnitProperty.UsersToMove: + entry.Properties.Add(new PropertyElement(AppsOrganizationNameTable.UsersToMove, value)); + + break; + default: + break; + } + } + return Update(entry); + } + + /// + /// Updates the orgunit of an organization user. + /// + /// + /// + /// The email address of the user + /// The old organization unit path. + /// If specified, validates the OrgUser's current path. + /// + /// + public AppsExtendedEntry UpdateOrganizationUser(String customerId, String orgUserEmail, + String newOrgUnitPath, String oldOrgUnitPath) + { + String uri = String.Format("{0}/{1}/{2}", + AppsOrganizationNameTable.AppsOrgUserBaseFeedUri, customerId, + orgUserEmail); + AppsExtendedEntry entry = new AppsExtendedEntry(); + entry.EditUri = new Uri(uri); + + if (!string.IsNullOrEmpty(oldOrgUnitPath)) + { + entry.Properties.Add(new PropertyElement(AppsOrganizationNameTable.OldOrgUnitPath, oldOrgUnitPath)); + } + entry.Properties.Add(new PropertyElement(AppsOrganizationNameTable.NewOrgUnitPath, newOrgUnitPath)); + return Update(entry); + } + + /// + /// Updates the orgunit of an organization user. + /// + /// + /// The email address of the user. + /// The new organization unit path. + /// + public AppsExtendedEntry UpdateOrganizationUser(String customerId, String orgUserEmail, + String newOrgUnitPath) + { + return UpdateOrganizationUser(customerId, orgUserEmail, newOrgUnitPath, null); + } + + /// + /// Retrieves the details of a given organization user. + /// + /// + /// The email address of the user + /// AppsExtendedEntry + public AppsExtendedEntry RetrieveOrganizationUser(String customerId, String orgUserEmail) + { + String uri = String.Format("{0}/{1}/{2}", + AppsOrganizationNameTable.AppsOrgUserBaseFeedUri, customerId, + orgUserEmail); + return Get(uri) as AppsExtendedEntry; + + } + + /// + /// Retrieves the next page of a paginated feed using resumeKey from the previous feed. + /// i.e. atom:next link + /// + /// + /// + public AppsExtendedFeed RetrieveNextPageFromResumeKey(String resumeKey) + { + return QueryExtendedFeed(new Uri(resumeKey), false); + } + + /// + /// Retrieves all users belongging to all org units. This may take a long time to execute for + /// domains with large number of users. Instead use pagination i.e. + /// RetrieveFirstPageOrganizationUsers + /// followed by RetrieveNextPageFromResumeKey + /// + /// + /// + public AppsExtendedFeed RetrieveAllOrganizationUsers(String customerId) + { + string uri = String.Format("{0}/{1}?get=all", + AppsOrganizationNameTable.AppsOrgUserBaseFeedUri, customerId); + return QueryExtendedFeed(new Uri(uri), true); + } + + /// + /// Retrieves first page of results for all org users query. For subsequent pages, + /// follow up with RetrieveNextPageFromResumeKey + /// + /// + /// + public AppsExtendedFeed RetrieveFirstPageOrganizationUsers(String customerId) + { + string uri = String.Format("{0}/{1}?get=all", + AppsOrganizationNameTable.AppsOrgUserBaseFeedUri, customerId); + return QueryExtendedFeed(new Uri(uri), false); + } + + + /// + /// Retrieves all users by org unit. This may take a long time to execute for domains with + /// large number of users. Instead use pagination i.e. + /// RetrieveFirstPageOfOrganizationUsersByOrgUnit + /// followed by RetrieveNextPageFromResumeKey + /// + /// The unique Id of the customer retrieved through customer feed. + /// The path of the unit to be retrieved for e.g /corp + /// + public AppsExtendedFeed RetrieveAllOrganizationUsersByOrgUnit(String customerId, String orgUnitPath) + { + String uri = String.Format("{0}/{1}?get=children&orgUnitPath={2}", + AppsOrganizationNameTable.AppsOrgUserBaseFeedUri, customerId, + HttpUtility.UrlPathEncode(orgUnitPath)); + return QueryExtendedFeed(new Uri(uri), true); + } + + /// + /// Retrieves first page of results for all org users by orgunit query. For subsequent pages, + /// follow up with RetrieveNextPageFromResumeKey + /// + /// The unique Id of the customer retrieved through customer feed. + /// The path of the unit to be retrieved for e.g /corp + /// + public AppsExtendedFeed RetrieveFirstPageOfOrganizationUsersByOrgUnit(String customerId, String orgUnitPath) + { + String uri = String.Format("{0}/{1}?get=children&orgUnitPath={2}", + AppsOrganizationNameTable.AppsOrgUserBaseFeedUri, customerId, + HttpUtility.UrlPathEncode(orgUnitPath)); + return QueryExtendedFeed(new Uri(uri), false); + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/gbase/Base.csproj gdata-sharp-1.7.0.1/src/gbase/Base.csproj --- gdata-sharp-1.4.0.2/src/gbase/Base.csproj 2008-12-12 15:10:21.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gbase/Base.csproj 2009-10-21 14:06:48.000000000 +0000 @@ -1,7 +1,6 @@ - + Local - 8.0.50727 2.0 {C9B83904-8002-455C-AA48-C47CDF74F365} Debug @@ -26,6 +25,7 @@ true + 2.0 bin\Debug\ diff -Nru gdata-sharp-1.4.0.2/src/gcalendar/Calendar.csproj gdata-sharp-1.7.0.1/src/gcalendar/Calendar.csproj --- gdata-sharp-1.4.0.2/src/gcalendar/Calendar.csproj 2008-12-12 15:10:21.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gcalendar/Calendar.csproj 2009-10-21 14:06:48.000000000 +0000 @@ -1,7 +1,6 @@ - + Local - 8.0.50727 2.0 {0AD0FA26-A071-4CAC-851C-05B6C26B9888} Debug @@ -26,6 +25,7 @@ true + 2.0 bin\Debug\ diff -Nru gdata-sharp-1.4.0.2/src/gcalendar/calendarentry.cs gdata-sharp-1.7.0.1/src/gcalendar/calendarentry.cs --- gdata-sharp-1.4.0.2/src/gcalendar/calendarentry.cs 2007-10-15 11:20:09.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gcalendar/calendarentry.cs 2009-11-25 14:22:39.000000000 +0000 @@ -109,7 +109,7 @@ } set { - setCalendarExtension(GDataParserNameTable.XmlHiddenElement, value.ToString()); + setCalendarExtension(GDataParserNameTable.XmlHiddenElement, Utilities.ConvertBooleanToXSDString(value)); } } @@ -124,7 +124,7 @@ } set { - setCalendarExtension(GDataParserNameTable.XmlSelectedElement, value.ToString()); + setCalendarExtension(GDataParserNameTable.XmlSelectedElement, Utilities.ConvertBooleanToXSDString(value)); } } diff -Nru gdata-sharp-1.4.0.2/src/gcalendar/webcontent.cs gdata-sharp-1.7.0.1/src/gcalendar/webcontent.cs --- gdata-sharp-1.4.0.2/src/gcalendar/webcontent.cs 2008-10-15 12:50:39.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gcalendar/webcontent.cs 2010-02-09 10:23:43.000000000 +0000 @@ -34,6 +34,7 @@ public class WebContent : IExtensionElementFactory { private string url; + private string display; private uint width; private uint height; private SortedList gadgetPrefs; @@ -48,6 +49,16 @@ get { return this.url; } set { this.url = value; } } + + ////////////////////////////////////////////////////////////////////// + /// Display property + /// + ////////////////////////////////////////////////////////////////////// + public string Display + { + get { return this.display; } + set { this.display = value; } + } ////////////////////////////////////////////////////////////////////// /// width of the iframe/gif @@ -124,6 +135,13 @@ webContent.Url = value; } + value = node.Attributes[GDataParserNameTable.XmlAttributeDisplay] != null ? + node.Attributes[GDataParserNameTable.XmlAttributeDisplay].Value : null; + if (value != null) + { + webContent.Display = value; + } + value = node.Attributes[GDataParserNameTable.XmlAttributeWidth] != null ? node.Attributes[GDataParserNameTable.XmlAttributeWidth].Value : null; @@ -208,6 +226,7 @@ { writer.WriteStartElement(XmlPrefix, XmlName, XmlNameSpace); writer.WriteAttributeString(GDataParserNameTable.XmlAttributeUrl, this.Url); + writer.WriteAttributeString(GDataParserNameTable.XmlAttributeDisplay, this.Display); writer.WriteAttributeString(GDataParserNameTable.XmlAttributeHeight, this.Height.ToString()); writer.WriteAttributeString(GDataParserNameTable.XmlAttributeWidth, this.Width.ToString()); if (this.gadgetPrefs != null && this.gadgetPrefs.Count > 0) diff -Nru gdata-sharp-1.4.0.2/src/gcodesearch/Codesearch.csproj gdata-sharp-1.7.0.1/src/gcodesearch/Codesearch.csproj --- gdata-sharp-1.4.0.2/src/gcodesearch/Codesearch.csproj 2008-12-16 11:11:21.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gcodesearch/Codesearch.csproj 2009-10-21 14:06:48.000000000 +0000 @@ -1,7 +1,6 @@ - + Local - 8.0.50727 2.0 {6C9717F6-4CEF-4665-82DA-31073493FFA0} Debug @@ -26,6 +25,7 @@ true + 2.0 bin\Debug\ diff -Nru gdata-sharp-1.4.0.2/src/gcontacts/contactentry.cs gdata-sharp-1.7.0.1/src/gcontacts/contactentry.cs --- gdata-sharp-1.4.0.2/src/gcontacts/contactentry.cs 2009-02-16 17:39:06.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gcontacts/contactentry.cs 2009-07-02 10:35:15.000000000 +0000 @@ -28,234 +28,7 @@ namespace Google.GData.Contacts { - /// - /// short table to hold the namespace and the prefix - /// - public class ContactsNameTable - { - /// static string to specify the Contacts namespace supported - public const string NSContacts = "http://schemas.google.com/contact/2008"; - /// static string to specify the Google Contacts prefix used - public const string contactsPrefix = "gContact"; - - /// - /// Group Member ship info element string - /// - public const string GroupMembershipInfo = "groupMembershipInfo"; - - /// - /// SystemGroup element, indicating that this entry is a system group - /// - public const string SystemGroupElement = "systemGroup"; - } - - - - /// - /// an element is defined that represents a group to which the contact belongs - /// - public class GroupMembership: SimpleElement - { - /// the href attribute - public const string XmlAttributeHRef = "href"; - /// the deleted attribute - public const string XmlAttributeDeleted = "deleted"; - - /// - /// default constructor - /// - public GroupMembership() - : base(ContactsNameTable.GroupMembershipInfo, ContactsNameTable.contactsPrefix, ContactsNameTable.NSContacts) - { - this.Attributes.Add(XmlAttributeHRef, null); - this.Attributes.Add(XmlAttributeDeleted, null); - } - - ///////////////////////////////////////////////////////////////////// - /// Identifies the group to which the contact belongs or belonged. - /// The group is referenced by its id. - ////////////////////////////////////////////////////////////////////// - public string HRef - { - get - { - return this.Attributes[XmlAttributeHRef] as string; - } - set - { - this.Attributes[XmlAttributeHRef] = value; - } - } - - ///////////////////////////////////////////////////////////////////// - /// Means, that the group membership was removed for the contact. - /// This attribute will only be included if showdeleted is specified - /// as query parameter, otherwise groupMembershipInfo for groups a contact - /// does not belong to anymore is simply not returned. - ////////////////////////////////////////////////////////////////////// - public string Deleted - { - get - { - return this.Attributes[XmlAttributeDeleted] as string; - } - } - } - - - /// - /// extension element to represent a system group - /// - public class SystemGroup : SimpleElement - { - /// - /// id attribute for the system group element - /// - /// - public const string XmlAttributeId = "id"; - - /// - /// default constructor - /// - public SystemGroup() - : base(ContactsNameTable.SystemGroupElement, ContactsNameTable.contactsPrefix, ContactsNameTable.NSContacts) - { - this.Attributes.Add(XmlAttributeId, null); - } - - ///////////////////////////////////////////////////////////////////// - /// Identifies the system group. Note that you still need - /// to use the group entries href membership to retrieve the group - /// - ////////////////////////////////////////////////////////////////////// - public string Id - { - get - { - return this.Attributes[XmlAttributeId] as string; - } - } - } - - /// - /// abstract class for a basecontactentry, used for contacts and groups - /// - public abstract class BaseContactEntry : AbstractEntry, IContainsDeleted - { - private ExtensionCollection xproperties; - - - /// - /// Constructs a new BaseContactEntry instance - /// to indicate that it is an event. - /// - public BaseContactEntry() - : base() - { - Tracing.TraceMsg("Created BaseContactEntry Entry"); - this.AddExtension(new ExtendedProperty()); - } - - - - /// - /// returns the extended properties on this object - /// - /// - public ExtensionCollection ExtendedProperties - { - get - { - if (this.xproperties == null) - { - this.xproperties = new ExtensionCollection(this); - } - return this.xproperties; - } - } - - - /// - /// if this is a previously deleted contact, returns true - /// to delete a contact, use the delete method - /// - public bool Deleted - { - get - { - if (FindExtension(GDataParserNameTable.XmlDeletedElement, - BaseNameTable.gNamespace) != null) - { - return true; - } - return false; - } - } - } - - ////////////////////////////////////////////////////////////////////// - /// - /// Entry API customization class for defining entries in an Group feed. - /// - ////////////////////////////////////////////////////////////////////// - public class GroupEntry : BaseContactEntry - { - - /// - /// default contact term string for the contact relationship link - /// - public static string GroupTerm = "http://schemas.google.com/contact/2008#group"; - /// ` - /// Category used to label entries that contain contact extension data. - /// - public static AtomCategory GROUP_CATEGORY = - new AtomCategory(GroupEntry.GroupTerm, new AtomUri(BaseNameTable.gKind)); - - /// - /// Constructs a new ContactEntry instance with the appropriate category - /// to indicate that it is an event. - /// - public GroupEntry() - : base() - { - Tracing.TraceMsg("Created Group Entry"); - this.AddExtension(new SystemGroup()); - Categories.Add(GROUP_CATEGORY); - } - - /// - /// typed override of the Update method - /// - /// - public new GroupEntry Update() - { - return base.Update() as GroupEntry; - } - - /// - /// returns the systemgroup id, if this groupentry represents - /// a system group. - /// The values of the system group ids corresponding to these - /// groups can be found in the Reference Guide for the Contacts Data API. - /// Currently the values can be Contacts, Friends, Family and Coworkers - /// - /// - public string SystemGroup - { - get - { - SystemGroup sg = FindExtension(ContactsNameTable.SystemGroupElement, - ContactsNameTable.NSContacts) as SystemGroup; - if (sg != null) - { - return sg.Id; - } - return null; - } - } - - - } + ////////////////////////////////////////////////////////////////////// /// @@ -279,9 +52,21 @@ private ExtensionCollection emails; private ExtensionCollection ims; private ExtensionCollection phonenumbers; - private ExtensionCollection postals; + private ExtensionCollection structuredAddress; private ExtensionCollection organizations; private ExtensionCollection groups; + private ExtensionCollection calendars; + private ExtensionCollection events; + private ExtensionCollection externalIds; + private ExtensionCollection hobbies; + private ExtensionCollection jots; + private ExtensionCollection languages; + private ExtensionCollection relations; + private ExtensionCollection userDefinedFiels; + private ExtensionCollection websites; + + + /// @@ -294,7 +79,34 @@ Tracing.TraceMsg("Created Contact Entry"); Categories.Add(CONTACT_CATEGORY); this.AddExtension(new GroupMembership()); - ContactsExtensions.AddExtension(this); + this.AddExtension(new Where()); + ContactsKindExtensions.AddExtension(this); + + // colletions + this.AddExtension(new CalendarLink()); + this.AddExtension(new Event()); + this.AddExtension(new ExternalId()); + this.AddExtension(new Hobby()); + this.AddExtension(new Jot()); + this.AddExtension(new Language()); + this.AddExtension(new Relation()); + this.AddExtension(new UserDefinedField()); + this.AddExtension(new Website()); + + // singletons + this.AddExtension(new BillingInformation()); + this.AddExtension(new Birthday()); + this.AddExtension(new DirectoryServer()); + this.AddExtension(new Initials()); + this.AddExtension(new MaidenName()); + this.AddExtension(new Mileage()); + this.AddExtension(new Nickname()); + this.AddExtension(new Occupation()); + this.AddExtension(new Priority()); + this.AddExtension(new Sensitivity()); + this.AddExtension(new ShortName()); + this.AddExtension(new Subject()); + } @@ -307,6 +119,29 @@ return base.Update() as ContactEntry; } + + /// + /// Location associated with the contact + /// + /// + public String Location + { + get + { + Where w = FindExtension(GDataParserNameTable.XmlWhereElement, BaseNameTable.gNamespace) as Where; + return w != null ? w.ValueString : null; + } + set + { + Where w = null; + if (value != null) + { + w = new Where(null, null, value); + } + ReplaceExtension(GDataParserNameTable.XmlWhereElement, BaseNameTable.gNamespace, w); + } + } + /// /// convienience accessor to find the primary Email /// there is no setter, to change this use the Primary Flag on @@ -352,11 +187,11 @@ /// there is no setter, to change this use the Primary Flag on /// an individual object /// - public PostalAddress PrimaryPostalAddress + public StructuredPostalAddress PrimaryPostalAddress { get { - foreach (PostalAddress p in this.PostalAddresses) + foreach (StructuredPostalAddress p in this.PostalAddresses) { if (p.Primary == true) { @@ -454,17 +289,18 @@ } /// - /// returns the phonenumber collection + /// Postal address split into components. It allows to store the address in locale independent format. + /// The fields can be interpreted and used to generate formatted, locale dependent address /// - public ExtensionCollection PostalAddresses + public ExtensionCollection PostalAddresses { get { - if (this.postals == null) + if (this.structuredAddress == null) { - this.postals = new ExtensionCollection(this); + this.structuredAddress = new ExtensionCollection(this); } - return this.postals; + return this.structuredAddress; } } @@ -484,6 +320,142 @@ } /// + /// getter for the CalendarLink collections + /// + public ExtensionCollection Calendars + { + get + { + if (this.calendars == null) + { + this.calendars = new ExtensionCollection(this); + } + return this.calendars; + } + } + + /// + /// getter for the Events collections + /// + public ExtensionCollection Events + { + get + { + if (this.events == null) + { + this.events = new ExtensionCollection(this); + } + return this.events; + } + } + + /// + /// getter for the externalids collections + /// + public ExtensionCollection ExternalIds + { + get + { + if (this.externalIds == null) + { + this.externalIds = new ExtensionCollection(this); + } + return this.externalIds; + } + } + + /// + /// getter for the Hobby collections + /// + public ExtensionCollection Hobbies + { + get + { + if (this.hobbies == null) + { + this.hobbies = new ExtensionCollection(this); + } + return this.hobbies; + } + } + + /// + /// getter for the Jot collections + /// + public ExtensionCollection Jots + { + get + { + if (this.jots == null) + { + this.jots = new ExtensionCollection(this); + } + return this.jots; + } + } + + /// + /// getter for the languages collections + /// + public ExtensionCollection Languages + { + get + { + if (this.languages == null) + { + this.languages = new ExtensionCollection(this); + } + return this.languages; + } + } + + /// + /// getter for the Relation collections + /// + public ExtensionCollection Relations + { + get + { + if (this.relations == null) + { + this.relations = new ExtensionCollection(this); + } + return this.relations; + } + } + + /// + /// getter for the UserDefinedField collections + /// + public ExtensionCollection UserDefinedFields + { + get + { + if (this.userDefinedFiels == null) + { + this.userDefinedFiels = new ExtensionCollection(this); + } + return this.userDefinedFiels; + } + } + + /// + /// getter for the website collections + /// + public ExtensionCollection Websites + { + get + { + if (this.websites == null) + { + this.websites = new ExtensionCollection(this); + } + return this.websites; + } + } + + + /// /// retrieves the Uri of the Photo Link. To set this, you need to create an AtomLink object /// and add/replace it in the atomlinks colleciton. /// @@ -543,6 +515,265 @@ return link; } } + + /// + /// returns the Name object + /// + public Name Name + { + get + { + return FindExtension(GDataParserNameTable.NameElement, BaseNameTable.gNamespace) as Name; + } + set + { + ReplaceExtension(GDataParserNameTable.NameElement, BaseNameTable.gNamespace, value); + } + } + + /// + /// Contacts billing information. + /// + /// + public string BillingInformation + { + get + { + return GetStringValue(ContactsNameTable.BillingInformationElement, + ContactsNameTable.NSContacts); + } + set + { + SetStringValue(value, ContactsNameTable.BillingInformationElement, + ContactsNameTable.NSContacts); + } + } + + + /// + /// Contact's birthday. + /// + /// + public string Birthday + { + get + { + Birthday b = FindExtension(ContactsNameTable.BirthdayElement, ContactsNameTable.NSContacts) as Birthday; + if (b != null) + { + return b.When; + } + return null; + } + set + { + Birthday b = null; + if (value != null) + { + b = new Birthday(value); + } + ReplaceExtension(ContactsNameTable.BirthdayElement, ContactsNameTable.NSContacts, b); + } + } + + + /// + /// Directory server associated with the contact. + /// + /// + public string DirectoryServer + { + get + { + return GetStringValue(ContactsNameTable.DirectoryServerElement, + ContactsNameTable.NSContacts); + } + set + { + SetStringValue(value, ContactsNameTable.DirectoryServerElement, + ContactsNameTable.NSContacts); + } + } + + + /// + /// Contacts initals + /// + /// + public string Initials + { + get + { + return GetStringValue(ContactsNameTable.InitialsElement, + ContactsNameTable.NSContacts); + } + set + { + SetStringValue(value, ContactsNameTable.InitialsElement, + ContactsNameTable.NSContacts); + } + } + + /// + /// Maiden name associated with the contact. + /// + /// + public string MaidenName + { + get + { + return GetStringValue(ContactsNameTable.MaidenNameElement, + ContactsNameTable.NSContacts); + } + set + { + SetStringValue(value, ContactsNameTable.MaidenNameElement, + ContactsNameTable.NSContacts); + } + } + + /// + /// Mileage associated with the contact. + /// + /// + public string Mileage + { + get + { + return GetStringValue(ContactsNameTable.MileageElement, + ContactsNameTable.NSContacts); + } + set + { + SetStringValue(value, ContactsNameTable.MileageElement, + ContactsNameTable.NSContacts); + } + } + + + /// + /// Nickname associated with the contact. + /// + /// + public string Nickname + { + get + { + return GetStringValue(ContactsNameTable.NicknameElement, + ContactsNameTable.NSContacts); + } + set + { + SetStringValue(value, ContactsNameTable.NicknameElement, + ContactsNameTable.NSContacts); + } + } + + /// + /// Occupation associated with the contact. + /// + /// + public string Occupation + { + get + { + return GetStringValue(ContactsNameTable.OccupationElement, + ContactsNameTable.NSContacts); + } + set + { + SetStringValue(value, ContactsNameTable.OccupationElement, + ContactsNameTable.NSContacts); + } + } + + /// + /// Priority ascribed to the contact. + /// + /// + public string Priority + { + get + { + Priority b = FindExtension(ContactsNameTable.PriorityElement, ContactsNameTable.NSContacts) as Priority; + if (b != null) + { + return b.Relation; + } + return null; + } + set + { + Priority b = null; + if (value != null) + { + b = new Priority(value); + } + ReplaceExtension(ContactsNameTable.PriorityElement, ContactsNameTable.NSContacts, b); + } + } + + /// + /// Sensitivity ascribed to the contact. + /// + /// + public string Sensitivity + { + get + { + Sensitivity b = FindExtension(ContactsNameTable.SensitivityElement, ContactsNameTable.NSContacts) as Sensitivity; + if (b != null) + { + return b.Relation; + } + return null; + } + set + { + Sensitivity b = null; + if (value != null) + { + b = new Sensitivity(value); + } + ReplaceExtension(ContactsNameTable.SensitivityElement, ContactsNameTable.NSContacts, b); + } + } + + /// + /// Contact's short name. + /// + /// + public string ShortName + { + get + { + return GetStringValue(ContactsNameTable.ShortNameElement, + ContactsNameTable.NSContacts); + } + set + { + SetStringValue(value, ContactsNameTable.ShortNameElement, + ContactsNameTable.NSContacts); + } + } + + /// + /// Subject associated with the contact. + /// + /// + public string Subject + { + get + { + return GetStringValue(ContactsNameTable.SubjectElement, + ContactsNameTable.NSContacts); + } + set + { + SetStringValue(value, ContactsNameTable.SubjectElement, + ContactsNameTable.NSContacts); + } + } } } diff -Nru gdata-sharp-1.4.0.2/src/gcontacts/contactextensions.cs gdata-sharp-1.7.0.1/src/gcontacts/contactextensions.cs --- gdata-sharp-1.4.0.2/src/gcontacts/contactextensions.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gcontacts/contactextensions.cs 2009-07-02 10:35:15.000000000 +0000 @@ -0,0 +1,1186 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* Change history +* Oct 13 2008 Joe Feser joseph.feser@gmail.com +* Converted ArrayLists and other .NET 1.1 collections to use Generics +* Combined IExtensionElement and IExtensionElementFactory interfaces +* +*/ + +#define USE_TRACING + +using System; +using Google.GData.Client; +using Google.GData.Extensions; + + +namespace Google.GData.Contacts { + + /// + /// short table to hold the namespace and the prefix + /// + public class ContactsNameTable + { + /// static string to specify the Contacts namespace supported + public const string NSContacts = "http://schemas.google.com/contact/2008"; + /// static string to specify the Google Contacts prefix used + public const string contactsPrefix = "gContact"; + + /// + /// Group Member ship info element string + /// + public const string GroupMembershipInfo = "groupMembershipInfo"; + + /// + /// SystemGroup element, indicating that this entry is a system group + /// + public const string SystemGroupElement = "systemGroup"; + + /// + /// Specifies billing information of the entity represented by the contact. The element cannot be repeated + /// + public const string BillingInformationElement = "billingInformation"; + + /// + /// Stores birthday date of the person represented by the contact. The element cannot be repeated + /// + public const string BirthdayElement = "birthday"; + + /// + /// Storage for URL of the contact's calendar. The element can be repeated + /// + public const string CalendarLinkElement = "calendarLink"; + + /// + /// A directory server associated with this contact. May not be repeated + /// + public const string DirectoryServerElement = "directoryServer"; + + /// + /// An event associated with a contact. May be repeated. + /// + public const string EventElement = "event"; + + /// + /// Describes an ID of the contact in an external system of some kind. This element may be repeated. + /// + public const string ExternalIdElement = "externalId"; + + /// + /// Specifies the gender of the person represented by the contact. The element cannot be repeated. + /// + public const string GenderElement = "gender"; + + /// + /// Specifies hobbies or interests of the person specified by the contact. The element can be repeated + /// + public const string HobbyElement = "hobby"; + + /// + /// Specifies the initials of the person represented by the contact. The element cannot be repeated. + /// + public const string InitialsElement = "initials"; + + /// + /// Storage for arbitrary pieces of information about the contact. Each jot has a type specified by the rel attribute and a text value. The element can be repeated. + /// + public const string JotElement = "jot"; + + /// + /// Specifies the preferred languages of the contact. The element can be repeated + /// + public const string LanguageElement = "language"; + + /// + /// Specifies maiden name of the person represented by the contact. The element cannot be repeated. + /// + public const string MaidenNameElement = "maidenName"; + + /// + /// Specifies the mileage for the entity represented by the contact. Can be used for example to document distance needed for reimbursement purposes. + /// The value is not interpreted. The element cannot be repeated + /// + public const string MileageElement = "mileage"; + + /// + /// Specifies the nickname of the person represented by the contact. The element cannot be repeated + /// + public const string NicknameElement = "nickname"; + + /// + /// Specifies the occupation/profession of the person specified by the contact. The element cannot be repeated. + /// + public const string OccupationElement = "occupation"; + + /// + /// Classifies importance into 3 categories. can not be repeated + /// + public const string PriorityElement = "priority"; + + /// + /// Describes the relation to another entity. maybe repeated + /// + public const string RelationElement = "relation"; + + /// + /// Classifies sensitifity of the contact + /// + public const string SensitivityElement = "sensitivity"; + + /// + /// Specifies short name of the person represented by the contact. The element cannot be repeated. + /// + public const string ShortNameElement = "shortName"; + + /// + /// Specifies the subject of the contact. The element cannot be repeated. + /// + public const string SubjectElement = "subject"; + + /// + /// Represents an arbitrary key-value pair attached to the contact. + /// + public const string UserDefinedFieldElement = "userDefinedField"; + + /// + /// Websites associated with the contact. Maybe repeated + /// + public const string WebsiteElement = "website"; + + /// + /// rel Attribute + /// + /// + public static string AttributeRel = "rel"; + /// + /// label Attribute + /// + /// + public static string AttributeLabel = "label"; + } + + + + /// + /// an element is defined that represents a group to which the contact belongs + /// + public class GroupMembership: SimpleElement + { + /// the href attribute + public const string XmlAttributeHRef = "href"; + /// the deleted attribute + public const string XmlAttributeDeleted = "deleted"; + + /// + /// default constructor + /// + public GroupMembership() + : base(ContactsNameTable.GroupMembershipInfo, ContactsNameTable.contactsPrefix, ContactsNameTable.NSContacts) + { + this.Attributes.Add(XmlAttributeHRef, null); + this.Attributes.Add(XmlAttributeDeleted, null); + } + + ///////////////////////////////////////////////////////////////////// + /// Identifies the group to which the contact belongs or belonged. + /// The group is referenced by its id. + ////////////////////////////////////////////////////////////////////// + public string HRef + { + get + { + return this.Attributes[XmlAttributeHRef] as string; + } + set + { + this.Attributes[XmlAttributeHRef] = value; + } + } + + ///////////////////////////////////////////////////////////////////// + /// Means, that the group membership was removed for the contact. + /// This attribute will only be included if showdeleted is specified + /// as query parameter, otherwise groupMembershipInfo for groups a contact + /// does not belong to anymore is simply not returned. + ////////////////////////////////////////////////////////////////////// + public string Deleted + { + get + { + return this.Attributes[XmlAttributeDeleted] as string; + } + } + } + + + /// + /// extension element to represent a system group + /// + public class SystemGroup : SimpleElement + { + /// + /// id attribute for the system group element + /// + /// + public const string XmlAttributeId = "id"; + + /// + /// default constructor + /// + public SystemGroup() + : base(ContactsNameTable.SystemGroupElement, ContactsNameTable.contactsPrefix, ContactsNameTable.NSContacts) + { + this.Attributes.Add(XmlAttributeId, null); + } + + ///////////////////////////////////////////////////////////////////// + /// Identifies the system group. Note that you still need + /// to use the group entries href membership to retrieve the group + /// + ////////////////////////////////////////////////////////////////////// + public string Id + { + get + { + return this.Attributes[XmlAttributeId] as string; + } + } + } + + /// + /// abstract class for a basecontactentry, used for contacts and groups + /// + public abstract class BaseContactEntry : AbstractEntry, IContainsDeleted + { + private ExtensionCollection xproperties; + + + /// + /// Constructs a new BaseContactEntry instance + /// to indicate that it is an event. + /// + public BaseContactEntry() + : base() + { + Tracing.TraceMsg("Created BaseContactEntry Entry"); + this.AddExtension(new ExtendedProperty()); + this.AddExtension(new Deleted()); + } + + + /// + /// returns the extended properties on this object + /// + /// + public ExtensionCollection ExtendedProperties + { + get + { + if (this.xproperties == null) + { + this.xproperties = new ExtensionCollection(this); + } + return this.xproperties; + } + } + + + /// + /// if this is a previously deleted contact, returns true + /// to delete a contact, use the delete method + /// + public bool Deleted + { + get + { + if (FindExtension(GDataParserNameTable.XmlDeletedElement, + BaseNameTable.gNamespace) != null) + { + return true; + } + return false; + } + } + } + + + + /// + /// Specifies billing information of the entity represented by the contact. The element cannot be repeated + /// + public class BillingInformation : SimpleElement + { + /// + /// default constructor for BillingInformation + /// + public BillingInformation() + : base(ContactsNameTable.BillingInformationElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts) + { + } + + /// + /// default constructor for BillingInformation with an initial value + /// + /// + public BillingInformation(string initValue) + : base(ContactsNameTable.BillingInformationElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts, initValue) + { + } + } + + /// + /// Stores birthday date of the person represented by the contact. The element cannot be repeated. + /// + public class Birthday : SimpleElement + { + + /// + /// When Attribute + /// + /// + public static string AttributeWhen = "when"; + + /// + /// default constructor for Birthday + /// + public Birthday() + : base(ContactsNameTable.BirthdayElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts) + { + this.Attributes.Add(AttributeWhen, null); + } + + /// + /// default constructor for Birthday with an initial value + /// + /// + public Birthday(string initValue) + : base(ContactsNameTable.BirthdayElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts) + { + this.Attributes.Add(AttributeWhen, initValue); + } + + ////////////////////////////////////////////////////////////////////// + /// Birthday date, given in format YYYY-MM-DD (with the year), or --MM-DD (without the year) + /// + ////////////////////////////////////////////////////////////////////// + public string When + { + get + { + return this.Attributes[AttributeWhen] as string; + } + set + { + this.Attributes[AttributeWhen] = value; + } + } + } + + + + + + /// + /// Storage for URL of the contact's information. The element can be repeated. + /// + public class ContactsLink : LinkAttributesElement + { + /// + /// href Attribute + /// + /// + public static string AttributeHref = "href"; + + /// + /// default constructor for CalendarLink + /// + public ContactsLink(string elementName, string elementPrefix, string elementNamespace) + : base(elementName, elementPrefix, elementNamespace) + { + this.Attributes.Add(AttributeHref, null); + } + + + + ////////////////////////////////////////////////////////////////////// + /// The URL of the the related link. + /// + ////////////////////////////////////////////////////////////////////// + public string Href + { + get + { + return this.Attributes[AttributeHref] as string; + } + set + { + this.Attributes[AttributeHref] = value; + } + } + } + + + + /// + /// Storage for URL of the contact's calendar. The element can be repeated. + /// + public class CalendarLink : ContactsLink + { + public CalendarLink() + : base(ContactsNameTable.CalendarLinkElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts) + { + + } + } + + + /// + /// DirectoryServer schema extension + /// + public class DirectoryServer : SimpleElement + { + /// + /// default constructor for DirectoryServer + /// + public DirectoryServer() + : base(ContactsNameTable.DirectoryServerElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts) + { + } + + /// + /// default constructor for DirectoryServer with an initial value + /// + /// + public DirectoryServer(string initValue) + : base(ContactsNameTable.DirectoryServerElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts, initValue) + { + } + } + + /// + /// Event schema extension + /// + public class Event : SimpleContainer + { + /// + /// default constructor for Event + /// + public Event() + : base(ContactsNameTable.EventElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts) + { + this.Attributes.Add(ContactsNameTable.AttributeRel, null); + this.Attributes.Add(ContactsNameTable.AttributeLabel, null); + this.ExtensionFactories.Add(new When()); + } + + ////////////////////////////////////////////////////////////////////// + /// Predefined calendar link type. Can be one of work, home or free-busy + /// + ////////////////////////////////////////////////////////////////////// + public string Relation + { + get + { + return this.Attributes[ContactsNameTable.AttributeRel] as string; + } + set + { + this.Attributes[ContactsNameTable.AttributeRel] = value; + } + } + + ////////////////////////////////////////////////////////////////////// + /// User-defined calendar link type. + /// + ////////////////////////////////////////////////////////////////////// + public string Label + { + get + { + return this.Attributes[ContactsNameTable.AttributeLabel] as string; + } + set + { + this.Attributes[ContactsNameTable.AttributeLabel] = value; + } + } + + /// + /// exposes the When element for this event + /// + /// + public When When + { + get + { + return FindExtension(GDataParserNameTable.XmlWhenElement, + BaseNameTable.gNamespace) as When; + } + set + { + ReplaceExtension(GDataParserNameTable.XmlWhenElement, + BaseNameTable.gNamespace, + value); + } + } + + + } + + /// + /// ExternalId schema extension + /// + public class ExternalId : SimpleAttribute + { + /// + /// default constructor for ExternalId + /// + public ExternalId() + : base(ContactsNameTable.ExternalIdElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts) + { + this.Attributes.Add(ContactsNameTable.AttributeRel, null); + this.Attributes.Add(ContactsNameTable.AttributeLabel, null); + + } + + /// + /// default constructor for ExternalId with an initial value + /// + /// + public ExternalId(string initValue) + : base(ContactsNameTable.ExternalIdElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts, initValue) + { + this.Attributes.Add(ContactsNameTable.AttributeRel, null); + this.Attributes.Add(ContactsNameTable.AttributeLabel, null); + } + + ////////////////////////////////////////////////////////////////////// + /// Predefined calendar link type. Can be one of work, home or free-busy + /// + ////////////////////////////////////////////////////////////////////// + public string Relation + { + get + { + return this.Attributes[ContactsNameTable.AttributeRel] as string; + } + set + { + this.Attributes[ContactsNameTable.AttributeRel] = value; + } + } + + ////////////////////////////////////////////////////////////////////// + /// User-defined calendar link type. + /// + ////////////////////////////////////////////////////////////////////// + public string Label + { + get + { + return this.Attributes[ContactsNameTable.AttributeLabel] as string; + } + set + { + this.Attributes[ContactsNameTable.AttributeLabel] = value; + } + } + } + + /// + /// Gender schema extension + /// + public class Gender : SimpleAttribute + { + /// + /// default constructor for Gender + /// + public Gender() + : base(ContactsNameTable.GenderElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts) + { + } + + /// + /// default constructor for Gender with an initial value + /// + /// + public Gender(string initValue) + : base(ContactsNameTable.GenderElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts, initValue) + { + } + } + + /// + /// Hobby schema extension + /// + public class Hobby : SimpleElement + { + /// + /// default constructor for Hobby + /// + public Hobby() + : base(ContactsNameTable.HobbyElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts) + { + } + + /// + /// default constructor for Hobby with an initial value + /// + /// + public Hobby(string initValue) + : base(ContactsNameTable.HobbyElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts, initValue) + { + } + } + + /// + /// Initials schema extension + /// + public class Initials : SimpleElement + { + /// + /// default constructor for Initials + /// + public Initials() + : base(ContactsNameTable.InitialsElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts) + { + } + + /// + /// default constructor for Initials with an initial value + /// + /// + public Initials(string initValue) + : base(ContactsNameTable.InitialsElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts, initValue) + { + } + } + + /// + /// Jot schema extension + /// + public class Jot : SimpleElement + { + /// + /// default constructor for Jot + /// + public Jot() + : base(ContactsNameTable.JotElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts) + { + this.Attributes.Add(ContactsNameTable.AttributeRel, null); + } + + + ////////////////////////////////////////////////////////////////////// + /// Predefined calendar link type. Can be one of work, home or free-busy + /// + ////////////////////////////////////////////////////////////////////// + public string Relation + { + get + { + return this.Attributes[ContactsNameTable.AttributeRel] as string; + } + set + { + this.Attributes[ContactsNameTable.AttributeRel] = value; + } + } + + } + + /// + /// Language schema extension + /// + public class Language : SimpleElement + { + /// + /// the code attribute + /// + /// + public static string AttributeCode = "code"; + + /// + /// default constructor for Language + /// + public Language() + : base(ContactsNameTable.LanguageElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts) + { + this.Attributes.Add(ContactsNameTable.AttributeLabel, null); + this.Attributes.Add(AttributeCode, null); + } + + /// + /// default constructor for Language with an initial value + /// + /// + public Language(string initValue) + : base(ContactsNameTable.LanguageElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts, initValue) + { + this.Attributes.Add(ContactsNameTable.AttributeLabel, null); + this.Attributes.Add(AttributeCode, null); + } + + ////////////////////////////////////////////////////////////////////// + /// A freeform name of a language. Must not be empty or all whitespace.. + /// + ////////////////////////////////////////////////////////////////////// + public string Label + { + get + { + return this.Attributes[ContactsNameTable.AttributeLabel] as string; + } + set + { + this.Attributes[ContactsNameTable.AttributeLabel] = value; + } + } + + + ////////////////////////////////////////////////////////////////////// + /// A language code conforming to the IETF BCP 47 specification. . + /// + ////////////////////////////////////////////////////////////////////// + public string Code + { + get + { + return this.Attributes[AttributeCode] as string; + } + set + { + this.Attributes[AttributeCode] = value; + } + } + } + + /// + /// Specifies maiden name of the person represented by the contact. The element cannot be repeated. + /// + public class MaidenName : SimpleElement + { + /// + /// default constructor for MaidenName + /// + public MaidenName() + : base(ContactsNameTable.MaidenNameElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts) + { + } + + /// + /// default constructor for MaidenName with an initial value + /// + /// + public MaidenName(string initValue) + : base(ContactsNameTable.MaidenNameElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts, initValue) + { + } + } + + /// + /// Specifies the mileage for the entity represented by the contact. Can be used for example to + /// document distance needed for reimbursement purposes. The value is not interpreted. The element cannot be repeated. + /// + public class Mileage : SimpleElement + { + /// + /// default constructor for Mileage + /// + public Mileage() + : base(ContactsNameTable.MileageElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts) + { + } + + /// + /// default constructor for Mileage with an initial value + /// + /// + public Mileage(string initValue) + : base(ContactsNameTable.MileageElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts, initValue) + { + } + } + + /// + /// Specifies the nickname of the person represented by the contact. The element cannot be repeated + /// + public class Nickname : SimpleElement + { + /// + /// default constructor for Nickname + /// + public Nickname() + : base(ContactsNameTable.NicknameElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts) + { + } + + /// + /// default constructor for Nickname with an initial value + /// + /// + public Nickname(string initValue) + : base(ContactsNameTable.NicknameElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts, initValue) + { + } + } + + /// + /// Specifies the occupation/profession of the person specified by the contact. The element cannot be repeated. + /// + public class Occupation : SimpleElement + { + /// + /// default constructor for Occupation + /// + public Occupation() + : base(ContactsNameTable.OccupationElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts) + { + + } + + /// + /// default constructor for Occupation with an initial value + /// + /// + public Occupation(string initValue) + : base(ContactsNameTable.OccupationElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts, initValue) + { + } + } + + /// + /// Classifies importance of the contact into 3 categories, low, normal and high + /// + public class Priority : SimpleElement + { + /// + /// default constructor for Priority + /// + public Priority() + : base(ContactsNameTable.PriorityElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts) + { + this.Attributes.Add(ContactsNameTable.AttributeRel, null); + } + + /// + /// default constructor for Priority with an initial value + /// + /// + public Priority(string initValue) + : base(ContactsNameTable.OccupationElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts) + { + this.Attributes.Add(ContactsNameTable.AttributeRel, initValue); + } + + ////////////////////////////////////////////////////////////////////// + /// Predefined calendar link type. Can be one of work, home or free-busy + /// + ////////////////////////////////////////////////////////////////////// + public string Relation + { + get + { + return this.Attributes[ContactsNameTable.AttributeRel] as string; + } + set + { + this.Attributes[ContactsNameTable.AttributeRel] = value; + } + } + } + + + + /// + /// Relation schema extension + /// + public class Relation : SimpleElement + { + /// + /// default constructor for Relation + /// + public Relation() + : base(ContactsNameTable.RelationElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts) + { + this.Attributes.Add(ContactsNameTable.AttributeLabel, null); + this.Attributes.Add(ContactsNameTable.AttributeRel, null); + } + + ////////////////////////////////////////////////////////////////////// + /// A freeform name of a language. Must not be empty or all whitespace.. + /// + ////////////////////////////////////////////////////////////////////// + public string Label + { + get + { + return this.Attributes[ContactsNameTable.AttributeLabel] as string; + } + set + { + this.Attributes[ContactsNameTable.AttributeLabel] = value; + } + } + + ////////////////////////////////////////////////////////////////////// + /// defines the link type. + /// + ////////////////////////////////////////////////////////////////////// + public string Rel + { + get + { + return this.Attributes[ContactsNameTable.AttributeRel] as string; + } + set + { + this.Attributes[ContactsNameTable.AttributeRel] = value; + } + } + } + + /// + /// Classifies sensitivity of the contact into the following categories: + /// confidential, normal, personal or private + /// + public class Sensitivity : SimpleElement + { + /// + /// default constructor for Sensitivity + /// + public Sensitivity() + : base(ContactsNameTable.SensitivityElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts) + { + this.Attributes.Add(ContactsNameTable.AttributeRel, null); + } + + /// + /// default constructor for Sensitivity with an initial value + /// + /// + public Sensitivity(string initValue) + : base(ContactsNameTable.OccupationElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts) + { + this.Attributes.Add(ContactsNameTable.AttributeRel, initValue); + } + + ////////////////////////////////////////////////////////////////////// + /// returns the relationship value + /// + ////////////////////////////////////////////////////////////////////// + public string Relation + { + get + { + return this.Attributes[ContactsNameTable.AttributeRel] as string; + } + set + { + this.Attributes[ContactsNameTable.AttributeRel] = value; + } + } + } + + + /// + /// Specifies short name of the person represented by the contact. The element cannot be repeated. + /// + public class ShortName : SimpleElement + { + /// + /// default constructor for ShortName + /// + public ShortName() + : base(ContactsNameTable.ShortNameElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts) + { + } + + /// + /// default constructor for ShortName with an initial value + /// + /// + public ShortName(string initValue) + : base(ContactsNameTable.ShortNameElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts, initValue) + { + } + } + + /// + /// Specifies the subject of the contact. The element cannot be repeated. + /// + public class Subject : SimpleElement + { + /// + /// default constructor for Subject + /// + public Subject() + : base(ContactsNameTable.SubjectElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts) + { + } + + /// + /// default constructor for Subject with an initial value + /// + /// + public Subject(string initValue) + : base(ContactsNameTable.SubjectElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts, initValue) + { + } + } + + /// + /// Represents an arbitrary key-value pair attached to the contact. + /// + public class UserDefinedField : SimpleAttribute + { + /// + /// key attribute + /// + /// + public static string AttributeKey = "key"; + + /// + /// default constructor for UserDefinedField + /// + public UserDefinedField() + : base(ContactsNameTable.UserDefinedFieldElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts) + { + this.Attributes.Add(AttributeKey, null); + } + + /// + /// default constructor for UserDefinedField with an initial value + /// + /// + /// + public UserDefinedField(string initValue, string initKey) + : base(ContactsNameTable.UserDefinedFieldElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts, initValue) + { + this.Attributes.Add(AttributeKey, initKey); + } + + ////////////////////////////////////////////////////////////////////// + /// A simple string value used to name this field. Case-sensitive + /// + ////////////////////////////////////////////////////////////////////// + public string Key + { + get + { + return this.Attributes[AttributeKey] as string; + } + set + { + this.Attributes[AttributeKey] = value; + } + } + + } + + /// + /// WebSite schema extension + /// + public class Website : ContactsLink + { + /// + /// default constructor for WebSite + /// + public Website() + : base(ContactsNameTable.WebsiteElement, + ContactsNameTable.contactsPrefix, + ContactsNameTable.NSContacts) + { + } + } + +} + diff -Nru gdata-sharp-1.4.0.2/src/gcontacts/contactrequest.cs gdata-sharp-1.7.0.1/src/gcontacts/contactrequest.cs --- gdata-sharp-1.4.0.2/src/gcontacts/contactrequest.cs 2009-02-16 17:39:06.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gcontacts/contactrequest.cs 2009-07-02 10:35:15.000000000 +0000 @@ -138,7 +138,7 @@ /// there is no setter, to change this use the Primary Flag on /// an individual object /// - public PostalAddress PrimaryPostalAddress + public StructuredPostalAddress PrimaryPostalAddress { get { @@ -218,7 +218,7 @@ /// /// returns the phonenumber collection /// - public ExtensionCollection PostalAddresses + public ExtensionCollection PostalAddresses { get { @@ -272,7 +272,41 @@ } } - + /// + /// returns the location associated with a contact + /// + /// + public string Location + { + get + { + EnsureInnerObject(); + return this.ContactEntry.Location; + } + set + { + EnsureInnerObject(); + this.ContactEntry.Location = value; + } + } + /// + /// the contacts name object + /// + public Name Name + { + get + { + EnsureInnerObject(); + if (this.ContactEntry.Name == null) + this.ContactEntry.Name = new Name(); + return this.ContactEntry.Name; + } + set + { + EnsureInnerObject(); + this.ContactEntry.Name = value; + } + } } @@ -390,7 +424,7 @@ /// - /// returns one of the youtube default feeds. + /// returns a feed of Groups for the default user /// /// a feed of Videos public Feed GetGroups() @@ -399,7 +433,7 @@ } /// - /// returns one of the youtube default feeds. + /// returns a feed of Groups for the given user /// /// the user for whom to retrieve the feed /// a feed of Videos diff -Nru gdata-sharp-1.4.0.2/src/gcontacts/Contacts.csproj gdata-sharp-1.7.0.1/src/gcontacts/Contacts.csproj --- gdata-sharp-1.4.0.2/src/gcontacts/Contacts.csproj 2009-02-03 15:10:46.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gcontacts/Contacts.csproj 2009-10-21 14:06:48.000000000 +0000 @@ -1,8 +1,7 @@ - + Debug AnyCPU - 8.0.50727 2.0 {66B2AD47-7DD2-43E5-9124-D53486609992} Library @@ -11,6 +10,11 @@ Google.GData.Contacts true contacts.sn + + + 2.0 + + true @@ -67,10 +71,12 @@ + + diff -Nru gdata-sharp-1.4.0.2/src/gcontacts/contactservice.cs gdata-sharp-1.7.0.1/src/gcontacts/contactservice.cs --- gdata-sharp-1.4.0.2/src/gcontacts/contactservice.cs 2009-02-03 15:10:46.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gcontacts/contactservice.cs 2009-08-13 15:59:00.000000000 +0000 @@ -70,12 +70,12 @@ /// /// by default all services now use version 1 for the protocol. /// this needs to be overridden by a service to specify otherwise. - /// YouTube uses version 2 + /// Contacts uses version 3 /// /// protected override void InitVersionInformation() { - this.ProtocolMajor = VersionDefaults.VersionTwo; + this.ProtocolMajor = VersionDefaults.VersionThree; } ////////////////////////////////////////////////////////////////////// diff -Nru gdata-sharp-1.4.0.2/src/gcontacts/groupentry.cs gdata-sharp-1.7.0.1/src/gcontacts/groupentry.cs --- gdata-sharp-1.4.0.2/src/gcontacts/groupentry.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gcontacts/groupentry.cs 2009-06-24 15:22:59.000000000 +0000 @@ -0,0 +1,95 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* Change history +* Oct 13 2008 Joe Feser joseph.feser@gmail.com +* Converted ArrayLists and other .NET 1.1 collections to use Generics +* Combined IExtensionElement and IExtensionElementFactory interfaces +* +*/ + +#define USE_TRACING + +using System; +using Google.GData.Client; +using Google.GData.Extensions; + + +namespace Google.GData.Contacts { + + ////////////////////////////////////////////////////////////////////// + /// + /// Entry API customization class for defining entries in an Group feed. + /// + ////////////////////////////////////////////////////////////////////// + public class GroupEntry : BaseContactEntry + { + + /// + /// default contact term string for the contact relationship link + /// + public static string GroupTerm = "http://schemas.google.com/contact/2008#group"; + /// ` + /// Category used to label entries that contain contact extension data. + /// + public static AtomCategory GROUP_CATEGORY = + new AtomCategory(GroupEntry.GroupTerm, new AtomUri(BaseNameTable.gKind)); + + /// + /// Constructs a new ContactEntry instance with the appropriate category + /// to indicate that it is an event. + /// + public GroupEntry() + : base() + { + Tracing.TraceMsg("Created Group Entry"); + this.AddExtension(new SystemGroup()); + Categories.Add(GROUP_CATEGORY); + } + + /// + /// typed override of the Update method + /// + /// + public new GroupEntry Update() + { + return base.Update() as GroupEntry; + } + + /// + /// returns the systemgroup id, if this groupentry represents + /// a system group. + /// The values of the system group ids corresponding to these + /// groups can be found in the Reference Guide for the Contacts Data API. + /// Currently the values can be Contacts, Friends, Family and Coworkers + /// + /// + public string SystemGroup + { + get + { + SystemGroup sg = FindExtension(ContactsNameTable.SystemGroupElement, + ContactsNameTable.NSContacts) as SystemGroup; + if (sg != null) + { + return sg.Id; + } + return null; + } + } + + + } +} + diff -Nru gdata-sharp-1.4.0.2/src/gdocuments/AssemblyInfo.cs gdata-sharp-1.7.0.1/src/gdocuments/AssemblyInfo.cs --- gdata-sharp-1.4.0.2/src/gdocuments/AssemblyInfo.cs 2008-02-28 16:23:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gdocuments/AssemblyInfo.cs 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -/* Copyright (c) 2006 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ -using System.Reflection; -using System.Runtime.CompilerServices; - - -[assembly: AssemblyDelaySign(false)] -[assembly: AssemblyKeyName("")] -[assembly: AssemblyTitle("Google Data API Documents Library")] - diff -Nru gdata-sharp-1.4.0.2/src/gdocuments/docrequest.cs gdata-sharp-1.7.0.1/src/gdocuments/docrequest.cs --- gdata-sharp-1.4.0.2/src/gdocuments/docrequest.cs 2009-02-18 09:26:05.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gdocuments/docrequest.cs 1970-01-01 00:00:00.000000000 +0000 @@ -1,561 +0,0 @@ -/* Copyright (c) 2006 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - - -using System; -using System.IO; -using System.Collections; -using System.Text; -using System.Net; -using Google.GData.Client; -using Google.GData.Extensions; -using Google.GData.AccessControl; -using Google.GData.Documents; -using System.Collections.Generic; - -namespace Google.Documents -{ - - /// - /// the base class for all documents in the document service. A document can represent folders, documents, spreadsheets etc. - /// - public class Document : Entry - { - - /// - /// descripes the type of the document entry - /// - public enum DocumentType - { - /// - /// a docuemtn - /// - Document, - /// - /// a spreadsheet - /// - Spreadsheet, - /// - /// a pdf file - /// - PDF, - /// - /// a presentation - /// - Presentation, - /// - /// a folder - /// - Folder, - /// - /// something unknown to us - /// - Unknown - } - - /// - /// describes the download type, in what format you want to download the document - /// - public enum DownloadType - { - /// - /// text file - /// - txt, - /// - /// open document format - /// - odt, - /// - /// portable document format PFDF - /// - pdf, - /// - /// html format - /// - html, - /// - /// rich text format - /// - rtf, - /// - /// microsoft word format - /// - doc, - /// - /// portable network graphics format - /// - png, - /// - /// flash format - /// - swf, - /// - /// Microsoft Powerpoint format - /// - ppt, - /// - /// Microsoft Excel format - /// - xls, - /// - /// commma seperated value format - /// - csv, - /// - /// open document spreadsheet format - /// - ods, - /// - /// tab seperated values format - /// - tsv - } - - /// - /// creates the inner contact object when needed - /// - /// - protected override void EnsureInnerObject() - { - if (this.AtomEntry == null) - { - this.AtomEntry = new DocumentEntry(); - } - } - - - - /// - /// readonly accessor for the DocumentEntry that is underneath this object. - /// - /// - public DocumentEntry DocumentEntry - { - get - { - EnsureInnerObject(); - return this.AtomEntry as DocumentEntry; - } - } - - /// - /// the type of the document entry - /// - /// - public Document.DocumentType Type - { - get - { - EnsureInnerObject(); - if (this.DocumentEntry.IsDocument) - { - return Document.DocumentType.Document; - } - else if (this.DocumentEntry.IsPDF) - { - return Document.DocumentType.PDF; - } - else if (this.DocumentEntry.IsSpreadsheet) - { - return Document.DocumentType.Spreadsheet; - } - else if (this.DocumentEntry.IsFolder) - { - return Document.DocumentType.Folder; - } - else if (this.DocumentEntry.IsPresentation) - { - return Document.DocumentType.Presentation; - } - return Document.DocumentType.Unknown; - } - set - { - EnsureInnerObject(); - switch (value) - { - case Document.DocumentType.Document: - this.DocumentEntry.IsDocument = true; - break; - case Document.DocumentType.Folder: - this.DocumentEntry.IsFolder = true; - break; - case Document.DocumentType.PDF: - this.DocumentEntry.IsPDF = true; - break; - case Document.DocumentType.Presentation: - this.DocumentEntry.IsPresentation = true; - break; - case Document.DocumentType.Spreadsheet: - this.DocumentEntry.IsSpreadsheet = true; - break; - case Document.DocumentType.Unknown: - throw new ArgumentException("Type.Unknown is not allowed to be set"); - } - } - } - - /// - /// returns the href values of the parent link releationships - /// can be used to retrieve the parent folder - /// - /// - public List ParentFolders - { - get - { - EnsureInnerObject(); - List strings = new List(); - foreach (AtomLink l in this.DocumentEntry.ParentFolders) - { - strings.Add(l.HRef.ToString()); - } - return strings; - } - } - - /// - /// returns the document id of the object - /// - /// - public string DocumentId - { - get - { - EnsureInnerObject(); - return DocumentsListQuery.DocumentId(this.Id); - } - } - } - - - ////////////////////////////////////////////////////////////////////// - /// - /// The Google Documents List Data API allows client applications - /// to view and update documents (spreadsheets and word processor) - /// using a Google Data API feed. Your client application can request - /// a list of a user's documents, query the content of a - /// user's documents, and upload new documents. - /// - /// - /// The following code illustrates a possible use of - /// the DocumentsRequest object: - /// - /// RequestSettings settings = new RequestSettings("yourApp"); - /// settings.PageSize = 50; - /// settings.AutoPaging = true; - /// DocumentsRequest c = new DocumentsRequest(settings); - /// Feed<Dcouments> feed = c.GetDocuments(); - /// - /// foreach (Document d in feed.Entries) - /// { - /// Console.WriteLine(d.Title); - /// } - /// - /// - ////////////////////////////////////////////////////////////////////// - public class DocumentsRequest : FeedRequest - { - - private string baseUri = DocumentsListQuery.documentsBaseUri; - private string folderUri = DocumentsListQuery.folderBaseUri; - private Service spreadsheetsService; - /// - /// default constructor for a DocumentsRequest - /// - /// - public DocumentsRequest(RequestSettings settings) : base(settings) - { - this.Service = new DocumentsService(settings.Application); - // we hardcode the service name here to avoid having a dependency - // on the spreadsheet dll for now. - this.spreadsheetsService = new Service("wise", settings.Application); - this.spreadsheetsService.ProtocolMajor = 2; - PrepareService(); - PrepareService(this.spreadsheetsService); - } - - /// - /// the base string to use for queries. Defaults to - /// DocumentsListQuery.documentsBaseUri - /// - /// - public string BaseUri - { - get - { - return this.baseUri; - } - set - { - this.BaseUri = value; - } - } - - /// - /// the base string to use for folder queries. Defaults to - /// DocumentsListQuery.folderBaseUri - /// - /// - public string FolderUri - { - get - { - return this.folderUri; - } - set - { - this.folderUri = value; - } - } - - /// - /// returns a Feed of all documents and folders for the authorized user - /// - /// a feed of everyting - public Feed GetEverything() - { - DocumentsListQuery q = PrepareQuery(this.BaseUri); - q.ShowFolders = true; - return PrepareFeed(q); - } - - /// - /// returns a Feed of all documents for the authorized user - /// - /// a feed of Documents - public Feed GetDocuments() - { - TextDocumentQuery q = PrepareQuery(this.BaseUri); - return PrepareFeed(q); - } - - /// - /// returns a Feed of all presentations for the authorized user - /// - /// a feed of Documents - public Feed GetPresentations() - { - PresentationsQuery q = PrepareQuery(this.BaseUri); - return PrepareFeed(q); - } - - /// - /// returns a Feed of all spreadsheets for the authorized user - /// - /// a feed of Documents - public Feed GetSpreadsheets() - { - SpreadsheetQuery q = PrepareQuery(this.BaseUri); - return PrepareFeed(q); - } - - /// - /// returns a Feed of all pdf files for the authorized user - /// - /// a feed of Documents - public Feed GetPDFs() - { - PDFsQuery q = PrepareQuery(this.BaseUri); - return PrepareFeed(q); - } - - /// - /// returns a Feed of all folders for the authorized user - /// - /// a feed of Documents - public Feed GetFolders() - { - FolderQuery q = PrepareQuery(this.BaseUri); - return PrepareFeed(q); - } - - /// - /// returns a feed of documents for the specified folder - /// - /// - /// - public Feed GetFolderContent(Document folder) - { - if (folder.Type != Document.DocumentType.Folder) - { - throw new ArgumentException("The parameter folder is not a folder"); - } - - string uri = this.FolderUri + folder.DocumentId; - - DocumentsListQuery q = PrepareQuery(uri); - return PrepareFeed(q); - } - - - - /// - /// this will create an empty document or folder, pending - /// the content of the newDocument parameter - /// - /// - /// the created document from the server - public Document CreateDocument(Document newDocument) - { - return Insert(new Uri(DocumentsListQuery.documentsBaseUri), newDocument); - } - - /// - /// moves a document or a folder into a folder - /// - /// this has to be a folder - /// can be a folder or a document - /// - public Document MoveDocumentTo(Document parent, Document child) - { - if (parent == null || child == null) - { - throw new ArgumentNullException("parent or child can not be null"); - } - if (parent.AtomEntry.Content == null || parent.AtomEntry.Content.AbsoluteUri == null) - { - throw new ArgumentException("parent has no content uri"); - } - if (parent.Type != Document.DocumentType.Folder) - { - throw new ArgumentException("wrong parent type"); - } - - Document payload = new Document(); - payload.DocumentEntry.Id = new AtomId(child.Id); - payload.Type = child.Type; - - // to do that, we just need to post the CHILD - // against the URI of the parent - return Insert(new Uri(parent.AtomEntry.Content.AbsoluteUri), payload); - } - - - /// - /// downloads a document. - /// - /// The document to download. It needs to have the document type set, as well as the id link - /// The output format of the document you want to download - /// - public Stream Download(Document document, Document.DownloadType type) - { - return this.Download(document, type, null, 0); - } - - - /// - /// downloads a document. - /// - /// The document to download. It needs to have the document type set, as well as the id link - /// The output format of the document you want to download - /// When requesting a CSV or TSV file you must specify an additional parameter called - /// gid which indicates which grid, or sheet, you wish to get (the index is 0 based, so gid 1 - /// actually refers to the second sheet sheet on a given spreadsheet). - /// if null, default is used. Otherwise needs to specify the domain to download from, ending with a slash - /// - public Stream Download(Document document, Document.DownloadType type, string baseDomain, int sheetNumber) - { - if (document.Type == Document.DocumentType.Unknown) - { - throw new ArgumentException("Document has an unknown type"); - } - - if (document.Type == Document.DocumentType.Folder) - { - throw new ArgumentException("Document is a folder, can not be downloaded"); - } - - // now figure out the parameters - string queryUri = ""; - - Service s = this.Service; - - switch (document.Type) - { - - case Document.DocumentType.Spreadsheet: - // spreadsheet has a different parameter - if (baseDomain == null) - { - baseDomain = "http://spreadsheets.google.com/"; - } - queryUri = baseDomain + "feeds/download/spreadsheets/Export?key=" + document.DocumentId + "&fmcmd="; - s = this.spreadsheetsService; - switch (type) - { - case Document.DownloadType.xls: - queryUri+="4"; - break; - case Document.DownloadType.csv: - queryUri+="5&gid="+sheetNumber.ToString(); - break; - case Document.DownloadType.pdf: - queryUri+="12"; - break; - case Document.DownloadType.ods: - queryUri+="13"; - break; - case Document.DownloadType.tsv: - queryUri+="23&gid="+sheetNumber.ToString();; - break; - case Document.DownloadType.html: - queryUri+="102"; - break; - default: - throw new ArgumentException("type is invalid for a spreadsheet"); - - } - break; - - case Document.DocumentType.Presentation: - if (baseDomain == null) - { - baseDomain = "http://docs.google.com/"; - } - - queryUri = baseDomain + "feeds/download/presentations/Export?docID=" + document.DocumentId + "&exportFormat="; - switch (type) - { - case Document.DownloadType.swf: - queryUri+="swf"; - break; - case Document.DownloadType.pdf: - queryUri+="pdf"; - break; - case Document.DownloadType.ppt: - queryUri+="ppt"; - break; - default: - throw new ArgumentException("type is invalid for a presentation"); - } - break; - default: - if (baseDomain == null) - { - baseDomain = "http://docs.google.com/"; - } - - queryUri = baseDomain + "feeds/download/documents/Export?docID=" + document.DocumentId + "&exportFormat=" + type.ToString(); - break; - - } - - Uri target = new Uri(queryUri); - return s.Query(target); - } - } -} diff -Nru gdata-sharp-1.4.0.2/src/gdocuments/documententry.cs gdata-sharp-1.7.0.1/src/gdocuments/documententry.cs --- gdata-sharp-1.4.0.2/src/gdocuments/documententry.cs 2009-02-16 17:39:06.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gdocuments/documententry.cs 1970-01-01 00:00:00.000000000 +0000 @@ -1,219 +0,0 @@ -/* Copyright (c) 2006 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ -#define USE_TRACING - -using System; -using System.Xml; -using System.IO; -using System.Collections.Generic; -using Google.GData.Client; -using Google.GData.Extensions; -using Google.GData.AccessControl; - - -namespace Google.GData.Documents { - - - ////////////////////////////////////////////////////////////////////// - /// - /// Entry API customization class for defining entries in an Event feed. - /// - ////////////////////////////////////////////////////////////////////// - public class DocumentEntry : AbstractEntry - { - - static string PRESENTATION_KIND = "http://schemas.google.com/docs/2007#presentation"; - static string DOCUMENT_KIND = "http://schemas.google.com/docs/2007#document"; - static string SPREADSHEET_KIND = "http://schemas.google.com/docs/2007#spreadsheet"; - static string PDF_KIND = "http://schemas.google.com/docs/2007#pdf"; - static string STARRED_KIND = "http://schemas.google.com/g/2005/labels#starred"; - static string FOLDER_KIND = "http://schemas.google.com/docs/2007#folder"; - static string PARENT_FOLDER_REL = "http://schemas.google.com/docs/2007#parent"; - - /// - /// a predefined atom category for Documents - /// - public static AtomCategory DOCUMENT_CATEGORY = - new AtomCategory(DOCUMENT_KIND, new AtomUri(BaseNameTable.gKind)); - /// - /// a predefined atom category for Spreadsheets - /// - public static AtomCategory SPREADSHEET_CATEGORY = - new AtomCategory(SPREADSHEET_KIND, new AtomUri(BaseNameTable.gKind)); - /// - /// a predefined atom category for PDF - /// - public static AtomCategory PDF_CATEGORY = - new AtomCategory(PDF_KIND, new AtomUri(BaseNameTable.gKind)); - /// - /// a predefined atom category for starred documentss - /// - /// - /// a predefined atom category for Presentations - /// - public static AtomCategory PRESENTATION_CATEGORY = - new AtomCategory(PRESENTATION_KIND, new AtomUri(BaseNameTable.gKind)); - /// - /// a predefined atom category for starred documentss - /// - public static AtomCategory STARRED_CATEGORY = - new AtomCategory(STARRED_KIND, new AtomUri(BaseNameTable.gLabels)); - /// - /// a predefined atom category for folders - /// - public static AtomCategory FOLDER_CATEGORY = - new AtomCategory(FOLDER_KIND, new AtomUri(BaseNameTable.gKind)); - - - - /// - /// Constructs a new EventEntry instance with the appropriate category - /// to indicate that it is an event. - /// - public DocumentEntry() - : base() - { - Tracing.TraceMsg("Created DocumentEntry"); - this.AddExtension(new FeedLink()); - } - - /// - /// Reflects if this entry is a word processor document - /// - public bool IsDocument - { - get - { - return this.Categories.Contains(DocumentEntry.DOCUMENT_CATEGORY); - } - set - { - this.ToggleCategory(DocumentEntry.DOCUMENT_CATEGORY, value); - } - } - - /// - /// Reflects if this entry is a spreadsheet document - /// - public bool IsSpreadsheet - { - get - { - return this.Categories.Contains(DocumentEntry.SPREADSHEET_CATEGORY); - } - set - { - this.ToggleCategory(DocumentEntry.SPREADSHEET_CATEGORY, value); - } - } - - /// - /// Reflects if this entry is a presentation document - /// - public bool IsPresentation - { - get - { - return this.Categories.Contains(DocumentEntry.PRESENTATION_CATEGORY); - } - set - { - this.ToggleCategory(DocumentEntry.PRESENTATION_CATEGORY, value); - } - } - - /// - /// Reflects if this entry is a PDF document - /// - public bool IsPDF - { - get - { - return this.Categories.Contains(DocumentEntry.PDF_CATEGORY); - } - set - { - this.ToggleCategory(DocumentEntry.PDF_CATEGORY, value); - } - } - - /// - /// Reflects if this entry is starred - /// - public bool IsStarred - { - get - { - return this.Categories.Contains(DocumentEntry.STARRED_CATEGORY); - } - set - { - this.ToggleCategory(DocumentEntry.STARRED_CATEGORY, value); - } - } - - /// - /// returns true if this is a folder - /// - public bool IsFolder - { - get - { - return this.Categories.Contains(DocumentEntry.FOLDER_CATEGORY); - } - set - { - this.ToggleCategory(DocumentEntry.FOLDER_CATEGORY, value); - } - } - - /// - /// returns the string that should represent the Uri to the access control list - /// - /// the value of the hret attribute for the acl feedlink, or null if not found - public string AccessControlList - { - get - { - List list = FindExtensions(GDataParserNameTable.XmlFeedLinkElement, - BaseNameTable.gNamespace); - - foreach (FeedLink fl in list) - { - if (fl.Rel == AclNameTable.LINK_REL_ACCESS_CONTROL_LIST) - { - return fl.Href; - } - } - return null; - } - } - - /// - /// returns the href value of the parent link releationship - /// - /// - public List ParentFolders - { - get - { - List links = this.Links.FindServiceList(PARENT_FOLDER_REL, AtomLink.ATOM_TYPE); - return links; - } - } - - } -} - diff -Nru gdata-sharp-1.4.0.2/src/gdocuments/documentfeed.cs gdata-sharp-1.7.0.1/src/gdocuments/documentfeed.cs --- gdata-sharp-1.4.0.2/src/gdocuments/documentfeed.cs 2007-10-10 13:02:44.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gdocuments/documentfeed.cs 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -/* Copyright (c) 2006 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -using System; -using System.Collections; -using System.Text; -using System.Xml; -using Google.GData.Client; -using Google.GData.Extensions; - -namespace Google.GData.Documents { - - - ////////////////////////////////////////////////////////////////////// - /// - /// Google Documents List feed URI takes the following form: - /// http://docs.google.com/feeds/documents/visibility/projection - /// The visibility parameter has two possible values: private and public. - /// In almost all cases, your client should use private. - /// The projection parameter indicates what information is included in the representation. - /// For example, if your client specifies a projection of basic, it's requesting an Atom feed - /// without any GData extension elements. - /// Currently, in the Documents List feed, only the private/full combination - /// for visibility and projection is available. - /// - ////////////////////////////////////////////////////////////////////// - public class DocumentsFeed : AbstractFeed - { - - /// - /// default constructor - /// - /// the base URI of the feedEntry - /// the Service to use - public DocumentsFeed(Uri uriBase, IService iService) : base(uriBase, iService) - { - // todo: add extension elements as appropriate - } - - /// - /// this needs to get implemented by subclasses - /// - /// AtomEntry - public override AtomEntry CreateFeedEntry() - { - return new DocumentEntry(); - } - - /// - /// get's called after we already handled the custom entry, to handle all - /// other potential parsing tasks - /// - /// - /// the atom feed parser used - protected override void HandleExtensionElements(ExtensionElementEventArgs e, AtomFeedParser parser) - { - base.HandleExtensionElements(e, parser); - } - } -} diff -Nru gdata-sharp-1.4.0.2/src/gdocuments/documentquery.cs gdata-sharp-1.7.0.1/src/gdocuments/documentquery.cs --- gdata-sharp-1.4.0.2/src/gdocuments/documentquery.cs 2009-02-17 13:58:56.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gdocuments/documentquery.cs 1970-01-01 00:00:00.000000000 +0000 @@ -1,391 +0,0 @@ -/* Copyright (c) 2006 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -using System; -using System.Xml; -using System.Text; -using System.Globalization; -using System.Diagnostics; -using Google.GData.Client; - -namespace Google.GData.Documents { - - ////////////////////////////////////////////////////////////////////// - /// - /// A subclass of FeedQuery, to create an Documents query URI. - /// Provides public properties that describe the different - /// aspects of the URI, as well as a composite URI. - /// - /// Documents List supports the following standard GData query parameters: - /// alt, author, q, start-index, max-results, updated-min, updated-max, /category - /// For more information about the standard parameters, see the GData protocol reference document. - /// In addition to the standard GData query parameters, the Documents List data API uses the following parameters. - /// Parameter Meaning - /// title Specifies the search terms for the title of a document. - /// This parameter used without title-exact will only submit partial queries, not exact queries. - /// - /// title-exact Specifies whether the title query should be taken as an exact string. - /// Meaningless without title. Possible values are true and false. - /// - /// The Documents List data API supports the following categories. - /// Category: Document Type - /// Scheme: http://schemas.google.com/g/2005#kind - /// Term: http://schemas.google.com/docs/2007#type - /// Label: type - /// All documents of the corresponding type in the requesting users document list. - /// Type is currently one of (document|spreadsheet|presentation) - /// Category: Starred Status - /// Scheme: http://schemas.google.com/g/2005/labels - /// Term: starred - /// Label: starred - /// All documents that have been starred by the requesting user - /// Category: Containing Folders - /// Scheme: http://schemas.google.com/docs/2007/folders/user-email - /// Term: folder-id - /// Label: folder-name - /// All documents inside the given folder for the requesting user - /// - ////////////////////////////////////////////////////////////////////// - public class DocumentsListQuery : FeedQuery - { - - - /// - /// document feed base URI - /// - public static string documentsBaseUri = "http://docs.google.com/feeds/documents/private/full"; - - /// - /// folder base uri - /// - /// - public static string folderBaseUri = "http://docs.google.com/feeds/folders/private/full/folder%3A"; - - private static AtomCategory ATOMCATEGORY_DOCUMENTS = new AtomCategory("document"); - /// - /// predefined query category for documents - /// - public static QueryCategory DOCUMENTS = new QueryCategory(ATOMCATEGORY_DOCUMENTS); - - private static AtomCategory ATOMCATEGORY_SPREADSHEETS = new AtomCategory("spreadsheet"); - /// - /// predefined query category for spreadsheets - /// - public static QueryCategory SPREADSHEETS = new QueryCategory(ATOMCATEGORY_SPREADSHEETS); - - private static AtomCategory ATOMCATEGORY_PRESENTATIONS = new AtomCategory("presentation"); - /// - /// predefined query category for presentations - /// - public static QueryCategory PRESENTATIONS = new QueryCategory(ATOMCATEGORY_PRESENTATIONS); - - private static AtomCategory ATOMCATEGORY_PDFS = new AtomCategory("pdf"); - /// - /// predefined query category for presentations - /// - public static QueryCategory PDFS = new QueryCategory(ATOMCATEGORY_PDFS); - - - /// - /// predefined query category for starred documents - /// - public static AtomCategory ATOMCATEGORY_STARRED = new AtomCategory("starred"); - /// - /// predefined query category for starred documents - /// - public static QueryCategory STARRED = new QueryCategory(ATOMCATEGORY_STARRED); - - - /// - /// predefined query category for starred documents - /// - public static AtomCategory ATOMCATEGORY_FOLDER = new AtomCategory("folder"); - /// - /// predefined query category for starred documents - /// - public static QueryCategory FOLDER = new QueryCategory(ATOMCATEGORY_FOLDER); - - //Local variable to hold the contents of a title query - private string title; - //Local variable to hold if the title query we are doing should be exact. - private bool titleExact; - - /// - /// base constructor - /// - public DocumentsListQuery() - : base(documentsBaseUri) - { - this.CategoryQueriesAsParameter = true; - } - - /// - /// base constructor, with initial queryUri - /// - /// the query to use - public DocumentsListQuery(string queryUri) - : base(queryUri) - { - this.CategoryQueriesAsParameter = true; - } - - /// - /// Restricts the results to only starred documents - /// - [CLSCompliant(false)] - public bool Starred - { - get - { - return this.Categories.Contains(DocumentsListQuery.STARRED); - } - set - { - if (value) - { - this.Categories.Add(DocumentsListQuery.STARRED); - } - else - { - this.Categories.Remove(DocumentsListQuery.STARRED); - } - } - } - - private bool showFolders; - /// - /// shows folders if true in the result - /// - [CLSCompliant(false)] - public bool ShowFolders - { - get - { - return this.showFolders; - } - set - { - this.showFolders = value; - } - } - - /// - /// Restricts the results to only documents with titles matching a string. - /// - public string Title - { - get - { - return this.title; - } - set - { - this.title = value; - } - } - - /// - /// Restricts the results to only documents matching a string provided - /// by the Title property exactly. (No partial matches.) - /// - public bool TitleExact - { - get - { - return this.titleExact; - } - set - { - this.titleExact = value; - } - } - - - /// - /// tries to parse a document id iri and return just the - /// ID portion of it - /// - /// the document id link as a string - /// the document id or null if failed - public static string DocumentId(string documentUri) - { - const string token="%3A"; - if (documentUri == null) - - { - throw new ArgumentNullException("documentUri"); - } - int pos = documentUri.LastIndexOf(token); - if (pos > 0) - { - pos += 3; - if (pos < documentUri.Length) - { - return documentUri.Substring(pos); - } - } - return null; - } - -#if WindowsCE || PocketPC -#else - ////////////////////////////////////////////////////////////////////// - /// Parses custom properties out of the incoming URI - /// A URI representing a query on a feed - /// returns the base uri - ////////////////////////////////////////////////////////////////////// - protected override Uri ParseUri(Uri targetUri) - { - base.ParseUri(targetUri); - if (targetUri != null) - { - char[] deli = { '?', '&' }; - - TokenCollection tokens = new TokenCollection(targetUri.Query, deli); - foreach (String token in tokens) - { - if (token.Length > 0) - { - char[] otherDeli = { '=' }; - String[] parameters = token.Split(otherDeli, 2); - switch (parameters[0]) - { - case "title-exact": - this.TitleExact = bool.Parse(parameters[1]); - break; - case "title": - this.Title = parameters[1]; - break; - case "showfolders": - this.ShowFolders = bool.Parse(parameters[1]); - break; - } - } - } - } - return this.Uri; - } -#endif - ////////////////////////////////////////////////////////////////////// - /// Creates the partial URI query string based on all - /// set properties. - /// A string representing the query part of the URI. - ////////////////////////////////////////////////////////////////////// - protected override string CalculateQuery(string basePath) - { - string path = base.CalculateQuery(basePath); - StringBuilder newPath = new StringBuilder(path, 2048); - char paramInsertion = InsertionParameter(path); - - paramInsertion = AppendQueryPart(this.Title, "title", paramInsertion, newPath); - - if (this.TitleExact == true) - { - paramInsertion = AppendQueryPart("true", "title-exact", paramInsertion, newPath); - } - if (this.ShowFolders == true) - { - paramInsertion = AppendQueryPart("true", "showfolders", paramInsertion, newPath); - } - return newPath.ToString(); - } - } - - - - /// - /// a subclass setup to just retrieve all word processor documents - /// - public class TextDocumentQuery : DocumentsListQuery - { - - /// - /// base constructor - /// - public TextDocumentQuery() - : base() - { - this.Categories.Add(DocumentsListQuery.DOCUMENTS); - } - } - - - /// - /// a subclass setup to just retrieve all spreadsheets - /// - public class SpreadsheetQuery : DocumentsListQuery - { - - /// - /// base constructor - /// - public SpreadsheetQuery() - : base() - { - this.Categories.Add(DocumentsListQuery.SPREADSHEETS); - } - } - - /// - /// a subclass setup to just retrieve all presentations - /// - public class PresentationsQuery : DocumentsListQuery - { - - /// - /// base constructor - /// - public PresentationsQuery() - : base() - { - this.Categories.Add(DocumentsListQuery.PRESENTATIONS); - } - } - - /// - /// a subclass setup to just retrieve all PDFs - /// - public class PDFsQuery : DocumentsListQuery - { - - /// - /// base constructor - /// - public PDFsQuery() - : base() - { - this.Categories.Add(DocumentsListQuery.PDFS); - } - } - - - /// - /// a subclass setup to just retrieve all Folders - /// - public class FolderQuery : DocumentsListQuery - { - - /// - /// base constructor - /// - public FolderQuery() - : base() - { - this.Categories.Add(DocumentsListQuery.FOLDER); - this.ShowFolders = true; - } - } - -} diff -Nru gdata-sharp-1.4.0.2/src/gdocuments/Documents.csproj gdata-sharp-1.7.0.1/src/gdocuments/Documents.csproj --- gdata-sharp-1.4.0.2/src/gdocuments/Documents.csproj 2009-02-11 15:32:47.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gdocuments/Documents.csproj 1970-01-01 00:00:00.000000000 +0000 @@ -1,143 +0,0 @@ - - - Local - 8.0.50727 - 2.0 - {1C00DDC8-021D-4F60-9EE9-314431586936} - Debug - AnyCPU - - - - - Google.GData.Documents - documents.sn - JScript - Grid - IE50 - false - Library - Google.GData.Documents - OnBuildSuccess - - - - - - - true - - - bin\Debug\ - false - 285212672 - false - - - DEBUG;TRACE - - - true - 4096 - false - - - false - false - false - false - 4 - full - prompt - - - bin\Release\ - false - 285212672 - false - - - TRACE - bin\gdocuments.xml - false - 4096 - false - - - true - false - false - false - 4 - none - prompt - - - bin\asp\ - false - 285212672 - false - - - PARTIALLY_TRUSTED - - - false - 4096 - false - - - true - false - false - false - 4 - none - prompt - - - - System - - - System.Data - - - System.XML - - - {B6F6D938-0D45-42BA-8A67-55D92EF03995} - Core Client - - - Common Data Extensions - {21BCB644-F9C3-4ADC-8BE1-4E55C6565011} - {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - - - {279D35CE-871A-4C76-B823-A73675EDF191} - Access Control - - - - - - - - AssemblyVersion.cs - - - - - - - - - - - - - - - - \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/src/gdocuments/documentservice.cs gdata-sharp-1.7.0.1/src/gdocuments/documentservice.cs --- gdata-sharp-1.4.0.2/src/gdocuments/documentservice.cs 2009-02-11 09:34:10.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gdocuments/documentservice.cs 1970-01-01 00:00:00.000000000 +0000 @@ -1,165 +0,0 @@ -/* Copyright (c) 2006 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - - -using System; -using System.IO; -using System.Collections; -using System.Text; -using System.Net; -using Google.GData.Client; -using Google.GData.Extensions; - - -namespace Google.GData.Documents { - - ////////////////////////////////////////////////////////////////////// - /// - /// The Google Documents List data API allows client applications to upload - /// documents to Google Documents and list them in the form of Google data - /// API ("GData") feeds. Your client application can request a list of a user's - /// documents, and query the content in an existing document. - /// Here are some of the things you can do with the Documents List data API: - /// Upload the word processing documents and spreadsheets on - /// your computer to allow you to back them up or - /// collaborate online when editing. - /// Find all of your documents that contain specific keywords. - /// Get a list of spreadsheets which can be accessed through the Google Spreadsheets data API. - /// - ////////////////////////////////////////////////////////////////////// - public class DocumentsService : Service - { - - /// The Calendar service's name - public const string GDocumentsService = "writely"; - - /// - /// A Hashtable that expresses the allowed content types. - /// - public static Hashtable GDocumentsAllowedTypes; - - /// - /// Static constructor used to initialize GDocumentsAllowedTypes. - /// - static DocumentsService() - { - GDocumentsAllowedTypes = new Hashtable(); - GDocumentsAllowedTypes.Add("CSV", "text/csv"); - GDocumentsAllowedTypes.Add("TAB", "text/tab-separated-values"); - GDocumentsAllowedTypes.Add("TSV", "text/tab-separated-values"); - GDocumentsAllowedTypes.Add("TXT", "text/plain"); - GDocumentsAllowedTypes.Add("HTML", "text/html"); - GDocumentsAllowedTypes.Add("HTM", "text/html"); - GDocumentsAllowedTypes.Add("DOC", "application/msword"); - GDocumentsAllowedTypes.Add("ODS", "application/x-vnd.oasis.opendocument.spreadsheet"); - GDocumentsAllowedTypes.Add("ODT", "application/vnd.oasis.opendocument.text"); - GDocumentsAllowedTypes.Add("RTF", "application/rtf"); - GDocumentsAllowedTypes.Add("SXW", "application/vnd.sun.xml.writer"); - GDocumentsAllowedTypes.Add("XLS", "application/vnd.ms-excel"); - GDocumentsAllowedTypes.Add("PPT", "application/vnd.ms-powerpoint"); - GDocumentsAllowedTypes.Add("PPS", "application/vnd.ms-powerpoint"); - GDocumentsAllowedTypes.Add("PDF", "application/pdf"); - } - - /// - /// default constructor - /// - /// the applicationname - public DocumentsService(string applicationName) : base(GDocumentsService, applicationName) - { - this.NewFeed += new ServiceEventHandler(this.OnNewFeed); - } - - /// - /// overloaded to create typed version of Query - /// - /// - /// EventFeed - public DocumentsFeed Query(DocumentsListQuery feedQuery) - { - return base.Query(feedQuery) as DocumentsFeed; - } - - - /// - /// Simple method to upload a document, presentation, or spreadsheet - /// based upon the file extension. - /// - /// The full path to the file. - /// The desired name of the document on the server. - /// A DocumentEntry describing the created document. - public DocumentEntry UploadDocument(string fileName, string documentName) - { - - FileInfo fileInfo = new FileInfo(fileName); - FileStream stream = fileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - Uri postUri = new Uri(DocumentsListQuery.documentsBaseUri); - - if (documentName == null) - { - documentName = fileInfo.Name; - } - - //convert the extension to caps and strip the "." off the front - string ext = fileInfo.Extension.ToUpper().Substring(1); - - String contentType = (String) GDocumentsAllowedTypes[ext]; - - if (contentType == null) - { - throw new ArgumentException("File extension '"+ext+"' is not recognized as valid."); - } - - DocumentEntry entry = this.Insert(postUri, stream, contentType, documentName) as DocumentEntry; - - stream.Close(); - - return entry; - } - - - /// - /// by default all services now use version 1 for the protocol. - /// this needs to be overridden by a service to specify otherwise. - /// YouTube uses version 2 - /// - /// - protected override void InitVersionInformation() - { - this.ProtocolMajor = VersionDefaults.VersionTwo; - } - - - - - ////////////////////////////////////////////////////////////////////// - /// eventchaining. We catch this by from the base service, which - /// would not by default create an atomFeed - /// the object which send the event - /// FeedParserEventArguments, holds the feedentry - /// - ////////////////////////////////////////////////////////////////////// - protected void OnNewFeed(object sender, ServiceEventArgs e) - { - Tracing.TraceMsg("Created new Documents Feed"); - if (e == null) - { - throw new ArgumentNullException("e"); - } - e.Feed = new DocumentsFeed(e.Uri, e.Service); - } - ///////////////////////////////////////////////////////////////////////////// - } -} Binary files /tmp/UhUzKTrMiD/gdata-sharp-1.4.0.2/src/gdocuments/documents.sn and /tmp/kt1AG0Pm9_/gdata-sharp-1.7.0.1/src/gdocuments/documents.sn differ diff -Nru gdata-sharp-1.4.0.2/src/ghealth/author.cs gdata-sharp-1.7.0.1/src/ghealth/author.cs --- gdata-sharp-1.4.0.2/src/ghealth/author.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/ghealth/author.cs 2009-08-17 17:41:48.000000000 +0000 @@ -0,0 +1,59 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using Google.GData.Client; + +namespace Google.GData.Health +{ + /// + /// Represents an simplified atom entry author. + /// + public class Author + { + /// + /// Gets or sets the email of the author. + /// + public string Email { get; set; } + + /// + /// Gets or sets the name of the author. + /// + public string Name { get; set; } + + /// + /// Gets or sets the language for this author. + /// + public string Language { get; set; } + + /// + /// Gets or sets the author's uri. + /// + public string Uri { get; set; } + + public static Author FromAtomPerson(AtomPerson person) + { + Author author = new Author(); + author.Uri = person.Uri.Content; + author.Language = person.Language; + author.Email = person.Email; + author.Name = person.Name; + + return author; + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/ghealth/basehealthservice.cs gdata-sharp-1.7.0.1/src/ghealth/basehealthservice.cs --- gdata-sharp-1.4.0.2/src/ghealth/basehealthservice.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/ghealth/basehealthservice.cs 2009-08-18 23:17:20.000000000 +0000 @@ -0,0 +1,205 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Google.GData.Client; +using ASTM.Org.CCR; +using Google.GData.Extensions; +using System.Xml.Serialization; +using System.Xml; +using System.IO; + +namespace Google.GData.Health +{ + ////////////////////////////////////////////////////////////////////// + /// + /// The Google Health Data API allows applications to view and send health data in the form of Google Data feeds. + /// The HealthService class encapsulates authentication to the Google HealthService. + /// + ////////////////////////////////////////////////////////////////////// + public abstract class BaseHealthService : Service + { + /// The Calendar service's name + public const string ServiceName = "health"; + /// The base Google Health Feeds address. + private string BaseAddress; + /// The Google Health Profile list feed. + private string ProfileListFeed; + /// The Google Health Profile UI feed + private string ProfileFeed; + /// The Google Health Register UI feed + private string RegisterFeed; + /// The Google Health Default Profile UI feed + private string DefaultProfileFeed; + /// The Google Health Default Register UI feed + private string DefaultRegisterFeed; + + /// + /// default constructor + /// + /// + /// + public BaseHealthService(string applicationName, string baseAddress, + string profileListFeed, string profileFeed, string registerFeed, + string defaultProfileFeed, string defaultRegisterFeed) + : base(ServiceName, applicationName) + { + this.NewFeed += new ServiceEventHandler(this.OnNewFeed); + this.BaseAddress = baseAddress; + this.ProfileListFeed = profileListFeed; + this.ProfileFeed = profileFeed; + this.RegisterFeed = registerFeed; + this.DefaultProfileFeed = defaultProfileFeed; + this.DefaultRegisterFeed = defaultRegisterFeed; + } + + /// + /// overloaded to create typed version of Query + /// + /// + /// EventFeed + public HealthFeed Query(HealthQuery feedQuery) + { + return base.Query(feedQuery) as HealthFeed; + } + + /// + /// Queries the Google Health Profile list feed. This is related to the + /// ClientLogin queries using ClientLogin. + /// + /// The list of profiles for the authenticated client. + public List GetProfiles() + { + HealthFeed feed = this.Query(new HealthQuery(ProfileListFeed)); + List profiles = new List(); + foreach (AtomEntry entry in feed.Entries) + { + profiles.Add(Profile.FromAtomEntry(entry)); + } + return profiles; + } + + /// + /// Queries the Google Health Profile Register feed for the list of notices. This + /// is for ClientLogin related queries. + /// + /// The profile to query against. + /// The list of notices available on this profile. + public List GetNotices(string profileId) + { + HealthQuery query = new HealthQuery(RegisterFeed + profileId); + query.Digest = true; + HealthFeed feed = this.Query(query); + List notices = new List(); + foreach (AtomEntry entry in feed.Entries) + { + notices.Add(Notice.FromAtomEntry(entry)); + } + return notices; + } + + /// + /// Queries the profile feed for the list of available CCR records with digest enabled. Available + /// for ClientLogin related queries. + /// + /// The profile to query against. + /// The list of CCR records available. + public ContinuityOfCareRecord GetCareRecordsDigest(string profileId) + { + List records = GetCareRecords(profileId, true); + if (records.Count > 0) + return records[0]; + return null; + } + + /// + /// Queries the profile feed for the list of available CCR records. Available + /// for ClientLogin related queries. + /// + /// The profile to query against. + /// True to aggregate all CCR into a single CCR element, false otherwise. + /// The list of CCR records available. + public List GetCareRecords(string profileId, bool digest) + { + HealthQuery query = new HealthQuery(ProfileFeed + profileId); + query.Digest = true; + HealthFeed feed = this.Query(query); + List ccrs = new List(); + foreach (AtomEntry entry in feed.Entries) + { + IExtensionElementFactory factory = entry.FindExtension("ContinuityOfCareRecord", "urn:astm-org:CCR"); + if (factory != null) + { + XmlExtension extension = factory as XmlExtension; + XmlSerializer serializer = new XmlSerializer(typeof(ContinuityOfCareRecord)); + XmlTextReader reader = new XmlTextReader(new StringReader(extension.Node.OuterXml)); + ccrs.Add(serializer.Deserialize(reader) as ContinuityOfCareRecord); + } + } + return ccrs; + } + + /// + /// Posts a notice to the particular profile on the register feed. Available + /// under ClientLogin only. + /// + /// + /// + public void PostNotice(Notice notice, string profileId) + { + PostNoticeUrl(notice, RegisterFeed + profileId); + } + + /// + /// Posts a notice to the default profile on the register feed. Usable + /// for the AuthSub profile feed. + /// + /// + public void PostNotice(Notice notice) + { + PostNoticeUrl(notice, DefaultRegisterFeed); + } + + private void PostNoticeUrl(Notice notice, string url) + { + AtomEntry entry = new AtomEntry(); + entry.Title.Text = notice.Subject; + entry.Content.Content = notice.Subject; + entry.Content.Type = notice.ContentType; + + if (notice.CareRecord != null) + { + XmlSerializer serializer = new XmlSerializer(typeof(ContinuityOfCareRecord)); + using (StringWriter strWriter = new StringWriter()) + { + XmlTextWriter writer = new XmlTextWriter(new StringWriter()); + serializer.Serialize(writer, notice.CareRecord); + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(strWriter.ToString()); + entry.ExtensionElements.Add(new XmlExtension(doc.DocumentElement)); + } + } + + notice = Notice.FromAtomEntry(this.Insert(new Uri(url), entry)); + } + + ////////////////////////////////////////////////////////////////////// + /// eventchaining. We catch this by from the base service, which + /// would not by default create an atomFeed + /// the object which send the event + /// FeedParserEventArguments, holds the feedentry + /// + ////////////////////////////////////////////////////////////////////// + protected void OnNewFeed(object sender, ServiceEventArgs e) + { + Tracing.TraceMsg("Created new Google Health Feed"); + if (e == null) + { + throw new ArgumentNullException("e"); + } + + e.Feed = new HealthFeed(e.Uri, e.Service); + } + ///////////////////////////////////////////////////////////////////////////// + } +} diff -Nru gdata-sharp-1.4.0.2/src/ghealth/ccrschema.cs gdata-sharp-1.7.0.1/src/ghealth/ccrschema.cs --- gdata-sharp-1.4.0.2/src/ghealth/ccrschema.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/ghealth/ccrschema.cs 2009-08-18 23:17:20.000000000 +0000 @@ -0,0 +1,2505 @@ +using System.Xml.Serialization; + +namespace ASTM.Org.CCR +{ + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:astm-org:CCR", IsNullable = false)] + public class ContinuityOfCareRecord + { + + /// + public string CCRDocumentObjectID; + + /// + public CodedDescriptionType Language; + + /// + public string Version; + + /// + public DateTimeType DateTime; + + /// + [System.Xml.Serialization.XmlElementAttribute("Patient")] + public ContinuityOfCareRecordPatient[] Patient; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("ActorLink", IsNullable = false)] + public ActorReferenceType[] From; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("ActorLink", IsNullable = false)] + public ActorReferenceType[] To; + + /// + [System.Xml.Serialization.XmlElementAttribute("Purpose")] + public PurposeType[] Purpose; + + /// + public ContinuityOfCareRecordBody Body; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Actor", IsNullable = false)] + public ActorType[] Actors; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Reference", IsNullable = false)] + public ReferenceType[] References; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Comment", IsNullable = false)] + public CommentType[] Comments; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("CCRSignature", IsNullable = false)] + public SignatureType[] Signatures; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(PositionType))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(MethodType))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(InstructionType))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(SiteType))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(DirectionRoute))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(VehicleTypeProductSize))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(VehicleTypeProductForm))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(StructuredProductTypeProductSize))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(StructuredProductTypeProductForm))] + [System.Xml.Serialization.XmlRootAttribute("Description", Namespace = "urn:astm-org:CCR", IsNullable = false)] + public class CodedDescriptionType + { + + /// + public string Text; + + /// + [System.Xml.Serialization.XmlElementAttribute("ObjectAttribute")] + public CodedDescriptionTypeObjectAttribute[] ObjectAttribute; + + /// + [System.Xml.Serialization.XmlElementAttribute("Code")] + public CodeType[] Code; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class CodedDescriptionTypeObjectAttribute + { + + /// + public string Attribute; + + /// + [System.Xml.Serialization.XmlElementAttribute("AttributeValue")] + public CodedDescriptionTypeObjectAttributeAttributeValue[] AttributeValue; + + /// + [System.Xml.Serialization.XmlElementAttribute("Code")] + public CodeType[] Code; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class CodedDescriptionTypeObjectAttributeAttributeValue + { + + /// + public object Value; + + /// + [System.Xml.Serialization.XmlElementAttribute("Code")] + public CodeType[] Code; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class ContinuityOfCareRecordBody + { + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Payer", IsNullable = false)] + public InsuranceType[] Payers; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("AdvanceDirective", IsNullable = false)] + public CCRCodedDataObjectType[] AdvanceDirectives; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("SupportProvider", IsNullable = false)] + public ActorReferenceType[] Support; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Function", IsNullable = false)] + public FunctionType[] FunctionalStatus; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Problem", IsNullable = false)] + public ProblemType[] Problems; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("FamilyProblemHistory", IsNullable = false)] + public FamilyHistoryType[] FamilyHistory; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("SocialHistoryElement", IsNullable = false)] + public SocialHistoryType[] SocialHistory; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Alert", IsNullable = false)] + public AlertType[] Alerts; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Medication", IsNullable = false)] + public StructuredProductType[] Medications; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Equipment", IsNullable = false)] + public StructuredProductType[] MedicalEquipment; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Immunization", IsNullable = false)] + public StructuredProductType[] Immunizations; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Result", IsNullable = false)] + public ResultType[] VitalSigns; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Result", IsNullable = false)] + public ResultType[] Results; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Procedure", IsNullable = false)] + public ProcedureType[] Procedures; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Encounter", IsNullable = false)] + public EncounterType[] Encounters; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Plan", IsNullable = false)] + public PlanType[] PlanOfCare; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Provider", IsNullable = false)] + public ActorReferenceType[] HealthCareProviders; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class InsuranceType : CCRCodedDataObjectType + { + + /// + public ActorReferenceType PaymentProvider; + + /// + public ActorReferenceType Subscriber; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Authorization", IsNullable = false)] + public AuthorizationType[] Authorizations; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(FamilyHistoryTypeFamilyMember))] + [System.Xml.Serialization.XmlRootAttribute("Actor", Namespace = "urn:astm-org:CCR", IsNullable = false)] + public class ActorReferenceType + { + + /// + public string ActorID; + + /// + [System.Xml.Serialization.XmlElementAttribute("ActorRole")] + public CodedDescriptionType[] ActorRole; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class FamilyHistoryTypeFamilyMember : ActorReferenceType + { + + /// + public CurrentHealthStatusType HealthStatus; + + /// + [System.Xml.Serialization.XmlElementAttribute("Source")] + public SourceType[] Source; + + /// + [System.Xml.Serialization.XmlElementAttribute("InternalCCRLink")] + public InternalCCRLink[] InternalCCRLink; + + /// + [System.Xml.Serialization.XmlElementAttribute("ReferenceID")] + public string[] ReferenceID; + + /// + [System.Xml.Serialization.XmlElementAttribute("CommentID")] + public string[] CommentID; + + /// + [System.Xml.Serialization.XmlElementAttribute("Signature")] + public IDTypeSignature[] Signature; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class CurrentHealthStatusType + { + + /// + [System.Xml.Serialization.XmlElementAttribute("DateTime")] + public DateTimeType[] DateTime; + + /// + public CodedDescriptionType Description; + + /// + public string CauseOfDeath; + + /// + [System.Xml.Serialization.XmlElementAttribute("Source")] + public SourceType[] Source; + + /// + [System.Xml.Serialization.XmlElementAttribute("InternalCCRLink")] + public InternalCCRLink[] InternalCCRLink; + + /// + [System.Xml.Serialization.XmlElementAttribute("ReferenceID")] + public string[] ReferenceID; + + /// + [System.Xml.Serialization.XmlElementAttribute("CommentID")] + public string[] CommentID; + + /// + [System.Xml.Serialization.XmlElementAttribute("Signature")] + public IDTypeSignature[] Signature; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(DirectionAdministrationTiming))] + public class DateTimeType + { + + /// + public CodedDescriptionType Type; + + /// + public string ExactDateTime; + + /// + public MeasureType Age; + + /// + public CodedDescriptionType ApproximateDateTime; + + /// + [System.Xml.Serialization.XmlElementAttribute("DateTimeRange")] + public DateTimeTypeDateTimeRange[] DateTimeRange; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(IndicationTypePhysiologicalParameter))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(VehicleTypeQuantity))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(VehicleTypeProductConcentration))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(VehicleTypeProductStrength))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(DoseCalculationTypeVariable))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(DirectionDose))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(StructuredProductTypeProductSizeDimension))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(StructuredProductTypeProductConcentration))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(StructuredProductTypeProductStrength))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(QuantityType))] + [System.Xml.Serialization.XmlRootAttribute("Age", Namespace = "urn:astm-org:CCR", IsNullable = false)] + public class MeasureType + { + + /// + public string Value; + + /// + public MeasureTypeUnits Units; + + /// + [System.Xml.Serialization.XmlElementAttribute("Code")] + public CodeType[] Code; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class MeasureTypeUnits + { + + /// + public string Unit; + + /// + [System.Xml.Serialization.XmlElementAttribute("Code")] + public CodeType[] Code; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class CodeType + { + + /// + public string Value; + + /// + public string CodingSystem; + + /// + public string Version; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class IndicationTypePhysiologicalParameter : MeasureType + { + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string ParameterSequencePosition; + + /// + public CodedDescriptionType VariableParameterModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class VehicleTypeQuantity : MeasureType + { + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string QuantitySequencePosition; + + /// + public CodedDescriptionType VariableQuantityModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class VehicleTypeProductConcentration : MeasureType + { + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string ConcentrationSequencePosition; + + /// + public CodedDescriptionType VariableConcentrationModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class VehicleTypeProductStrength : MeasureType + { + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string StrengthSequencePosition; + + /// + public CodedDescriptionType VariableStrengthModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class DoseCalculationTypeVariable : MeasureType + { + + /// + public string VariableIdentifier; + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string VariableSequencePosition; + + /// + public CodedDescriptionType VariableModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class DirectionDose : MeasureType + { + + /// + [System.Xml.Serialization.XmlElementAttribute("Rate")] + public RateType[] Rate; + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string DoseSequencePosition; + + /// + public CodedDescriptionType VariableDoseModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class RateType + { + + /// + public CodedDescriptionType Description; + + /// + public string Value; + + /// + public RateTypeUnits Units; + + /// + [System.Xml.Serialization.XmlElementAttribute("Code")] + public CodeType[] Code; + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string RateSequencePosition; + + /// + public CodedDescriptionType VariableRateModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class RateTypeUnits + { + + /// + public string Unit; + + /// + [System.Xml.Serialization.XmlElementAttribute("Code")] + public CodeType[] Code; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class StructuredProductTypeProductSizeDimension : MeasureType + { + + /// + public CodedDescriptionType Description; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class StructuredProductTypeProductConcentration : MeasureType + { + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string ConcentrationSequencePosition; + + /// + public CodedDescriptionType VariableConcentrationModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class StructuredProductTypeProductStrength : MeasureType + { + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string StrengthSequencePosition; + + /// + public CodedDescriptionType VariableStrengthModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class QuantityType : MeasureType + { + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string QuantitySequencePosition; + + /// + public CodedDescriptionType VariableQuantityModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class DateTimeTypeDateTimeRange + { + + /// + public DateTimeTypeDateTimeRangeBeginRange BeginRange; + + /// + public DateTimeTypeDateTimeRangeEndRange EndRange; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class DateTimeTypeDateTimeRangeBeginRange + { + + /// + public string ExactDateTime; + + /// + public MeasureType Age; + + /// + public CodedDescriptionType ApproximateDateTime; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class DateTimeTypeDateTimeRangeEndRange + { + + /// + public string ExactDateTime; + + /// + public MeasureType Age; + + /// + public CodedDescriptionType ApproximateDateTime; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class DirectionAdministrationTiming : DateTimeType + { + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string TimingSequencePosition; + + /// + public CodedDescriptionType VariableTimingModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(InternalCCRLinkSource))] + public class SourceType + { + + /// + public CodedDescriptionType Description; + + /// + [System.Xml.Serialization.XmlElementAttribute("Actor")] + public ActorReferenceType[] Actor; + + /// + public DateTimeType DateTime; + + /// + [System.Xml.Serialization.XmlElementAttribute("ReferenceID")] + public string[] ReferenceID; + + /// + [System.Xml.Serialization.XmlElementAttribute("CommentID")] + public string[] CommentID; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class InternalCCRLinkSource : SourceType + { + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:astm-org:CCR", IsNullable = false)] + public class InternalCCRLink + { + + /// + public string LinkID; + + /// + [System.Xml.Serialization.XmlElementAttribute("LinkRelationship")] + public string[] LinkRelationship; + + /// + public InternalCCRLinkSource Source; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class IDTypeSignature + { + + /// + public string SignatureID; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class AuthorizationType : CCRCodedDataObjectType + { + + /// + [System.Xml.Serialization.XmlElementAttribute("Purpose")] + public PurposeType[] Purpose; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Practitioner", IsNullable = false)] + public ActorReferenceType[] Practitioners; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Procedure", IsNullable = false)] + public ProcedureType[] Procedures; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Product", IsNullable = false)] + public StructuredProductType[] Products; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Medication", IsNullable = false)] + public StructuredProductType[] Medications; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Immunization", IsNullable = false)] + public StructuredProductType[] Immunizations; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Service", IsNullable = false)] + public EncounterType[] Services; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Encounter", IsNullable = false)] + public EncounterType[] Encounters; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class PurposeType + { + + /// + [System.Xml.Serialization.XmlElementAttribute("DateTime")] + public DateTimeType[] DateTime; + + /// + [System.Xml.Serialization.XmlElementAttribute("Description")] + public CodedDescriptionType[] Description; + + /// + [System.Xml.Serialization.XmlElementAttribute("OrderRequest")] + public PlanOfCareType[] OrderRequest; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Indication", typeof(IndicationType), IsNullable = false)] + public IndicationType[][] Indications; + + /// + [System.Xml.Serialization.XmlElementAttribute("ReferenceID")] + public string[] ReferenceID; + + /// + [System.Xml.Serialization.XmlElementAttribute("CommentID")] + public string[] CommentID; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class PlanOfCareType : InterventionType + { + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Goal", IsNullable = false)] + public GoalType[] Goals; + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string OrderSequencePosition; + + /// + public CodedDescriptionType MultipleOrderModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class GoalType : EncounterType + { + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Outcome", IsNullable = false)] + public CCRCodedDataObjectType[] Milestones; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(SocialHistoryType))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(PlanType))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(InsuranceType))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(FunctionType))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(FamilyHistoryType))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(InterventionType))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(PlanOfCareType))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(AuthorizationType))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(TestType))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(ResultType))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(OrderRxHistoryType))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(EncounterType))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(GoalType))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(EpisodeType))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(ProblemType))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(StructuredProductType))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(AlertType))] + public class CCRCodedDataObjectType + { + + /// + public string CCRDataObjectID; + + /// + [System.Xml.Serialization.XmlElementAttribute("DateTime")] + public DateTimeType[] DateTime; + + /// + [System.Xml.Serialization.XmlElementAttribute("IDs")] + public IDType[] IDs; + + /// + public CodedDescriptionType Type; + + /// + public CodedDescriptionType Description; + + /// + public CodedDescriptionType Status; + + /// + [System.Xml.Serialization.XmlElementAttribute("Source")] + public SourceType[] Source; + + /// + [System.Xml.Serialization.XmlElementAttribute("InternalCCRLink")] + public InternalCCRLink[] InternalCCRLink; + + /// + [System.Xml.Serialization.XmlElementAttribute("ReferenceID")] + public string[] ReferenceID; + + /// + [System.Xml.Serialization.XmlElementAttribute("CommentID")] + public string[] CommentID; + + /// + [System.Xml.Serialization.XmlElementAttribute("Signature")] + public IDTypeSignature[] Signature; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlRootAttribute("IDs", Namespace = "urn:astm-org:CCR", IsNullable = false)] + public class IDType + { + + /// + [System.Xml.Serialization.XmlElementAttribute("DateTime")] + public DateTimeType[] DateTime; + + /// + public CodedDescriptionType Type; + + /// + public string ID; + + /// + public ActorReferenceType IssuedBy; + + /// + [System.Xml.Serialization.XmlElementAttribute("Source")] + public SourceType[] Source; + + /// + [System.Xml.Serialization.XmlElementAttribute("InternalCCRLink")] + public InternalCCRLink[] InternalCCRLink; + + /// + [System.Xml.Serialization.XmlElementAttribute("ReferenceID")] + public string[] ReferenceID; + + /// + [System.Xml.Serialization.XmlElementAttribute("CommentID")] + public string[] CommentID; + + /// + [System.Xml.Serialization.XmlElementAttribute("Signature")] + public IDTypeSignature[] Signature; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class SocialHistoryType : CCRCodedDataObjectType + { + + /// + public EpisodesType Episodes; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class EpisodesType + { + + /// + public string Number; + + /// + public MeasureType Frequency; + + /// + [System.Xml.Serialization.XmlElementAttribute("Episode")] + public EpisodeType[] Episode; + + /// + [System.Xml.Serialization.XmlElementAttribute("Source")] + public SourceType[] Source; + + /// + [System.Xml.Serialization.XmlElementAttribute("InternalCCRLink")] + public InternalCCRLink[] InternalCCRLink; + + /// + [System.Xml.Serialization.XmlElementAttribute("ReferenceID")] + public string[] ReferenceID; + + /// + [System.Xml.Serialization.XmlElementAttribute("CommentID")] + public string[] CommentID; + + /// + [System.Xml.Serialization.XmlElementAttribute("Signature")] + public IDTypeSignature[] Signature; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class EpisodeType : CCRCodedDataObjectType + { + + /// + public DurationType Duration; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class DurationType + { + + /// + public CodedDescriptionType Description; + + /// + [System.Xml.Serialization.XmlElementAttribute("DateTime")] + public DateTimeType[] DateTime; + + /// + public string Value; + + /// + public RateTypeUnits Units; + + /// + [System.Xml.Serialization.XmlElementAttribute("Code")] + public CodeType[] Code; + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string DurationSequencePosition; + + /// + public CodedDescriptionType VariableDurationModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class PlanType : CCRCodedDataObjectType + { + + /// + [System.Xml.Serialization.XmlElementAttribute("OrderRequest")] + public PlanOfCareType[] OrderRequest; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class FunctionType : CCRCodedDataObjectType + { + + /// + [System.Xml.Serialization.XmlElementAttribute("Problem")] + public ProblemType[] Problem; + + /// + [System.Xml.Serialization.XmlElementAttribute("Test")] + public ResultType[] Test; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class ProblemType : CCRCodedDataObjectType + { + + /// + public EpisodesType Episodes; + + /// + public CurrentHealthStatusType HealthStatus; + + /// + public PatientKnowledgeType PatientKnowledge; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class PatientKnowledgeType + { + + /// + public string PatientAware; + + /// + public CodedDescriptionType Description; + + /// + [System.Xml.Serialization.XmlElementAttribute("Source")] + public SourceType[] Source; + + /// + [System.Xml.Serialization.XmlElementAttribute("InternalCCRLink")] + public InternalCCRLink[] InternalCCRLink; + + /// + [System.Xml.Serialization.XmlElementAttribute("ReferenceID")] + public string[] ReferenceID; + + /// + [System.Xml.Serialization.XmlElementAttribute("CommentID")] + public string[] CommentID; + + /// + [System.Xml.Serialization.XmlElementAttribute("Signature")] + public IDTypeSignature[] Signature; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class ResultType : CCRCodedDataObjectType + { + + /// + [System.Xml.Serialization.XmlElementAttribute("Procedure")] + public ProcedureType[] Procedure; + + /// + public CodedDescriptionType Substance; + + /// + [System.Xml.Serialization.XmlElementAttribute("Test")] + public TestType[] Test; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class ProcedureType + { + + /// + public string CCRDataObjectID; + + /// + [System.Xml.Serialization.XmlElementAttribute("DateTime")] + public DateTimeType[] DateTime; + + /// + public IDType IDs; + + /// + public CodedDescriptionType Type; + + /// + public CodedDescriptionType Description; + + /// + public CodedDescriptionType Status; + + /// + [System.Xml.Serialization.XmlElementAttribute("Source")] + public SourceType[] Source; + + /// + [System.Xml.Serialization.XmlElementAttribute("InternalCCRLink")] + public InternalCCRLink[] InternalCCRLink; + + /// + [System.Xml.Serialization.XmlElementAttribute("ReferenceID")] + public string[] ReferenceID; + + /// + [System.Xml.Serialization.XmlElementAttribute("CommentID")] + public string[] CommentID; + + /// + [System.Xml.Serialization.XmlElementAttribute("Signature")] + public IDTypeSignature[] Signature; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute(IsNullable = false)] + public Location[] Locations; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Practitioner", IsNullable = false)] + public ActorReferenceType[] Practitioners; + + /// + [System.Xml.Serialization.XmlElementAttribute("Frequency")] + public FrequencyType[] Frequency; + + /// + [System.Xml.Serialization.XmlElementAttribute("Interval")] + public IntervalType[] Interval; + + /// + [System.Xml.Serialization.XmlElementAttribute("Duration")] + public DurationType[] Duration; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Indication", typeof(IndicationType), IsNullable = false)] + public IndicationType[][] Indications; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Instruction", IsNullable = false)] + public CodedDescriptionType[] Instructions; + + /// + public CCRCodedDataObjectType Consent; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Product", IsNullable = false)] + public StructuredProductType[] Products; + + /// + public CodedDescriptionType Substance; + + /// + [System.Xml.Serialization.XmlElementAttribute("Method")] + public MethodType[] Method; + + /// + [System.Xml.Serialization.XmlElementAttribute("Position")] + public PositionType[] Position; + + /// + [System.Xml.Serialization.XmlElementAttribute("Site")] + public SiteType[] Site; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:astm-org:CCR", IsNullable = false)] + public class Location + { + + /// + public CodedDescriptionType Description; + + /// + public ActorReferenceType Actor; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class FrequencyType + { + + /// + public CodedDescriptionType Description; + + /// + public string Value; + + /// + public RateTypeUnits Units; + + /// + [System.Xml.Serialization.XmlElementAttribute("Code")] + public CodeType[] Code; + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string FrequencySequencePosition; + + /// + public CodedDescriptionType VariableFrequencyModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class IntervalType + { + + /// + public CodedDescriptionType Description; + + /// + public string Value; + + /// + public RateTypeUnits Units; + + /// + [System.Xml.Serialization.XmlElementAttribute("Code")] + public CodeType[] Code; + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string IntervalSequencePosition; + + /// + public CodedDescriptionType VariableIntervalModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class IndicationType + { + + /// + public CodedDescriptionType PRNFlag; + + /// + [System.Xml.Serialization.XmlElementAttribute("Description")] + public CodedDescriptionType[] Description; + + /// + [System.Xml.Serialization.XmlElementAttribute("Problem")] + public ProblemType[] Problem; + + /// + [System.Xml.Serialization.XmlElementAttribute("PhysiologicalParameter")] + public IndicationTypePhysiologicalParameter[] PhysiologicalParameter; + + /// + [System.Xml.Serialization.XmlElementAttribute("Source")] + public SourceType[] Source; + + /// + [System.Xml.Serialization.XmlElementAttribute("InternalCCRLink")] + public InternalCCRLink[] InternalCCRLink; + + /// + [System.Xml.Serialization.XmlElementAttribute("ReferenceID")] + public string[] ReferenceID; + + /// + [System.Xml.Serialization.XmlElementAttribute("CommentID")] + public string[] CommentID; + + /// + [System.Xml.Serialization.XmlElementAttribute("Signature")] + public IDTypeSignature[] Signature; + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string IndicationSequencePosition; + + /// + public CodedDescriptionType MultipleIndicationModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class StructuredProductType : CCRCodedDataObjectType + { + + /// + [System.Xml.Serialization.XmlElementAttribute("Product")] + public StructuredProductTypeProduct[] Product; + + /// + [System.Xml.Serialization.XmlElementAttribute("Quantity")] + public QuantityType[] Quantity; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute(typeof(Direction), IsNullable = false)] + public Direction[][] Directions; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Instruction", IsNullable = false)] + public InstructionType[] PatientInstructions; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Instruction", IsNullable = false)] + public InstructionType[] FulfillmentInstructions; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Refill", IsNullable = false)] + public StructuredProductTypeRefill[] Refills; + + /// + public string SeriesNumber; + + /// + public CCRCodedDataObjectType Consent; + + /// + public Reaction Reaction; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Fulfillment", IsNullable = false)] + public OrderRxHistoryType[] FulfillmentHistory; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class StructuredProductTypeProduct + { + + /// + public CodedDescriptionType ProductName; + + /// + public CodedDescriptionType BrandName; + + /// + [System.Xml.Serialization.XmlElementAttribute("Strength")] + public StructuredProductTypeProductStrength[] Strength; + + /// + [System.Xml.Serialization.XmlElementAttribute("Form")] + public StructuredProductTypeProductForm[] Form; + + /// + [System.Xml.Serialization.XmlElementAttribute("Concentration")] + public StructuredProductTypeProductConcentration[] Concentration; + + /// + [System.Xml.Serialization.XmlElementAttribute("Size")] + public StructuredProductTypeProductSize[] Size; + + /// + public ActorReferenceType Manufacturer; + + /// + [System.Xml.Serialization.XmlElementAttribute("IDs")] + public IDType[] IDs; + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string ProductSequencePosition; + + /// + public CodedDescriptionType MultipleProductModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class StructuredProductTypeProductForm : CodedDescriptionType + { + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string FormSequencePosition; + + /// + public CodedDescriptionType MultipleFormModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class StructuredProductTypeProductSize : CodedDescriptionType + { + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Dimension", IsNullable = false)] + public StructuredProductTypeProductSizeDimension[] Dimensions; + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string SizeSequencePosition; + + /// + public CodedDescriptionType VariableSizeModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:astm-org:CCR", IsNullable = false)] + public class Direction + { + + /// + public CodedDescriptionType Description; + + /// + public CodedDescriptionType DoseIndicator; + + /// + public CodedDescriptionType DeliveryMethod; + + /// + [System.Xml.Serialization.XmlElementAttribute("Dose")] + public DirectionDose[] Dose; + + /// + [System.Xml.Serialization.XmlElementAttribute("DoseCalculation")] + public DirectionDoseCalculation[] DoseCalculation; + + /// + [System.Xml.Serialization.XmlElementAttribute("Vehicle")] + public VehicleType[] Vehicle; + + /// + [System.Xml.Serialization.XmlElementAttribute("Route")] + public DirectionRoute[] Route; + + /// + [System.Xml.Serialization.XmlElementAttribute("Site")] + public SiteType[] Site; + + /// + [System.Xml.Serialization.XmlElementAttribute("AdministrationTiming")] + public DirectionAdministrationTiming[] AdministrationTiming; + + /// + [System.Xml.Serialization.XmlElementAttribute("Frequency")] + public FrequencyType[] Frequency; + + /// + [System.Xml.Serialization.XmlElementAttribute("Interval")] + public IntervalType[] Interval; + + /// + [System.Xml.Serialization.XmlElementAttribute("Duration")] + public DurationType[] Duration; + + /// + [System.Xml.Serialization.XmlElementAttribute("DoseRestriction")] + public DirectionDoseRestriction[] DoseRestriction; + + /// + [System.Xml.Serialization.XmlElementAttribute("Indication")] + public IndicationType[] Indication; + + /// + public CodedDescriptionType StopIndicator; + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string DirectionSequencePosition; + + /// + public CodedDescriptionType MultipleDirectionModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class DirectionDoseCalculation : DoseCalculationType + { + + /// + [System.Xml.Serialization.XmlElementAttribute("Rate")] + public RateType[] Rate; + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string CalculationSequencePosition; + + /// + public CodedDescriptionType VariableCalculationModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(DirectionDoseRestriction))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(DirectionDoseCalculation))] + public class DoseCalculationType + { + + /// + public MeasureType Dose; + + /// + [System.Xml.Serialization.XmlElementAttribute("Variable")] + public DoseCalculationTypeVariable[] Variable; + + /// + public DoseCalculationTypeCalculationEquation CalculationEquation; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class DoseCalculationTypeCalculationEquation + { + + /// + public string Value; + + /// + [System.Xml.Serialization.XmlElementAttribute("Code")] + public CodeType[] Code; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class DirectionDoseRestriction : DoseCalculationType + { + + /// + [System.Xml.Serialization.XmlElementAttribute("Rate")] + public RateType[] Rate; + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string RestrictionSequencePosition; + + /// + public CodedDescriptionType VariableRestrictionModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class VehicleType + { + + /// + public CodedDescriptionType Description; + + /// + [System.Xml.Serialization.XmlElementAttribute("Product")] + public VehicleTypeProduct[] Product; + + /// + public ActorReferenceType Manufacturer; + + /// + public IDType IDs; + + /// + [System.Xml.Serialization.XmlElementAttribute("Quantity")] + public VehicleTypeQuantity[] Quantity; + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string VehicleSequencePosition; + + /// + public CodedDescriptionType MultipleVehicleModifier; + + /// + public InternalCCRLink InternalCCRLink; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class VehicleTypeProduct + { + + /// + public CodedDescriptionType ProductName; + + /// + public CodedDescriptionType BrandName; + + /// + [System.Xml.Serialization.XmlElementAttribute("Strength")] + public VehicleTypeProductStrength[] Strength; + + /// + [System.Xml.Serialization.XmlElementAttribute("Form")] + public VehicleTypeProductForm[] Form; + + /// + [System.Xml.Serialization.XmlElementAttribute("Concentration")] + public VehicleTypeProductConcentration[] Concentration; + + /// + [System.Xml.Serialization.XmlElementAttribute("Size")] + public VehicleTypeProductSize[] Size; + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string ProductSequencePosition; + + /// + public CodedDescriptionType MultipleProductModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class VehicleTypeProductForm : CodedDescriptionType + { + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string FormSequencePosition; + + /// + public CodedDescriptionType MultipleFormModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class VehicleTypeProductSize : CodedDescriptionType + { + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string SizeSequencePosition; + + /// + public CodedDescriptionType VariableSizeModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class DirectionRoute : CodedDescriptionType + { + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string RouteSequencePosition; + + /// + public CodedDescriptionType MultipleRouteModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class SiteType : CodedDescriptionType + { + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string SiteSequencePosition; + + /// + public CodedDescriptionType MultipleSiteModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class InstructionType : CodedDescriptionType + { + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string instructionSequencePosition; + + /// + public CodedDescriptionType MultipleInstructionModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class StructuredProductTypeRefill + { + + /// + [System.Xml.Serialization.XmlElementAttribute("Number", DataType = "integer")] + public string[] Number; + + /// + [System.Xml.Serialization.XmlElementAttribute("Quantity")] + public QuantityType[] Quantity; + + /// + public CodedDescriptionType Status; + + /// + [System.Xml.Serialization.XmlElementAttribute("DateTime")] + public DateTimeType[] DateTime; + + /// + [System.Xml.Serialization.XmlElementAttribute("Comment")] + public CommentType[] Comment; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class CommentType + { + + /// + public string CommentObjectID; + + /// + public DateTimeType DateTime; + + /// + public CodedDescriptionType Type; + + /// + public CodedDescriptionType Description; + + /// + [System.Xml.Serialization.XmlElementAttribute("Source")] + public ActorReferenceType[] Source; + + /// + [System.Xml.Serialization.XmlElementAttribute("ReferenceID")] + public string[] ReferenceID; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:astm-org:CCR", IsNullable = false)] + public class Reaction + { + + /// + public CodedDescriptionType Description; + + /// + public CodedDescriptionType Status; + + /// + public CodedDescriptionType Severity; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Intervention", IsNullable = false)] + public ReactionIntervention[] Interventions; + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string ReactionSequencePosition; + + /// + public CodedDescriptionType MultipleReactionModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class ReactionIntervention + { + + /// + public string CCRDataObjectID; + + /// + [System.Xml.Serialization.XmlElementAttribute("DateTime")] + public DateTimeType[] DateTime; + + /// + public CodedDescriptionType Type; + + /// + public CodedDescriptionType Description; + + /// + public CodedDescriptionType Status; + + /// + [System.Xml.Serialization.XmlElementAttribute("Source")] + public SourceType[] Source; + + /// + [System.Xml.Serialization.XmlElementAttribute("InternalCCRLink")] + public InternalCCRLink[] InternalCCRLink; + + /// + [System.Xml.Serialization.XmlElementAttribute("ReferenceID")] + public string[] ReferenceID; + + /// + [System.Xml.Serialization.XmlElementAttribute("CommentID")] + public string[] CommentID; + + /// + [System.Xml.Serialization.XmlElementAttribute("Signature")] + public IDTypeSignature[] Signature; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Procedure", IsNullable = false)] + public ProcedureType[] Procedures; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Product", IsNullable = false)] + public StructuredProductType[] Products; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Medication", IsNullable = false)] + public StructuredProductType[] Medications; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Immunization", IsNullable = false)] + public StructuredProductType[] Immunizations; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Service", IsNullable = false)] + public EncounterType[] Services; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Encounter", IsNullable = false)] + public EncounterType[] Encounters; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(GoalType))] + public class EncounterType : CCRCodedDataObjectType + { + + /// + [System.Xml.Serialization.XmlArrayItemAttribute(IsNullable = false)] + public Location[] Locations; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Practitioner", IsNullable = false)] + public ActorReferenceType[] Practitioners; + + /// + [System.Xml.Serialization.XmlElementAttribute("Frequency")] + public FrequencyType[] Frequency; + + /// + [System.Xml.Serialization.XmlElementAttribute("Interval")] + public IntervalType[] Interval; + + /// + [System.Xml.Serialization.XmlElementAttribute("Duration")] + public DurationType[] Duration; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Indication", typeof(IndicationType), IsNullable = false)] + public IndicationType[][] Indications; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Instruction", IsNullable = false)] + public CodedDescriptionType[] Instructions; + + /// + public CCRCodedDataObjectType Consent; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class OrderRxHistoryType : CCRCodedDataObjectType + { + + /// + public CodedDescriptionType FulfillmentMethod; + + /// + public ActorReferenceType Provider; + + /// + public ActorReferenceType Location; + + /// + [System.Xml.Serialization.XmlElementAttribute("Reaction")] + public Reaction[] Reaction; + + /// + public CodedDescriptionType ProductName; + + /// + public string BrandName; + + /// + public ActorReferenceType Manufacturer; + + /// + [System.Xml.Serialization.XmlElementAttribute("IDs")] + public IDType[] IDs1; + + /// + [System.Xml.Serialization.XmlElementAttribute("Strength")] + public MeasureType[] Strength; + + /// + [System.Xml.Serialization.XmlElementAttribute("Form")] + public CodedDescriptionType[] Form; + + /// + [System.Xml.Serialization.XmlElementAttribute("Concentration")] + public MeasureType[] Concentration; + + /// + [System.Xml.Serialization.XmlElementAttribute("Quantity")] + public MeasureType[] Quantity; + + /// + [System.Xml.Serialization.XmlElementAttribute("LabelInstructions")] + public InstructionType[] LabelInstructions; + + /// + public string SeriesNumber; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class MethodType : CodedDescriptionType + { + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string MethodSequencePosition; + + /// + public CodedDescriptionType MultipleMethodModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class PositionType : CodedDescriptionType + { + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string PositionSequencePosition; + + /// + public CodedDescriptionType MultiplePositionModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class TestType : CCRCodedDataObjectType + { + + /// + [System.Xml.Serialization.XmlElementAttribute("Method")] + public CodedDescriptionType[] Method; + + /// + [System.Xml.Serialization.XmlElementAttribute("Agent")] + public Agent[] Agent; + + /// + public TestResultType TestResult; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Normal", IsNullable = false)] + public NormalType[] NormalResult; + + /// + [System.Xml.Serialization.XmlElementAttribute("Flag")] + public CodedDescriptionType[] Flag; + + /// + public CodedDescriptionType ConfidenceValue; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:astm-org:CCR", IsNullable = false)] + public class Agent + { + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Product", IsNullable = false)] + public StructuredProductType[] Products; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("EnvironmentalAgent", IsNullable = false)] + public CCRCodedDataObjectType[] EnvironmentalAgents; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Problem", IsNullable = false)] + public ProblemType[] Problems; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Procedure", IsNullable = false)] + public ProcedureType[] Procedures; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Result", IsNullable = false)] + public ResultType[] Results; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class TestResultType + { + + /// + public string Value; + + /// + public RateTypeUnits Units; + + /// + [System.Xml.Serialization.XmlElementAttribute("Code")] + public CodeType[] Code; + + /// + [System.Xml.Serialization.XmlElementAttribute("Description")] + public CodedDescriptionType[] Description; + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string ResultSequencePosition; + + /// + public CodedDescriptionType VariableResultModifier; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class NormalType + { + + /// + public CodedDescriptionType Description; + + /// + public CodedDescriptionType Type; + + /// + public string Value; + + /// + public RateTypeUnits Units; + + /// + [System.Xml.Serialization.XmlElementAttribute("Code")] + public CodeType[] Code; + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "integer")] + public string ValueSequencePosition; + + /// + public CodedDescriptionType VariableNormalModifier; + + /// + [System.Xml.Serialization.XmlElementAttribute("Source")] + public SourceType[] Source; + + /// + [System.Xml.Serialization.XmlElementAttribute("InternalCCRLink")] + public InternalCCRLink[] InternalCCRLink; + + /// + [System.Xml.Serialization.XmlElementAttribute("ReferenceID")] + public string[] ReferenceID; + + /// + [System.Xml.Serialization.XmlElementAttribute("CommentID")] + public string[] CommentID; + + /// + [System.Xml.Serialization.XmlElementAttribute("Signature")] + public IDTypeSignature[] Signature; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class FamilyHistoryType : CCRCodedDataObjectType + { + + /// + [System.Xml.Serialization.XmlElementAttribute("FamilyMember")] + public FamilyHistoryTypeFamilyMember[] FamilyMember; + + /// + [System.Xml.Serialization.XmlElementAttribute("Problem")] + public FamilyHistoryTypeProblem[] Problem; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class FamilyHistoryTypeProblem + { + + /// + public CodedDescriptionType Type; + + /// + public CodedDescriptionType Description; + + /// + public EpisodesType Episodes; + + /// + [System.Xml.Serialization.XmlElementAttribute("Source")] + public SourceType[] Source; + + /// + [System.Xml.Serialization.XmlElementAttribute("InternalCCRLink")] + public InternalCCRLink[] InternalCCRLink; + + /// + [System.Xml.Serialization.XmlElementAttribute("ReferenceID")] + public string[] ReferenceID; + + /// + [System.Xml.Serialization.XmlElementAttribute("CommentID")] + public string[] CommentID; + + /// + [System.Xml.Serialization.XmlElementAttribute("Signature")] + public IDTypeSignature[] Signature; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(PlanOfCareType))] + public class InterventionType : CCRCodedDataObjectType + { + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Procedure", IsNullable = false)] + public ProcedureType[] Procedures; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Product", IsNullable = false)] + public StructuredProductType[] Products; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Medication", IsNullable = false)] + public StructuredProductType[] Medications; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Immunization", IsNullable = false)] + public StructuredProductType[] Immunizations; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Service", IsNullable = false)] + public EncounterType[] Services; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Encounter", IsNullable = false)] + public EncounterType[] Encounters; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Authorization", IsNullable = false)] + public AuthorizationType[] Authorizatons; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class AlertType : CCRCodedDataObjectType + { + + /// + [System.Xml.Serialization.XmlElementAttribute("Agent")] + public Agent[] Agent; + + /// + [System.Xml.Serialization.XmlElementAttribute("Reaction")] + public Reaction[] Reaction; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class ContinuityOfCareRecordPatient + { + + /// + public string ActorID; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class SignatureType + { + + /// + public string SignatureObjectID; + + /// + public string ExactDateTime; + + /// + public CodedDescriptionType Type; + + /// + [System.Xml.Serialization.XmlElementAttribute("IDs")] + public IDType[] IDs; + + /// + public ActorReferenceType Source; + + /// + public object Signature; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class ReferenceType + { + + /// + public string ReferenceObjectID; + + /// + [System.Xml.Serialization.XmlElementAttribute("DateTime")] + public DateTimeType[] DateTime; + + /// + public CodedDescriptionType Type; + + /// + public CodedDescriptionType Description; + + /// + [System.Xml.Serialization.XmlElementAttribute("Source")] + public ActorReferenceType[] Source; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute(IsNullable = false)] + public Location[] Locations; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class CommunicationType + { + + /// + public string Value; + + /// + public CodedDescriptionType Type; + + /// + public string Priority; + + /// + public CodedDescriptionType Status; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class ActorTypeAddress + { + + /// + public CodedDescriptionType Type; + + /// + public string Line1; + + /// + public string Line2; + + /// + public string City; + + /// + public string County; + + /// + public string State; + + /// + public string Country; + + /// + public string PostalCode; + + /// + public string Priority; + + /// + public CodedDescriptionType Status; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Preferred; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class ActorTypeInformationSystem + { + + /// + public string Name; + + /// + public string Type; + + /// + public string Version; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class ActorTypeOrganization + { + + /// + public string Name; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class PersonNameType + { + + /// + [System.Xml.Serialization.XmlElementAttribute("Given")] + public string[] Given; + + /// + [System.Xml.Serialization.XmlElementAttribute("Middle")] + public string[] Middle; + + /// + [System.Xml.Serialization.XmlElementAttribute("Family")] + public string[] Family; + + /// + [System.Xml.Serialization.XmlElementAttribute("Suffix")] + public string[] Suffix; + + /// + [System.Xml.Serialization.XmlElementAttribute("Title")] + public string[] Title; + + /// + [System.Xml.Serialization.XmlElementAttribute("NickName")] + public object[] NickName; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class ActorTypePersonName + { + + /// + public PersonNameType BirthName; + + /// + [System.Xml.Serialization.XmlElementAttribute("AdditionalName")] + public PersonNameType[] AdditionalName; + + /// + public PersonNameType CurrentName; + + /// + public string DisplayName; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class ActorTypePerson + { + + /// + public ActorTypePersonName Name; + + /// + public DateTimeType DateOfBirth; + + /// + public CodedDescriptionType Gender; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + public class ActorType + { + + /// + public string ActorObjectID; + + /// + [System.Xml.Serialization.XmlElementAttribute("Organization", typeof(ActorTypeOrganization))] + [System.Xml.Serialization.XmlElementAttribute("InformationSystem", typeof(ActorTypeInformationSystem))] + [System.Xml.Serialization.XmlElementAttribute("Person", typeof(ActorTypePerson))] + public object Item; + + /// + [System.Xml.Serialization.XmlElementAttribute("IDs")] + public IDType[] IDs; + + /// + [System.Xml.Serialization.XmlElementAttribute("Relation")] + public CodedDescriptionType[] Relation; + + /// + [System.Xml.Serialization.XmlElementAttribute("Specialty")] + public CodedDescriptionType[] Specialty; + + /// + [System.Xml.Serialization.XmlElementAttribute("Address")] + public ActorTypeAddress[] Address; + + /// + [System.Xml.Serialization.XmlElementAttribute("Telephone")] + public CommunicationType[] Telephone; + + /// + [System.Xml.Serialization.XmlElementAttribute("EMail")] + public CommunicationType[] EMail; + + /// + [System.Xml.Serialization.XmlElementAttribute("URL")] + public CommunicationType[] URL; + + /// + public CodedDescriptionType Status; + + /// + [System.Xml.Serialization.XmlElementAttribute("Source")] + public SourceType[] Source; + + /// + [System.Xml.Serialization.XmlElementAttribute("InternalCCRLink")] + public InternalCCRLink[] InternalCCRLink; + + /// + [System.Xml.Serialization.XmlElementAttribute("ReferenceID")] + public string[] ReferenceID; + + /// + [System.Xml.Serialization.XmlElementAttribute("CommentID")] + public string[] CommentID; + + /// + [System.Xml.Serialization.XmlElementAttribute("Signature")] + public IDTypeSignature[] Signature; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:astm-org:CCR", IsNullable = false)] + public class Directions + { + + /// + [System.Xml.Serialization.XmlElementAttribute("Direction")] + public Direction[] Direction; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:astm-org:CCR", IsNullable = false)] + public class Encounters + { + + /// + [System.Xml.Serialization.XmlElementAttribute("Encounter")] + public EncounterType[] Encounter; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:astm-org:CCR", IsNullable = false)] + public class Goals + { + + /// + [System.Xml.Serialization.XmlElementAttribute("Goal")] + public GoalType[] Goal; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:astm-org:CCR", IsNullable = false)] + public class Immunizations + { + + /// + [System.Xml.Serialization.XmlElementAttribute("Immunization")] + public StructuredProductType[] Immunization; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:astm-org:CCR", IsNullable = false)] + public class Indications + { + + /// + [System.Xml.Serialization.XmlElementAttribute("Indication")] + public IndicationType[] Indication; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:astm-org:CCR", IsNullable = false)] + public class Instructions + { + + /// + [System.Xml.Serialization.XmlElementAttribute("Instruction")] + public CodedDescriptionType[] Instruction; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:astm-org:CCR", IsNullable = false)] + public class Locations + { + + /// + [System.Xml.Serialization.XmlElementAttribute("Location")] + public Location[] Location; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:astm-org:CCR", IsNullable = false)] + public class Medications + { + + /// + [System.Xml.Serialization.XmlElementAttribute("Medication")] + public StructuredProductType[] Medication; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:astm-org:CCR", IsNullable = false)] + public class Practitioners + { + + /// + [System.Xml.Serialization.XmlElementAttribute("Practitioner")] + public ActorReferenceType[] Practitioner; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:astm-org:CCR", IsNullable = false)] + public class Procedures + { + + /// + [System.Xml.Serialization.XmlElementAttribute("Procedure")] + public ProcedureType[] Procedure; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:astm-org:CCR", IsNullable = false)] + public class Products + { + + /// + [System.Xml.Serialization.XmlElementAttribute("Product")] + public StructuredProductType[] Product; + } + + /// + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:astm-org:CCR")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:astm-org:CCR", IsNullable = false)] + public class Services + { + + /// + [System.Xml.Serialization.XmlElementAttribute("Service")] + public EncounterType[] Service; + } +} \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/src/ghealth/h9service.cs gdata-sharp-1.7.0.1/src/ghealth/h9service.cs --- gdata-sharp-1.4.0.2/src/ghealth/h9service.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/ghealth/h9service.cs 2009-08-18 23:17:20.000000000 +0000 @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Google.GData.Health +{ + ////////////////////////////////////////////////////////////////////// + /// + /// The Google Health Data API allows applications to view and send health data in the form of Google Data feeds. + /// The HealthService class encapsulates authentication to the Google HealthService. + /// + ////////////////////////////////////////////////////////////////////// + public class H9Service : BaseHealthService + { + /// The Google Health service's name + public const string ServiceName = "weaver"; + /// The Google Health service's environment. + public const string ServiceEnvironment = "h9"; + /// The base Google Health Feeds address. + public const string BaseAddress = "https://www.google.com/h9/feeds/"; + /// The Google Health Profile list feed. + public const string ProfileListFeed = BaseAddress + "profile/list/"; + /// The Google Health Profile UI feed + public const string ProfileFeed = BaseAddress + "profile/ui/"; + /// The Google Health Register UI feed + public const string RegisterFeed = BaseAddress + "register/ui/"; + /// The Google Health Default Profile UI feed + public const string DefaultProfileFeed = BaseAddress + "profile/default"; + /// The Google Health Default Register UI feed + public const string DefaultRegisterFeed = BaseAddress + "register/default"; + + /// + /// Constructs the Google Health Service using the + /// primary H9 Feeds address. + /// + /// The name of the application leveraging the service. + public H9Service(string applicationName) + : base(applicationName, + BaseAddress, ProfileListFeed, ProfileFeed, RegisterFeed, + DefaultProfileFeed, DefaultRegisterFeed) { } + } +} diff -Nru gdata-sharp-1.4.0.2/src/ghealth/Health.csproj gdata-sharp-1.7.0.1/src/ghealth/Health.csproj --- gdata-sharp-1.4.0.2/src/ghealth/Health.csproj 2008-12-12 15:10:21.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/ghealth/Health.csproj 2009-10-21 14:06:48.000000000 +0000 @@ -1,7 +1,6 @@ - + Local - 8.0.50727 2.0 {EB301864-5CE6-4C63-A541-FE647F682D75} Debug @@ -26,6 +25,7 @@ true + 2.0 bin\Debug\ @@ -123,10 +123,16 @@ AssemblyVersion.cs + + + + + + diff -Nru gdata-sharp-1.4.0.2/src/ghealth/healthservice.cs gdata-sharp-1.7.0.1/src/ghealth/healthservice.cs --- gdata-sharp-1.4.0.2/src/ghealth/healthservice.cs 2008-12-16 11:11:21.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/ghealth/healthservice.cs 2009-08-18 23:17:20.000000000 +0000 @@ -22,61 +22,43 @@ using Google.GData.Client; using Google.GData.Extensions; using System.Collections.Specialized; +using System.Collections.Generic; +using System.Xml; +using System.Xml.Serialization; +using ASTM.Org.CCR; - -namespace Google.GData.Health { - +namespace Google.GData.Health +{ ////////////////////////////////////////////////////////////////////// /// /// The Google Health Data API allows applications to view and send health data in the form of Google Data feeds. /// The HealthService class encapsulates authentication to the Google HealthService. /// ////////////////////////////////////////////////////////////////////// - public class HealthService : Service + public class HealthService : BaseHealthService { - /// The Calendar service's name public const string ServiceName = "health"; + /// The base Google Health Feeds address. + public const string BaseAddress = "https://www.google.com/health/feeds/"; + /// The Google Health Profile list feed. + public const string ProfileListFeed = BaseAddress + "profile/list/"; + /// The Google Health Profile UI feed + public const string ProfileFeed = BaseAddress + "profile/ui/"; + /// The Google Health Register UI feed + public const string RegisterFeed = BaseAddress + "register/ui/"; + /// The Google Health Default Profile UI feed + public const string DefaultProfileFeed = BaseAddress + "profile/default"; + /// The Google Health Default Register UI feed + public const string DefaultRegisterFeed = BaseAddress + "register/default"; /// - /// default constructor - /// - /// - /// - public HealthService(string applicationName) : base(ServiceName, applicationName) - { - this.NewFeed += new ServiceEventHandler(this.OnNewFeed); - } - - /// - /// overloaded to create typed version of Query + /// Constructs the Google Health Service using the + /// primary Health Feeds address. /// - /// - /// EventFeed - public HealthFeed Query(HealthQuery feedQuery) - { - return base.Query(feedQuery) as HealthFeed; - } - - - - ////////////////////////////////////////////////////////////////////// - /// eventchaining. We catch this by from the base service, which - /// would not by default create an atomFeed - /// the object which send the event - /// FeedParserEventArguments, holds the feedentry - /// - ////////////////////////////////////////////////////////////////////// - protected void OnNewFeed(object sender, ServiceEventArgs e) - { - Tracing.TraceMsg("Created new YouTube Feed"); - if (e == null) - { - throw new ArgumentNullException("e"); - } - - e.Feed = new HealthFeed(e.Uri, e.Service); - } - ///////////////////////////////////////////////////////////////////////////// + /// The name of the application leveraging the service. + public HealthService(string applicationName) : base(applicationName, + BaseAddress, ProfileListFeed, ProfileFeed, RegisterFeed, + DefaultProfileFeed, DefaultRegisterFeed) { } } } diff -Nru gdata-sharp-1.4.0.2/src/ghealth/notice.cs gdata-sharp-1.7.0.1/src/ghealth/notice.cs --- gdata-sharp-1.4.0.2/src/ghealth/notice.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/ghealth/notice.cs 2009-08-18 23:17:20.000000000 +0000 @@ -0,0 +1,102 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using Google.GData.Health; +using Google.GData.Client; +using ASTM.Org.CCR; +using Google.GData.Extensions; +using System.Xml; +using System.Xml.Serialization; +using System.IO; + +namespace Google.GData.Health +{ + /// + /// Represents a simple user profile's notice. + /// + public class Notice + { + /// + /// Creates a notice with the default content type of text. + /// + public Notice() + { + this.ContentType = "text"; + } + + /// + /// Gets or sets the notice title. + /// + public string Subject { get; set; } + + /// + /// Gets or sets the notice content. + /// + public string Content { get; set; } + + /// + /// Gets or sets the notice content type. + /// + public string ContentType { get; set; } + + /// + /// Gets the notice entry id. + /// + public string Id { get; set; } + + /// + /// Gets the notice entry last updated datetime. + /// + public DateTime DateUpdated { get; set; } + + /// + /// Gets the notice entry publishing datetime. + /// + public DateTime DatePublished { get; set; } + + /// + /// Gets or sets the continuity of care record attached to this entry. + /// + public ContinuityOfCareRecord CareRecord { get; set; } + + /// + /// Gets whether the notice content type to html. + /// + public bool IsHtml { get { return ContentType.Equals("html"); } } + + public static Notice FromAtomEntry(AtomEntry entry) + { + Notice notice = new Notice(); + notice.DatePublished = entry.Published; + notice.DateUpdated = entry.Updated; + notice.Id = entry.Id.Uri.Content; + notice.ContentType = entry.Content.Type; + notice.Content = entry.Content.Content; + notice.Subject = entry.Title.Text; + IExtensionElementFactory factory = entry.FindExtension("ContinuityOfCareRecord", "urn:astm-org:CCR"); + if (factory != null) + { + XmlExtension extension = factory as XmlExtension; + XmlSerializer serializer = new XmlSerializer(typeof(ContinuityOfCareRecord)); + XmlTextReader reader = new XmlTextReader(new StringReader(extension.Node.OuterXml)); + notice.CareRecord = serializer.Deserialize(reader) as ContinuityOfCareRecord; + } + return notice; + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/ghealth/profile.cs gdata-sharp-1.7.0.1/src/ghealth/profile.cs --- gdata-sharp-1.4.0.2/src/ghealth/profile.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/ghealth/profile.cs 2009-08-17 18:56:20.000000000 +0000 @@ -0,0 +1,57 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using Google.GData.Client; + +namespace Google.GData.Health +{ + /// + /// Represents a simple user profile in Google Health. + /// + public class Profile + { + /// + /// Gets or sets the profile name. + /// + public string Name { get; set; } + + /// + /// Gets or sets the profile id. + /// + public string ID { get; set; } + + /// + /// Gets or sets the authors of this profile. + /// + public List Authors { get; set; } + + public static Profile FromAtomEntry(AtomEntry entry) + { + Profile profile = new Profile(); + profile.ID = entry.Content.Content; + profile.Name = entry.Title.Text; + profile.Authors = new List(); + foreach (AtomPerson person in entry.Authors) + { + profile.Authors.Add(Author.FromAtomPerson(person)); + } + + return profile; + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/Google Data API SDK.sln gdata-sharp-1.7.0.1/src/Google Data API SDK.sln --- gdata-sharp-1.4.0.2/src/Google Data API SDK.sln 2008-12-12 15:10:21.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/Google Data API SDK.sln 2010-05-26 08:04:54.000000000 +0000 @@ -1,5 +1,5 @@ -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common Data Extensions", "extensions\Common Data Extensions.csproj", "{21BCB644-F9C3-4ADC-8BE1-4E55C6565011}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Calendar", "gcalendar\Calendar.csproj", "{0AD0FA26-A071-4CAC-851C-05B6C26B9888}" @@ -16,8 +16,6 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Picasa", "gphotos\Picasa.csproj", "{6781DF3C-A44F-418B-989B-771D17937F91}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Documents", "gdocuments\Documents.csproj", "{1C00DDC8-021D-4F60-9EE9-314431586936}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "unittests", "unittests\unittests.csproj", "{22D56E6B-DF29-4675-A655-B33252B7FA4B}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Contacts", "gcontacts\Contacts.csproj", "{66B2AD47-7DD2-43E5-9124-D53486609992}" @@ -28,11 +26,13 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Blogger", "blogger\Blogger.csproj", "{BE48B106-7766-494C-B0F1-00989ACF2480}" EndProject -Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "CoreMergeModule", "MergeModules\CoreMergeModule\CoreMergeModule.vdproj", "{ECE5940A-EC7A-4818-8F87-A6C5F555A266}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core Client", "core\Core Client.csproj", "{B6F6D938-0D45-42BA-8A67-55D92EF03995}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Analytics", "analytics\Analytics.csproj", "{A7BA16A4-7636-46CA-AAAD-3CB3361ECD40}" EndProject -Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "YouTubeMergeModule", "MergeModules\YouTubeMergeModule\YouTubeMergeModule.vdproj", "{7CBE24A6-C32A-446D-A74F-597353AC5CCB}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Documents3", "documents3\Documents3.csproj", "{4E97E7C2-D30C-48ED-9C3D-FFA2127099AA}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core Client", "core\Core Client.csproj", "{B6F6D938-0D45-42BA-8A67-55D92EF03995}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebmasterTools", "webmastertools\WebmasterTools.csproj", "{321BC361-7817-4471-8E7D-8B9D09EC3B48}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -89,12 +89,6 @@ {6781DF3C-A44F-418B-989B-771D17937F91}.Debug|Any CPU.Build.0 = Debug|Any CPU {6781DF3C-A44F-418B-989B-771D17937F91}.Release|Any CPU.ActiveCfg = Release|Any CPU {6781DF3C-A44F-418B-989B-771D17937F91}.Release|Any CPU.Build.0 = Release|Any CPU - {1C00DDC8-021D-4F60-9EE9-314431586936}.ASP|Any CPU.ActiveCfg = ASP|Any CPU - {1C00DDC8-021D-4F60-9EE9-314431586936}.ASP|Any CPU.Build.0 = ASP|Any CPU - {1C00DDC8-021D-4F60-9EE9-314431586936}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1C00DDC8-021D-4F60-9EE9-314431586936}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1C00DDC8-021D-4F60-9EE9-314431586936}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1C00DDC8-021D-4F60-9EE9-314431586936}.Release|Any CPU.Build.0 = Release|Any CPU {22D56E6B-DF29-4675-A655-B33252B7FA4B}.ASP|Any CPU.ActiveCfg = ASP|Any CPU {22D56E6B-DF29-4675-A655-B33252B7FA4B}.ASP|Any CPU.Build.0 = ASP|Any CPU {22D56E6B-DF29-4675-A655-B33252B7FA4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -125,24 +119,30 @@ {BE48B106-7766-494C-B0F1-00989ACF2480}.Debug|Any CPU.Build.0 = Debug|Any CPU {BE48B106-7766-494C-B0F1-00989ACF2480}.Release|Any CPU.ActiveCfg = Release|Any CPU {BE48B106-7766-494C-B0F1-00989ACF2480}.Release|Any CPU.Build.0 = Release|Any CPU - {ECE5940A-EC7A-4818-8F87-A6C5F555A266}.ASP|Any CPU.ActiveCfg = Release - {ECE5940A-EC7A-4818-8F87-A6C5F555A266}.ASP|Any CPU.Build.0 = Release - {ECE5940A-EC7A-4818-8F87-A6C5F555A266}.Debug|Any CPU.ActiveCfg = Debug - {ECE5940A-EC7A-4818-8F87-A6C5F555A266}.Debug|Any CPU.Build.0 = Debug - {ECE5940A-EC7A-4818-8F87-A6C5F555A266}.Release|Any CPU.ActiveCfg = Release - {ECE5940A-EC7A-4818-8F87-A6C5F555A266}.Release|Any CPU.Build.0 = Release - {7CBE24A6-C32A-446D-A74F-597353AC5CCB}.ASP|Any CPU.ActiveCfg = Release - {7CBE24A6-C32A-446D-A74F-597353AC5CCB}.ASP|Any CPU.Build.0 = Release - {7CBE24A6-C32A-446D-A74F-597353AC5CCB}.Debug|Any CPU.ActiveCfg = Debug - {7CBE24A6-C32A-446D-A74F-597353AC5CCB}.Debug|Any CPU.Build.0 = Debug - {7CBE24A6-C32A-446D-A74F-597353AC5CCB}.Release|Any CPU.ActiveCfg = Release - {7CBE24A6-C32A-446D-A74F-597353AC5CCB}.Release|Any CPU.Build.0 = Release {B6F6D938-0D45-42BA-8A67-55D92EF03995}.ASP|Any CPU.ActiveCfg = ASP|Any CPU {B6F6D938-0D45-42BA-8A67-55D92EF03995}.ASP|Any CPU.Build.0 = ASP|Any CPU {B6F6D938-0D45-42BA-8A67-55D92EF03995}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B6F6D938-0D45-42BA-8A67-55D92EF03995}.Debug|Any CPU.Build.0 = Debug|Any CPU {B6F6D938-0D45-42BA-8A67-55D92EF03995}.Release|Any CPU.ActiveCfg = Release|Any CPU {B6F6D938-0D45-42BA-8A67-55D92EF03995}.Release|Any CPU.Build.0 = Release|Any CPU + {A7BA16A4-7636-46CA-AAAD-3CB3361ECD40}.ASP|Any CPU.ActiveCfg = ASP|Any CPU + {A7BA16A4-7636-46CA-AAAD-3CB3361ECD40}.ASP|Any CPU.Build.0 = ASP|Any CPU + {A7BA16A4-7636-46CA-AAAD-3CB3361ECD40}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A7BA16A4-7636-46CA-AAAD-3CB3361ECD40}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A7BA16A4-7636-46CA-AAAD-3CB3361ECD40}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A7BA16A4-7636-46CA-AAAD-3CB3361ECD40}.Release|Any CPU.Build.0 = Release|Any CPU + {4E97E7C2-D30C-48ED-9C3D-FFA2127099AA}.ASP|Any CPU.ActiveCfg = ASP|Any CPU + {4E97E7C2-D30C-48ED-9C3D-FFA2127099AA}.ASP|Any CPU.Build.0 = ASP|Any CPU + {4E97E7C2-D30C-48ED-9C3D-FFA2127099AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4E97E7C2-D30C-48ED-9C3D-FFA2127099AA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4E97E7C2-D30C-48ED-9C3D-FFA2127099AA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4E97E7C2-D30C-48ED-9C3D-FFA2127099AA}.Release|Any CPU.Build.0 = Release|Any CPU + {321BC361-7817-4471-8E7D-8B9D09EC3B48}.ASP|Any CPU.ActiveCfg = Release|Any CPU + {321BC361-7817-4471-8E7D-8B9D09EC3B48}.ASP|Any CPU.Build.0 = Release|Any CPU + {321BC361-7817-4471-8E7D-8B9D09EC3B48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {321BC361-7817-4471-8E7D-8B9D09EC3B48}.Debug|Any CPU.Build.0 = Debug|Any CPU + {321BC361-7817-4471-8E7D-8B9D09EC3B48}.Release|Any CPU.ActiveCfg = Release|Any CPU + {321BC361-7817-4471-8E7D-8B9D09EC3B48}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff -Nru gdata-sharp-1.4.0.2/src/gphotos/albumentry.cs gdata-sharp-1.7.0.1/src/gphotos/albumentry.cs --- gdata-sharp-1.4.0.2/src/gphotos/albumentry.cs 2008-11-05 22:10:50.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gphotos/albumentry.cs 2009-08-17 14:57:28.000000000 +0000 @@ -50,7 +50,8 @@ /// /// accessor for an AlbumEntry /// - public class AlbumAccessor + [Obsolete("Use Google.Picasa.Album instead. This code will be removed soon")] + public class AlbumAccessor { private PicasaEntry entry; @@ -341,28 +342,6 @@ } } - /// - /// The name of the album, which is the URL-usable name - /// derived from the title. This is the name that should be used in all - /// URLs involving the album. - /// - -#if WindowsCE || PocketPC -#else - [Category("Base Album Data"), - Description("Specifies the name for the album.")] -#endif - public string Name - { - get - { - return this.entry.GetPhotoExtensionValue(GPhotoNameTable.Name); - } - set - { - this.entry.SetPhotoExtensionValue(GPhotoNameTable.Name, value); - } - } /// /// the number of comments on an album diff -Nru gdata-sharp-1.4.0.2/src/gphotos/commententry.cs gdata-sharp-1.7.0.1/src/gphotos/commententry.cs --- gdata-sharp-1.4.0.2/src/gphotos/commententry.cs 2008-10-21 10:10:36.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gphotos/commententry.cs 2009-08-14 13:44:57.000000000 +0000 @@ -45,6 +45,7 @@ /// /// accessor for a Comment Entry /// + [Obsolete("Use Google.Picasa.Comment instead. This code will be removed soon")] public class CommentAccessor { diff -Nru gdata-sharp-1.4.0.2/src/gphotos/gextphotos.cs gdata-sharp-1.7.0.1/src/gphotos/gextphotos.cs --- gdata-sharp-1.4.0.2/src/gphotos/gextphotos.cs 2008-09-01 13:09:26.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gphotos/gextphotos.cs 2009-08-17 14:57:28.000000000 +0000 @@ -50,17 +50,18 @@ baseObject.AddExtension(new GPhotoNumPhotos()); baseObject.AddExtension(new GPhotoNumPhotosRemaining()); baseObject.AddExtension(new GPhotoChecksum()); - baseObject.AddExtension(new GPhotoClient()); baseObject.AddExtension(new GPhotoHeight()); - baseObject.AddExtension(new GPhotoPosition()); baseObject.AddExtension(new GPhotoRotation()); baseObject.AddExtension(new GPhotoSize()); baseObject.AddExtension(new GPhotoTimestamp()); - baseObject.AddExtension(new GPhotoVersion()); baseObject.AddExtension(new GPhotoWidth()); baseObject.AddExtension(new GPhotoPhotoId()); baseObject.AddExtension(new GPhotoWeight()); - baseObject.AddExtension(new GPhotoName()); + baseObject.AddExtension(new GPhotoAlbumDesc()); + baseObject.AddExtension(new GPhotoAlbumTitle()); + baseObject.AddExtension(new GPhotoSnippet()); + baseObject.AddExtension(new GPhotoSnippetType()); + baseObject.AddExtension(new GPhotoTruncated()); } } @@ -160,10 +161,6 @@ /// public const string Location = "location"; - /// - /// name element string - /// - public const string Name = "name"; /// /// numphotos element string @@ -230,6 +227,29 @@ /// public const string Weight = "weight"; + /// + /// Description of the album this photo is in. + /// + public const string AlbumDesc = "albumdesc"; + /// + /// Title of the album this photo is in. + /// + public const string AlbumTitle = "albumtitle"; + /// + /// Snippet that matches the search text. + /// + public const string Snippet = "snippet"; + /// + /// Describes where the match with the search query was found, and thus where the snippet + /// is from: the photo caption, the photo tags, the album title, + /// the album description, or the album location. + /// + public const string SnippetType = "snippettype"; + /// + /// Indicates whether search results are truncated or not + /// + public const string Truncated = "truncated"; + } @@ -481,24 +501,6 @@ {} } - /// - /// GPhotoName schema extension describing an name - /// - public class GPhotoName : SimpleElement - { - /// - /// default constructor - /// - public GPhotoName() - : base(GPhotoNameTable.Name, GPhotoNameTable.gPhotoPrefix, GPhotoNameTable.NSGPhotos) - {} - /// - /// default constructor with an initial value as a string - /// - public GPhotoName(string initValue) - : base(GPhotoNameTable.Name, GPhotoNameTable.gPhotoPrefix, GPhotoNameTable.NSGPhotos, initValue) - {} - } /// /// GPhotoNumPhotos schema extension describing an numphotos @@ -558,25 +560,6 @@ } /// - /// GPhotoClient schema extension describing an client - /// - public class GPhotoClient : SimpleElement - { - /// - /// default constructor - /// - public GPhotoClient() - : base(GPhotoNameTable.Client, GPhotoNameTable.gPhotoPrefix, GPhotoNameTable.NSGPhotos) - {} - /// - /// default constructor with an initial value as a string - /// - public GPhotoClient(string initValue) - : base(GPhotoNameTable.Client, GPhotoNameTable.gPhotoPrefix, GPhotoNameTable.NSGPhotos, initValue) - {} - } - - /// /// GPhotoHeight schema extension describing an height /// public class GPhotoHeight : SimpleElement @@ -595,24 +578,6 @@ {} } - /// - /// GPhotoPosition schema extension describing an position - /// - public class GPhotoPosition : SimpleElement - { - /// - /// default constructor - /// - public GPhotoPosition() - : base(GPhotoNameTable.Position, GPhotoNameTable.gPhotoPrefix, GPhotoNameTable.NSGPhotos) - {} - /// - /// default constructor with an initial value as a string - /// - public GPhotoPosition(string initValue) - : base(GPhotoNameTable.Position, GPhotoNameTable.gPhotoPrefix, GPhotoNameTable.NSGPhotos, initValue) - {} - } /// /// GPhotoRotation schema extension describing an rotation @@ -672,24 +637,6 @@ } - /// - /// GPhotoVersion schema extension describing an version - /// - public class GPhotoVersion : SimpleElement - { - /// - /// default constructor - /// - public GPhotoVersion() - : base(GPhotoNameTable.Version, GPhotoNameTable.gPhotoPrefix, GPhotoNameTable.NSGPhotos) - {} - /// - /// default constructor with an initial value as a string - /// - public GPhotoVersion(string initValue) - : base(GPhotoNameTable.Version, GPhotoNameTable.gPhotoPrefix, GPhotoNameTable.NSGPhotos, initValue) - {} - } /// /// GPhotoPhotoId schema extension describing an photoid @@ -747,4 +694,104 @@ : base(GPhotoNameTable.Weight, GPhotoNameTable.gPhotoPrefix, GPhotoNameTable.NSGPhotos, initValue) {} } + + /// + /// Description of the album this photo is in. + /// + public class GPhotoAlbumDesc : SimpleElement + { + /// + /// default constructor + /// + public GPhotoAlbumDesc() + : base(GPhotoNameTable.AlbumDesc, GPhotoNameTable.gPhotoPrefix, GPhotoNameTable.NSGPhotos) + {} + /// + /// default constructor with an initial value as a string + /// + public GPhotoAlbumDesc(string initValue) + : base(GPhotoNameTable.AlbumDesc, GPhotoNameTable.gPhotoPrefix, GPhotoNameTable.NSGPhotos, initValue) + {} + } + + /// + /// Title of the album this photo is in. + /// + public class GPhotoAlbumTitle : SimpleElement + { + /// + /// default constructor + /// + public GPhotoAlbumTitle() + : base(GPhotoNameTable.AlbumTitle, GPhotoNameTable.gPhotoPrefix, GPhotoNameTable.NSGPhotos) + {} + /// + /// default constructor with an initial value as a string + /// + public GPhotoAlbumTitle(string initValue) + : base(GPhotoNameTable.AlbumTitle, GPhotoNameTable.gPhotoPrefix, GPhotoNameTable.NSGPhotos, initValue) + {} + } + + /// + /// Snippet that matches the search text. + /// + public class GPhotoSnippet : SimpleElement + { + /// + /// default constructor + /// + public GPhotoSnippet() + : base(GPhotoNameTable.Snippet, GPhotoNameTable.gPhotoPrefix, GPhotoNameTable.NSGPhotos) + {} + /// + /// default constructor with an initial value as a string + /// + public GPhotoSnippet(string initValue) + : base(GPhotoNameTable.Snippet, GPhotoNameTable.gPhotoPrefix, GPhotoNameTable.NSGPhotos, initValue) + {} + } + + /// + /// Describes where the match with the search query was found, and thus where the snippet + /// is from: the photo caption, the photo tags, the album title, + /// the album description, or the album location. + /// Possible values are PHOTO_DESCRIPTION, PHOTO_TAGS, ALBUM_TITLE, + /// ALBUM_DESCRIPTION, or ALBUM_LOCATION. + /// + public class GPhotoSnippetType : SimpleElement + { + /// + /// default constructor + /// + public GPhotoSnippetType() + : base(GPhotoNameTable.SnippetType, GPhotoNameTable.gPhotoPrefix, GPhotoNameTable.NSGPhotos) + {} + /// + /// default constructor with an initial value as a string + /// + public GPhotoSnippetType(string initValue) + : base(GPhotoNameTable.SnippetType, GPhotoNameTable.gPhotoPrefix, GPhotoNameTable.NSGPhotos, initValue) + {} + } + + /// + /// Indicates whether search results are truncated or not + /// Possible values are 1 (results are truncated) or 0 (results are not truncated). + /// + public class GPhotoTruncated : SimpleElement + { + /// + /// default constructor + /// + public GPhotoTruncated() + : base(GPhotoNameTable.Truncated, GPhotoNameTable.gPhotoPrefix, GPhotoNameTable.NSGPhotos) + {} + /// + /// default constructor with an initial value as a string + /// + public GPhotoTruncated(string initValue) + : base(GPhotoNameTable.Truncated, GPhotoNameTable.gPhotoPrefix, GPhotoNameTable.NSGPhotos, initValue) + {} + } } diff -Nru gdata-sharp-1.4.0.2/src/gphotos/photoentry.cs gdata-sharp-1.7.0.1/src/gphotos/photoentry.cs --- gdata-sharp-1.4.0.2/src/gphotos/photoentry.cs 2008-10-21 10:10:36.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gphotos/photoentry.cs 2009-11-24 11:09:57.000000000 +0000 @@ -57,6 +57,7 @@ /// this is a pure accessor class that can either take a photoentry or work with /// a picasaentry to get you convienience accessors /// + [Obsolete("Use Google.Picasa.Photo instead. This code will be removed soon")] public class PhotoAccessor { @@ -140,25 +141,7 @@ } } - /// - /// The client application that created the photo. (Optional element.) - /// -#if WindowsCE || PocketPC -#else - [Category("Meta Photo Data"), - Description("The client application that created the photo.")] -#endif - public string Client - { - get - { - return this.entry.GetPhotoExtensionValue(GPhotoNameTable.Client); - } - set - { - this.entry.SetPhotoExtensionValue(GPhotoNameTable.Client, value); - } - } + /// /// The height of the photo in pixels @@ -201,25 +184,7 @@ } - /// - /// The ordinal position of the photo in the parent album - /// -#if WindowsCE || PocketPC -#else - [Category("Basic Photo Data"), - Description("The ordinal position of the photo in the parent album.")] -#endif - public double Position - { - get - { - return Convert.ToDouble(this.entry.GetPhotoExtensionValue(GPhotoNameTable.Position)); - } - set - { - this.entry.SetPhotoExtensionValue(GPhotoNameTable.Position, Convert.ToString(value)); - } - } + /// /// The rotation of the photo in degrees, used to change the rotation of the photo. Will only be shown if @@ -287,28 +252,7 @@ } - /// - /// The version number of the photo. Version numbers are based on modification time, - /// so they don't increment linearly. Note that if you try to update a photo using a - /// version number other than the latest one, you may receive an error; - /// for more information, see Optimistic concurrency (versioning) in the GData reference document - /// -#if WindowsCE || PocketPC -#else - [Category("Meta Photo Data"), - Description("The version number of the photo.")] -#endif - public string Version - { - get - { - return this.entry.GetPhotoExtensionValue(GPhotoNameTable.Version); - } - set - { - this.entry.SetPhotoExtensionValue(GPhotoNameTable.Version, value); - } - } + /// /// The albums ID diff -Nru gdata-sharp-1.4.0.2/src/gphotos/photosrequest.cs gdata-sharp-1.7.0.1/src/gphotos/photosrequest.cs --- gdata-sharp-1.4.0.2/src/gphotos/photosrequest.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gphotos/photosrequest.cs 2010-03-19 15:52:11.000000000 +0000 @@ -0,0 +1,967 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + + +using System; +using System.IO; +using System.Collections; +using System.Text; +using System.Net; +using Google.GData.Client; +using Google.GData.Extensions; +using Google.GData.Photos; +using Google.GData.Extensions.MediaRss; +using System.Collections.Generic; +using Google.GData.Extensions.Location; + +#if WindowsCE || PocketPC +#else +using System.ComponentModel; +#endif + + +namespace Google.Picasa +{ + + + /// + /// as all picasa entries are "similiar" we have this abstract baseclass here as + /// well, although it is not clear yet how this will benefit + /// + /// + public abstract class PicasaEntity : Entry + { + /// + /// readonly accessor for the AlbumEntry that is underneath this object. + /// + /// + public PicasaEntry PicasaEntry + { + get + { + EnsureInnerObject(); + return this.AtomEntry as PicasaEntry; + } + } + + } + + + public class Album : PicasaEntity + { + /// + /// needs to be subclassed to ensure the creation of the corrent AtomEntry based + /// object + /// + protected override void EnsureInnerObject() + { + if (this.AtomEntry == null) + { + this.AtomEntry = new AlbumEntry(); + } + } + + /// + /// The album's access level. In this document, access level is also + /// referred to as "visibility." Valid values are public or private. + /// +#if WindowsCE || PocketPC +#else + [Category("Meta Album Data"), + Description("Specifies the access for the album.")] +#endif + public string Access + { + get + { + return this.PicasaEntry.GetPhotoExtensionValue(GPhotoNameTable.Access); + } + set + { + this.PicasaEntry.SetPhotoExtensionValue(GPhotoNameTable.Access, value); + } + } + + + /// + /// The nickname of the author + /// +#if WindowsCE || PocketPC +#else + [Category("Base Album Data"), + Description("Specifies the author's nickname")] +#endif + public string AlbumAuthorNickname + { + get + { + return this.PicasaEntry.GetPhotoExtensionValue(GPhotoNameTable.Nickname); + } + set + { + this.PicasaEntry.SetPhotoExtensionValue(GPhotoNameTable.Nickname, value); + } + } + + /// + /// The number of bytes of storage that this album uses. + /// +#if WindowsCE || PocketPC +#else + [Category("Meta Album Data"), + Description("Specifies the bytes used for the album.")] +#endif + [CLSCompliant(false)] + public uint BytesUsed + { + get + { + return Convert.ToUInt32(this.PicasaEntry.GetPhotoExtensionValue(GPhotoNameTable.BytesUsed)); + } + set + { + this.PicasaEntry.SetPhotoExtensionValue(GPhotoNameTable.BytesUsed, Convert.ToString(value)); + } + } + + /// + /// The user-specified location associated with the album + /// +#if WindowsCE || PocketPC +#else + [Category("Location Data"), + Description("Specifies the location for the album.")] +#endif + public string Location + { + get + { + return this.PicasaEntry.GetPhotoExtensionValue(GPhotoNameTable.Location); + } + set + { + this.PicasaEntry.SetPhotoExtensionValue(GPhotoNameTable.Location, value); + } + } + + /// + /// the Longitude of the photo + /// +#if WindowsCE || PocketPC +#else + [Category("Location Data"), + Description("The longitude of the photo.")] +#endif + public double Longitude + { + get + { + GeoRssWhere w = this.PicasaEntry.FindExtension(GeoNametable.GeoRssWhereElement, GeoNametable.NSGeoRss) as GeoRssWhere; + if (w != null) + { + return w.Longitude; + } + return -1; + } + set + { + GeoRssWhere w = this.PicasaEntry.FindExtension(GeoNametable.GeoRssWhereElement, GeoNametable.NSGeoRss) as GeoRssWhere; + if (w == null) + { + w = this.PicasaEntry.CreateExtension(GeoNametable.GeoRssWhereElement, GeoNametable.NSGeoRss) as GeoRssWhere; + this.PicasaEntry.ExtensionElements.Add(w); + } + w.Longitude = value; + } + } + + /// + /// the Longitude of the photo + /// +#if WindowsCE || PocketPC +#else + [Category("Location Data"), + Description("The Latitude of the photo.")] +#endif + public double Latitude + { + get + { + GeoRssWhere w = this.PicasaEntry.FindExtension(GeoNametable.GeoRssWhereElement, GeoNametable.NSGeoRss) as GeoRssWhere; + if (w != null) + { + return w.Latitude; + } + return -1; + } + set + { + GeoRssWhere w = this.PicasaEntry.FindExtension(GeoNametable.GeoRssWhereElement, GeoNametable.NSGeoRss) as GeoRssWhere; + if (w == null) + { + w = this.PicasaEntry.CreateExtension(GeoNametable.GeoRssWhereElement, GeoNametable.NSGeoRss) as GeoRssWhere; + this.PicasaEntry.ExtensionElements.Add(w); + } + w.Latitude = value; + } + } + + /// + /// The number of photos in the album. + /// + /// +#if WindowsCE || PocketPC +#else + [Category("Meta Album Data"), + Description("Specifies the number of photos in the album.")] +#endif + [CLSCompliant(false)] + public uint NumPhotos + { + get + { + return Convert.ToUInt32(this.PicasaEntry.GetPhotoExtensionValue(GPhotoNameTable.NumPhotos)); + } + set + { + this.PicasaEntry.SetPhotoExtensionValue(GPhotoNameTable.NumPhotos, Convert.ToString(value)); + } + } + + /// + /// The number of remaining photo uploads allowed in this album. + /// This is equivalent to the user's maximum number of photos per + /// album (gphoto:maxPhotosPerAlbum) minus the number of photos + /// currently in the album (gphoto:numphotos). + /// + +#if WindowsCE || PocketPC +#else + [Category("Meta Album Data"), + Description("Specifies the number of remaining photo uploads for the album.")] +#endif + [CLSCompliant(false)] + public uint NumPhotosRemaining + { + get + { + return Convert.ToUInt32(this.PicasaEntry.GetPhotoExtensionValue(GPhotoNameTable.NumPhotosRemaining)); + } + set + { + this.PicasaEntry.SetPhotoExtensionValue(GPhotoNameTable.NumPhotosRemaining, Convert.ToString(value)); + } + } + + + /// + /// the number of comments on an album + /// +#if WindowsCE || PocketPC +#else + [Category("Commenting"), + Description("Specifies the number of comments for the album.")] +#endif + [CLSCompliant(false)] + public uint CommentCount + { + get + { + return Convert.ToUInt32(this.PicasaEntry.GetPhotoExtensionValue(GPhotoNameTable.CommentCount)); + } + set + { + this.PicasaEntry.SetPhotoExtensionValue(GPhotoNameTable.CommentCount, Convert.ToString(value)); + } + } + + /// + /// is commenting enabled on an album + /// + +#if WindowsCE || PocketPC +#else + [Category("Commenting"), + Description("Comments enabled?")] +#endif + public bool CommentingEnabled + { + get + { + return Convert.ToBoolean(this.PicasaEntry.GetPhotoExtensionValue(GPhotoNameTable.CommentingEnabled)); + } + set + { + this.PicasaEntry.SetPhotoExtensionValue(GPhotoNameTable.CommentingEnabled, Utilities.ConvertBooleanToXSDString(value)); + } + } + + /// + /// the id of the album + /// + +#if WindowsCE || PocketPC +#else + [Category("Base Album Data"), + Description("Specifies the id for the album.")] +#endif + public string Id + { + get + { + return this.PicasaEntry.GetPhotoExtensionValue(GPhotoNameTable.Id); + } + set + { + this.PicasaEntry.SetPhotoExtensionValue(GPhotoNameTable.Id, value); + } + } + } + + + /// + /// The Tag is just a base PicasaEntity, beside the category it is not different + /// from a standard atom entry + /// + /// + public class Tag : PicasaEntity + { + /// + /// needs to be subclassed to ensure the creation of the corrent AtomEntry based + /// object + /// + protected override void EnsureInnerObject() + { + if (this.AtomEntry == null) + { + this.AtomEntry = new TagEntry(); + } + } + } + + /// + /// a comment object for a picasa photo + /// + /// + public class Comment : PicasaEntity + { + /// + /// needs to be subclassed to ensure the creation of the corrent AtomEntry based + /// object + /// + protected override void EnsureInnerObject() + { + if (this.AtomEntry == null) + { + this.AtomEntry = new CommentEntry(); + } + } + + + /// + /// The ID of the photo associated with the current comment. + /// +#if WindowsCE || PocketPC +#else + [Category("Base Comment Data"), + Description("The ID of the photo associated with the current comment.")] +#endif + public string PhotoId + { + get + { + return this.PicasaEntry.GetPhotoExtensionValue(GPhotoNameTable.Photoid); + } + set + { + this.PicasaEntry.SetPhotoExtensionValue(GPhotoNameTable.Photoid, value); + } + } + + /// + /// The albums ID + /// +#if WindowsCE || PocketPC +#else + [Category("Base Comment Data"), + Description("The ID of the album associated with the current comment.")] +#endif + public string AlbumId + { + get + { + return this.PicasaEntry.GetPhotoExtensionValue(GPhotoNameTable.AlbumId); + } + set + { + this.PicasaEntry.SetPhotoExtensionValue(GPhotoNameTable.AlbumId, value); + } + } + + /// + /// the id of the comment + /// +#if WindowsCE || PocketPC +#else + [Category("Base Comment Data"), + Description("The ID of the comment itself.")] +#endif + public string CommentId + { + get + { + return this.PicasaEntry.GetPhotoExtensionValue(GPhotoNameTable.Id); + } + set + { + this.PicasaEntry.SetPhotoExtensionValue(GPhotoNameTable.Id, value); + } + } + } + + /// + /// represents a photo based on a PicasaEntry object + /// + public class Photo : PicasaEntity + { + /// + /// creates the inner contact object when needed + /// + /// + protected override void EnsureInnerObject() + { + if (this.AtomEntry == null) + { + this.AtomEntry = new PhotoEntry(); + } + } + + + + + /// + /// tries to construct an URI on the Url attribute in media.content + /// + /// a Uri object or null +#if WindowsCE || PocketPC +#else + [Category("Base Photo Data"), + Description("Returns the URL to the photo media.")] +#endif + public Uri PhotoUri + { + get + { + EnsureInnerObject(); + if (this.PicasaEntry.Media != null && + this.PicasaEntry.Media.Content != null) + { + return new Uri(this.PicasaEntry.Media.Content.Attributes["url"] as string); + } + return null; + } + set + { + EnsureMediaContent(); + this.PicasaEntry.Media.Content.Attributes["url"] = value.AbsoluteUri; + } + } + + + + + /// + /// The checksum on the photo. This optional field can be used by + /// uploaders to associate a checksum with a photo to ease duplicate detection + /// +#if WindowsCE || PocketPC +#else + [Category("Meta Photo Data"), + Description("The checksum on the photo.")] +#endif + public string Checksum + { + get + { + return this.PicasaEntry.GetPhotoExtensionValue(GPhotoNameTable.Checksum); + } + set + { + this.PicasaEntry.SetPhotoExtensionValue(GPhotoNameTable.Checksum, value); + } + } + + + + /// + /// The height of the photo in pixels + /// +#if WindowsCE || PocketPC +#else + [Category("Basic Photo Data"), + Description("The height of the photo in pixels.")] +#endif + public int Height + { + get + { + return Convert.ToInt32(this.PicasaEntry.GetPhotoExtensionValue(GPhotoNameTable.Height)); + } + set + { + this.PicasaEntry.SetPhotoExtensionValue(GPhotoNameTable.Height, Convert.ToString(value)); + } + } + + /// + /// The width of the photo in pixels + /// +#if WindowsCE || PocketPC +#else + [Category("Basic Photo Data"), + Description("The width of the photo in pixels.")] +#endif + public int Width + { + get + { + return Convert.ToInt32(this.PicasaEntry.GetPhotoExtensionValue(GPhotoNameTable.Width)); + } + set + { + this.PicasaEntry.SetPhotoExtensionValue(GPhotoNameTable.Width, Convert.ToString(value)); + } + } + + + + + /// + /// The rotation of the photo in degrees, used to change the rotation of the photo. Will only be shown if + /// the rotation has not already been applied to the requested images. + /// +#if WindowsCE || PocketPC +#else + [Category("Basic Photo Data"), + Description("The rotation of the photo in degrees.")] +#endif + public int Rotation + { + get + { + return Convert.ToInt32(this.PicasaEntry.GetPhotoExtensionValue(GPhotoNameTable.Rotation)); + } + set + { + this.PicasaEntry.SetPhotoExtensionValue(GPhotoNameTable.Rotation, Convert.ToString(value)); + } + } + + /// + /// The size of the photo in bytes + /// +#if WindowsCE || PocketPC +#else + [Category("Basic Photo Data"), + Description("The size of the photo in bytes.")] +#endif + public long Size + { + get + { + return Convert.ToInt32(this.PicasaEntry.GetPhotoExtensionValue(GPhotoNameTable.Size)); + } + set + { + this.PicasaEntry.SetPhotoExtensionValue(GPhotoNameTable.Size, Convert.ToString(value)); + } + } + + + /// + /// The photo's timestamp, represented as the number of milliseconds since + /// January 1st, 1970. Contains the date of the photo either set externally + /// or retrieved from the Exif data. + /// +#if WindowsCE || PocketPC +#else + [Category("Meta Photo Data"), + Description("The photo's timestamp")] +#endif + [CLSCompliant(false)] + public ulong Timestamp + { + get + { + return Convert.ToUInt64(this.PicasaEntry.GetPhotoExtensionValue(GPhotoNameTable.Timestamp)); + } + set + { + this.PicasaEntry.SetPhotoExtensionValue(GPhotoNameTable.Timestamp, Convert.ToString(value)); + } + } + + + + /// + /// The albums ID + /// +#if WindowsCE || PocketPC +#else + [Category("Meta Photo Data"), + Description("The albums ID.")] +#endif + public string AlbumId + { + get + { + return this.PicasaEntry.GetPhotoExtensionValue(GPhotoNameTable.AlbumId); + } + set + { + this.PicasaEntry.SetPhotoExtensionValue(GPhotoNameTable.AlbumId, value); + } + } + + /// + /// the number of comments on a photo + /// +#if WindowsCE || PocketPC +#else + [Category("Commenting"), + Description("the number of comments on a photo.")] +#endif + [CLSCompliant(false)] + public uint CommentCount + { + get + { + return Convert.ToUInt32(this.PicasaEntry.GetPhotoExtensionValue(GPhotoNameTable.CommentCount)); + } + set + { + this.PicasaEntry.SetPhotoExtensionValue(GPhotoNameTable.CommentCount, Convert.ToString(value)); + } + } + + /// + /// is commenting enabled on a photo + /// +#if WindowsCE || PocketPC +#else + [Category("Commenting"), + Description("is commenting enabled on a photo.")] +#endif + public bool CommentingEnabled + { + get + { + return Convert.ToBoolean(this.PicasaEntry.GetPhotoExtensionValue(GPhotoNameTable.CommentingEnabled)); + } + set + { + this.PicasaEntry.SetPhotoExtensionValue(GPhotoNameTable.CommentingEnabled, Utilities.ConvertBooleanToXSDString(value)); + } + } + + + /// + /// the id of the photo + /// +#if WindowsCE || PocketPC +#else + [Category("Meta Photo Data"), + Description("the id of the photo.")] +#endif + public string Id + { + get + { + return this.PicasaEntry.GetPhotoExtensionValue(GPhotoNameTable.Id); + } + set + { + this.PicasaEntry.SetPhotoExtensionValue(GPhotoNameTable.Id, value); + } + } + + /// + /// the Longitude of the photo + /// +#if WindowsCE || PocketPC +#else + [Category("Location Photo Data"), + Description("The longitude of the photo.")] +#endif + public double Longitude + { + get + { + GeoRssWhere where = this.PicasaEntry.FindExtension(GeoNametable.GeoRssWhereElement, GeoNametable.NSGeoRss) as GeoRssWhere; + if (where != null) + { + return where.Longitude; + } + return -1; + } + set + { + GeoRssWhere where = this.PicasaEntry.FindExtension(GeoNametable.GeoRssWhereElement, GeoNametable.NSGeoRss) as GeoRssWhere; + if (where == null) + { + where = this.PicasaEntry.CreateExtension(GeoNametable.GeoRssWhereElement, GeoNametable.NSGeoRss) as GeoRssWhere; + this.PicasaEntry.ExtensionElements.Add(where); + } + where.Longitude = value; + } + } + + /// + /// the Longitude of the photo + /// +#if WindowsCE || PocketPC +#else + [Category("Location Photo Data"), + Description("The Latitude of the photo.")] +#endif + public double Latitude + { + get + { + GeoRssWhere where = this.PicasaEntry.FindExtension(GeoNametable.GeoRssWhereElement, GeoNametable.NSGeoRss) as GeoRssWhere; + if (where != null) + { + return where.Latitude; + } + return -1; + } + set + { + GeoRssWhere where = this.PicasaEntry.FindExtension(GeoNametable.GeoRssWhereElement, GeoNametable.NSGeoRss) as GeoRssWhere; + if (where == null) + { + where = this.PicasaEntry.CreateExtension(GeoNametable.GeoRssWhereElement, GeoNametable.NSGeoRss) as GeoRssWhere; + this.PicasaEntry.ExtensionElements.Add(where); + } + where.Latitude = value; + } + } + + /// + /// Description of the album this photo is in. + /// +#if WindowsCE || PocketPC +#else + [Category("Base Photo Data"), + Description("Description of the album this photo is in.")] +#endif + public string AlbumDescription + { + get + { + return this.PicasaEntry.GetPhotoExtensionValue(GPhotoNameTable.AlbumDesc); + } + set + { + this.PicasaEntry.SetPhotoExtensionValue(GPhotoNameTable.AlbumDesc, value); + } + } + + /// + /// Snippet that matches the search text. + /// +#if WindowsCE || PocketPC +#else + [Category("Search Photo Data"), + Description("Snippet that matches the search text.")] +#endif + public string Snippet + { + get + { + return this.PicasaEntry.GetPhotoExtensionValue(GPhotoNameTable.Snippet); + } + } + + + /// + /// Describes where the match with the search query was found, and thus where + /// the snippet is from: the photo caption, the photo tags, the album title, + /// the album description, or the album location. + /// Possible values are PHOTO_DESCRIPTION, PHOTO_TAGS, ALBUM_TITLE, + /// ALBUM_DESCRIPTION, or ALBUM_LOCATION. + /// +#if WindowsCE || PocketPC +#else + [Category("Search Photo Data"), + Description("Describes where the match with the search query was found.")] +#endif + public string SnippetType + { + get + { + return this.PicasaEntry.GetPhotoExtensionValue(GPhotoNameTable.SnippetType); + } + } + + + /// + /// Indicates whether search results are truncated or not. + /// Possible values are 1 (results are truncated) or 0 (results are not truncated). + /// +#if WindowsCE || PocketPC +#else + [Category("Search Photo Data"), + Description("Indicates whether search results are truncated or not.")] +#endif + public string Truncated + { + get + { + return this.PicasaEntry.GetPhotoExtensionValue(GPhotoNameTable.Truncated); + } + } + + + + private void EnsureMediaContent() + { + EnsureInnerObject(); + if (this.PicasaEntry.Media == null) + { + this.PicasaEntry.Media = new MediaGroup(); + } + if (this.PicasaEntry.Media.Content == null) + { + this.PicasaEntry.Media.Content = new MediaContent(); + } + } + + } + + ////////////////////////////////////////////////////////////////////// + /// + /// The Picasa Web Albums Data API allows client applications to view and + /// update albums, photos, and comments in the form of Google Data API feeds. + /// Your client application can use the Picasa Web Albums Data API to create + /// new albums, upload photos, add comments, edit or delete existing albums, + /// photos, and comments, and query for items that match particular criteria. + /// + /// + /// The following code illustrates a possible use of + /// the PicasaRequest object: + /// + /// RequestSettings settings = new RequestSettings("yourApp"); + /// settings.PageSize = 50; + /// settings.AutoPaging = true; + /// PicasaRequest pr = new PicasaRequest(settings); + /// Feed<Photo> feed = c.GetPhotos(); + /// + /// foreach (Photo p in feed.Entries) + /// { + /// Console.WriteLine(d.Title); + /// } + /// + /// + ////////////////////////////////////////////////////////////////////// + public class PicasaRequest : FeedRequest + { + + /// + /// default constructor for a PicasaRequest + /// + /// + public PicasaRequest(RequestSettings settings) : base(settings) + { + this.Service = new PicasaService(settings.Application); + PrepareService(); + } + + + /// + /// returns the list of Albums for the default user + /// + public Feed GetAlbums() + { + AlbumQuery q = PrepareQuery(PicasaQuery.CreatePicasaUri(Utilities.DefaultUser)); + return PrepareFeed(q); + } + + + /// + /// returns a Feed of all photos for the authorized user + /// + /// a feed of everyting + public Feed GetPhotos() + { + PhotoQuery q = PrepareQuery(PicasaQuery.CreatePicasaUri(Utilities.DefaultUser)); + return PrepareFeed(q); + } + + + /// + /// returns a feed of photos in that particular album for the default user + /// + /// + /// + public Feed GetPhotosInAlbum(string albumId) + { + PhotoQuery q = PrepareQuery(PicasaQuery.CreatePicasaUri(Utilities.DefaultUser, albumId)); + return PrepareFeed(q); + } + + + /// + /// Returns the comments a single photo based on + /// the default user, the albumid and the photoid + /// + /// The Id of the Album + /// The id of the photo + /// + public Feed GetComments(string albumId, string photoId) + { + CommentsQuery q = PrepareQuery(PicasaQuery.CreatePicasaUri(Utilities.DefaultUser, albumId, photoId)); + return PrepareFeed(q); + } + + + /// + /// Get all Tags for the default user + /// + /// + public Feed GetTags() + { + TagQuery q = PrepareQuery(PicasaQuery.CreatePicasaUri(Utilities.DefaultUser)); + return PrepareFeed(q); + } + + + /// + /// downloads a photo. + /// + /// The photo to download. + /// either a stream to the photo, or NULL if the photo has no media URL set + public Stream Download(Photo photo) + { + Service s = this.Service; + Uri target = photo.PhotoUri; + if (target != null) + { + return s.Query(target); + } + return null; + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/gphotos/Picasa.csproj gdata-sharp-1.7.0.1/src/gphotos/Picasa.csproj --- gdata-sharp-1.4.0.2/src/gphotos/Picasa.csproj 2008-12-12 15:10:21.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gphotos/Picasa.csproj 2009-10-21 14:06:48.000000000 +0000 @@ -1,7 +1,6 @@ - + Local - 8.0.50727 2.0 {6781DF3C-A44F-418B-989B-771D17937F91} Debug @@ -26,6 +25,7 @@ true + 2.0 bin\Debug\ @@ -133,6 +133,7 @@ + diff -Nru gdata-sharp-1.4.0.2/src/gphotos/picasaservice.cs gdata-sharp-1.7.0.1/src/gphotos/picasaservice.cs --- gdata-sharp-1.4.0.2/src/gphotos/picasaservice.cs 2008-11-24 13:54:48.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gphotos/picasaservice.cs 2009-08-13 15:59:00.000000000 +0000 @@ -63,6 +63,17 @@ { this.NewFeed += new ServiceEventHandler(this.OnNewFeed); } + + /// + /// by default all services now use version 1 for the protocol. + /// this needs to be overridden by a service to specify otherwise. + /// Picasa uses version 2 + /// + /// + protected override void InitVersionInformation() + { + this.ProtocolMajor = VersionDefaults.VersionTwo; + } /// /// overloaded to create typed version of Query diff -Nru gdata-sharp-1.4.0.2/src/gspreadsheet/AssemblyInfo.cs gdata-sharp-1.7.0.1/src/gspreadsheet/AssemblyInfo.cs --- gdata-sharp-1.4.0.2/src/gspreadsheet/AssemblyInfo.cs 2008-02-28 16:23:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gspreadsheet/AssemblyInfo.cs 2010-04-20 15:18:39.000000000 +0000 @@ -1,22 +1,22 @@ -/* Copyright (c) 2006 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ -using System.Reflection; -using System.Runtime.CompilerServices; - - -[assembly: AssemblyDelaySign(false)] +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +using System.Reflection; +using System.Runtime.CompilerServices; + + +[assembly: AssemblyDelaySign(false)] [assembly: AssemblyKeyName("")] [assembly: AssemblyTitle("Google Data API Spreadsheets Library")] diff -Nru gdata-sharp-1.4.0.2/src/gspreadsheet/Spreadsheets.csproj gdata-sharp-1.7.0.1/src/gspreadsheet/Spreadsheets.csproj --- gdata-sharp-1.4.0.2/src/gspreadsheet/Spreadsheets.csproj 2008-12-12 15:10:21.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/gspreadsheet/Spreadsheets.csproj 2009-10-21 14:06:48.000000000 +0000 @@ -1,7 +1,6 @@ - + Local - 8.0.50727 2.0 {3FF0C48A-48CC-49CE-8B65-0C780770A75D} Debug @@ -26,6 +25,7 @@ true + 2.0 bin\Debug\ diff -Nru gdata-sharp-1.4.0.2/src/MergeModules/YouTubeMergeModule/YouTubeMergeModule.vdproj gdata-sharp-1.7.0.1/src/MergeModules/YouTubeMergeModule/YouTubeMergeModule.vdproj --- gdata-sharp-1.4.0.2/src/MergeModules/YouTubeMergeModule/YouTubeMergeModule.vdproj 2008-12-12 15:10:21.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/MergeModules/YouTubeMergeModule/YouTubeMergeModule.vdproj 2009-11-17 13:23:07.000000000 +0000 @@ -15,44 +15,44 @@ { "Entry" { - "MsmKey" = "8:_5A943AD2E32AEED95F3BF29D99D4FC0E" + "MsmKey" = "8:_55CDA3579E76ECF84FAEF483BC0A02C6" "OwnerKey" = "8:_E05AF71925AA4B81BBD9C00C1109B6DE" "MsmSig" = "8:_UNDEFINED" } "Entry" { - "MsmKey" = "8:_E05AF71925AA4B81BBD9C00C1109B6DE" - "OwnerKey" = "8:_UNDEFINED" + "MsmKey" = "8:_55CDA3579E76ECF84FAEF483BC0A02C6" + "OwnerKey" = "8:_B171DBF19F7B85A327B23E3F25A99DD5" "MsmSig" = "8:_UNDEFINED" } "Entry" { - "MsmKey" = "8:_F591B1BDB2015F4239F7C4C6175CE115" + "MsmKey" = "8:_B171DBF19F7B85A327B23E3F25A99DD5" "OwnerKey" = "8:_E05AF71925AA4B81BBD9C00C1109B6DE" "MsmSig" = "8:_UNDEFINED" } "Entry" { - "MsmKey" = "8:_F591B1BDB2015F4239F7C4C6175CE115" - "OwnerKey" = "8:_5A943AD2E32AEED95F3BF29D99D4FC0E" + "MsmKey" = "8:_E05AF71925AA4B81BBD9C00C1109B6DE" + "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" } "Entry" { "MsmKey" = "8:_UNDEFINED" - "OwnerKey" = "8:_F591B1BDB2015F4239F7C4C6175CE115" + "OwnerKey" = "8:_B171DBF19F7B85A327B23E3F25A99DD5" "MsmSig" = "8:_UNDEFINED" } "Entry" { "MsmKey" = "8:_UNDEFINED" - "OwnerKey" = "8:_E05AF71925AA4B81BBD9C00C1109B6DE" + "OwnerKey" = "8:_55CDA3579E76ECF84FAEF483BC0A02C6" "MsmSig" = "8:_UNDEFINED" } "Entry" { "MsmKey" = "8:_UNDEFINED" - "OwnerKey" = "8:_5A943AD2E32AEED95F3BF29D99D4FC0E" + "OwnerKey" = "8:_E05AF71925AA4B81BBD9C00C1109B6DE" "MsmSig" = "8:_UNDEFINED" } } @@ -126,20 +126,20 @@ } "File" { - "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_5A943AD2E32AEED95F3BF29D99D4FC0E" + "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_55CDA3579E76ECF84FAEF483BC0A02C6" { "AssemblyRegister" = "3:1" "AssemblyIsInGAC" = "11:FALSE" - "AssemblyAsmDisplayName" = "8:Google.GData.Extensions, Version=1.3.0.27084, Culture=neutral, PublicKeyToken=0b4c5df2ebf20876, processorArchitecture=MSIL" + "AssemblyAsmDisplayName" = "8:Google.GData.Client, Version=1.4.2.24028, Culture=neutral, PublicKeyToken=04a59ca9b0273830, processorArchitecture=MSIL" "ScatterAssemblies" { - "_5A943AD2E32AEED95F3BF29D99D4FC0E" + "_55CDA3579E76ECF84FAEF483BC0A02C6" { - "Name" = "8:Google.GData.Extensions.dll" + "Name" = "8:Google.GData.Client.dll" "Attributes" = "3:512" } } - "SourcePath" = "8:Google.GData.Extensions.dll" + "SourcePath" = "8:Google.GData.Client.dll" "TargetName" = "8:" "Tag" = "8:" "Folder" = "8:_0349CADFD8AE4F579478064880E26A9F" @@ -157,20 +157,20 @@ "IsDependency" = "11:TRUE" "IsolateTo" = "8:" } - "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_F591B1BDB2015F4239F7C4C6175CE115" + "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_B171DBF19F7B85A327B23E3F25A99DD5" { "AssemblyRegister" = "3:1" "AssemblyIsInGAC" = "11:FALSE" - "AssemblyAsmDisplayName" = "8:Google.GData.Client, Version=1.3.0.27084, Culture=neutral, PublicKeyToken=04a59ca9b0273830, processorArchitecture=MSIL" + "AssemblyAsmDisplayName" = "8:Google.GData.Extensions, Version=1.4.2.21781, Culture=neutral, PublicKeyToken=0b4c5df2ebf20876, processorArchitecture=MSIL" "ScatterAssemblies" { - "_F591B1BDB2015F4239F7C4C6175CE115" + "_B171DBF19F7B85A327B23E3F25A99DD5" { - "Name" = "8:Google.GData.Client.dll" + "Name" = "8:Google.GData.Extensions.dll" "Attributes" = "3:512" } } - "SourcePath" = "8:Google.GData.Client.dll" + "SourcePath" = "8:Google.GData.Extensions.dll" "TargetName" = "8:" "Tag" = "8:" "Folder" = "8:_0349CADFD8AE4F579478064880E26A9F" @@ -235,7 +235,7 @@ { "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_E05AF71925AA4B81BBD9C00C1109B6DE" { - "SourcePath" = "8:..\\youtube\\obj\\Release\\Google.GData.YouTube.dll" + "SourcePath" = "8:..\\..\\youtube\\obj\\Debug\\Google.GData.YouTube.dll" "TargetName" = "8:" "Tag" = "8:" "Folder" = "8:_0349CADFD8AE4F579478064880E26A9F" diff -Nru gdata-sharp-1.4.0.2/src/unittests/analytics/AccountEntryTest.cs gdata-sharp-1.7.0.1/src/unittests/analytics/AccountEntryTest.cs --- gdata-sharp-1.4.0.2/src/unittests/analytics/AccountEntryTest.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/analytics/AccountEntryTest.cs 2009-08-19 06:54:43.000000000 +0000 @@ -0,0 +1,47 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* Created by Alex Maitland, maitlandalex@gmail.com */ +using Google.GData.Analytics; +using NUnit.Framework; + +namespace Google.GData.Client.UnitTests.Analytics +{ + [TestFixture, Category("Analytics")] + public class AccountEntryTest + { + private TestContext testContextInstance; + + /// + ///Gets or sets the test context which provides + ///information about and functionality for the current test run. + /// + public TestContext TestContext + { + get { return testContextInstance; } + set { testContextInstance = value; } + } + + + /// + ///A test for AccountEntry Constructor + /// + [Test] + public void DataEntryConstructorTest() + { + AccountEntry target = new AccountEntry(); + Assert.IsNotNull(target, "object better not be null"); + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/unittests/analytics/AccountFeedTest.cs gdata-sharp-1.7.0.1/src/unittests/analytics/AccountFeedTest.cs --- gdata-sharp-1.4.0.2/src/unittests/analytics/AccountFeedTest.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/analytics/AccountFeedTest.cs 2010-04-06 13:06:49.000000000 +0000 @@ -0,0 +1,228 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* Created by Alex Maitland, maitlandalex@gmail.com */ +using System; +using System.IO; +using System.Text; +using Google.GData.Analytics; +using Google.GData.Client; +using Google.GData.Client.UnitTests; +using Google.Analytics; +using NUnit.Framework; + +namespace Google.GData.Client.UnitTests.Analytics +{ + /// + ///This is a test class for AccountFeedTest and is intended + ///to contain all AccountFeedTest Unit Tests + /// + [TestFixture, Category("Analytics")] + public class AccountFeedTest + { + private const string AccountFeedUrl = "https://www.google.com/analytics/feeds/accounts/default"; + + private TestContext testContextInstance; + + /// + ///Gets or sets the test context which provides + ///information about and functionality for the current test run. + /// + public TestContext TestContext + { + get { return testContextInstance; } + set { testContextInstance = value; } + } + + /// + ///A test for CreateAccountFeed + /// + [Test] + public void CreateAccountFeedTest() + { + AccountFeed target = new AccountFeed(null, null); + AccountEntry entry = target.CreateFeedEntry() as AccountEntry; + Assert.IsNotNull(entry, "better have a AccountEntry here"); + } + + /// + ///A test for AccountFeed Constructor + /// + [Test] + public void AccountFeedConstructorTest() + { + AccountFeed target = new AccountFeed(null, null); + Assert.IsNotNull(target, "better have an object"); + Assert.IsNull(target.Service, "better have no service yet"); + } + + [Test] + public void AccountParseTest() + { + string xml = @" + + + Google Analytics + + Google Analytics + http://www.google.com/analytics/feeds/accounts/test@test.com + + Profile list for test@test.com + 2009-01-31T01:01:01+10:00 + + + + + ga:visitorType==New Visitor + + + + + + + ga:1234567 + + + + + www.test.com + http://www.google.com/analytics/feeds/accounts/ga:1234567 + + + 2009-01-31T01:01:01+10:00 + + + + + + + + + + + + + + + + + "; + + AccountFeed feed = Parse(xml); + AccountEntry entry = feed.Entries[0] as AccountEntry; + Assert.IsNotNull(entry, "entry"); + Assert.IsNotNull(entry.Properties); + Assert.IsNotNull(entry.ProfileId); + + Assert.AreEqual("ga:accountId", entry.Properties[0].Name); + Assert.AreEqual("123456", entry.Properties[0].Value); + + Assert.AreEqual("ga:accountName", entry.Properties[1].Name); + Assert.AreEqual("Test Account", entry.Properties[1].Value); + + Assert.AreEqual("ga:profileId", entry.Properties[2].Name); + Assert.AreEqual("1234567", entry.Properties[2].Value); + + Assert.AreEqual("ga:webPropertyId", entry.Properties[3].Name); + Assert.AreEqual("UA-111111-1", entry.Properties[3].Value); + + Assert.AreEqual("www.test.com", entry.Title.Text); + + Account a = new Account(); + a.AtomEntry = entry; + + Assert.AreEqual("123456", a.AccountId); + Assert.AreEqual("Test Account", a.AccountName); + Assert.AreEqual("1234567", a.ProfileId); + Assert.AreEqual("UA-111111-1", a.WebPropertyId); + Assert.AreEqual("www.test.com", a.Title); + Assert.AreEqual("ga:1234567", a.TableId); + + Assert.IsNotEmpty(feed.Segments); + foreach (Segment s in feed.Segments) + { + Assert.IsNotNull(s.Name); + Assert.IsNotNull(s.Id); + } + + Assert.AreEqual(feed.Segments[0].Name, "All Visits"); + Assert.AreEqual(feed.Segments[0].Id, "gaid::-1"); + + Assert.AreEqual(feed.Segments[1].Name, "New Visitors"); + Assert.AreEqual(feed.Segments[1].Id, "gaid::-2"); + + System.Collections.Generic.List goals = entry.Goals; + Assert.IsNotEmpty(goals); + Assert.AreEqual(goals.Count, 3); + + //First goal: Test all the way down + Goal firstGoal = goals[0]; + Assert.AreEqual(firstGoal.Active, "true" ); + Assert.AreEqual(firstGoal.Name , "Completing Order"); + Assert.AreEqual(firstGoal.Number, "1"); + Assert.AreEqual(firstGoal.Value, "10.0"); + + //Destination + Assert.IsNotNull(firstGoal.Destination); + Destination destination = firstGoal.Destination; + Assert.AreEqual(destination.CaseSensitive , "false" ); + Assert.AreEqual(destination.Expression , "/purchaseComplete.html" ); + Assert.AreEqual(destination.MatchType , "regex" ); + Assert.AreEqual(destination.Step1Required , "false" ); + + //Test first step of destination + // + + Assert.IsNotNull(destination.Steps); + Assert.IsNotEmpty(destination.Steps); + Step step = destination.Steps[0]; + + Assert.AreEqual(step.Name, "View Product Categories"); + Assert.AreEqual(step.Number, "1"); + Assert.AreEqual(step.Path, "/Apps|Accessories"); + + //Engagement + //testing against node: + + Assert.IsNotNull(goals[1].Engagement); + Engagement engagement = goals[1].Engagement; + + Assert.AreEqual(engagement.Comparison, ">"); + Assert.AreEqual(engagement.Threshold, "300"); + Assert.AreEqual(engagement.Type, "timeOnSite"); + + + //Custom Variables + + + Assert.IsNotNull(entry.CustomVariables); + Assert.IsNotEmpty(entry.CustomVariables); + CustomVariable cv = entry.CustomVariables[0]; + + Assert.AreEqual(cv.Name, "My Custom Variable"); + Assert.AreEqual(cv.Index, "1"); + Assert.AreEqual(cv.Scope, "3"); + + + } + + private static AccountFeed Parse(string xml) + { + byte[] bytes = new UTF8Encoding().GetBytes(xml); + AccountFeed feed = new AccountFeed(new Uri(AccountFeedUrl), new AnalyticsService("Test")); + feed.Parse(new MemoryStream(bytes), AlternativeFormat.Atom); + return feed; + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/unittests/analytics/AccountQueryTest.cs gdata-sharp-1.7.0.1/src/unittests/analytics/AccountQueryTest.cs --- gdata-sharp-1.4.0.2/src/unittests/analytics/AccountQueryTest.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/analytics/AccountQueryTest.cs 2009-05-20 09:45:51.000000000 +0000 @@ -0,0 +1,163 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* Created by Alex Maitland, maitlandalex@gmail.com */ +using NUnit.Framework; +using Google.GData.Analytics; +using System; + +namespace Google.GData.Client.UnitTests.Analytics +{ + + /// + ///This is a test class for AccountQueryTest and is intended + ///to contain all AccountQueryTest Unit Tests + /// + [TestFixture, Category("Analytics")] + public class AccountQueryTest + { + private TestContext testContextInstance; + + /// + ///Gets or sets the test context which provides + ///information about and functionality for the current test run. + /// + public TestContext TestContext + { + get { return testContextInstance; } + set + { + testContextInstance = value; + } + } + + /// + ///Empty Query Test + /// + [Test] + public void EmptyQueryTest() + { + const string result = "http://www.test.com/"; + AccountQuery target = new AccountQuery(); + target.BaseAddress = result; + Assert.AreEqual(new Uri(result), target.Uri); + } + + + /// + ///A test for Uri + /// + [Test] + public void UriTest() + { + AccountQuery target = new AccountQuery(); + Uri expected = new Uri("http://www.test.com/"); + Uri actual; + target.Uri = expected; + actual = target.Uri; + Assert.AreEqual(expected, actual); + } + + /// + ///A test for StartDate + /// + [Test] + public void StartDateTest() + { + AccountQuery target = new AccountQuery(); + DateTime expected = DateTime.Now; + DateTime actual; + target.StartDate = expected; + actual = target.StartDate; + Assert.AreEqual(expected, actual); + } + + /// + ///A test for Query + /// + [Test] + public void QueryTest() + { + AccountQuery target = new AccountQuery(); + string expected = "TestValue"; + string actual; + target.Query = expected; + actual = target.Query; + Assert.AreEqual(expected, actual); + } + + /// + ///A test for NumberToRetrieve + /// + [Test] + public void NumberToRetrieveTest() + { + AccountQuery target = new AccountQuery(); + int expected = 12; + int actual; + target.NumberToRetrieve = expected; + actual = target.NumberToRetrieve; + Assert.AreEqual(expected, actual); + } + + /// + ///A test for ExtraParameters + /// + [Test] + public void ExtraParametersTest() + { + AccountQuery target = new AccountQuery(); + string expected = "TestValue"; + string actual; + target.ExtraParameters = expected; + actual = target.ExtraParameters; + Assert.AreEqual(expected, actual); + } + + /// + ///A test for EndDate + /// + [Test] + public void EndDateTest() + { + AccountQuery target = new AccountQuery(); + DateTime expected = DateTime.Now; + DateTime actual; + target.EndDate = expected; + actual = target.EndDate; + Assert.AreEqual(expected, actual); + } + + /// + ///A test for AccountQuery Constructor + /// + [Test] + public void AccountQueryConstructorTest1() + { + AccountQuery target = new AccountQuery(); + Assert.IsNotNull(target); + } + + /// + ///A test for AccountQuery Constructor + /// + [Test] + public void AccountQueryConstructorTest() + { + const string baseUri = "http://www.test.com/"; + AccountQuery target = new AccountQuery(baseUri); + Assert.AreEqual(target.Uri, new Uri(baseUri)); + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/unittests/analytics/AnalyticsDataServiceTest.cs gdata-sharp-1.7.0.1/src/unittests/analytics/AnalyticsDataServiceTest.cs --- gdata-sharp-1.4.0.2/src/unittests/analytics/AnalyticsDataServiceTest.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/analytics/AnalyticsDataServiceTest.cs 2010-04-06 13:06:49.000000000 +0000 @@ -0,0 +1,324 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* Created by Alex Maitland, maitlandalex@gmail.com */ +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; +using Google.GData.Analytics; +using Google.GData.Client; +using Google.GData.Client.LiveTests; +using Google.GData.Client.UnitTests; +using Google.Analytics; +using NUnit.Framework; + +namespace Google.GData.Client.UnitTests.Analytics +{ + [TestFixture, Category("Analytics")] + public class AnalyticsDataServiceTest : BaseLiveTestClass + { + private const string DataFeedUrl = "http://www.google.com/analytics/feeds/data"; + private const string AccountFeedUrl = "http://www.google.com/analytics/feeds/accounts/default"; + + private string accountId; + + + private TestContext TestContext1; + + + protected override void ReadConfigFile() + { + base.ReadConfigFile(); + + if (unitTestConfiguration.Contains("analyticsUserName") == true) + { + this.userName = (string)unitTestConfiguration["analyticsUserName"]; + Tracing.TraceInfo("Read userName value: " + this.userName); + } + if (unitTestConfiguration.Contains("analyticsPassWord") == true) + { + this.passWord = (string)unitTestConfiguration["analyticsPassWord"]; + Tracing.TraceInfo("Read passWord value: " + this.passWord); + } + + if (unitTestConfiguration.Contains("accountId") == true) + { + this.accountId = (string)unitTestConfiguration["accountId"]; + Tracing.TraceInfo("Read accountId value: " + this.accountId); + } + + } + + /// + ///Gets or sets the test context which provides + ///information about and functionality for the current test run. + /// + public TestContext TestContext + { + get { return TestContext1; } + set { TestContext1 = value; } + } + + [Test] + public void QueryAccountIds() + { + AnalyticsService service = new AnalyticsService(this.ApplicationName); + service.Credentials = new GDataCredentials(this.userName, this.passWord); + + AccountQuery feedQuery = new AccountQuery(AccountFeedUrl); + AccountFeed actual = service.Query(feedQuery); + + foreach (AccountEntry entry in actual.Entries) + { + Assert.IsNotNull(entry.Id); + Assert.IsNotNull(entry.ProfileId.Value); + if (this.accountId == null) + this.accountId = entry.ProfileId.Value; + } + } + + [Test] + public void QueryBrowserMetrics() + { + AnalyticsService service = new AnalyticsService(this.ApplicationName); + service.Credentials = new GDataCredentials(this.userName, this.passWord); + + DataQuery query = new DataQuery(DataFeedUrl); + query.Ids = this.accountId; + query.Metrics = "ga:pageviews"; + query.Dimensions = "ga:browser"; + query.Sort = "ga:browser,ga:pageviews"; + query.GAStartDate = DateTime.Now.AddDays(-14).ToString("yyyy-MM-dd"); + query.GAEndDate = DateTime.Now.AddDays(-2).ToString("yyyy-MM-dd"); + query.NumberToRetrieve = 200; + + DataFeed actual = service.Query(query); + + XmlTextWriter writer = new XmlTextWriter("QueryBrowserMetricsOutput.xml", Encoding.UTF8); + writer.Formatting = Formatting.Indented; + writer.Indentation = 2; + + actual.SaveToXml(writer); + + foreach (DataEntry entry in actual.Entries) + { + Assert.IsNotNull(entry.Id); + } + } + + [Test] + public void QueryProductCategoryResultForPeriod() + { + AnalyticsService service = new AnalyticsService(this.ApplicationName); + service.Credentials = new GDataCredentials(this.userName, this.passWord); + + DataQuery query = new DataQuery(DataFeedUrl); + query.Ids = this.accountId; + query.Dimensions = "ga:productCategory,ga:productName"; + query.Metrics = "ga:itemRevenue,ga:itemQuantity"; + query.Sort = "ga:productCategory"; + query.GAStartDate = new DateTime(2009, 04, 19).ToString("yyyy-MM-dd"); + query.GAEndDate = new DateTime(2009, 04, 25).ToString("yyyy-MM-dd"); + + DataFeed actual = service.Query(query); + + Assert.IsNotNull(actual); + Assert.IsNotNull(actual.Entries); + + foreach(DataEntry entry in actual.Entries) + { + Assert.AreEqual(2, entry.Dimensions.Count); + Assert.IsNotNull(entry.Dimensions[0]); + Assert.IsNotNull(entry.Dimensions[0].Name); + Assert.IsNotNull(entry.Dimensions[0].Value); + Assert.IsNotNull(entry.Dimensions[1]); + Assert.IsNotNull(entry.Dimensions[1].Name); + Assert.IsNotNull(entry.Dimensions[1].Value); + Assert.AreEqual(2, entry.Metrics.Count); + Assert.IsNotNull(entry.Metrics[0]); + Assert.IsNotNull(entry.Metrics[0].Name); + Assert.IsNotNull(entry.Metrics[0].Value); + Assert.IsNotNull(entry.Metrics[1]); + Assert.IsNotNull(entry.Metrics[1].Name); + Assert.IsNotNull(entry.Metrics[1].Value); + } + } + + [Test] + public void QueryVisitorsResultForPeriod() + { + AnalyticsService service = new AnalyticsService(this.ApplicationName); + service.Credentials = new GDataCredentials(this.userName, this.passWord); + + DataQuery query = new DataQuery(DataFeedUrl); + query.Ids = this.accountId; + query.Metrics = "ga:visitors"; + query.GAStartDate = new DateTime(2009, 04, 19).ToString("yyyy-MM-dd"); + query.GAEndDate = new DateTime(2009, 04, 25).ToString("yyyy-MM-dd"); + query.StartIndex = 1; + + DataFeed actual = service.Query(query); + + Assert.IsNotNull(actual.Aggregates); + Assert.AreEqual(1, actual.Aggregates.Metrics.Count); + } + + [Test] + public void QuerySiteStatsResultForPeriod() + { + AnalyticsService service = new AnalyticsService(this.ApplicationName); + service.Credentials = new GDataCredentials(this.userName, this.passWord); + + DataQuery query = new DataQuery(DataFeedUrl); + query.Ids = this.accountId; + query.Metrics = "ga:pageviews,ga:visits,ga:newVisits,ga:transactions,ga:uniquePageviews"; + query.GAStartDate = new DateTime(2009, 04, 19).ToString("yyyy-MM-dd"); + query.GAEndDate = new DateTime(2009, 04, 25).ToString("yyyy-MM-dd"); + query.StartIndex = 1; + + DataFeed actual = service.Query(query); + + Assert.IsNotNull(actual.Aggregates); + Assert.AreEqual(5, actual.Aggregates.Metrics.Count); + } + + [Test] + public void QueryTransactionIdReturnAllResults() + { + AnalyticsService service = new AnalyticsService(this.ApplicationName); + service.Credentials = new GDataCredentials(this.userName, this.passWord); + + int currentIndex = 1; + const int resultsPerPage = 1000; + List querys = new List(); + + DataQuery query = new DataQuery(DataFeedUrl); + query.Ids = this.accountId; + query.Dimensions = "ga:transactionId,ga:date"; + query.Metrics = "ga:transactionRevenue"; + query.Sort = "ga:date"; + query.GAStartDate = new DateTime(2009, 04, 01).ToString("yyyy-MM-dd"); + query.GAEndDate = new DateTime(2009, 04, 30).ToString("yyyy-MM-dd"); + query.NumberToRetrieve = resultsPerPage; + + query.StartIndex = currentIndex; + DataFeed actual = service.Query(query); + + querys.Add(actual); + + double totalPages = Math.Round(((double)actual.TotalResults / (double)resultsPerPage) + 0.5); + + for (int i = 1; i < totalPages; i++) + { + currentIndex += resultsPerPage; + query.StartIndex = currentIndex; + actual = service.Query(query); + querys.Add(actual); + } + + for (int i = 0; i < querys.Count; i++) + { + foreach (DataEntry entry in querys[i].Entries) + { + Assert.IsNotNull(entry.Id); + } + } + } + + [Test] + public void QueryTransactionIdReturn200Results() + { + AnalyticsService service = new AnalyticsService(this.ApplicationName); + service.Credentials = new GDataCredentials(this.userName, this.passWord); + + DataQuery query = new DataQuery(DataFeedUrl); + query.Ids = this.accountId; + query.Dimensions = "ga:transactionId,ga:date"; + query.Metrics = "ga:transactionRevenue"; + query.Sort = "ga:date"; + query.GAStartDate = new DateTime(2009, 04, 01).ToString("yyyy-MM-dd"); + query.GAEndDate = new DateTime(2009, 04, 30).ToString("yyyy-MM-dd"); + query.NumberToRetrieve = 200; + DataFeed actual = service.Query(query); + + Assert.AreEqual(200, actual.ItemsPerPage); + + Assert.IsNotNull(actual.Aggregates); + Assert.AreEqual(1, actual.Aggregates.Metrics.Count); + + foreach (DataEntry entry in actual.Entries) + { + Assert.IsNotNull(entry.Id); + } + } + + [Test] + public void QueryPageViews() + { + AnalyticsService service = new AnalyticsService(this.ApplicationName); + service.Credentials = new GDataCredentials(this.userName, this.passWord); + + DataQuery query = new DataQuery(DataFeedUrl); + query.Ids = this.accountId; + query.Metrics = "ga:pageviews"; + query.Dimensions = "ga:pageTitle"; + query.Sort = "-ga:pageviews"; + query.GAStartDate = DateTime.Now.AddDays(-14).ToString("yyyy-MM-dd"); + query.GAEndDate = DateTime.Now.AddDays(-2).ToString("yyyy-MM-dd"); + query.NumberToRetrieve = 200; + DataFeed actual = service.Query(query); + + Assert.IsNotNull(actual.Aggregates); + Assert.AreEqual(1, actual.Aggregates.Metrics.Count); + + foreach (DataEntry entry in actual.Entries) + { + Assert.IsNotNull(entry.Id); + } + } + + [Test] + public void TestAnalyticsModel() + { + RequestSettings settings = new RequestSettings("Unittests", this.userName, this.passWord); + + AnalyticsRequest request = new AnalyticsRequest(settings); + + Feed accounts = request.GetAccounts(); + + foreach (Account a in accounts.Entries) + { + Assert.IsNotNull(a.AccountId); + Assert.IsNotNull(a.ProfileId); + Assert.IsNotNull(a.WebPropertyId); + if (this.accountId == null) + this.accountId = a.TableId; + } + + + DataQuery q = new DataQuery(this.accountId, DateTime.Now.AddDays(-14), DateTime.Now.AddDays(-2), "ga:pageviews", "ga:pageTitle", "ga:pageviews"); + + + Dataset set = request.Get(q); + + foreach (Data d in set.Entries) + { + Assert.IsNotNull(d.Id); + Assert.IsNotNull(d.Metrics); + Assert.IsNotNull(d.Dimensions); + } + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/unittests/analytics/DataEntryTest.cs gdata-sharp-1.7.0.1/src/unittests/analytics/DataEntryTest.cs --- gdata-sharp-1.4.0.2/src/unittests/analytics/DataEntryTest.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/analytics/DataEntryTest.cs 2009-05-20 09:45:51.000000000 +0000 @@ -0,0 +1,48 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* Created by Alex Maitland, maitlandalex@gmail.com */ +using Google.GData.Analytics; +using Google.GData.Client.UnitTests; +using NUnit.Framework; + +namespace Google.GData.Client.UnitTests.Analytics +{ + [TestFixture, Category("Analytics")] + public class DataEntryTest + { + private TestContext testContextInstance; + + /// + ///Gets or sets the test context which provides + ///information about and functionality for the current test run. + /// + public TestContext TestContext + { + get { return testContextInstance; } + set { testContextInstance = value; } + } + + + /// + ///A test for DataEntry Constructor + /// + [Test] + public void DataEntryConstructorTest() + { + DataEntry target = new DataEntry(); + Assert.IsNotNull(target, "object better not be null"); + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/unittests/analytics/DataFeedTest.cs gdata-sharp-1.7.0.1/src/unittests/analytics/DataFeedTest.cs --- gdata-sharp-1.4.0.2/src/unittests/analytics/DataFeedTest.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/analytics/DataFeedTest.cs 2010-04-06 13:06:49.000000000 +0000 @@ -0,0 +1,223 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* Created by Alex Maitland, maitlandalex@gmail.com */ +using System; +using System.IO; +using System.Text; +using Google.GData.Analytics; +using Google.GData.Client; +using Google.GData.Client.UnitTests; +using Google.GData.GoogleBase; +using Google.Analytics; +using NUnit.Framework; + + + +namespace Google.GData.Client.UnitTests.Analytics +{ + /// + ///This is a test class for DataFeedTest and is intended + ///to contain all DataFeedTest Unit Tests + /// + [TestFixture, Category("Analytics")] + public class DataFeedTest + { + private const string DataFeedUrl = "https://www.google.com/analytics/feeds/data"; + + private TestContext testContextInstance; + + /// + ///Gets or sets the test context which provides + ///information about and functionality for the current test run. + /// + public TestContext TestContext + { + get { return testContextInstance; } + set { testContextInstance = value; } + } + + /// + ///A test for CreateDataFeed + /// + [Test] + public void CreateDataFeedTest() + { + DataFeed target = new DataFeed(null, null); + DataEntry entry = target.CreateFeedEntry() as DataEntry; + Assert.IsNotNull(entry, "better have a DataEntry here"); + } + + /// + ///A test for DataFeed Constructor + /// + [Test] + public void DataFeedConstructorTest() + { + DataFeed target = new DataFeed(null, null); + Assert.IsNotNull(target, "better have an object"); + Assert.IsNull(target.Service, "better have no service yet"); + } + + [Test] + public void DataParseTest() + { + string xml = @" + + http://www.google.com/analytics/feeds/data?ids=ga:1174&dimensions=ga:medium,ga:source&metrics=ga:bounces,ga:visits&filters=ga:medium%3D%3Dreferral&start-date=2008-10-01&end-date=2008-10-31 + 2008-10-31T16:59:59.999-07:00 + Google Analytics Data for Profile 1174 + + + + Google Analytics + + Google Analytics + 6451 + 1 + 5 + + + + + + + + + ga:1174 + www.googlestore.com + + 2008-10-31 + 2008-10-01 + + ga:operatingSystem==iPhone + + + http://www.google.com/analytics/feeds/data?ids=ga:1174&ga:medium=referral&ga:source=blogger.com&filters=ga:medium%3D%3Dreferral&start-date=2008-10-01&end-date=2008-10-31 + 2008-10-30T17:00:00.001-07:00 + ga:source=blogger.com | ga:medium=referral + + + + + + + + http://www.google.com/analytics/feeds/data?ids=ga:1174&ga:medium=referral&ga:source=google.com&filters=ga:medium%3D%3Dreferral&start-date=2008-10-01&end-date=2008-10-31 + 2008-10-30T17:00:00.001-07:00 + ga:source=google.com | ga:medium=referral + + + + + + + + "; + + Google.GData.Analytics.DataFeed feed = Parse(xml); + + Dataset f = new Dataset(feed); + f.AutoPaging = false; + + Assert.IsNotNull(f.Aggregates); + Assert.IsNotNull(f.DataSource); + Assert.IsNotNull(f.Entries); + + Assert.AreEqual(136540, f.Aggregates.Metrics[0].IntegerValue); + Assert.AreEqual("0.0", f.Aggregates.Metrics[0].ConfidenceInterval); + Assert.AreEqual("ga:visits", f.Aggregates.Metrics[0].Name); + Assert.AreEqual("integer", f.Aggregates.Metrics[0].Type); + + Assert.AreEqual("ga:1174", f.DataSource.TableId); + Assert.AreEqual("www.googlestore.com", f.DataSource.TableName); + Assert.AreEqual("1174", f.DataSource.ProfileId); + Assert.AreEqual("UA-30481-1", f.DataSource.WebPropertyId); + Assert.AreEqual("Google Store", f.DataSource.AccountName); + + + Assert.AreEqual(136540, Int32.Parse(feed.Aggregates.Metrics[0].Value)); + + + DataEntry blogger = feed.Entries[0] as DataEntry; + Assert.IsNotNull(blogger, "entry"); + Assert.IsNotNull(blogger.Dimensions); + Assert.IsNotNull(blogger.Metrics); + + Assert.AreEqual("ga:source", blogger.Dimensions[0].Name); + Assert.AreEqual("blogger.com", blogger.Dimensions[0].Value); + + Assert.AreEqual("ga:visits", blogger.Metrics[0].Name); + Assert.AreEqual(68140, int.Parse(blogger.Metrics[0].Value)); + + DataEntry google = feed.Entries[1] as DataEntry; + Assert.IsNotNull(google, "entry"); + Assert.IsNotNull(google.Dimensions); + Assert.IsNotNull(google.Metrics); + + Assert.AreEqual("ga:source", google.Dimensions[0].Name); + Assert.AreEqual("google.com", google.Dimensions[0].Value); + + Assert.AreEqual("ga:visits", google.Metrics[0].Name); + Assert.AreEqual(29666, int.Parse(google.Metrics[0].Value)); + + foreach (DataEntry entry in feed.Entries) + { + Assert.IsNotNull(entry, "entry"); + Assert.IsNotNull(entry.Dimensions); + Assert.IsNotNull(entry.Metrics); + + Assert.AreEqual("ga:source", entry.Dimensions[0].Name); + Assert.IsNotEmpty(entry.Dimensions[0].Value); + + Assert.AreEqual("ga:visits", entry.Metrics[0].Name); + Assert.Greater(int.Parse(entry.Metrics[0].Value), 0); + } + + foreach (Data d in f.Entries) + { + Assert.IsNotNull(d, "entry"); + Assert.IsNotNull(d.Dimensions); + Assert.IsNotNull(d.Metrics); + + Assert.AreEqual("ga:source", d.Dimensions[0].Name); + Assert.IsNotEmpty(d.Dimensions[0].Value); + + Assert.AreEqual("ga:visits", d.Metrics[0].Name); + Assert.Greater(int.Parse(d.Metrics[0].Value), 0); + } + + Assert.IsNotEmpty(feed.Segments); + + Segment s = feed.Segments[0]; + Assert.IsNotNull(s.Name); + Assert.AreEqual(s.Id, "gaid::-11"); + Assert.IsNotNull(s.Id); + Assert.AreEqual(s.Name, "Mobile Traffic"); + Assert.IsNotNull(s.Definition); + Assert.IsNotEmpty(s.Definition.Value); + Assert.AreEqual(s.Definition.Value, "ga:operatingSystem==iPhone"); + + + } + + private static Google.GData.Analytics.DataFeed Parse(string xml) + { + byte[] bytes = new UTF8Encoding().GetBytes(xml); + DataFeed feed = new DataFeed(new Uri(DataFeedUrl), null); + feed.Parse(new MemoryStream(bytes), AlternativeFormat.Atom); + return feed; + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/unittests/analytics/DataQueryTest.cs gdata-sharp-1.7.0.1/src/unittests/analytics/DataQueryTest.cs --- gdata-sharp-1.4.0.2/src/unittests/analytics/DataQueryTest.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/analytics/DataQueryTest.cs 2010-04-06 13:06:49.000000000 +0000 @@ -0,0 +1,348 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +/* Created by Alex Maitland, maitlandalex@gmail.com */ +using NUnit.Framework; +using Google.GData.Analytics; +using System; + +namespace Google.GData.Client.UnitTests.Analytics +{ + + /// + ///This is a test class for DataQueryTest and is intended + ///to contain all DataQueryTest Unit Tests + /// + [TestFixture, Category("Analytics")] + public class DataQueryTest + { + private TestContext testContextInstance; + + /// + ///Gets or sets the test context which provides + ///information about and functionality for the current test run. + /// + public TestContext TestContext + { + get { return testContextInstance; } + set + { + testContextInstance = value; + } + } + + /// + ///A test for Dimensions property + /// + [Test] + public void DimensionPropertyTest() + { + DataQuery target = new DataQuery(); + const string expected = "ga:productCategory,ga:productName"; + target.Dimensions = expected; + string actual = target.Dimensions; + Assert.AreEqual(expected, actual); + } + + /// + ///A test for Dimensions parsing + /// + [Test] + public void DimensionParseTest() + { + const string expected = "ga:productCategory,ga:productName"; + DataQuery target = new DataQuery(); + //Force expected to be parsed + target.Uri = new Uri("http://test.com?dimensions=" + expected); + string actual = target.Dimensions; + Assert.AreEqual(expected, actual); + } + + /// + ///A test for Metric parsing + /// + [Test] + public void MetricParseTest() + { + const string expected = "ga:itemRevenue,ga:itemQuantity"; + DataQuery target = new DataQuery(); + //Force expected to be parsed + target.Uri = new Uri("http://test.com?metrics=" + expected); + string actual = target.Metrics; + Assert.AreEqual(expected, actual); + } + + /// + ///A test for Ids parsing + /// + [Test] + public void IdsParseTest() + { + const string expected = "ga:1234"; + DataQuery target = new DataQuery(); + //Force expected to be parsed + target.Uri = new Uri("http://test.com?ids=" + expected); + string actual = target.Ids; + Assert.AreEqual(expected, actual); + } + + /// + ///A test for Filters parsing + /// + [Test] + public void FiltersParseTest() + { + const string expected = "ga:country%3D%3DCanada"; + DataQuery target = new DataQuery(); + //Force expected to be parsed + target.Uri = new Uri("http://test.com?filters=" + expected); + string actual = target.Filters; + Assert.AreEqual(expected, actual); + } + + /// + ///A test for Dynamic Advanced-Segment parsing + /// + [Test] + public void DynamicSegmentParseTest() + { + const string expected = "dynamic::ga:country%3D%3DCanada"; + DataQuery target = new DataQuery(); + //Force expected to be parsed + target.Uri = new Uri("http://test.com?segment=" + expected); + string actual = target.Segment; + Assert.AreEqual(expected, actual); + } + + /// + ///A test for Indexed Advanced-Segment parsing (Advanced Segments saved via web interface) + /// + [Test] + public void IndexedSegmentParseTest() + { + const string expected = "gaid::-2"; + DataQuery target = new DataQuery(); + //Force expected to be parsed + target.Uri = new Uri("http://test.com?segment=" + expected); + string actual = target.Segment; + Assert.AreEqual(expected, actual); + } + + + /// + ///A test for Sort parsing + /// + [Test] + public void SortParseTest() + { + const string expected = "ga:productCategory"; + DataQuery target = new DataQuery(); + //Force expected to be parsed + target.Uri = new Uri("http://test.com?sort=" + expected); + string actual = target.Sort; + Assert.AreEqual(expected, actual); + } + + /// + ///A test for GAStartDate parsing + /// + [Test] + public void GAStartDateParseTest() + { + const string expected = "2009-04-1"; + DataQuery target = new DataQuery(); + //Force expected to be parsed + target.Uri = new Uri("http://test.com?start-date=" + expected); + string actual = target.GAStartDate; + Assert.AreEqual(expected, actual); + } + + /// + ///A test for GAEndDate parsing + /// + [Test] + public void GAEndDateParseTest() + { + const string expected = "2009-04-25"; + DataQuery target = new DataQuery(); + //Force expected to be parsed + target.Uri = new Uri("http://test.com?end-date=" + expected); + string actual = target.GAEndDate; + Assert.AreEqual(expected, actual); + } + + /// + /// A test for parsing of a complete query + /// Parse complete query URL and check the results + /// + [Test] + public void ParseTest() + { + const string dimensionExpected = "ga:productCategory,ga:productName"; + const string metricExpected = "ga:itemRevenue,ga:itemQuantity"; + const string idsExpected = "ga:1234"; + const string filtersExpected = "ga:country%3D%3DCanada"; + const string sortExpected = "ga:productCategory"; + const string startDateExpected = "2009-04-1"; + const string endDateExpected = "2009-04-25"; + DataQuery target = new DataQuery(); + + target.Uri = new Uri(string.Format("http://test.com?ids={0}&dimensions={1}&metrics={2}&filters={3}&sort={4}&start-date={5}&end-date={6}", idsExpected, dimensionExpected, metricExpected, filtersExpected, sortExpected, startDateExpected, endDateExpected)); + Assert.AreEqual("http://test.com/", target.BaseAddress); + Assert.AreEqual(dimensionExpected, target.Dimensions); + Assert.AreEqual(metricExpected, target.Metrics); + Assert.AreEqual(idsExpected, target.Ids); + Assert.AreEqual(filtersExpected, target.Filters); + Assert.AreEqual(sortExpected, target.Sort); + Assert.AreEqual(startDateExpected, target.GAStartDate); + Assert.AreEqual(endDateExpected, target.GAEndDate); + } + + /// + /// A test for calculating the query by setting the paramaters + /// Parse complete query URL and check the results + /// + [Test] + public void CalculateQueryTest() + { + const string baseUrlExpected = "http://test.com/"; + const string dimensionExpected = "ga:productCategory,ga:productName"; + const string metricExpected = "ga:itemRevenue,ga:itemQuantity"; + const string idsExpected = "ga:1234"; + const string filtersExpected = "ga:country%3D%3DCanada"; + const string sortExpected = "ga:productCategory"; + const string startDateExpected = "2009-04-1"; + const string endDateExpected = "2009-04-25"; + DataQuery target = new DataQuery(); + + target.BaseAddress = baseUrlExpected; + target.Dimensions = dimensionExpected; + target.Metrics = metricExpected; + target.Ids = idsExpected; + target.Filters = filtersExpected; + target.Sort = sortExpected; + target.GAStartDate = startDateExpected; + target.GAEndDate = endDateExpected; + + Uri expectedResult = new Uri(string.Format("http://test.com?dimensions={0}&end-date={1}&filters={2}&ids={3}&metrics={4}&sort={5}&start-date={6}", Utilities.UriEncodeReserved(dimensionExpected), Utilities.UriEncodeReserved(endDateExpected), Utilities.UriEncodeReserved(filtersExpected), Utilities.UriEncodeReserved(idsExpected), Utilities.UriEncodeReserved(metricExpected), Utilities.UriEncodeReserved(sortExpected), Utilities.UriEncodeReserved(startDateExpected))); + + Assert.AreEqual(expectedResult.AbsoluteUri, target.Uri.AbsoluteUri); + } + + /// + ///A test for Uri + /// + [Test] + public void UriTest() + { + DataQuery target = new DataQuery(); + Uri expected = new Uri("http://www.test.com/"); + Uri actual; + target.Uri = expected; + actual = target.Uri; + Assert.AreEqual(expected, actual); + } + + /// + ///A test for StartDate + /// + [Test] + public void StartDateTest() + { + DataQuery target = new DataQuery(); + DateTime expected = DateTime.Now; + DateTime actual; + target.StartDate = expected; + actual = target.StartDate; + Assert.AreEqual(expected, actual); + } + + /// + ///A test for Query + /// + [Test] + public void QueryTest() + { + DataQuery target = new DataQuery(); + string expected = "TestValue"; + string actual; + target.Query = expected; + actual = target.Query; + Assert.AreEqual(expected, actual); + } + + /// + ///A test for NumberToRetrieve + /// + [Test] + public void NumberToRetrieveTest() + { + DataQuery target = new DataQuery(); + int expected = 12; + int actual; + target.NumberToRetrieve = expected; + actual = target.NumberToRetrieve; + Assert.AreEqual(expected, actual); + } + + /// + ///A test for ExtraParameters + /// + [Test] + public void ExtraParametersTest() + { + DataQuery target = new DataQuery(); + string expected = "TestValue"; + string actual; + target.ExtraParameters = expected; + actual = target.ExtraParameters; + Assert.AreEqual(expected, actual); + } + + /// + ///A test for EndDate + /// + [Test] + public void EndDateTest() + { + DataQuery target = new DataQuery(); + DateTime expected = DateTime.Now; + DateTime actual; + target.EndDate = expected; + actual = target.EndDate; + Assert.AreEqual(expected, actual); + } + + /// + ///A test for DataQuery Constructor + /// + [Test] + public void DataQueryConstructorTest1() + { + DataQuery target = new DataQuery(); + Assert.IsNotNull(target); + } + + /// + ///A test for DataQuery Constructor + /// + [Test] + public void FeedQueryConstructorTest() + { + const string baseUri = "http://www.test.com/"; + DataQuery target = new DataQuery(baseUri); + Assert.AreEqual(target.Uri, new Uri(baseUri)); + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/unittests/AuthenticatorTests.cs gdata-sharp-1.7.0.1/src/unittests/AuthenticatorTests.cs --- gdata-sharp-1.4.0.2/src/unittests/AuthenticatorTests.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/AuthenticatorTests.cs 2010-05-26 08:04:54.000000000 +0000 @@ -0,0 +1,164 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +#define USE_TRACING +#define DEBUG + +using System; +using System.IO; +using System.Xml; +using System.Collections; +using System.Configuration; +using System.Net; +using NUnit.Framework; +using Google.GData.Client; +using Google.GData.Documents; + + +namespace Google.GData.Client.LiveTests +{ + [TestFixture] + [Category("AuthenticatorTests")] + public class AuthenticatorTestSuite : OAuthTestSuite + { + ////////////////////////////////////////////////////////////////////// + /// default empty constructor + ////////////////////////////////////////////////////////////////////// + public AuthenticatorTestSuite() + { + } + + ////////////////////////////////////////////////////////////////////// + /// the setup method + ////////////////////////////////////////////////////////////////////// + [SetUp] + public override void InitTest() + { + Tracing.TraceCall(); + base.InitTest(); + } + ///////////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////// + /// the end it all method + ////////////////////////////////////////////////////////////////////// + [TearDown] + public override void EndTest() + { + Tracing.ExitTracing(); + } + ///////////////////////////////////////////////////////////////////////////// + + + + ////////////////////////////////////////////////////////////////////// + /// private void ReadConfigFile() + /// + ////////////////////////////////////////////////////////////////////// + protected override void ReadConfigFile() + { + base.ReadConfigFile(); + } + ///////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////// + /// runs an authentication test with client auth + ////////////////////////////////////////////////////////////////////// + [Test] + public void ClientAuthenticatorTest() + { + Tracing.TraceMsg("Entering ClientAuthenticatorTest"); + + ClientLoginAuthenticator auth = new ClientLoginAuthenticator(this.ApplicationName, + ServiceNames.Documents, + this.userName, + this.passWord); + + HttpWebRequest request = auth.CreateHttpWebRequest("GET", new Uri(DocumentsListQuery.documentsBaseUri)); + + request.Headers.Add(GDataGAuthRequestFactory.GDataVersion, "3.0"); + HttpWebResponse response = request.GetResponse() as HttpWebResponse; + + if (response.StatusCode == HttpStatusCode.Redirect) + { + request = WebRequest.Create(response.Headers["Location"]) as HttpWebRequest; + auth.ApplyAuthenticationToRequest(request); + + response = request.GetResponse() as HttpWebResponse; + + } + Assert.IsTrue(response.StatusCode == HttpStatusCode.OK); + } + ///////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////// + /// runs an authentication test with 2 legged oauth + ////////////////////////////////////////////////////////////////////// + [Test] + public void OAuth2LeggedAuthenticatorTest() + { + Tracing.TraceMsg("Entering OAuth2LeggedAuthenticationTest"); + + OAuth2LeggedAuthenticator auth = new OAuth2LeggedAuthenticator(this.ApplicationName, + this.oAuthConsumerKey, + this.oAuthConsumerSecret, + this.oAuthUser, + this.oAuthDomain); + + HttpWebRequest request = auth.CreateHttpWebRequest("GET", new Uri("http://www.google.com/calendar/feeds/default/owncalendars/full")); + HttpWebResponse response = request.GetResponse() as HttpWebResponse; + + if (response.StatusCode == HttpStatusCode.Redirect) + { + request = WebRequest.Create(response.Headers["Location"]) as HttpWebRequest; + auth.ApplyAuthenticationToRequest(request); + + response = request.GetResponse() as HttpWebResponse; + + } + Assert.IsTrue(response.StatusCode == HttpStatusCode.OK); + } + ///////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////// + /// runs an authentication test with 2 legged oauth + ////////////////////////////////////////////////////////////////////// + [Test] + public void OAuth3LeggedAuthenticatorTest() + { + Tracing.TraceMsg("Entering OAuth3LeggedAuthenticationTest"); + + OAuth3LeggedAuthenticator auth = new OAuth3LeggedAuthenticator(this.ApplicationName, + this.oAuthConsumerKey, + this.oAuthConsumerSecret, + this.oAuthToken, + this.oAuthTokenSecret); + + HttpWebRequest request = auth.CreateHttpWebRequest("GET", new Uri("https://www.google.com/calendar/feeds/default/owncalendars/full")); + HttpWebResponse response = request.GetResponse() as HttpWebResponse; + + if (response.StatusCode == HttpStatusCode.Redirect) + { + request = WebRequest.Create(response.Headers["Location"]) as HttpWebRequest; + auth.ApplyAuthenticationToRequest(request); + + response = request.GetResponse() as HttpWebResponse; + + } + Assert.IsTrue(response.StatusCode == HttpStatusCode.OK); + } + ///////////////////////////////////////////////////////////////////////////// + + } +} \ No newline at end of file diff -Nru gdata-sharp-1.4.0.2/src/unittests/caltest.cs gdata-sharp-1.7.0.1/src/unittests/caltest.cs --- gdata-sharp-1.4.0.2/src/unittests/caltest.cs 2008-11-17 13:22:02.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/caltest.cs 2010-04-26 14:03:09.000000000 +0000 @@ -1174,6 +1174,7 @@ newCalendar.Summary.Text = "some unique summary" + Guid.NewGuid().ToString(); newCalendar.TimeZone = "America/Los_Angeles"; newCalendar.Hidden = false; + newCalendar.Selected = true; newCalendar.Color = "#2952A3"; newCalendar.Location = new Where("", "", "Test City"); @@ -1190,6 +1191,7 @@ Assert.AreEqual(newCalendar.Location.ValueString, createdCalendar.Location.ValueString, "Where should be equal"); createdCalendar.Title.Text = "renamed calendar" + Guid.NewGuid().ToString(); + createdCalendar.Hidden = true; CalendarEntry updatedCalendar = (CalendarEntry) createdCalendar.Update(); Assert.AreEqual(createdCalendar.Title.Text, updatedCalendar.Title.Text, "entry should have been updated"); @@ -1666,9 +1668,13 @@ } ///////////////////////////////////////////////////////////////////////////// } ///////////////////////////////////////////////////////////////////////////// + + } + + diff -Nru gdata-sharp-1.4.0.2/src/unittests/contactstest.cs gdata-sharp-1.7.0.1/src/unittests/contactstest.cs --- gdata-sharp-1.4.0.2/src/unittests/contactstest.cs 2009-02-27 14:38:35.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/contactstest.cs 2010-04-26 14:03:09.000000000 +0000 @@ -235,7 +235,6 @@ currentEntry = currentEntry.Update(); // now we should have 2 new groups and one new entry with no groups anymore - int oldCountGroups = feed.Entries.Count; int oldCountContacts = cf.Entries.Count; @@ -355,16 +354,20 @@ } finally { } - } - - + } private void DeleteAllContacts() { - RequestSettings rs = new RequestSettings(this.ApplicationName, this.userName, this.passWord); + ContactsTestSuite.DeleteAllContacts(rs); + + } + + internal static void DeleteAllContacts(RequestSettings rs) + { + rs.AutoPaging = true; ContactsRequest cr = new ContactsRequest(rs); Feed f = cr.GetContacts(); @@ -381,7 +384,7 @@ list.Add(c); } - cr.Batch(list, new Uri(f.AtomFeed.Batch), GDataBatchOperationType.insert); + cr.Batch(list, new Uri(f.AtomFeed.Batch), GDataBatchOperationType.delete); f = cr.GetContacts(); @@ -496,6 +499,50 @@ } ///////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////// + /// runs an authentication test, inserts a new contact with an extended property + ////////////////////////////////////////////////////////////////////// + [Test] + public void InsertExtendedPropertyContactsTest() + { + Tracing.TraceMsg("Entering InsertExtendedPropertyContactsTest"); + + DeleteAllContacts(); + + RequestSettings rs = new RequestSettings(this.ApplicationName, this.userName, this.passWord); + rs.AutoPaging = true; + + FeedQuery query = new FeedQuery(); + query.Uri = new Uri(CreateUri(this.resourcePath + "contactsextendedprop.xml")); + + + + ContactsRequest cr = new ContactsRequest(rs); + + Feed f = cr.Get(query); + + Contact newEntry = null; + + foreach (Contact c in f.Entries) + { + ExtendedProperty e = c.ExtendedProperties[0]; + Assert.IsTrue(e != null); + newEntry = c; + } + + f = cr.GetContacts(); + + Contact createdEntry = cr.Insert(f, newEntry); + + cr.Delete(createdEntry); + + + + + } + ///////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// /// Tests the primary Accessors ////////////////////////////////////////////////////////////////////// @@ -532,8 +579,7 @@ } - PostalAddress p = new PostalAddress("Testaddress"); - p.Primary = true; + StructuredPostalAddress p = CreatePostalAddress(); Assert.IsTrue(entry.PrimaryPostalAddress == null, "Entry should have no primary Postal"); entry.PostalAddresses.Add(p); Assert.IsTrue(entry.PrimaryPostalAddress == p, "Entry should have one primary Postal"); @@ -562,6 +608,20 @@ Assert.IsTrue(entry.PrimaryIMAddress == null, "Entry should have no primary IM"); } + public static StructuredPostalAddress CreatePostalAddress() + { + StructuredPostalAddress p = new StructuredPostalAddress(); + p.City = "TestTown"; + p.Street = "Rosanna Drive"; + p.Postcode = "12345"; + p.Country = "The good ole Country"; + + p.Primary = true; + + return p; + } + + ////////////////////////////////////////////////////////////////////// /// Tests the primary Accessors ////////////////////////////////////////////////////////////////////// @@ -597,9 +657,7 @@ } } - - PostalAddress p = new PostalAddress("Testaddress"); - p.Primary = true; + StructuredPostalAddress p = CreatePostalAddress(); Assert.IsTrue(c.PrimaryPostalAddress == null, "Contact should have no primary Postal"); c.PostalAddresses.Add(p); Assert.IsTrue(c.PrimaryPostalAddress == p, "Contact should have one primary Postal"); @@ -718,8 +776,8 @@ } ///////////////////////////////////////////////////////////////////////////// - - private void DeleteList(List list, ContactsRequest cr, Uri batch) + + internal static void DeleteList(List list, ContactsRequest cr, Uri batch) { int i = 0; foreach (Contact c in list) @@ -787,7 +845,7 @@ // verify we got the phonenumber back.... Assert.IsTrue(e.PrimaryPhonenumber != null, "They should have a primary phonenumber"); Assert.AreEqual(e.PrimaryPhonenumber.Value,p.Value, "They should be identical"); - e.Title = newTitle; + e.Name.FamilyName = newTitle; inserted[i] = cr.Update(e); } } @@ -812,7 +870,7 @@ // verify we got the phonenumber back.... Assert.IsTrue(e.PrimaryPhonenumber != null, "They should have a primary phonenumber"); Assert.AreEqual(e.PrimaryPhonenumber.Value,p.Value, "They should be identical"); - Assert.AreEqual(e.Title, newTitle, "The title should have been updated"); + Assert.AreEqual(e.Name.FamilyName, newTitle, "The familyname should have been updated"); } } } @@ -823,6 +881,116 @@ // now delete them again DeleteList(inserted, cr, new Uri(f.AtomFeed.Batch)); + // now make sure they are gone + if (inserted.Count > 0) + { + int iVer = inserted.Count; + f = cr.GetContacts(); + foreach (Contact e in f.Entries) + { + // let's find those guys, we should not find ANY + for (int i = 0; i < inserted.Count; i++) + { + Contact test = inserted[i] as Contact; + Assert.IsTrue(e.Id != test.Id, "The new entries should all be deleted now"); + } + } + Assert.IsTrue(f.TotalResults == originalCount, "The count should be correct as well"); + } + } + ///////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////// + /// runs an authentication test, inserts a new contact + ////////////////////////////////////////////////////////////////////// + [Test] + public void ModelUpdateIfMatchAllContactsTest() + { + const int numberOfInserts = 5; + Tracing.TraceMsg("Entering ModelInsertContactsTest"); + + DeleteAllContacts(); + + RequestSettings rs = new RequestSettings(this.ApplicationName, this.userName, this.passWord); + rs.AutoPaging = true; + + ContactsRequest cr = new ContactsRequest(rs); + + Feed f = cr.GetContacts(); + + int originalCount = f.TotalResults; + + PhoneNumber p = null; + List inserted = new List(); + + if (f != null) + { + Assert.IsTrue(f.Entries != null, "the contacts needs entries"); + + for (int i = 0; i < numberOfInserts; i++) + { + Contact entry = new Contact(); + entry.AtomEntry = ObjectModelHelper.CreateContactEntry(i); + entry.PrimaryEmail.Address = "joe" + i.ToString() + "@doe.com"; + p = entry.PrimaryPhonenumber; + inserted.Add(cr.Insert(f, entry)); + } + } + + string newTitle = "This is an update to the title"; + f = cr.GetContacts(); + if (inserted.Count > 0) + { + int iVer = numberOfInserts; + // let's find those guys + foreach (Contact e in f.Entries) + { + for (int i = 0; i < inserted.Count; i++) + { + Contact test = inserted[i]; + if (e.Id == test.Id) + { + iVer--; + // verify we got the phonenumber back.... + Assert.IsTrue(e.PrimaryPhonenumber != null, "They should have a primary phonenumber"); + Assert.AreEqual(e.PrimaryPhonenumber.Value, p.Value, "They should be identical"); + e.Name.FamilyName = newTitle; + e.ETag = GDataRequestFactory.IfMatchAll; + inserted[i] = cr.Update(e); + } + } + } + + Assert.IsTrue(iVer == 0, "The new entries should all be part of the feed now, we have " + iVer + " left"); + } + + f = cr.GetContacts(); + if (inserted.Count > 0) + { + int iVer = numberOfInserts; + // let's find those guys + foreach (Contact e in f.Entries) + { + for (int i = 0; i < inserted.Count; i++) + { + Contact test = inserted[i]; + if (e.Id == test.Id) + { + iVer--; + // verify we got the phonenumber back.... + Assert.IsTrue(e.PrimaryPhonenumber != null, "They should have a primary phonenumber"); + Assert.AreEqual(e.PrimaryPhonenumber.Value, p.Value, "They should be identical"); + Assert.AreEqual(e.Name.FamilyName, newTitle, "The familyname should have been updated"); + } + } + } + Assert.IsTrue(iVer == 0, "The new entries should all be part of the feed now, we have: " + iVer + " now"); + } + + + // now delete them again + DeleteList(inserted, cr, new Uri(f.AtomFeed.Batch)); + // now make sure they are gone @@ -851,7 +1019,6 @@ [Test] public void ModelTestETagQuery() { - const int numberOfInserts = 5; Tracing.TraceMsg("Entering ModelTestETagQuery"); RequestSettings rs = new RequestSettings(this.ApplicationName, this.userName, this.passWord); @@ -965,13 +1132,13 @@ { // let's count and update them iVerify++; - c.Title = "get a nother one"; + c.Name.FamilyName = "get a nother one"; c.BatchData.Type = GDataBatchOperationType.update; list.Add(c); } Assert.IsTrue(iVerify == numberOfInserts, "should have gotten 5 inserts"); - Feed u = cr.Batch(list, new Uri(r.AtomFeed.Batch), GDataBatchOperationType.Default); + Feed u = cr.Batch(list, new Uri(f.AtomFeed.Batch), GDataBatchOperationType.Default); list.Clear(); iVerify = 0; @@ -984,7 +1151,7 @@ } Assert.IsTrue(iVerify == numberOfInserts, "should have gotten 5 updates"); - Feed d = cr.Batch(list, new Uri(u.AtomFeed.Batch), GDataBatchOperationType.Default); + Feed d = cr.Batch(list, new Uri(f.AtomFeed.Batch), GDataBatchOperationType.Default); iVerify = 0; foreach (Contact c in d.Entries ) diff -Nru gdata-sharp-1.4.0.2/src/unittests/documentslive.cs gdata-sharp-1.7.0.1/src/unittests/documentslive.cs --- gdata-sharp-1.4.0.2/src/unittests/documentslive.cs 2009-02-27 14:38:35.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/documentslive.cs 2010-06-22 15:02:23.000000000 +0000 @@ -22,6 +22,7 @@ using Google.GData.Client.UnitTests; using Google.GData.Documents; using Google.Documents; +using Google.AccessControl; namespace Google.GData.Client.LiveTests @@ -30,8 +31,6 @@ [Category("LiveTest")] public class DocumentsTestSuite : BaseLiveTestClass { - - ////////////////////////////////////////////////////////////////////// /// default empty constructor ////////////////////////////////////////////////////////////////////// @@ -117,6 +116,8 @@ { throw e; } + + entry.Update(); //try to delete the document we created @@ -210,16 +211,38 @@ /// /// tests document download /// - [Test] public void ModelTestDocumentDownload() + [Test] + public void ModelTestSSL() { RequestSettings settings = new RequestSettings(this.ApplicationName, this.userName, this.passWord); settings.AutoPaging = true; + settings.UseSSL = true; DocumentsRequest r = new DocumentsRequest(settings); // this returns the server default answer Feed feed = r.GetDocuments(); - Document d = null; + foreach (Document x in feed.Entries) + { + Assert.IsTrue(x != null, "We should have something"); + + Stream ret = r.Download(x, Document.DownloadType.pdf); + ret.Close(); + } + } + + + /// + /// tests document download + /// + [Test] public void ModelTestDocumentDownload() + { + RequestSettings settings = new RequestSettings(this.ApplicationName, this.userName, this.passWord); + settings.AutoPaging = true; + DocumentsRequest r = new DocumentsRequest(settings); + + // this returns the server default answer + Feed feed = r.GetDocuments(); foreach (Document x in feed.Entries ) { @@ -265,6 +288,56 @@ } } + /// + /// tests to verify that an acl was detected + /// + [Test] + public void ModelTestACLs() + { + RequestSettings settings = new RequestSettings(this.ApplicationName, this.userName, this.passWord); + // settings.PageSize = 15; + DocumentsRequest r = new DocumentsRequest(settings); + + // this returns the server default answer + Feed feed = r.GetDocuments(); + + foreach (Document x in feed.Entries) + { + Assert.IsTrue(x != null, "We should have something"); + Assert.IsNotNull(x.AccessControlList); + + Feed f = r.Get(x.AccessControlList); + foreach (Acl a in f.Entries) + { + Assert.IsNotNull(a.Role); + Assert.IsNotNull(a.Scope); + Assert.IsNotNull(a.Scope.Type); + Assert.IsNotNull(a.Scope.Value); + } + } + } + + /// + /// tests including acls during feed download + /// + [Test] public void ModelTestIncludeACLs() + { + RequestSettings settings = new RequestSettings(this.ApplicationName, this.userName, this.passWord); + // settings.PageSize = 15; + DocumentsRequest r = new DocumentsRequest(settings); + + r.BaseUri = DocumentsListQuery.documentsAclUri; + + // this returns the server default answer + Feed feed = r.GetDocuments(); + + foreach (Document x in feed.Entries ) + { + Assert.IsTrue(x != null, "We should have something"); + Assert.IsNotNull(x.AccessControlList); + } + } + /// /// tests etag refresh on an entry level @@ -398,7 +471,7 @@ bool fFound = false; foreach (Document child in children.Entries ) { - if (child.DocumentId == doc.DocumentId) + if (child.ResourceId == doc.ResourceId) { fFound = true; break; @@ -409,8 +482,33 @@ } + + /// + /// tests moving a document in and out of folders + /// + [Test] public void ModelTestArbitraryDownload() + { + RequestSettings settings = new RequestSettings(this.ApplicationName, this.userName, this.passWord); + // settings.PageSize = 15; + DocumentsRequest r = new DocumentsRequest(settings); + + Feed feed = r.GetEverything(); + + foreach (Document d in feed.Entries) + { + Stream res = r.Download(d, null); + Assert.IsNotNull(res, "The download stream should not be null"); + } + foreach (Document d in feed.Entries) + { + Stream res = r.Download(d, "pdf"); + Assert.IsNotNull(res, "The download stream should not be null"); + } + } } ///////////////////////////////////////////////////////////////////////////// + + } diff -Nru gdata-sharp-1.4.0.2/src/unittests/gapps/adminsettingsentrytest.cs gdata-sharp-1.7.0.1/src/unittests/gapps/adminsettingsentrytest.cs --- gdata-sharp-1.4.0.2/src/unittests/gapps/adminsettingsentrytest.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/gapps/adminsettingsentrytest.cs 2010-03-25 12:08:16.000000000 +0000 @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Xml; +using NUnit.Framework; +using Google.GData.Client; +using Google.GData.Apps; +using Google.GData.Apps.AdminSettings; +using Google.GData.Extensions.Apps; + + +namespace Google.GData.Apps.UnitTests +{ + class AdminSettingsEntryTest + { + private AdminSettingsEntry entry; + + [SetUp] + public void Init() + { + entry = new AdminSettingsEntry(); + } + + [TearDown] + public void Dispose() + { + + } + + [Test] + public void SaveAndReadTest() + { + entry.Properties.Add(new PropertyElement("name", "value")); + + StringBuilder sb = new StringBuilder(); + XmlWriter writer = new XmlTextWriter(new StringWriter(sb)); + entry.SaveToXml(writer); + writer.Close(); + + XmlDocument document = new XmlDocument(); + document.LoadXml(sb.ToString()); + + AdminSettingsEntry newEntry = new AdminSettingsEntry(); + foreach (XmlNode node in document.FirstChild.ChildNodes) + { + ExtensionElementEventArgs args = new ExtensionElementEventArgs(); + args.ExtensionElement = node; + args.Base = newEntry; + newEntry.Parse(args, new AtomFeedParser()); + } + + Assert.AreEqual(entry.Properties[0].Name, newEntry.Properties[0].Name, + "Parsed entry should have same name for property[0] as original entry"); + Assert.AreEqual(entry.Properties[0].Value, newEntry.Properties[0].Value, + "Parsed entry should have same value for property[0] as original entry"); + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/unittests/gapps/adminsettingsservicetest.cs gdata-sharp-1.7.0.1/src/unittests/gapps/adminsettingsservicetest.cs --- gdata-sharp-1.4.0.2/src/unittests/gapps/adminsettingsservicetest.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/gapps/adminsettingsservicetest.cs 2010-03-25 12:08:16.000000000 +0000 @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Xml; +using NUnit.Framework; +using Google.GData.Client; +using Google.GData.Apps; +using Google.GData.Apps.AdminSettings; +using Google.GData.Extensions.Apps; + + +namespace Google.GData.Apps.UnitTests +{ + class AdminSettingsServiceTest + { + private AdminSettingsService service; + + [SetUp] + public void Init() + { + service = new AdminSettingsService("example.com", "apps-example.com"); + } + + [TearDown] + public void Dispose() + { + + } + + [Test] + public void GetDomainTest() + { + Assert.AreEqual("example.com", service.Domain, "Domain should initially be example.com"); + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/unittests/gziplivetest.cs gdata-sharp-1.7.0.1/src/unittests/gziplivetest.cs --- gdata-sharp-1.4.0.2/src/unittests/gziplivetest.cs 2007-09-03 11:51:44.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/gziplivetest.cs 2009-11-03 14:00:14.000000000 +0000 @@ -54,7 +54,6 @@ Stream responseStream = request.GetResponseStream(); Assert.IsTrue(responseStream != null, "Response stream should not be null."); - Assert.IsTrue(responseStream is Google.GData.Client.GZipStream, "Response stream is not Google.GData.Client.GZipStream."); AtomFeed feed = new AtomFeed(new Uri(calendarUri), this.calendarService); feed.Parse(request.GetResponseStream(), AlternativeFormat.Atom); diff -Nru gdata-sharp-1.4.0.2/src/unittests/gzipstreamtest.cs gdata-sharp-1.7.0.1/src/unittests/gzipstreamtest.cs --- gdata-sharp-1.4.0.2/src/unittests/gzipstreamtest.cs 2007-08-01 19:38:47.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/gzipstreamtest.cs 2009-11-03 14:00:14.000000000 +0000 @@ -2,6 +2,7 @@ using System.Text; using System.Xml; using System.IO; +using System.IO.Compression; using Google.GData.Client; @@ -15,7 +16,7 @@ [TestFixture] public class GZipStreamTest : BaseTestClass { - private const string Data = "Google.GData.Client.GZipStream"; + private const string Data = "System.IO.Compression.GZipStream"; private const string Base64GZipData = "H4sIAEDbsEYAA3PPz0/PSdVzd0ksSdRzzslMzSvRc4/KLAguKUpNzAUAg1++Bx4AAAA="; private byte[] compressedData; diff -Nru gdata-sharp-1.4.0.2/src/unittests/health/h9servicelive.cs gdata-sharp-1.7.0.1/src/unittests/health/h9servicelive.cs --- gdata-sharp-1.4.0.2/src/unittests/health/h9servicelive.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/health/h9servicelive.cs 2009-08-18 23:17:20.000000000 +0000 @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Text; +using NUnit.Framework; +using Google.GData.Client.LiveTests; +using Google.GData.Client; +using Google.GData.Client.UnitTests; + +namespace Google.GData.Health.UnitTests +{ + [TestFixture] + [Category("LiveTest")] + public class H9ServiceTestSuite : BaseLiveTestClass + { + [Test] + public void GoogleAuthenticationTest() + { + Tracing.TraceMsg("Entering Health AuthenticationTest"); + + HealthQuery query = new HealthQuery(); + H9Service service = new H9Service(this.ApplicationName); + if (this.userName != null) + { + service.Credentials = new GDataCredentials(this.userName, this.passWord); + } + service.RequestFactory = this.factory; + + HealthFeed feed = service.Query(query) as HealthFeed; + + ObjectModelHelper.DumpAtomObject(feed, CreateDumpFileName("AuthenticationTest")); + service.Credentials = null; + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/unittests/oauthtest.cs gdata-sharp-1.7.0.1/src/unittests/oauthtest.cs --- gdata-sharp-1.4.0.2/src/unittests/oauthtest.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/oauthtest.cs 2010-06-28 13:31:33.000000000 +0000 @@ -0,0 +1,545 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +#define USE_TRACING +#define DEBUG + +using System; +using System.IO; +using System.Xml; +using System.Collections; +using System.Configuration; +using System.Net; +using NUnit.Framework; +using Google.GData.Client; +using Google.GData.Client.UnitTests; +using Google.GData.Extensions; +using Google.GData.Calendar; +using Google.GData.AccessControl; +using Google.Contacts; +using Google.Documents; +using System.Collections.Generic; + + + + +namespace Google.GData.Client.LiveTests +{ + [TestFixture] + [Category("LiveTest")] + public class OAuthTestSuite : BaseLiveTestClass + { + protected string oAuthConsumerKey; + protected string oAuthConsumerSecret; + protected string oAuthDomain; + protected string oAuthUser; + protected string oAuthToken; + protected string oAuthTokenSecret; + + + ////////////////////////////////////////////////////////////////////// + /// default empty constructor + ////////////////////////////////////////////////////////////////////// + public OAuthTestSuite() + { + } + + ////////////////////////////////////////////////////////////////////// + /// the setup method + ////////////////////////////////////////////////////////////////////// + [SetUp] + public override void InitTest() + { + Tracing.TraceCall(); + base.InitTest(); + } + ///////////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////// + /// the end it all method + ////////////////////////////////////////////////////////////////////// + [TearDown] + public override void EndTest() + { + Tracing.ExitTracing(); + } + ///////////////////////////////////////////////////////////////////////////// + + + + ////////////////////////////////////////////////////////////////////// + /// private void ReadConfigFile() + /// + ////////////////////////////////////////////////////////////////////// + protected override void ReadConfigFile() + { + base.ReadConfigFile(); + + if (unitTestConfiguration.Contains("OAUTHCONSUMERKEY") == true) + { + this.oAuthConsumerKey = (string)unitTestConfiguration["OAUTHCONSUMERKEY"]; + } + if (unitTestConfiguration.Contains("OAUTHCONSUMERSECRET") == true) + { + this.oAuthConsumerSecret = (string)unitTestConfiguration["OAUTHCONSUMERSECRET"]; + } + if (unitTestConfiguration.Contains("OAUTHDOMAIN") == true) + { + this.oAuthDomain = (string)unitTestConfiguration["OAUTHDOMAIN"]; + } + if (unitTestConfiguration.Contains("OAUTHUSER") == true) + { + this.oAuthUser = (string)unitTestConfiguration["OAUTHUSER"]; + } + if (unitTestConfiguration.Contains("OAUTHTOKEN") == true) + { + this.oAuthToken = (string)unitTestConfiguration["OAUTHTOKEN"]; + } + if (unitTestConfiguration.Contains("OAUTHTOKENSECRET") == true) + { + this.oAuthTokenSecret = (string)unitTestConfiguration["OAUTHTOKENSECRET"]; + } + } + ///////////////////////////////////////////////////////////////////////////// + + + ////////////////////////////////////////////////////////////////////// + /// Verifies the signature generation + ////////////////////////////////////////////////////////////////////// + [Test] + public void OAuthBaseSignatureTest() + { + Tracing.TraceMsg("Entering OAuthBaseSignatureTest"); + + Uri uri = new Uri("http://photos.example.net/photos?file=vacation.jpg&size=original"); + + string sig = OAuthBase.GenerateSignatureBase(uri, + "dpf43f3p2l4k3l03", + "nnch734d00sl2jdk", + null, + "GET", + "1191242096", + "kllo9940pd9333jh", + "HMAC-SHA1"); + Assert.AreEqual("GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal", + sig); + + + uri = new Uri("https://www.google.com/calendar/feeds/default/owncalendars/full"); + + sig = OAuthBase.GenerateSignatureBase(uri, + this.oAuthConsumerKey, + "1/ZTmkWjywYI5qJhcuwjHi8Xx9he7Gu7FXuX9OXXpM_Ac", + "pHqmVqazj2mdG9EVyW1OzVix", + "GET", + "1274286639", + "bdcc500c4dbdb2fd8d6bf3e3346007c7", + "HMAC-SHA1"); + + Assert.AreEqual("GET&https%3A%2F%2Fwww.google.com%2Fcalendar%2Ffeeds%2Fdefault%2Fowncalendars%2Ffull&oauth_consumer_key%3Dmantek.org%26oauth_nonce%3Dbdcc500c4dbdb2fd8d6bf3e3346007c7%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1274286639%26oauth_token%3D1%252FZTmkWjywYI5qJhcuwjHi8Xx9he7Gu7FXuX9OXXpM_Ac%26oauth_version%3D1.0", + sig); + + + uri = new Uri("http://example.com/request?b5=%3D%253D&a3=a&c%40=&a2=r%20b&c2&a3=2+q"); + sig = OAuthBase.GenerateSignatureBase(uri, + "9djdj82h48djs9d2", + "kkk9d7dh3k39sjv7", + null, + "GET", + "137131201", + "7d8f3e4a", + "HMAC-SHA1"); + + Assert.AreEqual("GET&http%3A%2F%2Fexample.com%2Frequest&a2%3Dr%2520b%26a3%3D2%2520q%26a3%3Da%26b5%3D%253D%25253D%26c%2540%3D%26c2%3D%26oauth_consumer_key%3D9djdj82h48djs9d2%26oauth_nonce%3D7d8f3e4a%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D137131201%26oauth_token%3Dkkk9d7dh3k39sjv7%26oauth_version%3D1.0", sig); + + + + } + ///////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////// + /// Verifies the signature generation + ////////////////////////////////////////////////////////////////////// + [Test] + public void OAuthBaseGenerateOAuthSignatureTest() + { + Tracing.TraceMsg("Entering OAuthBaseGenerateOAuthSignatureTest"); + + string sig; + + sig = OAuthBase.GenerateOAuthSignatureEncoded("djr9rjt0jd78jf88", ""); + Assert.AreEqual("djr9rjt0jd78jf88%26", sig); + + sig = OAuthBase.GenerateOAuthSignatureEncoded("djr9rjt0jd78jf88", "jjd99$tj88uiths3"); + Assert.AreEqual("djr9rjt0jd78jf88%26jjd99%2524tj88uiths3", sig); + + + sig = OAuthBase.GenerateOAuthSignatureEncoded("djr9rjt0jd78jf88", "jjd999tj88uiths3"); + Assert.AreEqual("djr9rjt0jd78jf88%26jjd999tj88uiths3", sig); + } + ///////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// + /// Verifies the signed signature generation + ////////////////////////////////////////////////////////////////////// + [Test] + public void OAuthBaseSigningTest() + { + Tracing.TraceMsg("Entering OAuthBaseSignatureTest"); + + + Uri uri = new Uri("http://photos.example.net/photos?file=vacation.jpg&size=original"); + + string sig = OAuthBase.GenerateSignature(uri, + "dpf43f3p2l4k3l03", + "kd94hf93k423kf44", + "nnch734d00sl2jdk", + "pfkkdhi9sl3r4s00", + "GET", + "1191242096", + "kllo9940pd9333jh", + OAuthBase.SignatureTypes.HMACSHA1); + + Assert.AreEqual("tR3+Ty81lMeYAr/Fid0kMTYa/WM=", + sig); + + + uri = new Uri("https://www.google.com/calendar/feeds/default/owncalendars/full"); + + sig = OAuthBase.GenerateSignatureBase(uri, + this.oAuthConsumerKey, + "1/NOQv9YTpvvzo8aFC9WpDuRxDl58cSF7JJaDQV1LnXgs", + "MS3p04xWG7MkEyUwk91D1xEU", + "GET", + "1274791118", + "f425726b32231fb9a363957f44e00227", + "HMAC-SHA1"); + + + Assert.AreEqual("GET&https%3A%2F%2Fwww.google.com%2Fcalendar%2Ffeeds%2Fdefault%2Fowncalendars%2Ffull&oauth_consumer_key%3Dmantek.org%26oauth_nonce%3Df425726b32231fb9a363957f44e00227%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1274791118%26oauth_token%3D1%252FNOQv9YTpvvzo8aFC9WpDuRxDl58cSF7JJaDQV1LnXgs%26oauth_version%3D1.0", + sig); + + sig = OAuthBase.GenerateSignature(uri, + this.oAuthConsumerKey, + this.oAuthConsumerSecret, + "1/NOQv9YTpvvzo8aFC9WpDuRxDl58cSF7JJaDQV1LnXgs", + "MS3p04xWG7MkEyUwk91D1xEU", + "GET", + "1274791118", + "f425726b32231fb9a363957f44e00227", + OAuthBase.SignatureTypes.HMACSHA1); + + + Assert.AreEqual("NrqbCmBZ4GePYLeAg6m4WHjvD1w=", sig); + + uri = new Uri("http://www.google.com/calendar/feeds/default/owncalendars/full?xoauth_requestor_id=admin%40mantek.org"); + + sig = OAuthBase.GenerateSignature(uri, + this.oAuthConsumerKey, + this.oAuthConsumerSecret, + null, + null, + "GET", + "1274791118", + "f425726b32231fb9a363957f44e00227", + OAuthBase.SignatureTypes.HMACSHA1); + + Assert.AreEqual("f4mWCiT6IR6Ybq7fq9zc7860xE4=", sig); + + sig = OAuthBase.GenerateSignature(uri, + this.oAuthConsumerKey, + this.oAuthConsumerSecret, + null, + null, + "GET", + "1274809835", + "c198e3abc8bfb1b11ea9a79987e80252", + OAuthBase.SignatureTypes.HMACSHA1); + + Assert.AreEqual("omsn9/am4uIQZdDxmuWzeEap3hE=", sig); + + + } + ///////////////////////////////////////////////////////////////////////////// + + + + ////////////////////////////////////////////////////////////////////// + /// runs an authentication test with 2 legged oauth + ////////////////////////////////////////////////////////////////////// + [Test] + public void OAuth2LeggedAuthenticationTest() + { + Tracing.TraceMsg("Entering OAuth2LeggedAuthenticationTest"); + + CalendarService service = new CalendarService("OAuthTestcode"); + + GOAuthRequestFactory requestFactory = new GOAuthRequestFactory("cl", "OAuthTestcode"); + requestFactory.ConsumerKey = this.oAuthConsumerKey; + requestFactory.ConsumerSecret = this.oAuthConsumerSecret; + service.RequestFactory = requestFactory; + + CalendarEntry calendar = new CalendarEntry(); + calendar.Title.Text = "Test OAuth"; + + OAuthUri postUri = new OAuthUri("http://www.google.com/calendar/feeds/default/owncalendars/full", this.oAuthUser, + this.oAuthDomain); + CalendarEntry createdCalendar = (CalendarEntry)service.Insert(postUri, calendar); + + + } + ///////////////////////////////////////////////////////////////////////////// + + + + + [Test] + public void OAuth2LeggedContactsTest() + { + Tracing.TraceMsg("Entering OAuth2LeggedContactsTest"); + + + RequestSettings rs = new RequestSettings(this.ApplicationName, this.oAuthConsumerKey, this.oAuthConsumerSecret, + this.oAuthUser, this.oAuthDomain); + + ContactsRequest cr = new ContactsRequest(rs); + + Feed f = cr.GetContacts(); + + // modify one + foreach (Contact c in f.Entries) + { + c.Title = "new title"; + cr.Update(c); + break; + } + + + Contact entry = new Contact(); + entry.AtomEntry = ObjectModelHelper.CreateContactEntry(1); + entry.PrimaryEmail.Address = "joe@doe.com"; + Contact e = cr.Insert(f, entry); + + + cr.Delete(e); + + } + ///////////////////////////////////////////////////////////////////////////// + + [Test] + public void OAuth2LeggedDocumentsTest() + { + Tracing.TraceMsg("Entering OAuth2LeggedDocumentsTest"); + + + RequestSettings rs = new RequestSettings(this.ApplicationName, this.oAuthConsumerKey, this.oAuthConsumerSecret, + this.oAuthUser, this.oAuthDomain); + + DocumentsRequest dr = new DocumentsRequest(rs); + + Feed f = dr.GetDocuments(); + + // modify one + foreach (Document d in f.Entries) + { + string s = d.AtomEntry.EditUri.ToString(); + d.AtomEntry.EditUri = new AtomUri(s.Replace("@", "%40")); + + dr.Update(d); + AclQuery q = new AclQuery(); + q.Uri = d.AccessControlList; + Feed facl = dr.Get(q); + + foreach (Google.AccessControl.Acl a in facl.Entries) + { + s = a.AclEntry.EditUri.ToString(); + a.AclEntry.EditUri = new AtomUri(s.Replace("@", "%40")); + dr.Update(a); + } + } + } + ///////////////////////////////////////////////////////////////////////////// + + + ////////////////////////////////////////////////////////////////////// + /// runs an authentication test using OAUTH, inserts lot's of new contacts + /// and deletes them again + ////////////////////////////////////////////////////////////////////// + [Test] + public void OAuth2LeggedModelContactsBatchInsertTest() + { + const int numberOfInserts = 37; + Tracing.TraceMsg("Entering OAuth2LeggedModelContactsBatchInsertTest"); + + + RequestSettings rs = new RequestSettings(this.ApplicationName, this.oAuthConsumerKey, this.oAuthConsumerSecret, + this.oAuthUser, this.oAuthDomain); + + ContactsTestSuite.DeleteAllContacts(rs); + + rs.AutoPaging = true; + + ContactsRequest cr = new ContactsRequest(rs); + + Feed f = cr.GetContacts(); + + int originalCount = f.TotalResults; + + PhoneNumber p = null; + List inserted = new List(); + + if (f != null) + { + Assert.IsTrue(f.Entries != null, "the contacts needs entries"); + + for (int i = 0; i < numberOfInserts; i++) + { + Contact entry = new Contact(); + entry.AtomEntry = ObjectModelHelper.CreateContactEntry(i); + entry.PrimaryEmail.Address = "joe" + i.ToString() + "@doe.com"; + p = entry.PrimaryPhonenumber; + inserted.Add(cr.Insert(f, entry)); + } + } + + + List list = new List(); + + f = cr.GetContacts(); + foreach (Contact e in f.Entries) + { + list.Add(e); + } + + if (inserted.Count > 0) + { + int iVer = numberOfInserts; + // let's find those guys + for (int i = 0; i < inserted.Count; i++) + { + Contact test = inserted[i]; + foreach (Contact e in list) + { + if (e.Id == test.Id) + { + iVer--; + // verify we got the phonenumber back.... + Assert.IsTrue(e.PrimaryPhonenumber != null, "They should have a primary phonenumber"); + Assert.AreEqual(e.PrimaryPhonenumber.Value, p.Value, "They should be identical"); + } + } + } + + Assert.IsTrue(iVer == 0, "The new entries should all be part of the feed now, " + iVer + " left over"); + } + + // now delete them again + ContactsTestSuite.DeleteList(inserted, cr, new Uri(f.AtomFeed.Batch)); + + // now make sure they are gone + if (inserted.Count > 0) + { + f = cr.GetContacts(); + Assert.IsTrue(f.TotalResults == originalCount, "The count should be correct as well"); + foreach (Contact e in f.Entries) + { + // let's find those guys, we should not find ANY + for (int i = 0; i < inserted.Count; i++) + { + Contact test = inserted[i] as Contact; + Assert.IsTrue(e.Id != test.Id, "The new entries should all be deleted now"); + } + } + } + } + ///////////////////////////////////////////////////////////////////////////// + + + + ////////////////////////////////////////////////////////////////////// + /// runs an authentication test with 2 legged oauth + ////////////////////////////////////////////////////////////////////// + [Test] + public void OAuth3LeggedAuthenticationTest() + { + Tracing.TraceMsg("Entering OAuth3LeggedAuthenticationTest"); + + CalendarService service = new CalendarService("OAuthTestcode"); + + GOAuthRequestFactory requestFactory = new GOAuthRequestFactory("cl", "OAuthTestcode"); + requestFactory.ConsumerKey = this.oAuthConsumerKey; + requestFactory.ConsumerSecret = this.oAuthConsumerSecret; + requestFactory.Token = this.oAuthToken; + requestFactory.TokenSecret = this.oAuthTokenSecret; + service.RequestFactory = requestFactory; + + CalendarEntry calendar = new CalendarEntry(); + calendar.Title.Text = "Test OAuth"; + + Uri postUri = new Uri("https://www.google.com/calendar/feeds/default/owncalendars/full"); + CalendarEntry createdCalendar = (CalendarEntry)service.Insert(postUri, calendar); + + // delete the guy again + + createdCalendar.Delete(); + + + } + ///////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////// + /// runs an authentication test with 2 legged oauth + ////////////////////////////////////////////////////////////////////// + [Test] + public void OAuth3LeggedModelAuthenticationTest() + { + + Tracing.TraceMsg("Entering OAuth3LeggedModelAuthenticationTest"); + + + RequestSettings rs = new RequestSettings(this.ApplicationName, this.oAuthConsumerKey, this.oAuthConsumerSecret, + this.oAuthToken, this.oAuthTokenSecret, null, null); + + ContactsRequest cr = new ContactsRequest(rs); + + Feed f = cr.GetContacts(); + + // modify one + foreach (Contact c in f.Entries) + { + c.Title = "new title"; + cr.Update(c); + break; + } + + + Contact entry = new Contact(); + entry.AtomEntry = ObjectModelHelper.CreateContactEntry(1); + entry.PrimaryEmail.Address = "joe@doe.com"; + Contact e = cr.Insert(f, entry); + + + cr.Delete(e); + + } + ///////////////////////////////////////////////////////////////////////////// + + + + } +} + + + + + diff -Nru gdata-sharp-1.4.0.2/src/unittests/objectmodelhelper.cs gdata-sharp-1.7.0.1/src/unittests/objectmodelhelper.cs --- gdata-sharp-1.4.0.2/src/unittests/objectmodelhelper.cs 2008-10-15 12:50:39.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/objectmodelhelper.cs 2009-07-02 09:38:26.000000000 +0000 @@ -24,6 +24,7 @@ using Google.GData.Calendar; using Google.GData.Contacts; using Google.GData.Extensions; +using Google.GData.Client.LiveTests; using System.IO; using System.Xml; @@ -227,8 +228,7 @@ p.Label = "some other thing"; entry.Phonenumbers.Add(p); - PostalAddress pa = new PostalAddress("This is the address"); - pa.Primary = true; + StructuredPostalAddress pa = ContactsTestSuite.CreatePostalAddress(); pa.Rel = ContactsRelationships.IsHome; entry.PostalAddresses.Add(pa); diff -Nru gdata-sharp-1.4.0.2/src/unittests/picasa/AlbumAccessorTest.cs gdata-sharp-1.7.0.1/src/unittests/picasa/AlbumAccessorTest.cs --- gdata-sharp-1.4.0.2/src/unittests/picasa/AlbumAccessorTest.cs 2008-09-01 13:09:26.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/picasa/AlbumAccessorTest.cs 2009-08-17 14:57:28.000000000 +0000 @@ -1,6 +1,7 @@ using Google.GData.Photos; using NUnit.Framework; using Google.GData.Client.UnitTests; +using Google.Picasa; @@ -72,8 +73,7 @@ [Test] public void NumPhotosRemainingTest() { - PicasaEntry entry = new AlbumEntry(); - AlbumAccessor target = new AlbumAccessor(entry); + Album target = new Album(); uint expected = 4; // TODO: Initialize to an appropriate value uint actual; target.NumPhotosRemaining = expected; @@ -87,8 +87,7 @@ [Test] public void NumPhotosTest() { - PicasaEntry entry = new AlbumEntry(); - AlbumAccessor target = new AlbumAccessor(entry); + Album target = new Album(); uint expected = 4; // TODO: Initialize to an appropriate value uint actual; target.NumPhotos = expected; @@ -96,20 +95,7 @@ Assert.AreEqual(expected, actual); } - /// - ///A test for Name - /// - [Test] - public void NameTest() - { - PicasaEntry entry = new AlbumEntry(); - AlbumAccessor target = new AlbumAccessor(entry); - string expected = "TestValue"; - string actual; - target.Name = expected; - actual = target.Name; - Assert.AreEqual(expected, actual); - } + /// ///A test for Longitude @@ -117,8 +103,7 @@ [Test] public void LongitudeTest() { - PicasaEntry entry = new AlbumEntry(); - AlbumAccessor target = new AlbumAccessor(entry); + Album target = new Album(); double expected = 0F; // TODO: Initialize to an appropriate value double actual; target.Longitude = expected; @@ -132,8 +117,7 @@ [Test] public void LocationTest() { - PicasaEntry entry = new AlbumEntry(); - AlbumAccessor target = new AlbumAccessor(entry); + Album target = new Album(); string expected = "TestValue"; string actual; target.Location = expected; @@ -147,8 +131,7 @@ [Test] public void LatitudeTest() { - PicasaEntry entry = new AlbumEntry(); - AlbumAccessor target = new AlbumAccessor(entry); + Album target = new Album(); double expected = 0F; // TODO: Initialize to an appropriate value double actual; target.Latitude = expected; @@ -162,8 +145,7 @@ [Test] public void IdTest() { - PicasaEntry entry = new AlbumEntry(); - AlbumAccessor target = new AlbumAccessor(entry); + Album target = new Album(); string expected = "TestValue"; string actual; target.Id = expected; @@ -177,8 +159,7 @@ [Test] public void CommentingEnabledTest() { - PicasaEntry entry = new AlbumEntry(); - AlbumAccessor target = new AlbumAccessor(entry); + Album target = new Album(); bool expected = false; // TODO: Initialize to an appropriate value bool actual; target.CommentingEnabled = expected; @@ -192,8 +173,7 @@ [Test] public void CommentCountTest() { - PicasaEntry entry = new AlbumEntry(); - AlbumAccessor target = new AlbumAccessor(entry); + Album target = new Album(); uint expected = 12; // TODO: Initialize to an appropriate value uint actual; target.CommentCount = expected; @@ -207,8 +187,7 @@ [Test] public void BytesUsedTest() { - PicasaEntry entry = new AlbumEntry(); - AlbumAccessor target = new AlbumAccessor(entry); + Album target = new Album(); uint expected = 12; // TODO: Initialize to an appropriate value uint actual; target.BytesUsed = expected; @@ -222,12 +201,11 @@ [Test] public void AlbumTitleTest() { - PicasaEntry entry = new AlbumEntry(); - AlbumAccessor target = new AlbumAccessor(entry); + Album target = new Album(); string expected = "TestValue"; string actual; - target.AlbumTitle = expected; - actual = target.AlbumTitle; + target.Title = expected; + actual = target.Title; Assert.AreEqual(expected, actual); } @@ -237,12 +215,11 @@ [Test] public void AlbumSummaryTest() { - PicasaEntry entry = new AlbumEntry(); - AlbumAccessor target = new AlbumAccessor(entry); + Album target = new Album(); string expected = "TestValue"; string actual; - target.AlbumSummary = expected; - actual = target.AlbumSummary; + target.Summary = expected; + actual = target.Summary; Assert.AreEqual(expected, actual); } @@ -252,8 +229,7 @@ [Test] public void AlbumAuthorNicknameTest() { - PicasaEntry entry = new AlbumEntry(); - AlbumAccessor target = new AlbumAccessor(entry); + Album target = new Album(); string expected = "TestValue"; string actual; target.AlbumAuthorNickname = expected; @@ -267,12 +243,11 @@ [Test] public void AlbumAuthorTest() { - PicasaEntry entry = new AlbumEntry(); - AlbumAccessor target = new AlbumAccessor(entry); + Album target = new Album(); string expected = "TestValue"; string actual; - target.AlbumAuthor = expected; - actual = target.AlbumAuthor; + target.Author = expected; + actual = target.Author; Assert.AreEqual(expected, actual); } @@ -282,8 +257,7 @@ [Test] public void AccessTest() { - PicasaEntry entry = new AlbumEntry(); - AlbumAccessor target = new AlbumAccessor(entry); + Album target = new Album(); string expected = "TestValue"; string actual; target.Access = expected; @@ -297,8 +271,7 @@ [Test] public void AlbumAccessorConstructorTest() { - PicasaEntry entry = new AlbumEntry(); - AlbumAccessor target = new AlbumAccessor(entry); + Album target = new Album(); Assert.IsNotNull(target); } } diff -Nru gdata-sharp-1.4.0.2/src/unittests/picasa/CommentAccessorTest.cs gdata-sharp-1.7.0.1/src/unittests/picasa/CommentAccessorTest.cs --- gdata-sharp-1.4.0.2/src/unittests/picasa/CommentAccessorTest.cs 2008-09-01 13:09:26.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/picasa/CommentAccessorTest.cs 2009-11-24 11:09:57.000000000 +0000 @@ -1,5 +1,6 @@ using Google.GData.Photos; -using NUnit.Framework; +using Google.Picasa; +using NUnit.Framework; using Google.GData.Client.UnitTests; namespace Google.GData.Client.UnitTests.Picasa { @@ -69,8 +70,7 @@ [Test] public void PhotoIdTest() { - PicasaEntry entry = new CommentEntry(); - CommentAccessor target = new CommentAccessor(entry); // TODO: Initialize to an appropriate value + Comment target = new Comment(); string expected = "TestValue"; string actual; target.PhotoId = expected; @@ -84,9 +84,8 @@ [Test] public void IdTest() { - PicasaEntry entry = new CommentEntry(); - CommentAccessor target = new CommentAccessor(entry); - string expected = "TestValue"; + Comment target = new Comment(); + string expected = "http://www.test.com/TestValue"; string actual; target.Id = expected; actual = target.Id; @@ -99,8 +98,7 @@ [Test] public void AlbumIdTest() { - PicasaEntry entry = new CommentEntry(); - CommentAccessor target = new CommentAccessor(entry); + Comment target = new Comment(); string expected = "TestValue"; string actual; target.AlbumId = expected; @@ -114,8 +112,7 @@ [Test] public void CommentAccessorConstructorTest() { - PicasaEntry entry = new CommentEntry(); - CommentAccessor target = new CommentAccessor(entry); + Comment target = new Comment(); Assert.IsNotNull(target); } } diff -Nru gdata-sharp-1.4.0.2/src/unittests/picasa/GPhotoClientTest.cs gdata-sharp-1.7.0.1/src/unittests/picasa/GPhotoClientTest.cs --- gdata-sharp-1.4.0.2/src/unittests/picasa/GPhotoClientTest.cs 2008-09-01 14:23:15.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/picasa/GPhotoClientTest.cs 1970-01-01 00:00:00.000000000 +0000 @@ -1,91 +0,0 @@ -using Google.GData.Photos; -using NUnit.Framework; -using Google.GData.Client.UnitTests; -using System; - - -namespace Google.GData.Client.UnitTests.Picasa -{ - - - /// - ///This is a test class for GPhotoClientTest and is intended - ///to contain all GPhotoClientTest Unit Tests - /// - [TestFixture][Category("Picasa")] - public class GPhotoClientTest - { - - - private TestContext testContextInstance; - - /// - ///Gets or sets the test context which provides - ///information about and functionality for the current test run. - /// - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - #region Additional test attributes - // - //You can use the following additional attributes as you write your tests: - // - //Use ClassInitialize to run code before running the first test in the class - //[ClassInitialize()] - //public static void MyClassInitialize(TestContext testContext) - //{ - //} - // - //Use ClassCleanup to run code after all tests in a class have run - //[ClassCleanup()] - //public static void MyClassCleanup() - //{ - //} - // - //Use TestInitialize to run code before running each test - //[TestInitialize()] - //public void MyTestInitialize() - //{ - //} - // - //Use TestCleanup to run code after each test has run - //[TestCleanup()] - //public void MyTestCleanup() - //{ - //} - // - #endregion - - - /// - ///A test for GPhotoClient Constructor - /// - [Test] - public void GPhotoClientConstructorTest1() - { - GPhotoClient target = new GPhotoClient(); - Assert.IsNotNull(target); - Assert.IsTrue(String.IsNullOrEmpty(target.Value)); - } - - /// - ///A test for GPhotoClient Constructor - /// - [Test] - public void GPhotoClientConstructorTest() - { - string initValue = "TestValue"; - GPhotoClient target = new GPhotoClient(initValue); - Assert.AreEqual(initValue, target.Value); - } - } -} diff -Nru gdata-sharp-1.4.0.2/src/unittests/picasa/GPhotoNameTest.cs gdata-sharp-1.7.0.1/src/unittests/picasa/GPhotoNameTest.cs --- gdata-sharp-1.4.0.2/src/unittests/picasa/GPhotoNameTest.cs 2008-09-01 14:23:15.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/picasa/GPhotoNameTest.cs 1970-01-01 00:00:00.000000000 +0000 @@ -1,91 +0,0 @@ -using Google.GData.Photos; -using NUnit.Framework; -using Google.GData.Client.UnitTests; -using System; - -namespace Google.GData.Client.UnitTests.Picasa -{ - - - /// - ///This is a test class for GPhotoNameTest and is intended - ///to contain all GPhotoNameTest Unit Tests - /// - [TestFixture][Category("Picasa")] - public class GPhotoNameTest - { - - - private TestContext testContextInstance; - - /// - ///Gets or sets the test context which provides - ///information about and functionality for the current test run. - /// - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - #region Additional test attributes - // - //You can use the following additional attributes as you write your tests: - // - //Use ClassInitialize to run code before running the first test in the class - //[ClassInitialize()] - //public static void MyClassInitialize(TestContext testContext) - //{ - //} - // - //Use ClassCleanup to run code after all tests in a class have run - //[ClassCleanup()] - //public static void MyClassCleanup() - //{ - //} - // - //Use TestInitialize to run code before running each test - //[TestInitialize()] - //public void MyTestInitialize() - //{ - //} - // - //Use TestCleanup to run code after each test has run - //[TestCleanup()] - //public void MyTestCleanup() - //{ - //} - // - #endregion - - - /// - ///A test for GPhotoName Constructor - /// - [Test] - public void GPhotoNameConstructorTest1() - { - GPhotoName target = new GPhotoName(); - Assert.IsNotNull(target); - Assert.IsTrue(String.IsNullOrEmpty(target.Value)); - } - - /// - ///A test for GPhotoName Constructor - /// - [Test] - public void GPhotoNameConstructorTest() - { - string initValue = "TestValue"; - GPhotoName target = new GPhotoName(initValue); - Assert.AreEqual(initValue, target.Value); - - } - } -} diff -Nru gdata-sharp-1.4.0.2/src/unittests/picasa/GPhotoPositionTest.cs gdata-sharp-1.7.0.1/src/unittests/picasa/GPhotoPositionTest.cs --- gdata-sharp-1.4.0.2/src/unittests/picasa/GPhotoPositionTest.cs 2008-09-01 14:23:15.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/picasa/GPhotoPositionTest.cs 1970-01-01 00:00:00.000000000 +0000 @@ -1,91 +0,0 @@ -using Google.GData.Photos; -using NUnit.Framework; -using Google.GData.Client.UnitTests; -using System; - -namespace Google.GData.Client.UnitTests.Picasa -{ - - - /// - ///This is a test class for GPhotoPositionTest and is intended - ///to contain all GPhotoPositionTest Unit Tests - /// - [TestFixture][Category("Picasa")] - public class GPhotoPositionTest - { - - - private TestContext testContextInstance; - - /// - ///Gets or sets the test context which provides - ///information about and functionality for the current test run. - /// - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - #region Additional test attributes - // - //You can use the following additional attributes as you write your tests: - // - //Use ClassInitialize to run code before running the first test in the class - //[ClassInitialize()] - //public static void MyClassInitialize(TestContext testContext) - //{ - //} - // - //Use ClassCleanup to run code after all tests in a class have run - //[ClassCleanup()] - //public static void MyClassCleanup() - //{ - //} - // - //Use TestInitialize to run code before running each test - //[TestInitialize()] - //public void MyTestInitialize() - //{ - //} - // - //Use TestCleanup to run code after each test has run - //[TestCleanup()] - //public void MyTestCleanup() - //{ - //} - // - #endregion - - - /// - ///A test for GPhotoPosition Constructor - /// - [Test] - public void GPhotoPositionConstructorTest1() - { - GPhotoPosition target = new GPhotoPosition(); - Assert.IsNotNull(target); - Assert.IsTrue(String.IsNullOrEmpty(target.Value)); - } - - /// - ///A test for GPhotoPosition Constructor - /// - [Test] - public void GPhotoPositionConstructorTest() - { - string initValue = "TestValue"; - GPhotoPosition target = new GPhotoPosition(initValue); - Assert.AreEqual(initValue, target.Value); - - } - } -} diff -Nru gdata-sharp-1.4.0.2/src/unittests/picasa/GPhotoVersionTest.cs gdata-sharp-1.7.0.1/src/unittests/picasa/GPhotoVersionTest.cs --- gdata-sharp-1.4.0.2/src/unittests/picasa/GPhotoVersionTest.cs 2008-09-01 14:23:15.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/picasa/GPhotoVersionTest.cs 1970-01-01 00:00:00.000000000 +0000 @@ -1,91 +0,0 @@ -using Google.GData.Photos; -using NUnit.Framework; -using Google.GData.Client.UnitTests; -using System; - -namespace Google.GData.Client.UnitTests.Picasa -{ - - - /// - ///This is a test class for GPhotoVersionTest and is intended - ///to contain all GPhotoVersionTest Unit Tests - /// - [TestFixture][Category("Picasa")] - public class GPhotoVersionTest - { - - - private TestContext testContextInstance; - - /// - ///Gets or sets the test context which provides - ///information about and functionality for the current test run. - /// - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - #region Additional test attributes - // - //You can use the following additional attributes as you write your tests: - // - //Use ClassInitialize to run code before running the first test in the class - //[ClassInitialize()] - //public static void MyClassInitialize(TestContext testContext) - //{ - //} - // - //Use ClassCleanup to run code after all tests in a class have run - //[ClassCleanup()] - //public static void MyClassCleanup() - //{ - //} - // - //Use TestInitialize to run code before running each test - //[TestInitialize()] - //public void MyTestInitialize() - //{ - //} - // - //Use TestCleanup to run code after each test has run - //[TestCleanup()] - //public void MyTestCleanup() - //{ - //} - // - #endregion - - - /// - ///A test for GPhotoVersion Constructor - /// - [Test] - public void GPhotoVersionConstructorTest1() - { - GPhotoVersion target = new GPhotoVersion(); - Assert.IsNotNull(target); - Assert.IsTrue(String.IsNullOrEmpty(target.Value)); - } - - /// - ///A test for GPhotoVersion Constructor - /// - [Test] - public void GPhotoVersionConstructorTest() - { - string initValue = "TestValue"; - GPhotoVersion target = new GPhotoVersion(initValue); - Assert.AreEqual(initValue, target.Value); - - } - } -} diff -Nru gdata-sharp-1.4.0.2/src/unittests/picasa/PhotoAccessorTest.cs gdata-sharp-1.7.0.1/src/unittests/picasa/PhotoAccessorTest.cs --- gdata-sharp-1.4.0.2/src/unittests/picasa/PhotoAccessorTest.cs 2008-09-01 13:09:26.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/picasa/PhotoAccessorTest.cs 2009-11-24 11:09:57.000000000 +0000 @@ -1,6 +1,8 @@ using Google.GData.Photos; -using NUnit.Framework; +using NUnit.Framework; using Google.GData.Client.UnitTests; +using Google.Picasa; + namespace Google.GData.Client.UnitTests.Picasa { @@ -69,8 +71,7 @@ [Test] public void WidthTest() { - PicasaEntry entry = new PhotoEntry(); - PhotoAccessor target = new PhotoAccessor(entry); + Photo target = new Photo(); int expected = 5; // TODO: Initialize to an appropriate value int actual; target.Width = expected; @@ -78,20 +79,7 @@ Assert.AreEqual(expected, actual); } - /// - ///A test for Version - /// - [Test] - public void VersionTest() - { - PicasaEntry entry = new PhotoEntry(); - PhotoAccessor target = new PhotoAccessor(entry); - string expected = "TestValue"; - string actual; - target.Version = expected; - actual = target.Version; - Assert.AreEqual(expected, actual); - } + /// ///A test for Timestamp @@ -99,8 +87,7 @@ [Test] public void TimestampTest() { - PicasaEntry entry = new PhotoEntry(); - PhotoAccessor target = new PhotoAccessor(entry); + Photo target = new Photo(); ulong expected = 122; // TODO: Initialize to an appropriate value ulong actual; target.Timestamp = expected; @@ -114,8 +101,7 @@ [Test] public void SizeTest() { - PicasaEntry entry = new PhotoEntry(); - PhotoAccessor target = new PhotoAccessor(entry); + Photo target = new Photo(); long expected = 12; // TODO: Initialize to an appropriate value long actual; target.Size = expected; @@ -129,8 +115,7 @@ [Test] public void RotationTest() { - PicasaEntry entry = new PhotoEntry(); - PhotoAccessor target = new PhotoAccessor(entry); + Photo target = new Photo(); int expected = 45; // TODO: Initialize to an appropriate value int actual; target.Rotation = expected; @@ -138,20 +123,7 @@ Assert.AreEqual(expected, actual); } - /// - ///A test for Position - /// - [Test] - public void PositionTest() - { - PicasaEntry entry = new PhotoEntry(); - PhotoAccessor target = new PhotoAccessor(entry); - double expected = 0.5F; // TODO: Initialize to an appropriate value - double actual; - target.Position = expected; - actual = target.Position; - Assert.AreEqual(expected, actual); - } + /// ///A test for PhotoTitle @@ -159,12 +131,11 @@ [Test] public void PhotoTitleTest() { - PicasaEntry entry = new PhotoEntry(); - PhotoAccessor target = new PhotoAccessor(entry); + Photo target = new Photo(); string expected = "TestValue"; string actual; - target.PhotoTitle = expected; - actual = target.PhotoTitle; + target.Title = expected; + actual = target.Title; Assert.AreEqual(expected, actual); } @@ -174,12 +145,11 @@ [Test] public void PhotoSummaryTest() { - PicasaEntry entry = new PhotoEntry(); - PhotoAccessor target = new PhotoAccessor(entry); + Photo target = new Photo(); string expected = "TestValue"; string actual; - target.PhotoSummary = expected; - actual = target.PhotoSummary; + target.Summary = expected; + actual = target.Summary; Assert.AreEqual(expected, actual); } @@ -189,8 +159,7 @@ [Test] public void LongitudeTest() { - PicasaEntry entry = new PhotoEntry(); - PhotoAccessor target = new PhotoAccessor(entry); + Photo target = new Photo(); double expected = 12.5F; // TODO: Initialize to an appropriate value double actual; target.Longitude = expected; @@ -204,8 +173,7 @@ [Test] public void LatitudeTest() { - PicasaEntry entry = new PhotoEntry(); - PhotoAccessor target = new PhotoAccessor(entry); + Photo target = new Photo(); double expected = 12.5F; // TODO: Initialize to an appropriate value double actual; target.Latitude = expected; @@ -219,8 +187,7 @@ [Test] public void IdTest() { - PicasaEntry entry = new PhotoEntry(); - PhotoAccessor target = new PhotoAccessor(entry); + Photo target = new Photo(); string expected = "TestValue"; string actual; target.Id = expected; @@ -234,8 +201,7 @@ [Test] public void HeightTest() { - PicasaEntry entry = new PhotoEntry(); - PhotoAccessor target = new PhotoAccessor(entry); + Photo target = new Photo(); int expected = 12; // TODO: Initialize to an appropriate value int actual; target.Height = expected; @@ -249,8 +215,7 @@ [Test] public void CommentingEnabledTest() { - PicasaEntry entry = new PhotoEntry(); - PhotoAccessor target = new PhotoAccessor(entry); + Photo target = new Photo(); bool expected = true; bool actual; target.CommentingEnabled = expected; @@ -264,8 +229,7 @@ [Test] public void CommentCountTest() { - PicasaEntry entry = new PhotoEntry(); - PhotoAccessor target = new PhotoAccessor(entry); + Photo target = new Photo(); uint expected = 12; // TODO: Initialize to an appropriate value uint actual; target.CommentCount = expected; @@ -273,20 +237,7 @@ Assert.AreEqual(expected, actual); } - /// - ///A test for Client - /// - [Test] - public void ClientTest() - { - PicasaEntry entry = new PhotoEntry(); - PhotoAccessor target = new PhotoAccessor(entry); - string expected = "TestValue"; - string actual; - target.Client = expected; - actual = target.Client; - Assert.AreEqual(expected, actual); - } + /// ///A test for Checksum @@ -294,9 +245,7 @@ [Test] public void ChecksumTest() { - PicasaEntry entry = new PhotoEntry(); - PhotoAccessor target = new PhotoAccessor(entry); - + Photo target = new Photo(); string expected = "TestValue"; string actual; target.Checksum = expected; @@ -310,8 +259,7 @@ [Test] public void AlbumIdTest() { - PicasaEntry entry = new PhotoEntry(); - PhotoAccessor target = new PhotoAccessor(entry); + Photo target = new Photo(); string expected = "TestValue"; string actual; target.AlbumId = expected; diff -Nru gdata-sharp-1.4.0.2/src/unittests/resources/contactsextendedprop.xml gdata-sharp-1.7.0.1/src/unittests/resources/contactsextendedprop.xml --- gdata-sharp-1.4.0.2/src/unittests/resources/contactsextendedprop.xml 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/resources/contactsextendedprop.xml 2010-03-24 11:01:14.000000000 +0000 @@ -0,0 +1,18 @@ + + + + COMPANY_NAME_HERE + + + + CONTACT_EMAIL_ADDRESS_HERE + CONTACTG_ACCOUNTNAME(CONTACT_EMAIL_ADDRESS_HERE) + CONTACT_EMAIL_ADDRESS_HERE + SMTP + 32791 + LAST_NAME FIRST_NAME + + + this is the value + + diff -Nru gdata-sharp-1.4.0.2/src/unittests/resources/unittests.dll.config gdata-sharp-1.7.0.1/src/unittests/resources/unittests.dll.config --- gdata-sharp-1.4.0.2/src/unittests/resources/unittests.dll.config 2008-12-12 14:46:56.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/resources/unittests.dll.config 2009-12-01 18:36:40.000000000 +0000 @@ -20,18 +20,25 @@ domainAdminPassword="youradminpassword" userName="youaccount" passWord="yourpassword" + accountId="ga:youraccountId" youTubeClientID="yourclientid" youTubeDevKey="yourdevKey" youTubeUser="youtubeuser" youTubePwd="youtubepwd" + analyticsURI="https://www.google.com/analytics/feeds/data" calendarURI="http://www.google.com/calendar/feeds/default/private/full/" ownCalendarsURI="http://www.google.com/calendar/feeds/default/owncalendars/full/" bloggerURI="http://beta.blogger.com/feeds//posts/full" gBaseURI="http://base.google.com/base/feeds/items" gBaseKey="your app key" compositeURI="http://www.google.com/calendar/feeds/default/private/composite/" + OAUTHCONSUMERKEY="key" + OAUTHCONSUMERSECRET="secret" + OAUTHDOMAIN="domain" + OAUTHUSER="user" + iteration="3" requestlogging="true"/> diff -Nru gdata-sharp-1.4.0.2/src/unittests/unittests.csproj gdata-sharp-1.7.0.1/src/unittests/unittests.csproj --- gdata-sharp-1.4.0.2/src/unittests/unittests.csproj 2009-02-26 11:44:40.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/unittests.csproj 2010-04-20 15:18:39.000000000 +0000 @@ -1,7 +1,6 @@ - + Local - 8.0.50727 2.0 {22D56E6B-DF29-4675-A655-B33252B7FA4B} Debug @@ -26,6 +25,7 @@ + 2.0 bin\Debug\ @@ -102,14 +102,27 @@ + + + {A7BA16A4-7636-46CA-AAAD-3CB3361ECD40} + Analytics + {B6F6D938-0D45-42BA-8A67-55D92EF03995} Core Client + + {4E97E7C2-D30C-48ED-9C3D-FFA2127099AA} + Documents3 + + + {321BC361-7817-4471-8E7D-8B9D09EC3B48} + WebmasterTools + {2C497F73-7C10-4DC6-A680-CAA9DF442E91} YouTube @@ -142,10 +155,6 @@ {66B2AD47-7DD2-43E5-9124-D53486609992} Contacts - - {1C00DDC8-021D-4F60-9EE9-314431586936} - Documents - {21BCB644-F9C3-4ADC-8BE1-4E55C6565011} Common Data Extensions @@ -160,12 +169,23 @@ + + + + + + + + + + + @@ -273,7 +293,6 @@ - @@ -281,12 +300,10 @@ - - @@ -294,7 +311,6 @@ - @@ -317,6 +333,11 @@ + + + + + @@ -351,7 +372,6 @@ - diff -Nru gdata-sharp-1.4.0.2/src/unittests/webmastertools/WebmasterToolsDeleteTests.cs gdata-sharp-1.7.0.1/src/unittests/webmastertools/WebmasterToolsDeleteTests.cs --- gdata-sharp-1.4.0.2/src/unittests/webmastertools/WebmasterToolsDeleteTests.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/webmastertools/WebmasterToolsDeleteTests.cs 2010-12-06 13:36:40.000000000 +0000 @@ -0,0 +1,87 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +/* + * Created by Morten Christensen, http://blog.sitereactor.dk | http://twitter.com/sitereactor + */ + +using System; +using Google.GData.Client; +using Google.GData.Client.LiveTests; +using Google.GData.Client.UnitTests; +using Google.GData.WebmasterTools; +using NUnit.Framework; + +namespace unittests.webmastertools +{ + public class WebmasterToolsDeleteTests : BaseLiveTestClass + { + private Google.GData.Client.UnitTests.TestContext TestContext1; + + protected override void ReadConfigFile() + { + base.ReadConfigFile(); + + if (unitTestConfiguration.Contains("userName") == true) + { + this.userName = (string)unitTestConfiguration["userName"]; + Tracing.TraceInfo("Read userName value: " + this.userName); + } + if (unitTestConfiguration.Contains("passWord") == true) + { + this.passWord = (string)unitTestConfiguration["passWord"]; + Tracing.TraceInfo("Read passWord value: " + this.passWord); + } + } + + /// + ///Gets or sets the test context which provides + ///information about and functionality for the current test run. + /// + public Google.GData.Client.UnitTests.TestContext TestContext + { + get { return TestContext1; } + set { TestContext1 = value; } + } + + [Test] + public void DeleteSite() + { + WebmasterToolsService service = new WebmasterToolsService(this.ApplicationName); + service.Credentials = new GDataCredentials(this.userName, this.passWord); + + SitesQuery feedQuery = new SitesQuery(); + SitesFeed beforeFeed = service.Query(feedQuery); + + int before = beforeFeed.Entries.Count; + + Uri deleteUrl = SitesQuery.CreateCustomUri("http://www.example.com"); + service.Delete(deleteUrl); + + SitesFeed afterFeed = service.Query(feedQuery); + int after = afterFeed.Entries.Count; + + Assert.Greater(before, after); + } + + [Test] + public void DeleteSitemap() + {} + + [Test] + public void DeleteMessage() + { } + } +} diff -Nru gdata-sharp-1.4.0.2/src/unittests/webmastertools/WebmasterToolsInsertTests.cs gdata-sharp-1.7.0.1/src/unittests/webmastertools/WebmasterToolsInsertTests.cs --- gdata-sharp-1.4.0.2/src/unittests/webmastertools/WebmasterToolsInsertTests.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/webmastertools/WebmasterToolsInsertTests.cs 2010-12-06 13:36:40.000000000 +0000 @@ -0,0 +1,102 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +/* + * Created by Morten Christensen, http://blog.sitereactor.dk | http://twitter.com/sitereactor + */ + +using System; +using Google.GData.Client; +using Google.GData.Client.LiveTests; +using Google.GData.Client.UnitTests; +using Google.GData.WebmasterTools; +using Google.WebmasterTools; +using NUnit.Framework; + +namespace unittests.webmastertools +{ + public class WebmasterToolsInsertTests : BaseLiveTestClass + { + private Google.GData.Client.UnitTests.TestContext TestContext1; + + protected override void ReadConfigFile() + { + base.ReadConfigFile(); + + if (unitTestConfiguration.Contains("userName") == true) + { + this.userName = (string)unitTestConfiguration["userName"]; + Tracing.TraceInfo("Read userName value: " + this.userName); + } + if (unitTestConfiguration.Contains("passWord") == true) + { + this.passWord = (string)unitTestConfiguration["passWord"]; + Tracing.TraceInfo("Read passWord value: " + this.passWord); + } + } + + /// + ///Gets or sets the test context which provides + ///information about and functionality for the current test run. + /// + public Google.GData.Client.UnitTests.TestContext TestContext + { + get { return TestContext1; } + set { TestContext1 = value; } + } + + [Test] + public void InsertSite() + { + WebmasterToolsService service = new WebmasterToolsService(this.ApplicationName); + service.Credentials = new GDataCredentials(this.userName, this.passWord); + + SitesQuery feedQuery = new SitesQuery(); + SitesFeed beforeFeed = service.Query(feedQuery); + + int before = beforeFeed.Entries.Count; + + SitesEntry entry = new SitesEntry(); + string siteUrl = "http://www.example.com/"; + entry.Content.Src = siteUrl; + entry.Content.Type = "text/plain"; + service.Insert(new Uri(SitesQuery.HttpsFeedUrl), entry); + + SitesFeed afterFeed = service.Query(feedQuery); + int after = afterFeed.Entries.Count; + + Assert.Greater(after, before); + } + + [Test] + public void AddSite() + { + RequestSettings settings = new RequestSettings("NETUnittests", this.userName, this.passWord); + WebmasterToolsRequest f = new WebmasterToolsRequest(settings); + + Sites site = new Sites(); + site.AtomEntry = new AtomEntry(); + site.AtomEntry.Content.Src = "http://www.example-five.com/"; + site.AtomEntry.Content.Type = "text/plain"; + Sites newSite = f.AddSite(site); + + Assert.IsNotNull(newSite); + } + + [Test] + public void SubmitSitemap() + {} + } +} diff -Nru gdata-sharp-1.4.0.2/src/unittests/webmastertools/WebmasterToolsRequestTests.cs gdata-sharp-1.7.0.1/src/unittests/webmastertools/WebmasterToolsRequestTests.cs --- gdata-sharp-1.4.0.2/src/unittests/webmastertools/WebmasterToolsRequestTests.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/webmastertools/WebmasterToolsRequestTests.cs 2010-12-06 13:36:40.000000000 +0000 @@ -0,0 +1,134 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +/* + * Created by Morten Christensen, http://blog.sitereactor.dk | http://twitter.com/sitereactor + */ + +using Google.GData.Client; +using Google.GData.Client.LiveTests; +using Google.GData.Client.UnitTests; +using Google.WebmasterTools; +using NUnit.Framework; + +namespace unittests.webmastertools +{ + [TestFixture] + public class WebmasterToolsRequestTests : BaseLiveTestClass + { + private Google.GData.Client.UnitTests.TestContext TestContext1; + + protected override void ReadConfigFile() + { + base.ReadConfigFile(); + + if (unitTestConfiguration.Contains("userName") == true) + { + this.userName = (string)unitTestConfiguration["userName"]; + Tracing.TraceInfo("Read userName value: " + this.userName); + } + if (unitTestConfiguration.Contains("passWord") == true) + { + this.passWord = (string)unitTestConfiguration["passWord"]; + Tracing.TraceInfo("Read passWord value: " + this.passWord); + } + } + + /// + ///Gets or sets the test context which provides + ///information about and functionality for the current test run. + /// + public Google.GData.Client.UnitTests.TestContext TestContext + { + get { return TestContext1; } + set { TestContext1 = value; } + } + + [Test] + public void TestWebmasterToolsCrawlIssuesRequest() + { + Tracing.TraceMsg("Entering Webmaster Tools Crawl Issues RequestTest"); + + RequestSettings settings = new RequestSettings("NETUnittests", this.userName, this.passWord); + WebmasterToolsRequest f = new WebmasterToolsRequest(settings); + + Feed crawlIssues = f.GetCrawlIssues("http%3A%2F%2Fwww%2Eexample%2Ecom%2F"); + foreach (CrawlIssues crawlIssue in crawlIssues.Entries) + { + Assert.IsTrue(crawlIssue.AtomEntry != null, "There should be an atomentry"); + } + } + + [Test] + public void TestWebmasterToolsKeywordsRequest() + { + Tracing.TraceMsg("Entering Webmaster Tools Keywords RequestTest"); + + RequestSettings settings = new RequestSettings("NETUnittests", this.userName, this.passWord); + WebmasterToolsRequest f = new WebmasterToolsRequest(settings); + + Feed keywords = f.GetKeywords("http%3A%2F%2Fwww%2Eexample%2Ecom%2F"); + foreach (Keywords keyword in keywords.Entries) + { + Assert.IsTrue(keyword.AtomEntry != null, "There should be an atomentry"); + } + } + + [Test] + public void TestWebmasterToolsMessagesRequest() + { + Tracing.TraceMsg("Entering Webmaster Tools Keywords RequestTest"); + + RequestSettings settings = new RequestSettings("NETUnittests", this.userName, this.passWord); + WebmasterToolsRequest f = new WebmasterToolsRequest(settings); + + Feed messages = f.GetMessages(); + foreach (Messages message in messages.Entries) + { + Assert.IsTrue(message.AtomEntry != null, "There should be an atomentry"); + } + } + + [Test] + public void TestWebmasterToolsSitemapsRequest() + { + Tracing.TraceMsg("Entering Webmaster Tools Sitemap RequestTest"); + + RequestSettings settings = new RequestSettings("NETUnittests", this.userName, this.passWord); + WebmasterToolsRequest f = new WebmasterToolsRequest(settings); + + Feed sitemaps = f.GetSitemaps("http%3A%2F%2Fwww%2Eexample%2Ecom%2F"); + foreach (Sitemap sitemap in sitemaps.Entries) + { + Assert.IsTrue(sitemap.AtomEntry != null, "There should be an atomentry"); + } + } + + [Test] + public void TestWebmasterToolsSitesRequest() + { + Tracing.TraceMsg("Entering Webmaster Tools Sites RequestTest"); + + RequestSettings settings = new RequestSettings("NETUnittests", this.userName, this.passWord); + WebmasterToolsRequest f = new WebmasterToolsRequest(settings); + + Feed sites = f.GetSites(); + foreach (Sites site in sites.Entries) + { + Assert.IsTrue(site.AtomEntry != null, "There should be an atomentry"); + } + } + } +} diff -Nru gdata-sharp-1.4.0.2/src/unittests/webmastertools/WebmasterToolsServiceTest.cs gdata-sharp-1.7.0.1/src/unittests/webmastertools/WebmasterToolsServiceTest.cs --- gdata-sharp-1.4.0.2/src/unittests/webmastertools/WebmasterToolsServiceTest.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/webmastertools/WebmasterToolsServiceTest.cs 2010-12-06 13:36:40.000000000 +0000 @@ -0,0 +1,164 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +/* + * Created by Morten Christensen, http://blog.sitereactor.dk | http://twitter.com/sitereactor + */ + +using Google.GData.Client; +using Google.GData.Client.LiveTests; +using Google.GData.Client.UnitTests; +using Google.GData.WebmasterTools; +using NUnit.Framework; + +namespace unittests.webmastertools +{ + [TestFixture] + public class WebmasterToolsServiceTest : BaseLiveTestClass + { + private Google.GData.Client.UnitTests.TestContext TestContext1; + + protected override void ReadConfigFile() + { + base.ReadConfigFile(); + + if (unitTestConfiguration.Contains("userName") == true) + { + this.userName = (string)unitTestConfiguration["userName"]; + Tracing.TraceInfo("Read userName value: " + this.userName); + } + if (unitTestConfiguration.Contains("passWord") == true) + { + this.passWord = (string)unitTestConfiguration["passWord"]; + Tracing.TraceInfo("Read passWord value: " + this.passWord); + } + } + + /// + ///Gets or sets the test context which provides + ///information about and functionality for the current test run. + /// + public Google.GData.Client.UnitTests.TestContext TestContext + { + get { return TestContext1; } + set { TestContext1 = value; } + } + + [Test] + public void QuerySites() + { + WebmasterToolsService service = new WebmasterToolsService(this.ApplicationName); + service.Credentials = new GDataCredentials(this.userName, this.passWord); + + SitesQuery feedQuery = new SitesQuery(); + SitesFeed feed = service.Query(feedQuery); + + Assert.GreaterOrEqual(feed.Entries.Count, 0); + + foreach (SitesEntry entry in feed.Entries) + { + Assert.IsNotNull(entry.Id); + Assert.IsNotNull(entry.Verified); + } + } + + [Test] + public void QuerySitemaps() + { + WebmasterToolsService service = new WebmasterToolsService(this.ApplicationName); + service.Credentials = new GDataCredentials(this.userName, this.passWord); + + SitemapsQuery feedQuery = new SitemapsQuery(SitemapsQuery.CreateCustomUri("http%3A%2F%2Fwww%2Eexample%2Ecom%2F")); + SitemapsFeed feed = service.Query(feedQuery); + + Assert.GreaterOrEqual(feed.Entries.Count, 0); + + foreach (SitemapsEntry entry in feed.Entries) + { + Assert.IsNotNull(entry.Id); + } + } + + [Test] + public void QueryKeywords() + { + WebmasterToolsService service = new WebmasterToolsService(this.ApplicationName); + service.Credentials = new GDataCredentials(this.userName, this.passWord); + + KeywordsQuery feedQuery = new KeywordsQuery(KeywordsQuery.CreateCustomUri("http%3A%2F%2Fwww%2Eexample%2Ecom%2F")); + KeywordsFeed feed = service.Query(feedQuery); + + Assert.GreaterOrEqual(feed.Entries.Count, 0); + + foreach (KeywordsEntry entry in feed.Entries) + { + Assert.IsNotNull(entry.Id); + } + } + + [Test] + public void QueryMessages() + { + WebmasterToolsService service = new WebmasterToolsService(this.ApplicationName); + service.Credentials = new GDataCredentials(this.userName, this.passWord); + + MessagesQuery feedQuery = new MessagesQuery(); + MessagesFeed feed = service.Query(feedQuery); + + Assert.GreaterOrEqual(feed.Entries.Count, 0); + + foreach (MessagesEntry entry in feed.Entries) + { + Assert.IsNotNull(entry.Id); + } + } + + [Test] + public void QueryCrawlIssues() + { + WebmasterToolsService service = new WebmasterToolsService(this.ApplicationName); + service.Credentials = new GDataCredentials(this.userName, this.passWord); + + string slug = + Utilities.EncodeSlugHeader( + "https://www.google.com/webmasters/tools/feeds/http%3A%2F%2Fwww%2Eexample%2Ecom%2F/crawlissues/"); + CrawlIssuesQuery feedQuery = new CrawlIssuesQuery(slug); + CrawlIssuesFeed feed = service.Query(feedQuery); + + Assert.GreaterOrEqual(feed.Entries.Count, 0); + + foreach (CrawlIssuesEntry entry in feed.Entries) + { + Assert.IsNotNull(entry.Id); + } + } + + [Test] + public void BasicQuery() + { + WebmasterToolsService service = new WebmasterToolsService(this.ApplicationName); + service.Credentials = new GDataCredentials(this.userName, this.passWord); + + string slug = + Utilities.EncodeSlugHeader( + "https://www.google.com/webmasters/tools/feeds/http%3A%2F%2Fwww%2Eexample%2Ecom%2F/crawlissues/"); + FeedQuery query = new FeedQuery(slug); + AtomFeed feed = service.Query(query); + + Assert.IsNotNull(feed); + } + + } +} diff -Nru gdata-sharp-1.4.0.2/src/unittests/webmastertools/WebmasterToolsUpdateTests.cs gdata-sharp-1.7.0.1/src/unittests/webmastertools/WebmasterToolsUpdateTests.cs --- gdata-sharp-1.4.0.2/src/unittests/webmastertools/WebmasterToolsUpdateTests.cs 1970-01-01 00:00:00.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/webmastertools/WebmasterToolsUpdateTests.cs 2010-12-06 13:36:40.000000000 +0000 @@ -0,0 +1,122 @@ +/* Copyright (c) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +/* + * Created by Morten Christensen, http://blog.sitereactor.dk | http://twitter.com/sitereactor + */ + +using System; +using Google.GData.Client; +using Google.GData.Client.LiveTests; +using Google.GData.Client.UnitTests; +using Google.GData.WebmasterTools; +using Google.WebmasterTools; +using NUnit.Framework; + +namespace unittests.webmastertools +{ + public class WebmasterToolsUpdateTests : BaseLiveTestClass + { + private Google.GData.Client.UnitTests.TestContext TestContext1; + + protected override void ReadConfigFile() + { + base.ReadConfigFile(); + + if (unitTestConfiguration.Contains("userName") == true) + { + this.userName = (string)unitTestConfiguration["userName"]; + Tracing.TraceInfo("Read userName value: " + this.userName); + } + if (unitTestConfiguration.Contains("passWord") == true) + { + this.passWord = (string)unitTestConfiguration["passWord"]; + Tracing.TraceInfo("Read passWord value: " + this.passWord); + } + } + + /// + ///Gets or sets the test context which provides + ///information about and functionality for the current test run. + /// + public Google.GData.Client.UnitTests.TestContext TestContext + { + get { return TestContext1; } + set { TestContext1 = value; } + } + + [Test] + public void UpdateGeolocation() + { + WebmasterToolsService service = new WebmasterToolsService(this.ApplicationName); + service.Credentials = new GDataCredentials(this.userName, this.passWord); + + try + { + + SitesQuery q = new SitesQuery(); + SitesFeed sf = service.Query(q); + + SitesEntry entry = new SitesEntry(); + string siteUrl = "http://www.example.dk/"; + entry.Content.Src = siteUrl; + entry.Content.Type = "text/plain"; + SitesEntry newEntry = service.Insert(new Uri(SitesQuery.HttpsFeedUrl), entry); + + newEntry.GeoLocation = "US"; + SitesEntry updatedEntry = newEntry.Update(); + + Assert.IsTrue(updatedEntry != null); + Assert.IsTrue(updatedEntry.GeoLocation == "US"); + } + finally + { + Uri deleteUrl = SitesQuery.CreateCustomUri("http://www.example.dk"); + service.Delete(deleteUrl, null); + } + + } + + [Test] + public void RequestUpdateGeolocation() + { + RequestSettings settings = new RequestSettings("NETUnittests", this.userName, this.passWord); + WebmasterToolsRequest f = new WebmasterToolsRequest(settings); + + try + { + + Sites site = new Sites("http://www.example.com", "text/plain"); + Sites newSite = f.AddSite(site); + + newSite.GeoLocation = "US"; + //Sites updatedSite = f.Update(newSite); + Sites updatedSite = f.UpdateSiteEntry(newSite, "http://www.example.com"); + + Assert.IsNotNull(updatedSite); + } + finally + { + Uri deleteUrl = SitesQuery.CreateCustomUri("http://www.example.com"); + f.Delete(deleteUrl, null); + } + + } + + [Test] + public void MarkReadMessage() + { } + } +} diff -Nru gdata-sharp-1.4.0.2/src/unittests/youtube/MessageEntryTest.cs gdata-sharp-1.7.0.1/src/unittests/youtube/MessageEntryTest.cs --- gdata-sharp-1.4.0.2/src/unittests/youtube/MessageEntryTest.cs 2008-07-02 14:53:12.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/youtube/MessageEntryTest.cs 2009-08-13 15:59:00.000000000 +0000 @@ -74,8 +74,8 @@ MessageEntry target = new MessageEntry(); // TODO: Initialize to an appropriate value string expected = "secret text string"; // TODO: Initialize to an appropriate value string actual; - target.Description = expected; - actual = target.Description; + target.Summary.Text = expected; + actual = target.Summary.Text; Assert.AreEqual(expected, actual); } } diff -Nru gdata-sharp-1.4.0.2/src/unittests/youtube/PlaylistsEntryTest.cs gdata-sharp-1.7.0.1/src/unittests/youtube/PlaylistsEntryTest.cs --- gdata-sharp-1.4.0.2/src/unittests/youtube/PlaylistsEntryTest.cs 2008-07-02 12:37:42.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/youtube/PlaylistsEntryTest.cs 2009-11-24 11:09:57.000000000 +0000 @@ -71,10 +71,10 @@ public void FeedLinkTest() { PlaylistsEntry target = new PlaylistsEntry(); // TODO: Initialize to an appropriate value - FeedLink expected = new FeedLink(); - FeedLink actual; - target.FeedLink = expected; - actual = target.FeedLink; + string expected = "secret text string"; + string actual; + target.Content.Src = new AtomUri(expected); + actual = target.Content.Src.Content; Assert.AreEqual(expected, actual); } @@ -87,8 +87,8 @@ PlaylistsEntry target = new PlaylistsEntry(); // TODO: Initialize to an appropriate value string expected = "secret text string"; // TODO: Initialize to an appropriate value string actual; - target.Description = expected; - actual = target.Description; + target.Summary.Text = expected; + actual = target.Summary.Text; Assert.AreEqual(expected, actual); } @@ -100,8 +100,8 @@ { PlaylistsEntry target = new PlaylistsEntry(); Assert.IsNotNull(target); - Assert.IsNull(target.FeedLink); - Assert.IsNull(target.Description); + Assert.IsNull(target.Content.Src); + Assert.IsNull(target.Summary.Text); } } } diff -Nru gdata-sharp-1.4.0.2/src/unittests/youtube/RacyTest.cs gdata-sharp-1.7.0.1/src/unittests/youtube/RacyTest.cs --- gdata-sharp-1.4.0.2/src/unittests/youtube/RacyTest.cs 2008-07-02 12:37:42.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/youtube/RacyTest.cs 1970-01-01 00:00:00.000000000 +0000 @@ -1,90 +0,0 @@ -using NUnit.Framework; -using Google.GData.Client.UnitTests; -using Google.GData.YouTube; - -namespace Google.GData.Client.UnitTests.YouTube -{ - - - /// - ///This is a test class for RacyTest and is intended - ///to contain all RacyTest Unit Tests - /// - [TestFixture] -[Category("YouTube")] - - public class RacyTest - { - - - private TestContext testContextInstance; - - /// - ///Gets or sets the test context which provides - ///information about and functionality for the current test run. - /// - public TestContext TestContext - { - get - { - return testContextInstance; - } - set - { - testContextInstance = value; - } - } - - #region Additional test attributes - // - //You can use the following additional attributes as you write your tests: - // - //Use ClassInitialize to run code before running the first test in the class - //[ClassInitialize()] - //public static void MyClassInitialize(TestContext testContext) - //{ - //} - // - //Use ClassCleanup to run code after all tests in a class have run - //[ClassCleanup()] - //public static void MyClassCleanup() - //{ - //} - // - //Use TestInitialize to run code before running each test - //[TestInitialize()] - //public void MyTestInitialize() - //{ - //} - // - //Use TestCleanup to run code after each test has run - //[TestCleanup()] - //public void MyTestCleanup() - //{ - //} - // - #endregion - - - /// - ///A test for Racy Constructor - /// - [Test] - public void RacyConstructorTest1() - { - Racy target = new Racy(); - Assert.IsNull(target.Value, "Object value should be null after construction"); - } - - /// - ///A test for Racy Constructor - /// - [Test] - public void RacyConstructorTest() - { - string initValue = "secret test string"; - Racy target = new Racy(initValue); - Assert.AreEqual(target.Value, initValue, "Object value should be identical after construction"); - } - } -} diff -Nru gdata-sharp-1.4.0.2/src/unittests/youtube/YouTubeQueryTest.cs gdata-sharp-1.7.0.1/src/unittests/youtube/YouTubeQueryTest.cs --- gdata-sharp-1.4.0.2/src/unittests/youtube/YouTubeQueryTest.cs 2008-07-02 17:30:40.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/youtube/YouTubeQueryTest.cs 2009-08-13 15:59:00.000000000 +0000 @@ -69,19 +69,7 @@ #endregion - /// - ///A test for VQ - /// - [Test] - public void VQTest() - { - YouTubeQuery target = new YouTubeQuery(); // TODO: Initialize to an appropriate value - string expected = "secret text string"; // TODO: Initialize to an appropriate value - string actual; - target.VQ = expected; - actual = target.VQ; - Assert.AreEqual(expected, actual); - } + /// ///A test for Time @@ -111,19 +99,6 @@ Assert.AreEqual(expected, actual); } - /// - ///A test for Racy - /// - [Test] - public void RacyTest() - { - YouTubeQuery target = new YouTubeQuery(); // TODO: Initialize to an appropriate value - string expected = "secret text string"; // TODO: Initialize to an appropriate value - string actual; - target.Racy = expected; - actual = target.Racy; - Assert.AreEqual(expected, actual); - } /// ///A test for OrderBy diff -Nru gdata-sharp-1.4.0.2/src/unittests/youtubetest.cs gdata-sharp-1.7.0.1/src/unittests/youtubetest.cs --- gdata-sharp-1.4.0.2/src/unittests/youtubetest.cs 2009-02-27 14:38:35.000000000 +0000 +++ gdata-sharp-1.7.0.1/src/unittests/youtubetest.cs 2010-06-22 15:02:23.000000000 +0000 @@ -43,8 +43,6 @@ [Category("LiveTest")] public class YouTubeTestSuite : BaseLiveTestClass { - - private string ytClient; private string ytDevKey; private string ytUser; private string ytPwd; @@ -59,7 +57,7 @@ public override string ServiceName { get { - return YouTubeService.YTService; + return ServiceNames.YouTube; } } @@ -72,10 +70,6 @@ { base.ReadConfigFile(); - if (unitTestConfiguration.Contains("youTubeClientID") == true) - { - this.ytClient = (string) unitTestConfiguration["youTubeClientID"]; - } if (unitTestConfiguration.Contains("youTubeDevKey") == true) { this.ytDevKey = (string) unitTestConfiguration["youTubeDevKey"]; @@ -115,8 +109,6 @@ Assert.AreEqual(query.Time, YouTubeQuery.UploadTime.ThisWeek, "Should be this week"); Assert.AreEqual(query.Formats[0], YouTubeQuery.VideoFormat.RTSP, "Should be RTSP"); - Assert.AreEqual(query.Racy, "included", "Racy should be included"); - } ///////////////////////////////////////////////////////////////////////////// @@ -130,7 +122,7 @@ Tracing.TraceMsg("Entering YouTubeQueryPrivateTest"); YouTubeQuery query = new YouTubeQuery(YouTubeQuery.DefaultVideoUri); - YouTubeService service = new YouTubeService("NETUnittests", this.ytClient, this.ytDevKey); + YouTubeService service = new YouTubeService("NETUnittests", this.ytDevKey); query.Query = "Education expertvillage"; query.NumberToRetrieve = 50; @@ -164,7 +156,7 @@ Tracing.TraceMsg("Entering YouTubeFeedTest"); YouTubeQuery query = new YouTubeQuery(YouTubeQuery.TopRatedVideo); - YouTubeService service = new YouTubeService("NETUnittests", this.ytClient, this.ytDevKey); + YouTubeService service = new YouTubeService("NETUnittests", this.ytDevKey); if (this.userName != null) { service.Credentials = new GDataCredentials(this.ytUser, this.ytPwd); @@ -218,7 +210,7 @@ { Tracing.TraceMsg("Entering YouTubeFeedTest"); - YouTubeService service = new YouTubeService("NETUnittests", this.ytClient, this.ytDevKey); + YouTubeService service = new YouTubeService("NETUnittests", this.ytDevKey); if (this.userName != null) { service.Credentials = new GDataCredentials(this.ytUser, this.ytPwd); @@ -289,7 +281,7 @@ { Tracing.TraceMsg("Entering YouTubeRatingsTest"); - YouTubeService service = new YouTubeService("NETUnittests", this.ytClient, this.ytDevKey); + YouTubeService service = new YouTubeService("NETUnittests", this.ytDevKey); if (this.userName != null) { service.Credentials = new GDataCredentials(this.ytUser, this.ytPwd); @@ -332,7 +324,7 @@ YouTubeQuery query = new YouTubeQuery(); query.Uri = new Uri(CreateUri(this.resourcePath + "uploaderyt.xml")); - YouTubeService service = new YouTubeService("NETUnittests", this.ytClient, this.ytDevKey); + YouTubeService service = new YouTubeService("NETUnittests", this.ytDevKey); if (this.userName != null) { service.Credentials = new GDataCredentials(this.ytUser, this.ytPwd); @@ -365,7 +357,7 @@ Tracing.TraceMsg("Entering YouTubeRequestTest"); - YouTubeRequestSettings settings = new YouTubeRequestSettings("NETUnittests", this.ytClient, this.ytDevKey, this.ytUser, this.ytPwd); + YouTubeRequestSettings settings = new YouTubeRequestSettings("NETUnittests", this.ytDevKey, this.ytUser, this.ytPwd); YouTubeRequest f = new YouTubeRequest(settings); // GetVideoFeed get's you a users video feed @@ -412,7 +404,7 @@ { Tracing.TraceMsg("Entering YouTubePlaylistRequestTest"); - YouTubeRequestSettings settings = new YouTubeRequestSettings("NETUnittests", this.ytClient, this.ytDevKey, this.ytUser, this.ytPwd); + YouTubeRequestSettings settings = new YouTubeRequestSettings("NETUnittests", this.ytDevKey, this.ytUser, this.ytPwd); YouTubeRequest f = new YouTubeRequest(settings); // GetVideoFeed get's you a users video feed @@ -453,7 +445,7 @@ { Tracing.TraceMsg("Entering YouTubePlaylistBatchTest"); - YouTubeRequestSettings settings = new YouTubeRequestSettings("NETUnittests", this.ytClient, this.ytDevKey, this.ytUser, this.ytPwd); + YouTubeRequestSettings settings = new YouTubeRequestSettings("NETUnittests", this.ytDevKey, this.ytUser, this.ytPwd); YouTubeRequest f = new YouTubeRequest(settings); // GetVideoFeed get's you a users video feed @@ -517,7 +509,7 @@ { Tracing.TraceMsg("Entering YouTubeCommentRequestTest"); - YouTubeRequestSettings settings = new YouTubeRequestSettings("NETUnittests", this.ytClient, this.ytDevKey, this.ytUser, this.ytPwd); + YouTubeRequestSettings settings = new YouTubeRequestSettings("NETUnittests", this.ytDevKey, this.ytUser, this.ytPwd); YouTubeRequest f = new YouTubeRequest(settings); Feed /// The name of the application - /// the client ID to use /// the developer key to use /// the authentication token /// - public YouTubeRequestSettings(string applicationName, string client, string developerKey, string authSubToken) + public YouTubeRequestSettings(string applicationName, string developerKey, string authSubToken) : base(applicationName, authSubToken) { - this.clientID = client; this.developerKey = developerKey; } /// - /// returns the client ID + /// a constructor for OpenAuthentication login use cases using 2 or 3 legged oAuth /// - /// - public string Client + /// The name of the application + /// the developer key to use + /// the consumerKey to use + /// the consumerSecret to use + /// The token to be used + /// The tokenSecret to be used + /// the username to use + /// the domain to use + /// + public YouTubeRequestSettings(string applicationName, + string developerKey, + string consumerKey, string consumerSecret, + string token, string tokenSecret, + string user, string domain) : base(applicationName, consumerKey, consumerSecret, + token, tokenSecret, user, domain) { - get - { - return this.clientID; - } + this.developerKey = developerKey; } + + + /// /// returns the developer key /// @@ -1009,9 +1046,9 @@ /// public YouTubeRequest(YouTubeRequestSettings settings) : base(settings) { - if (settings.Client != null && settings.DeveloperKey != null) + if (settings.DeveloperKey != null) { - this.Service = new YouTubeService(settings.Application, settings.Client, settings.DeveloperKey); + this.Service = new YouTubeService(settings.Application, settings.DeveloperKey); } else { @@ -1303,7 +1340,7 @@ v.YouTubeEntry.Comments != null && v.YouTubeEntry.Comments.FeedLink != null) { - Uri target = new Uri(v.YouTubeEntry.Comments.FeedLink.Href); + Uri target = CreateUri(v.YouTubeEntry.Comments.FeedLink.Href); rc = new Comment(); rc.AtomEntry = this.Service.Insert(target, c.AtomEntry); } @@ -1326,7 +1363,7 @@ p.PlaylistsEntry.Content != null && p.PlaylistsEntry.Content.Src != null) { - Uri target = new Uri(p.PlaylistsEntry.Content.Src.Content); + Uri target = CreateUri(p.PlaylistsEntry.Content.Src.Content); newMember = new PlayListMember(); newMember.AtomEntry = this.Service.Insert(target, m.AtomEntry); } @@ -1359,11 +1396,23 @@ if (videos.Count > 0) { - meta = this.Batch(videos, new Uri(YouTubeQuery.BatchVideoUri), GDataBatchOperationType.query); + meta = this.Batch(videos, CreateUri(YouTubeQuery.BatchVideoUri), GDataBatchOperationType.query); } } return meta == null? new Feed public const string AuthenticationHandler = "https://www.google.com/youtube/accounts/ClientLogin"; - - - private string clientID; private string developerID; @@ -66,29 +59,38 @@ /// the applicationname /// the client identifier /// the developerKey/// - public YouTubeService(string applicationName, string client, string developerKey) : base(YTService, applicationName) + [Obsolete("The client id was removed from the YouTubeService, use the constructor without a clientid")] + public YouTubeService(string applicationName, string client, string developerKey) : base(ServiceNames.YouTube, applicationName) { - if (client == null) - { - throw new ArgumentNullException("client"); - } if (developerKey == null) { throw new ArgumentNullException("developerKey"); } this.NewFeed += new ServiceEventHandler(this.OnNewFeed); - clientID = client; developerID = developerKey; OnRequestFactoryChanged(); } + public YouTubeService(string applicationName, string developerKey) + : base(ServiceNames.YouTube, applicationName) + { + if (developerKey == null) + { + throw new ArgumentNullException("developerKey"); + } + + this.NewFeed += new ServiceEventHandler(this.OnNewFeed); + developerID = developerKey; + OnRequestFactoryChanged(); + } + /// /// readonly constructor /// /// the application identifier - public YouTubeService(string applicationName) : base(YTService, applicationName) + public YouTubeService(string applicationName) : base(ServiceNames.YouTube, applicationName) { this.NewFeed += new ServiceEventHandler(this.OnNewFeed); OnRequestFactoryChanged(); @@ -235,10 +237,9 @@ { base.OnRequestFactoryChanged(); GDataGAuthRequestFactory factory = this.RequestFactory as GDataGAuthRequestFactory; - if (factory != null && this.developerID != null && this.clientID != null) + if (factory != null && this.developerID != null) { RemoveOldKeys(factory.CustomHeaders); - factory.CustomHeaders.Add(GoogleAuthentication.YouTubeClientId + this.clientID); factory.CustomHeaders.Add(GoogleAuthentication.YouTubeDevKey + this.developerID); factory.Handler = YouTubeService.AuthenticationHandler; } Binary files /tmp/UhUzKTrMiD/gdata-sharp-1.4.0.2/Templates/ProjectTemplates/Google YouTube.zip and /tmp/kt1AG0Pm9_/gdata-sharp-1.7.0.1/Templates/ProjectTemplates/Google YouTube.zip differ diff -Nru gdata-sharp-1.4.0.2/version/AssemblyVersion.cs gdata-sharp-1.7.0.1/version/AssemblyVersion.cs --- gdata-sharp-1.4.0.2/version/AssemblyVersion.cs 2009-02-27 14:38:35.000000000 +0000 +++ gdata-sharp-1.7.0.1/version/AssemblyVersion.cs 2010-11-23 18:14:29.000000000 +0000 @@ -54,7 +54,7 @@ // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.4.0.2")] +[assembly: AssemblyVersion("1.7.0.*")]