Kaydet (Commit) b3c7bf54 authored tarafından David Tardon's avatar David Tardon

upload libcmis 0.5.2

Change-Id: I0a7e888af770a332e2fec057507eecebf83621c4
Reviewed-on: https://gerrit.libreoffice.org/65646
Tested-by: Jenkins
Reviewed-by: 's avatarDavid Tardon <dtardon@redhat.com>
üst 4a0af123
......@@ -678,7 +678,7 @@ else # !SYSTEM_LIBCMIS
define gb_LinkTarget__use_libcmis
$(call gb_LinkTarget_set_include,$(1),\
-I$(call gb_UnpackedTarball_get_dir,libcmis)/src \
-I$(call gb_UnpackedTarball_get_dir,libcmis)/inc \
$$(INCLUDE) \
)
$(call gb_LinkTarget_use_static_libraries,$(1),\
......
......@@ -21,8 +21,8 @@ export CDR_SHA256SUM := e7a7e8b00a3df5798110024d7061fe9d1c3330277d2e4fa9213294f9
export CDR_TARBALL := libcdr-0.1.4.tar.xz
export CLUCENE_SHA256SUM := ddfdc433dd8ad31b5c5819cc4404a8d2127472a3b720d3e744e8c51d79732eab
export CLUCENE_TARBALL := 48d647fbd8ef8889e5a7f422c1bfda94-clucene-core-2.3.3.4.tar.gz
export LIBCMIS_SHA256SUM := 6acbdf22ecdbaba37728729b75bfc085ee5a4b49a6024757cfb86ccd3da27b0e
export LIBCMIS_TARBALL := libcmis-0.5.1.tar.gz
export LIBCMIS_SHA256SUM := d7b18d9602190e10d437f8a964a32e983afd57e2db316a07d87477a79f5000a2
export LIBCMIS_TARBALL := libcmis-0.5.2.tar.xz
export COINMP_SHA256SUM := 86c798780b9e1f5921fe4efe651a93cb420623b45aa1fdff57af8c37f116113f
export COINMP_TARBALL := CoinMP-1.7.6.tgz
export CPPUNIT_SHA256SUM := 3d569869d27b48860210c758c4f313082103a5e58219a7669b52bfd29d674780
......
From 219e6d6586c8280dfd9c4851cee0d14d68b6ad65 Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Fri, 28 Dec 2018 15:26:28 +0100
Subject: [PATCH] rename class GetObject to avoid name clash on Windows
---
src/libcmis/ws-objectservice.cxx | 2 +-
src/libcmis/ws-requests.cxx | 2 +-
src/libcmis/ws-requests.hxx | 7 +++----
3 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/src/libcmis/ws-objectservice.cxx b/src/libcmis/ws-objectservice.cxx
index 9e40085..d57f3cc 100644
--- a/src/libcmis/ws-objectservice.cxx
+++ b/src/libcmis/ws-objectservice.cxx
@@ -71,7 +71,7 @@ libcmis::ObjectPtr ObjectService::getObject( string repoId, string id )
{
libcmis::ObjectPtr object;
- class GetObject request( repoId, id );
+ GetObjectRequest request( repoId, id );
vector< SoapResponsePtr > responses = m_session->soapRequest( m_url, request );
if ( responses.size( ) == 1 )
{
diff --git a/src/libcmis/ws-requests.cxx b/src/libcmis/ws-requests.cxx
index f8bc245..408d053 100644
--- a/src/libcmis/ws-requests.cxx
+++ b/src/libcmis/ws-requests.cxx
@@ -269,7 +269,7 @@ SoapResponsePtr GetTypeChildrenResponse::create( xmlNodePtr node, RelatedMultipa
return SoapResponsePtr( response );
}
-void GetObject::toXml( xmlTextWriterPtr writer )
+void GetObjectRequest::toXml( xmlTextWriterPtr writer )
{
xmlTextWriterStartElement( writer, BAD_CAST( "cmism:getObject" ) );
xmlTextWriterWriteAttribute( writer, BAD_CAST( "xmlns:cmis" ), BAD_CAST( NS_CMIS_URL ) );
diff --git a/src/libcmis/ws-requests.hxx b/src/libcmis/ws-requests.hxx
index 2c4ae92..534d9a4 100644
--- a/src/libcmis/ws-requests.hxx
+++ b/src/libcmis/ws-requests.hxx
@@ -203,21 +203,20 @@ class GetTypeChildrenResponse : public SoapResponse
std::vector< libcmis::ObjectTypePtr > getChildren( ) { return m_children; }
};
-#undef GetObject
-class GetObject : public SoapRequest
+class GetObjectRequest : public SoapRequest
{
private:
std::string m_repositoryId;
std::string m_id;
public:
- GetObject( std::string repoId, std::string id ) :
+ GetObjectRequest( std::string repoId, std::string id ) :
m_repositoryId( repoId ),
m_id( id )
{
}
- ~GetObject( ) { }
+ ~GetObjectRequest( ) { }
void toXml( xmlTextWriterPtr writer );
};
--
2.19.2
......@@ -13,21 +13,9 @@ $(eval $(call gb_StaticLibrary_set_warnings_not_errors,libcmis))
ifeq ($(COM_IS_CLANG),TRUE)
# Avoid narrowing conversion error (even though the option is technically a warning)
# caused by boost, and avoid -Wdynamic-exception-spec errors.
# caused by boost
$(eval $(call gb_StaticLibrary_add_cxxflags,libcmis,\
-Wno-error=c++11-narrowing \
-Wno-error=dynamic-exception-spec \
))
endif
# Build as C++14 if necessary to avoid GCC C++17 "error: ISO C++1z does not
# allow dynamic exception specifications", until upstream libcmis is ported to
# C++17:
ifeq ($(COM)-$(COM_IS_CLANG),GCC-)
$(eval $(call gb_StaticLibrary_add_cxxflags,libcmis, \
$(if $(filter -std=gnu++2a -std=c++2a -std=gnu++17 -std=gnu++1z -std=c++17 -std=c++1z, \
$(CXXFLAGS_CXX11)), \
-std=gnu++14) \
))
endif
......@@ -36,6 +24,7 @@ $(eval $(call gb_StaticLibrary_add_defs,libcmis, \
))
$(eval $(call gb_StaticLibrary_set_include,libcmis, \
-I$(call gb_UnpackedTarball_get_dir,libcmis/inc) \
-I$(call gb_UnpackedTarball_get_dir,libcmis/src/libcmis) \
$$(INCLUDE) \
))
......
......@@ -13,21 +13,9 @@ $(eval $(call gb_UnpackedTarball_set_tarball,libcmis,$(LIBCMIS_TARBALL)))
$(eval $(call gb_UnpackedTarball_set_patchlevel,libcmis,1))
# xwwwformurlencoded.patch.0 sent upstream as <https://github.com/tdf/libcmis/pull/20>
$(eval $(call gb_UnpackedTarball_add_patches,libcmis, \
external/libcmis/libcmis-libxml2_compatibility.patch \
external/libcmis/libcmis-fix-google-drive.patch \
external/libcmis/libcmis-google-2FA-implementation.patch \
external/libcmis/libcmis-fix-google-drive-2.patch \
external/libcmis/libcmis-sharepoint-repository-root.patch \
external/libcmis/libcmis-fix-error-handling.patch \
external/libcmis/c++17.patch.0 \
external/libcmis/boost-1.68.patch.0 \
external/libcmis/xwwwformurlencoded.patch.0 \
external/libcmis/libcmis-libxml2_compatibility.patch \
external/libcmis/0001-rename-class-GetObject-to-avoid-name-clash-on-Window.patch \
))
ifeq ($(OS),WNT)
$(eval $(call gb_UnpackedTarball_add_patches,libcmis,external/libcmis/boost-win.patch))
endif
# vim: set noet sw=4 ts=4:
--- src/libcmis/xml-utils.cxx.orig 2016-03-01 16:14:26 UTC
+++ src/libcmis/xml-utils.cxx
@@ -31,7 +31,12 @@
#include <sstream>
#include <stdlib.h>
+#include <boost/version.hpp>
+#if (BOOST_VERSION >= 106800)
+#include <boost/uuid/detail/sha1.hpp>
+#else
#include <boost/uuid/sha1.hpp>
+#endif
#include <curl/curl.h>
#include "xml-utils.hxx"
diff --git src/libcmis/atom-object.cxx src/libcmis/atom-object.cxx
index ce21384..eef8102 100644
--- a/src/libcmis/atom-object.cxx
+++ b/src/libcmis/atom-object.cxx
@@ -30,6 +30,9 @@
#include <locale>
#include <sstream>
+#ifndef BOOST_DATE_TIME_NO_LIB
+#define BOOST_DATE_TIME_NO_LIB
+#endif
#include <boost/date_time/posix_time/posix_time.hpp>
#include "atom-document.hxx"
diff --git src/libcmis/object.hxx src/libcmis/object.hxx
index 449bb22..c320f06 100644
--- a/src/libcmis/object.hxx
+++ b/src/libcmis/object.hxx
@@ -36,6 +36,9 @@
#include <stdbool.h>
#endif
+#ifndef BOOST_DATE_TIME_NO_LIB
+#define BOOST_DATE_TIME_NO_LIB
+#endif
#include <boost/date_time.hpp>
#include <boost/shared_ptr.hpp>
#include <libxml/tree.h>
diff --git src/libcmis/property-type.hxx src/libcmis/property-type.hxx
index 1a8bee9..6ac946c 100644
--- a/src/libcmis/property-type.hxx
+++ b/src/libcmis/property-type.hxx
@@ -28,6 +28,9 @@
#ifndef _PROPERTY_TYPE_HXX_
#define _PROPERTY_TYPE_HXX_
+#ifndef BOOST_DATE_TIME_NO_LIB
+#define BOOST_DATE_TIME_NO_LIB
+#endif
#include <boost/date_time.hpp>
#include <libxml/tree.h>
diff --git src/libcmis/property.hxx src/libcmis/property.hxx
index f9be04a..2977fb3 100644
--- a/src/libcmis/property.hxx
+++ b/src/libcmis/property.hxx
@@ -31,6 +31,9 @@
#include <libxml/tree.h>
#include <libxml/xmlwriter.h>
+#ifndef BOOST_DATE_TIME_NO_LIB
+#define BOOST_DATE_TIME_NO_LIB
+#endif
#include <boost/date_time.hpp>
#include <boost/shared_ptr.hpp>
diff --git src/libcmis/ws-session.cxx src/libcmis/ws-session.cxx
index b906a5a..bf50644 100644
--- a/src/libcmis/ws-session.cxx
+++ b/src/libcmis/ws-session.cxx
@@ -28,6 +28,9 @@
#include <sstream>
+#ifndef BOOST_DATE_TIME_NO_LIB
+#define BOOST_DATE_TIME_NO_LIB
+#endif
#include <boost/date_time.hpp>
#include <libxml/parser.h>
#include <libxml/tree.h>
diff --git src/libcmis/xml-utils.hxx src/libcmis/xml-utils.hxx
index 52853e2..2f80b91 100644
--- a/src/libcmis/xml-utils.hxx
+++ b/src/libcmis/xml-utils.hxx
@@ -33,6 +33,9 @@
#include <sstream>
#include <string>
+#ifndef BOOST_DATE_TIME_NO_LIB
+#define BOOST_DATE_TIME_NO_LIB
+#endif
#include <boost/date_time.hpp>
#include <libxml/tree.h>
#include <libxml/xpathInternals.h>
This diff is collapsed.
diff -ur cmis.org/src/libcmis/xml-utils.cxx cmis/src/libcmis/xml-utils.cxx
--- cmis.org/src/libcmis/xml-utils.cxx 2016-12-09 02:19:47.900961750 +0100
+++ cmis/src/libcmis/xml-utils.cxx 2016-12-09 02:23:56.392206339 +0100
@@ -382,9 +382,14 @@
// Get the time zone offset
boost::posix_time::time_duration tzOffset( boost::posix_time::duration_from_string( "+00:00" ) );
+ if ( dateTimeStr.empty( ) )
+ return t; // obviously not a time
+
size_t teePos = dateTimeStr.find( 'T' );
- string noTzStr = dateTimeStr.substr( 0, teePos + 1 );
+ if ( teePos == string::npos )
+ return t; // obviously not a time
+ string noTzStr = dateTimeStr.substr( 0, teePos + 1 );
string timeStr = dateTimeStr.substr( teePos + 1 );
// Get the TZ if any
@@ -459,10 +459,9 @@
bool value = false;
if ( boolStr == "true" || boolStr == "1" )
value = true;
- else if ( boolStr == "false" || boolStr == "0" )
- value = false;
else
- throw Exception( string( "Invalid xsd:boolean input: " ) + boolStr );
+ // treat everthing else, including absence of property, as 'false', not as an error
+ value = false;
return value;
}
diff --git a/src/libcmis/oauth2-providers.cxx b/src/libcmis/oauth2-providers.cxx
index 74c0fec..30fedb0 100644
--- a/src/libcmis/oauth2-providers.cxx
+++ b/src/libcmis/oauth2-providers.cxx
@@ -41,6 +41,7 @@
#define CHALLENGE_PAGE_ACTION_LEN sizeof( CHALLENGE_PAGE_ACTION ) - 1
#define PIN_FORM_ACTION "/signin/challenge/ipp"
#define PIN_FORM_ACTION_LEN sizeof( PIN_FORM_ACTION ) - 1
+#define PIN_INPUT_NAME "Pin"
using namespace std;
@@ -80,7 +81,7 @@ string OAuth2Providers::OAuth2Gdrive( HttpSession* session, const string& authUr
// send the first get, receive the html login page
res = session->httpGetRequest( authUrl )->getStream( )->str( );
}
- catch ( const CurlException& e )
+ catch ( const CurlException& )
{
return string( );
}
@@ -102,7 +103,7 @@ string OAuth2Providers::OAuth2Gdrive( HttpSession* session, const string& authUr
loginEmailRes = session->httpPostRequest ( loginEmailLink, loginEmailIs, CONTENT_TYPE )
->getStream( )->str( );
}
- catch ( const CurlException& e )
+ catch ( const CurlException& )
{
return string( );
}
@@ -113,7 +114,7 @@ string OAuth2Providers::OAuth2Gdrive( HttpSession* session, const string& authUr
if ( !parseResponse( loginEmailRes.c_str( ), loginPasswdPost, loginPasswdLink ) )
return string( );
- loginPasswdPost += "&Passwd=";
+ loginPasswdPost += "Passwd=";
loginPasswdPost += string( password );
istringstream loginPasswdIs( loginPasswdPost );
@@ -124,7 +125,7 @@ string OAuth2Providers::OAuth2Gdrive( HttpSession* session, const string& authUr
loginPasswdRes = session->httpPostRequest ( loginPasswdLink, loginPasswdIs, CONTENT_TYPE )
->getStream( )->str( );
}
- catch ( const CurlException& e )
+ catch ( const CurlException& )
{
return string( );
}
@@ -152,7 +153,7 @@ string OAuth2Providers::OAuth2Gdrive( HttpSession* session, const string& authUr
}
loginChallengeLink = "https://accounts.google.com" + loginChallengeLink;
- loginChallengePost += "Pin=";
+ loginChallengePost += string( PIN_INPUT_NAME ) + "=";
loginChallengePost += string( pin );
istringstream loginChallengeIs( loginChallengePost );
@@ -163,7 +164,7 @@ string OAuth2Providers::OAuth2Gdrive( HttpSession* session, const string& authUr
loginChallengeRes = session->httpPostRequest ( loginChallengeLink, loginChallengeIs, CONTENT_TYPE )
->getStream( )->str( );
}
- catch ( const CurlException& e )
+ catch ( const CurlException& )
{
return string( );
}
@@ -221,7 +222,7 @@ string OAuth2Providers::OAuth2Alfresco( HttpSession* session, const string& auth
{
res = session->httpGetRequest( authUrl )->getStream( )->str( );
}
- catch ( const CurlException& e )
+ catch ( const CurlException& )
{
return string( );
}
@@ -247,7 +248,7 @@ string OAuth2Providers::OAuth2Alfresco( HttpSession* session, const string& auth
// Alfresco code is in the redirect link
resp = session->httpPostRequest( loginLink, loginIs, CONTENT_TYPE, false );
}
- catch ( const CurlException& e )
+ catch ( const CurlException& )
{
return string( );
}
@@ -291,6 +292,8 @@ int OAuth2Providers::parseResponse ( const char* response, string& post, string&
if ( reader == NULL ) return 0;
bool readInputField = false;
+ bool bIsRightForm = false;
+ bool bHasPinField = false;
while ( true )
{
@@ -301,6 +304,12 @@ int OAuth2Providers::parseResponse ( const char* response, string& post, string&
// Find the redirect link
if ( xmlStrEqual( nodeName, BAD_CAST( "form" ) ) )
{
+ // 2FA: Don't add fields form other forms not having pin field
+ if ( bIsRightForm && !bHasPinField )
+ post = string( "" );
+ if ( bIsRightForm && bHasPinField )
+ break;
+
xmlChar* action = xmlTextReaderGetAttribute( reader,
BAD_CAST( "action" ));
@@ -311,7 +320,7 @@ int OAuth2Providers::parseResponse ( const char* response, string& post, string&
bool bChallengePage = ( strncmp( (char*)action,
CHALLENGE_PAGE_ACTION,
CHALLENGE_PAGE_ACTION_LEN ) == 0 );
- bool bIsRightForm = ( strncmp( (char*)action,
+ bIsRightForm = ( strncmp( (char*)action,
PIN_FORM_ACTION,
PIN_FORM_ACTION_LEN ) == 0 );
if ( ( xmlStrlen( action ) > 0 )
@@ -332,6 +341,8 @@ int OAuth2Providers::parseResponse ( const char* response, string& post, string&
BAD_CAST( "name" ));
xmlChar* value = xmlTextReaderGetAttribute( reader,
BAD_CAST( "value" ));
+ if ( name != NULL && strcmp( (char*)name, PIN_INPUT_NAME ) == 0 )
+ bHasPinField = true;
if ( ( name != NULL ) && ( value!= NULL ) )
{
if ( ( xmlStrlen( name ) > 0) && ( xmlStrlen( value ) > 0) )
diff -aru old-src/src/libcmis/oauth2-providers.cxx new-src/src/libcmis/oauth2-providers.cxx
--- old-src/src/libcmis/oauth2-providers.cxx 2016-03-01 17:14:26.000000000 +0100
+++ new-src/src/libcmis/oauth2-providers.cxx 2016-04-28 11:28:25.233803971 +0200
@@ -37,11 +37,28 @@
string OAuth2Providers::OAuth2Gdrive( HttpSession* session, const string& authUrl,
const string& username, const string& password )
{
+ /* This member function implements 'Google OAuth 2.0'
+ *
+ * The interaction is carried out by libcmis, with no web browser involved.
+ *
+ * Normal sequence (without 2FA) is:
+ * 1) a get to activate login page
+ * receive first login page, html format
+ * 2) subsequent post to sent email
+ * receive html page for password input
+ * 3) subsequent post to send password
+ * receive html page for application consent
+ * 4) subsequent post to send a consent for the application
+ * receive a single-use authorization code
+ * this code is returned as a string
+ */
+
static const string CONTENT_TYPE( "application/x-www-form-urlencoded" );
// STEP 1: Log in
string res;
try
{
+ // send the first get, receive the html login page
res = session->httpGetRequest( authUrl )->getStream( )->str( );
}
catch ( const CurlException& e )
@@ -49,20 +66,39 @@
return string( );
}
- string loginPost, loginLink;
- if ( !parseResponse( res.c_str( ), loginPost, loginLink ) )
+ string loginEmailPost, loginEmailLink;
+ if ( !parseResponse( res.c_str( ), loginEmailPost, loginEmailLink ) )
+ return string( );
+
+ loginEmailPost += "Email=";
+ loginEmailPost += string( username );
+
+ istringstream loginEmailIs( loginEmailPost );
+ string loginEmailRes;
+ try
+ {
+ // send a post with user email, receive the html page for password input
+ loginEmailRes = session->httpPostRequest ( loginEmailLink, loginEmailIs, CONTENT_TYPE )
+ ->getStream( )->str( );
+ }
+ catch ( const CurlException& e )
+ {
+ return string( );
+ }
+
+ string loginPasswdPost, loginPasswdLink;
+ if ( !parseResponse( loginEmailRes.c_str( ), loginPasswdPost, loginPasswdLink ) )
return string( );
-
- loginPost += "Email=";
- loginPost += string( username );
- loginPost += "&Passwd=";
- loginPost += string( password );
-
- istringstream loginIs( loginPost );
- string loginRes;
- try
+
+ loginPasswdPost += "&Passwd=";
+ loginPasswdPost += string( password );
+
+ istringstream loginPasswdIs( loginPasswdPost );
+ string loginPasswdRes;
+ try
{
- loginRes = session->httpPostRequest ( loginLink, loginIs, CONTENT_TYPE )
+ // send a post with user password, receive the application consent page
+ loginPasswdRes = session->httpPostRequest ( loginPasswdLink, loginPasswdIs, CONTENT_TYPE )
->getStream( )->str( );
}
catch ( const CurlException& e )
@@ -71,8 +107,8 @@
}
// STEP 2: allow libcmis to access google drive
- string approvalPost, approvalLink;
- if ( !parseResponse( loginRes. c_str( ), approvalPost, approvalLink) )
+ string approvalPost, approvalLink;
+ if ( !parseResponse( loginPasswdRes. c_str( ), approvalPost, approvalLink) )
return string( );
approvalPost += "submit_access=true";
@@ -80,7 +116,8 @@
string approvalRes;
try
{
- approvalRes = session->httpPostRequest ( approvalLink, approvalIs,
+ // send a post with application consent
+ approvalRes = session->httpPostRequest ( approvalLink, approvalIs,
CONTENT_TYPE) ->getStream( )->str( );
}
catch ( const CurlException& e )
Only in new-src/src/libcmis: oauth2-providers.cxx~
diff --git a/src/libcmis/oauth2-providers.cxx b/src/libcmis/oauth2-providers.cxx
--- a/src/libcmis/oauth2-providers.cxx
+++ b/src/libcmis/oauth2-providers.cxx
@@ -29,9 +29,15 @@
#include <libxml/HTMLparser.h>
#include <libxml/xmlreader.h>
+#include "session-factory.hxx"
#include "oauth2-providers.hxx"
#include "http-session.hxx"
+#define CHALLENGE_PAGE_ACTION "/signin"
+#define CHALLENGE_PAGE_ACTION_LEN sizeof( CHALLENGE_PAGE_ACTION ) - 1
+#define PIN_FORM_ACTION "/signin/challenge/ipp"
+#define PIN_FORM_ACTION_LEN sizeof( PIN_FORM_ACTION ) - 1
+
using namespace std;
#if LIBXML_VERSION < 20621
@@ -51,10 +52,23 @@ string OAuth2Providers::OAuth2Gdrive( HttpSession* session, const string& authUr
* 4) subsequent post to send a consent for the application
* receive a single-use authorization code
* this code is returned as a string
+ *
+ * Sequence with 2FA is:
+ * 1) a get to activate login page
+ * receive first login page, html format
+ * 2) subsequent post to sent email
+ * receive html page for password input
+ * 3) subsequent post to send password
+ * receive html page for pin input
+ * 3b) subsequent post to send pin number
+ * receive html page for application consent
+ * 4) subsequent post to send a consent for the application
+ * receive a single-use authorization code
+ * this code is returned as a string
*/
static const string CONTENT_TYPE( "application/x-www-form-urlencoded" );
- // STEP 1: Log in
+ // STEP 1: get login page
string res;
try
{
@@ -66,6 +80,8 @@ string OAuth2Providers::OAuth2Gdrive( HttpSession* session, const string& authUr
return string( );
}
+ // STEP 2: send email
+
string loginEmailPost, loginEmailLink;
if ( !parseResponse( res.c_str( ), loginEmailPost, loginEmailLink ) )
return string( );
@@ -86,6 +102,8 @@ string OAuth2Providers::OAuth2Gdrive( HttpSession* session, const string& authUr
return string( );
}
+ // STEP 3: password page
+
string loginPasswdPost, loginPasswdLink;
if ( !parseResponse( loginEmailRes.c_str( ), loginPasswdPost, loginPasswdLink ) )
return string( );
@@ -106,10 +124,60 @@ string OAuth2Providers::OAuth2Gdrive( HttpSession* session, const string& authUr
return string( );
}
- // STEP 2: allow libcmis to access google drive
string approvalPost, approvalLink;
if ( !parseResponse( loginPasswdRes. c_str( ), approvalPost, approvalLink) )
return string( );
+
+ // when 2FA is enabled, link doesn't start with 'http'
+ if ( approvalLink.compare(0, 4, "http") != 0 )
+ {
+ // STEP 3b: 2 Factor Authentication, pin code request
+
+ string loginChallengePost( approvalPost );
+ string loginChallengeLink( approvalLink );
+
+ libcmis::OAuth2AuthCodeProvider fallbackProvider = libcmis::SessionFactory::getOAuth2AuthCodeProvider( );
+ string pin( fallbackProvider( "", "", "" ) );
+
+ if( pin.empty() )
+ {
+ // unset OAuth2AuthCode Provider to avoid showing pin request again in the HttpSession::oauth2Authenticate
+ libcmis::SessionFactory::setOAuth2AuthCodeProvider( NULL );
+ return string( );
+ }
+
+ loginChallengeLink = "https://accounts.google.com" + loginChallengeLink;
+ loginChallengePost += "Pin=";
+ loginChallengePost += string( pin );
+
+ istringstream loginChallengeIs( loginChallengePost );
+ string loginChallengeRes;
+ try
+ {
+ // send a post with pin, receive the application consent page
+ loginChallengeRes = session->httpPostRequest ( loginChallengeLink, loginChallengeIs, CONTENT_TYPE )
+ ->getStream( )->str( );
+ }
+ catch ( const CurlException& e )
+ {
+ return string( );
+ }
+
+ approvalPost = string();
+ approvalLink = string();
+
+ if ( !parseResponse( loginChallengeRes. c_str( ), approvalPost, approvalLink) )
+ return string( );
+ }
+ else if( approvalLink.compare( "https://accounts.google.com/ServiceLoginAuth" ) == 0 )
+ {
+ // wrong password,
+ // unset OAuth2AuthCode Provider to avoid showing pin request again in the HttpSession::oauth2Authenticate
+ libcmis::SessionFactory::setOAuth2AuthCodeProvider( NULL );
+ return string( );
+ }
+
+ // STEP 4: allow libcmis to access google drive
approvalPost += "submit_access=true";
istringstream approvalIs( approvalPost );
@@ -125,7 +186,7 @@ string OAuth2Providers::OAuth2Gdrive( HttpSession* session, const string& authUr
throw e.getCmisException( );
}
- // STEP 3: Take the authentication code from the text bar
+ // Take the authentication code from the text bar
string code = parseCode( approvalRes.c_str( ) );
return code;
@@ -216,6 +277,9 @@ int OAuth2Providers::parseResponse ( const char* response, string& post, string&
if ( doc == NULL ) return 0;
xmlTextReaderPtr reader = xmlReaderWalker( doc );
if ( reader == NULL ) return 0;
+
+ bool readInputField = false;
+
while ( true )
{
// Go to the next node, quit if not found
@@ -227,15 +291,30 @@ int OAuth2Providers::parseResponse ( const char* response, string& post, string&
{
xmlChar* action = xmlTextReaderGetAttribute( reader,
BAD_CAST( "action" ));
+
+ // GDrive pin code page contains many forms.
+ // We have to parse only the form with pin field.
if ( action != NULL )
{
- if ( xmlStrlen(action) > 0)
+ bool bChallengePage = ( strncmp( (char*)action,
+ CHALLENGE_PAGE_ACTION,
+ CHALLENGE_PAGE_ACTION_LEN ) == 0 );
+ bool bIsRightForm = ( strncmp( (char*)action,
+ PIN_FORM_ACTION,
+ PIN_FORM_ACTION_LEN ) == 0 );
+ if ( ( xmlStrlen( action ) > 0 )
+ && ( ( bChallengePage && bIsRightForm ) || !bChallengePage ) )
+ {
link = string ( (char*) action);
+ readInputField = true;
+ }
+ else
+ readInputField = false;
xmlFree (action);
}
}
// Find input values
- if ( !xmlStrcmp( nodeName, BAD_CAST( "input" ) ) )
+ if ( readInputField && !xmlStrcmp( nodeName, BAD_CAST( "input" ) ) )
{
xmlChar* name = xmlTextReaderGetAttribute( reader,
BAD_CAST( "name" ));
......@@ -9,6 +9,6 @@
+#define HTML_PARSE_RECOVER 0
+#endif
+
string OAuth2Providers::OAuth2Gdrive( HttpSession* session, const string& authUrl,
const string& username, const string& password )
{
namespace {
// Encodes the given data according to the application/x-www-form-urlencoded format, see
diff --git a/src/libcmis/sharepoint-repository.cxx b/src/libcmis/sharepoint-repository.cxx
index 780624d..f992689 100644
--- a/src/libcmis/sharepoint-repository.cxx
+++ b/src/libcmis/sharepoint-repository.cxx
@@ -35,7 +35,18 @@ SharePointRepository::SharePointRepository( std::string baseUrl ) :
m_description = "SharePoint repository";
m_productName = "SharePoint";
m_productVersion = "2010/2013";
- m_rootId = baseUrl + "/getFolderByServerRelativeUrl('/')";
+ // getFolderByServerRelativeUrl() API expects path to be
+ // *server-relative*, i.e. they must include site path.
+ // Given the baseUrl like "https://sp2013/sites/mysite/_api/Web"
+ // for a site "mysite" on sharepoint server "sp2013",
+ // the site root is '/sites/mysite/', not '/'.
+ // Trying to get folder '/' results in "Value does not fall
+ // within expected range" error.
+ // Preferrable here is to extract the root path from baseUrl,
+ // stripping server and api parts. But it can be unreliable
+ // if api part (_api/Web) is different for some server.
+ // On the other side, just querying empty path '' gives the root folder.
+ m_rootId = baseUrl + "/getFolderByServerRelativeUrl('')";
m_capabilities[ ACL ] = "discover";
m_capabilities[ AllVersionsSearchable ] = "true";
--- src/libcmis/oauth2-providers.cxx
+++ src/libcmis/oauth2-providers.cxx
@@ -26,6 +26,8 @@
* instead of those above.
*/
+#include <cassert>
+
#include <libxml/HTMLparser.h>
#include <libxml/xmlreader.h>
@@ -45,6 +47,29 @@
#define HTML_PARSE_RECOVER 0
#endif
+namespace {
+
+// See <https://url.spec.whatwg.org/#concept-urlencoded-byte-serializer>:
+void addXWwwFormUrlencoded(std::string * buffer, std::string const & data) {
+ assert(buffer);
+ for (string::const_iterator i = data.begin(); i != data.end(); ++i) {
+ unsigned char c = static_cast<unsigned char>(*i);
+ if (c == ' ' || c == '*' || c == '-' || c == '.' || (c >= '0' && c <= '9')
+ || (c >= 'A' && c <= 'Z') || c == '_' || (c >= 'a' && c <= 'z'))
+ {
+ *buffer += static_cast<char>(c);
+ } else {
+ static const char hex[16] = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+ *buffer += '%';
+ *buffer += hex[c >> 4];
+ *buffer += hex[c & 0xF];
+ }
+ }
+}
+
+}
+
string OAuth2Providers::OAuth2Gdrive( HttpSession* session, const string& authUrl,
const string& username, const string& password )
{
@@ -97,7 +120,7 @@
return string( );
loginEmailPost += "Email=";
- loginEmailPost += string( username );
+ addXWwwFormUrlencoded(&loginEmailPost, username);
istringstream loginEmailIs( loginEmailPost );
string loginEmailRes;
@@ -119,7 +142,7 @@
return string( );
loginPasswdPost += "Passwd=";
- loginPasswdPost += string( password );
+ addXWwwFormUrlencoded(&loginPasswdPost, password);
istringstream loginPasswdIs( loginPasswdPost );
string loginPasswdRes;
......@@ -211,10 +211,10 @@
"dest-filename": "external/tarballs/libcdr-0.1.4.tar.xz"
},
{
"url": "https://dev-www.libreoffice.org/src/libcmis-0.5.1.tar.gz",
"sha256": "6acbdf22ecdbaba37728729b75bfc085ee5a4b49a6024757cfb86ccd3da27b0e",
"url": "https://dev-www.libreoffice.org/src/libcmis-0.5.2.tar.xz",
"sha256": "d7b18d9602190e10d437f8a964a32e983afd57e2db316a07d87477a79f5000a2",
"type": "file",
"dest-filename": "external/tarballs/libcmis-0.5.1.tar.gz"
"dest-filename": "external/tarballs/libcmis-0.5.2.tar.xz"
},
{
"url": "https://dev-www.libreoffice.org/src/libe-book-0.1.3.tar.xz",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment