upload libcmis 0.5.2
Change-Id: I0a7e888af770a332e2fec057507eecebf83621c4 Reviewed-on: https://gerrit.libreoffice.org/65646 Tested-by: Jenkins Reviewed-by: David Tardon <dtardon@redhat.com>
This commit is contained in:
@@ -678,7 +678,7 @@ else # !SYSTEM_LIBCMIS
|
|||||||
|
|
||||||
define gb_LinkTarget__use_libcmis
|
define gb_LinkTarget__use_libcmis
|
||||||
$(call gb_LinkTarget_set_include,$(1),\
|
$(call gb_LinkTarget_set_include,$(1),\
|
||||||
-I$(call gb_UnpackedTarball_get_dir,libcmis)/src \
|
-I$(call gb_UnpackedTarball_get_dir,libcmis)/inc \
|
||||||
$$(INCLUDE) \
|
$$(INCLUDE) \
|
||||||
)
|
)
|
||||||
$(call gb_LinkTarget_use_static_libraries,$(1),\
|
$(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 CDR_TARBALL := libcdr-0.1.4.tar.xz
|
||||||
export CLUCENE_SHA256SUM := ddfdc433dd8ad31b5c5819cc4404a8d2127472a3b720d3e744e8c51d79732eab
|
export CLUCENE_SHA256SUM := ddfdc433dd8ad31b5c5819cc4404a8d2127472a3b720d3e744e8c51d79732eab
|
||||||
export CLUCENE_TARBALL := 48d647fbd8ef8889e5a7f422c1bfda94-clucene-core-2.3.3.4.tar.gz
|
export CLUCENE_TARBALL := 48d647fbd8ef8889e5a7f422c1bfda94-clucene-core-2.3.3.4.tar.gz
|
||||||
export LIBCMIS_SHA256SUM := 6acbdf22ecdbaba37728729b75bfc085ee5a4b49a6024757cfb86ccd3da27b0e
|
export LIBCMIS_SHA256SUM := d7b18d9602190e10d437f8a964a32e983afd57e2db316a07d87477a79f5000a2
|
||||||
export LIBCMIS_TARBALL := libcmis-0.5.1.tar.gz
|
export LIBCMIS_TARBALL := libcmis-0.5.2.tar.xz
|
||||||
export COINMP_SHA256SUM := 86c798780b9e1f5921fe4efe651a93cb420623b45aa1fdff57af8c37f116113f
|
export COINMP_SHA256SUM := 86c798780b9e1f5921fe4efe651a93cb420623b45aa1fdff57af8c37f116113f
|
||||||
export COINMP_TARBALL := CoinMP-1.7.6.tgz
|
export COINMP_TARBALL := CoinMP-1.7.6.tgz
|
||||||
export CPPUNIT_SHA256SUM := 3d569869d27b48860210c758c4f313082103a5e58219a7669b52bfd29d674780
|
export CPPUNIT_SHA256SUM := 3d569869d27b48860210c758c4f313082103a5e58219a7669b52bfd29d674780
|
||||||
|
69
external/libcmis/0001-rename-class-GetObject-to-avoid-name-clash-on-Window.patch
vendored
Normal file
69
external/libcmis/0001-rename-class-GetObject-to-avoid-name-clash-on-Window.patch
vendored
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
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
|
||||||
|
|
15
external/libcmis/StaticLibrary_libcmis.mk
vendored
15
external/libcmis/StaticLibrary_libcmis.mk
vendored
@@ -13,21 +13,9 @@ $(eval $(call gb_StaticLibrary_set_warnings_not_errors,libcmis))
|
|||||||
|
|
||||||
ifeq ($(COM_IS_CLANG),TRUE)
|
ifeq ($(COM_IS_CLANG),TRUE)
|
||||||
# Avoid narrowing conversion error (even though the option is technically a warning)
|
# 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,\
|
$(eval $(call gb_StaticLibrary_add_cxxflags,libcmis,\
|
||||||
-Wno-error=c++11-narrowing \
|
-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
|
endif
|
||||||
|
|
||||||
@@ -36,6 +24,7 @@ $(eval $(call gb_StaticLibrary_add_defs,libcmis, \
|
|||||||
))
|
))
|
||||||
|
|
||||||
$(eval $(call gb_StaticLibrary_set_include,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) \
|
-I$(call gb_UnpackedTarball_get_dir,libcmis/src/libcmis) \
|
||||||
$$(INCLUDE) \
|
$$(INCLUDE) \
|
||||||
))
|
))
|
||||||
|
16
external/libcmis/UnpackedTarball_libcmis.mk
vendored
16
external/libcmis/UnpackedTarball_libcmis.mk
vendored
@@ -13,21 +13,9 @@ $(eval $(call gb_UnpackedTarball_set_tarball,libcmis,$(LIBCMIS_TARBALL)))
|
|||||||
|
|
||||||
$(eval $(call gb_UnpackedTarball_set_patchlevel,libcmis,1))
|
$(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, \
|
$(eval $(call gb_UnpackedTarball_add_patches,libcmis, \
|
||||||
external/libcmis/libcmis-libxml2_compatibility.patch \
|
external/libcmis/libcmis-libxml2_compatibility.patch \
|
||||||
external/libcmis/libcmis-fix-google-drive.patch \
|
external/libcmis/0001-rename-class-GetObject-to-avoid-name-clash-on-Window.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 \
|
|
||||||
))
|
))
|
||||||
|
|
||||||
ifeq ($(OS),WNT)
|
|
||||||
$(eval $(call gb_UnpackedTarball_add_patches,libcmis,external/libcmis/boost-win.patch))
|
|
||||||
endif
|
|
||||||
|
|
||||||
# vim: set noet sw=4 ts=4:
|
# vim: set noet sw=4 ts=4:
|
||||||
|
15
external/libcmis/boost-1.68.patch.0
vendored
15
external/libcmis/boost-1.68.patch.0
vendored
@@ -1,15 +0,0 @@
|
|||||||
--- 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"
|
|
84
external/libcmis/boost-win.patch
vendored
84
external/libcmis/boost-win.patch
vendored
@@ -1,84 +0,0 @@
|
|||||||
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>
|
|
412
external/libcmis/c++17.patch.0
vendored
412
external/libcmis/c++17.patch.0
vendored
@@ -1,412 +0,0 @@
|
|||||||
--- src/libcmis/allowable-actions.cxx
|
|
||||||
+++ src/libcmis/allowable-actions.cxx
|
|
||||||
@@ -62,7 +62,7 @@
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- ObjectAction::Type ObjectAction::parseType( string type ) throw ( Exception )
|
|
||||||
+ ObjectAction::Type ObjectAction::parseType( string type )
|
|
||||||
{
|
|
||||||
Type value = DeleteObject;
|
|
||||||
if ( type == "canDeleteObject" )
|
|
||||||
--- src/libcmis/allowable-actions.hxx
|
|
||||||
+++ src/libcmis/allowable-actions.hxx
|
|
||||||
@@ -92,7 +92,7 @@
|
|
||||||
/** Parses the permission name into one of the enum values or throws
|
|
||||||
an exception for invalid input strings.
|
|
||||||
*/
|
|
||||||
- static Type parseType( std::string type ) throw ( Exception );
|
|
||||||
+ static Type parseType( std::string type );
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
--- src/libcmis/document.hxx
|
|
||||||
+++ src/libcmis/document.hxx
|
|
||||||
@@ -56,7 +56,7 @@
|
|
||||||
|
|
||||||
@return the parents folder if any.
|
|
||||||
*/
|
|
||||||
- virtual std::vector< boost::shared_ptr< Folder > > getParents( ) throw ( Exception ) = 0;
|
|
||||||
+ virtual std::vector< boost::shared_ptr< Folder > > getParents( ) = 0;
|
|
||||||
|
|
||||||
/** Get the content stream without using a temporary file.
|
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@
|
|
||||||
guaranteed.
|
|
||||||
*/
|
|
||||||
virtual boost::shared_ptr< std::istream > getContentStream( std::string streamId = std::string( ) )
|
|
||||||
- throw ( Exception ) = 0;
|
|
||||||
+ = 0;
|
|
||||||
|
|
||||||
/** Set or replace the content stream of the document.
|
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@
|
|
||||||
capability.
|
|
||||||
*/
|
|
||||||
virtual void setContentStream( boost::shared_ptr< std::ostream > os, std::string contentType,
|
|
||||||
- std::string filename, bool overwrite = true ) throw ( Exception ) = 0;
|
|
||||||
+ std::string filename, bool overwrite = true ) = 0;
|
|
||||||
|
|
||||||
/** Get the content mime type.
|
|
||||||
*/
|
|
||||||
@@ -107,12 +107,12 @@
|
|
||||||
|
|
||||||
\return the Private Working Copy document
|
|
||||||
*/
|
|
||||||
- virtual boost::shared_ptr< Document > checkOut( ) throw ( Exception ) = 0;
|
|
||||||
+ virtual boost::shared_ptr< Document > checkOut( ) = 0;
|
|
||||||
|
|
||||||
/** Cancels the checkout if the document is a private working copy, or
|
|
||||||
throws an exception.
|
|
||||||
*/
|
|
||||||
- virtual void cancelCheckout( ) throw ( Exception ) = 0;
|
|
||||||
+ virtual void cancelCheckout( ) = 0;
|
|
||||||
|
|
||||||
/** Check in the private working copy and create a new version or throw
|
|
||||||
an exception.
|
|
||||||
@@ -131,9 +131,9 @@
|
|
||||||
virtual boost::shared_ptr< Document > checkIn( bool isMajor, std::string comment,
|
|
||||||
const std::map< std::string, PropertyPtr >& properties,
|
|
||||||
boost::shared_ptr< std::ostream > stream,
|
|
||||||
- std::string contentType, std::string fileName ) throw ( Exception ) = 0;
|
|
||||||
+ std::string contentType, std::string fileName ) = 0;
|
|
||||||
|
|
||||||
- virtual std::vector< boost::shared_ptr< Document > > getAllVersions( ) throw ( Exception ) = 0;
|
|
||||||
+ virtual std::vector< boost::shared_ptr< Document > > getAllVersions( ) = 0;
|
|
||||||
|
|
||||||
// virtual methods form Object
|
|
||||||
virtual std::vector< std::string > getPaths( );
|
|
||||||
--- src/libcmis/folder.cxx
|
|
||||||
+++ src/libcmis/folder.cxx
|
|
||||||
@@ -40,7 +40,7 @@
|
|
||||||
return paths;
|
|
||||||
}
|
|
||||||
|
|
||||||
- libcmis::FolderPtr Folder::getFolderParent( ) throw ( libcmis::Exception )
|
|
||||||
+ libcmis::FolderPtr Folder::getFolderParent( )
|
|
||||||
{
|
|
||||||
if ( getAllowableActions( ).get() && !getAllowableActions()->isAllowed( libcmis::ObjectAction::GetFolderParent ) )
|
|
||||||
throw libcmis::Exception( string( "GetFolderParent not allowed on node " ) + getId() );
|
|
||||||
--- src/libcmis/folder.hxx
|
|
||||||
+++ src/libcmis/folder.hxx
|
|
||||||
@@ -59,20 +59,20 @@
|
|
||||||
|
|
||||||
virtual std::vector< std::string > getPaths( );
|
|
||||||
|
|
||||||
- virtual ::boost::shared_ptr< Folder > getFolderParent( ) throw ( Exception );
|
|
||||||
- virtual std::vector< ObjectPtr > getChildren( ) throw ( Exception ) = 0;
|
|
||||||
+ virtual ::boost::shared_ptr< Folder > getFolderParent( );
|
|
||||||
+ virtual std::vector< ObjectPtr > getChildren( ) = 0;
|
|
||||||
virtual std::string getParentId( );
|
|
||||||
virtual std::string getPath( );
|
|
||||||
|
|
||||||
virtual bool isRootFolder( );
|
|
||||||
|
|
||||||
virtual ::boost::shared_ptr< Folder > createFolder( const std::map< std::string, PropertyPtr >& properties )
|
|
||||||
- throw ( libcmis::Exception ) = 0;
|
|
||||||
+ = 0;
|
|
||||||
virtual ::boost::shared_ptr< Document > createDocument( const std::map< std::string, PropertyPtr >& properties,
|
|
||||||
- boost::shared_ptr< std::ostream > os, std::string contentType, std::string fileName ) throw ( Exception ) = 0;
|
|
||||||
+ boost::shared_ptr< std::ostream > os, std::string contentType, std::string fileName ) = 0;
|
|
||||||
|
|
||||||
virtual std::vector< std::string > removeTree( bool allVersion = true, UnfileObjects::Type unfile = UnfileObjects::Delete,
|
|
||||||
- bool continueOnError = false ) throw ( Exception ) = 0;
|
|
||||||
+ bool continueOnError = false ) = 0;
|
|
||||||
|
|
||||||
virtual std::string toString( );
|
|
||||||
};
|
|
||||||
--- src/libcmis/object.cxx
|
|
||||||
+++ src/libcmis/object.cxx
|
|
||||||
@@ -226,7 +226,6 @@
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectPtr Object::addSecondaryType( string id, PropertyPtrMap properties )
|
|
||||||
- throw ( Exception )
|
|
||||||
{
|
|
||||||
// First make sure the cmis:secondaryObjectTypeIds property can be defined
|
|
||||||
map< string, PropertyTypePtr >& propertyTypes = getTypeDescription( )->
|
|
||||||
@@ -253,7 +252,7 @@
|
|
||||||
return updateProperties( newProperties );
|
|
||||||
}
|
|
||||||
|
|
||||||
- ObjectPtr Object::removeSecondaryType( string id ) throw ( Exception )
|
|
||||||
+ ObjectPtr Object::removeSecondaryType( string id )
|
|
||||||
{
|
|
||||||
// First make sure the cmis:secondaryObjectTypeIds property can be defined
|
|
||||||
map< string, PropertyTypePtr >& propertyTypes = getTypeDescription( )->
|
|
||||||
@@ -297,12 +296,12 @@
|
|
||||||
return m_typeDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
- vector< RenditionPtr> Object::getRenditions( string /*filter*/ ) throw ( Exception )
|
|
||||||
+ vector< RenditionPtr> Object::getRenditions( string /*filter*/ )
|
|
||||||
{
|
|
||||||
return m_renditions;
|
|
||||||
}
|
|
||||||
|
|
||||||
- string Object::getThumbnailUrl( ) throw ( Exception )
|
|
||||||
+ string Object::getThumbnailUrl( )
|
|
||||||
{
|
|
||||||
string url;
|
|
||||||
vector< RenditionPtr > renditions = getRenditions( );
|
|
||||||
--- src/libcmis/object.hxx
|
|
||||||
+++ src/libcmis/object.hxx
|
|
||||||
@@ -129,8 +129,7 @@
|
|
||||||
*/
|
|
||||||
virtual boost::shared_ptr< Object > addSecondaryType(
|
|
||||||
std::string id,
|
|
||||||
- PropertyPtrMap properties )
|
|
||||||
- throw ( Exception );
|
|
||||||
+ PropertyPtrMap properties );
|
|
||||||
|
|
||||||
/** Convenience function removing a secondary type from the object.
|
|
||||||
|
|
||||||
@@ -154,8 +153,7 @@
|
|
||||||
to throw a constraint exception if it doesn't allow the
|
|
||||||
operation.
|
|
||||||
*/
|
|
||||||
- virtual boost::shared_ptr< Object > removeSecondaryType( std::string id )
|
|
||||||
- throw ( Exception );
|
|
||||||
+ virtual boost::shared_ptr< Object > removeSecondaryType( std::string id );
|
|
||||||
|
|
||||||
/** Gives access to the properties of the object.
|
|
||||||
|
|
||||||
@@ -179,8 +177,7 @@
|
|
||||||
\attention
|
|
||||||
The streamId of the rendition is used in getContentStream( )
|
|
||||||
*/
|
|
||||||
- virtual std::vector< RenditionPtr> getRenditions( std::string filter = std::string( ) )
|
|
||||||
- throw ( Exception );
|
|
||||||
+ virtual std::vector< RenditionPtr> getRenditions( std::string filter = std::string( ) );
|
|
||||||
virtual AllowableActionsPtr getAllowableActions( ) { return m_allowableActions; }
|
|
||||||
|
|
||||||
/** Update the object properties and return the updated object.
|
|
||||||
@@ -191,21 +188,21 @@
|
|
||||||
are still two different instances to ease memory handling.
|
|
||||||
*/
|
|
||||||
virtual boost::shared_ptr< Object > updateProperties(
|
|
||||||
- const PropertyPtrMap& properties ) throw ( Exception ) = 0;
|
|
||||||
+ const PropertyPtrMap& properties ) = 0;
|
|
||||||
|
|
||||||
virtual ObjectTypePtr getTypeDescription( );
|
|
||||||
|
|
||||||
/** Reload the data from the server.
|
|
||||||
*/
|
|
||||||
- virtual void refresh( ) throw ( Exception ) = 0;
|
|
||||||
+ virtual void refresh( ) = 0;
|
|
||||||
virtual time_t getRefreshTimestamp( ) { return m_refreshTimestamp; }
|
|
||||||
|
|
||||||
- virtual void remove( bool allVersions = true ) throw ( Exception ) = 0;
|
|
||||||
+ virtual void remove( bool allVersions = true ) = 0;
|
|
||||||
|
|
||||||
- virtual void move( boost::shared_ptr< Folder > source, boost::shared_ptr< Folder > destination ) throw ( Exception ) = 0;
|
|
||||||
+ virtual void move( boost::shared_ptr< Folder > source, boost::shared_ptr< Folder > destination ) = 0;
|
|
||||||
|
|
||||||
|
|
||||||
- virtual std::string getThumbnailUrl( ) throw ( Exception );
|
|
||||||
+ virtual std::string getThumbnailUrl( );
|
|
||||||
|
|
||||||
/** Dump the object as a string for debugging or display purpose.
|
|
||||||
*/
|
|
||||||
--- src/libcmis/object-type.cxx
|
|
||||||
+++ src/libcmis/object-type.cxx
|
|
||||||
@@ -293,22 +293,22 @@
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- void ObjectType::refresh( ) throw ( Exception )
|
|
||||||
+ void ObjectType::refresh( )
|
|
||||||
{
|
|
||||||
throw Exception( "ObjectType::refresh() shouldn't be called" );
|
|
||||||
}
|
|
||||||
|
|
||||||
- ObjectTypePtr ObjectType::getParentType( ) throw ( Exception )
|
|
||||||
+ ObjectTypePtr ObjectType::getParentType( )
|
|
||||||
{
|
|
||||||
throw Exception( "ObjectType::getParentType() shouldn't be called" );
|
|
||||||
}
|
|
||||||
|
|
||||||
- ObjectTypePtr ObjectType::getBaseType( ) throw ( Exception )
|
|
||||||
+ ObjectTypePtr ObjectType::getBaseType( )
|
|
||||||
{
|
|
||||||
throw Exception( "ObjectType::getBaseType() shouldn't be called" );
|
|
||||||
}
|
|
||||||
|
|
||||||
- vector< ObjectTypePtr > ObjectType::getChildren( ) throw ( Exception )
|
|
||||||
+ vector< ObjectTypePtr > ObjectType::getChildren( )
|
|
||||||
{
|
|
||||||
throw Exception( "ObjectType::getChildren() shouldn't be called" );
|
|
||||||
}
|
|
||||||
--- src/libcmis/object-type.hxx
|
|
||||||
+++ src/libcmis/object-type.hxx
|
|
||||||
@@ -94,7 +94,7 @@
|
|
||||||
This method needs to be implemented in subclasses or it will
|
|
||||||
do nothing
|
|
||||||
*/
|
|
||||||
- virtual void refresh( ) throw ( Exception );
|
|
||||||
+ virtual void refresh( );
|
|
||||||
virtual time_t getRefreshTimestamp( ) const;
|
|
||||||
|
|
||||||
std::string getId( ) const;
|
|
||||||
@@ -104,9 +104,9 @@
|
|
||||||
std::string getQueryName( ) const;
|
|
||||||
std::string getDescription( ) const;
|
|
||||||
|
|
||||||
- virtual boost::shared_ptr< ObjectType > getParentType( ) throw ( Exception );
|
|
||||||
- virtual boost::shared_ptr< ObjectType > getBaseType( ) throw ( Exception );
|
|
||||||
- virtual std::vector< boost::shared_ptr< ObjectType > > getChildren( ) throw ( Exception );
|
|
||||||
+ virtual boost::shared_ptr< ObjectType > getParentType( );
|
|
||||||
+ virtual boost::shared_ptr< ObjectType > getBaseType( );
|
|
||||||
+ virtual std::vector< boost::shared_ptr< ObjectType > > getChildren( );
|
|
||||||
|
|
||||||
/** Get the parent type id without extracting the complete parent type from
|
|
||||||
the repository. This is mainly provided for performance reasons.
|
|
||||||
--- src/libcmis/session-factory.cxx
|
|
||||||
+++ src/libcmis/session-factory.cxx
|
|
||||||
@@ -57,7 +57,7 @@
|
|
||||||
|
|
||||||
Session* SessionFactory::createSession( string bindingUrl, string username,
|
|
||||||
string password, string repository, bool noSslCheck,
|
|
||||||
- libcmis::OAuth2DataPtr oauth2, bool verbose ) throw ( Exception )
|
|
||||||
+ libcmis::OAuth2DataPtr oauth2, bool verbose )
|
|
||||||
{
|
|
||||||
Session* session = NULL;
|
|
||||||
|
|
||||||
@@ -138,7 +138,7 @@
|
|
||||||
}
|
|
||||||
|
|
||||||
vector< RepositoryPtr > SessionFactory::getRepositories( string bindingUrl,
|
|
||||||
- string username, string password, bool verbose ) throw ( Exception )
|
|
||||||
+ string username, string password, bool verbose )
|
|
||||||
{
|
|
||||||
vector< RepositoryPtr > repos;
|
|
||||||
|
|
||||||
--- src/libcmis/session-factory.hxx
|
|
||||||
+++ src/libcmis/session-factory.hxx
|
|
||||||
@@ -128,7 +128,7 @@
|
|
||||||
std::string password = std::string( ),
|
|
||||||
std::string repositoryId = std::string( ),
|
|
||||||
bool noSslCheck = false,
|
|
||||||
- OAuth2DataPtr oauth2 = OAuth2DataPtr(), bool verbose = false ) throw ( Exception );
|
|
||||||
+ OAuth2DataPtr oauth2 = OAuth2DataPtr(), bool verbose = false );
|
|
||||||
|
|
||||||
/**
|
|
||||||
Gets the informations of the repositories on the server.
|
|
||||||
@@ -142,7 +142,7 @@
|
|
||||||
static std::vector< RepositoryPtr > getRepositories( std::string bindingUrl,
|
|
||||||
std::string username = std::string( ),
|
|
||||||
std::string password = std::string( ),
|
|
||||||
- bool verbose = false ) throw ( Exception );
|
|
||||||
+ bool verbose = false );
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
--- src/libcmis/session.hxx
|
|
||||||
+++ src/libcmis/session.hxx
|
|
||||||
@@ -47,7 +47,7 @@
|
|
||||||
|
|
||||||
/** Get the current repository.
|
|
||||||
*/
|
|
||||||
- virtual RepositoryPtr getRepository( ) throw ( Exception ) = 0;
|
|
||||||
+ virtual RepositoryPtr getRepository( ) = 0;
|
|
||||||
|
|
||||||
virtual std::vector< RepositoryPtr > getRepositories( ) = 0;
|
|
||||||
|
|
||||||
@@ -61,27 +61,27 @@
|
|
||||||
|
|
||||||
/** Get the Root folder of the repository
|
|
||||||
*/
|
|
||||||
- virtual FolderPtr getRootFolder() throw ( Exception )= 0;
|
|
||||||
+ virtual FolderPtr getRootFolder() = 0;
|
|
||||||
|
|
||||||
/** Get a CMIS object from its ID.
|
|
||||||
*/
|
|
||||||
- virtual ObjectPtr getObject( std::string id ) throw ( Exception ) = 0;
|
|
||||||
+ virtual ObjectPtr getObject( std::string id ) = 0;
|
|
||||||
|
|
||||||
/** Get a CMIS object from one of its path.
|
|
||||||
*/
|
|
||||||
- virtual ObjectPtr getObjectByPath( std::string path ) throw ( Exception ) = 0;
|
|
||||||
+ virtual ObjectPtr getObjectByPath( std::string path ) = 0;
|
|
||||||
|
|
||||||
/** Get a CMIS folder from its ID.
|
|
||||||
*/
|
|
||||||
- virtual libcmis::FolderPtr getFolder( std::string id ) throw ( Exception ) = 0;
|
|
||||||
+ virtual libcmis::FolderPtr getFolder( std::string id ) = 0;
|
|
||||||
|
|
||||||
/** Get a CMIS object type from its ID.
|
|
||||||
*/
|
|
||||||
- virtual ObjectTypePtr getType( std::string id ) throw ( Exception ) = 0;
|
|
||||||
+ virtual ObjectTypePtr getType( std::string id ) = 0;
|
|
||||||
|
|
||||||
/** Get all the CMIS base object types known by the server.
|
|
||||||
*/
|
|
||||||
- virtual std::vector< ObjectTypePtr > getBaseTypes( ) throw ( Exception ) = 0;
|
|
||||||
+ virtual std::vector< ObjectTypePtr > getBaseTypes( ) = 0;
|
|
||||||
|
|
||||||
/** Enable or disable the SSL certificate verification.
|
|
||||||
|
|
||||||
--- src/libcmis/xml-utils.cxx
|
|
||||||
+++ src/libcmis/xml-utils.cxx
|
|
||||||
@@ -361,7 +361,6 @@
|
|
||||||
string getXmlNodeAttributeValue( xmlNodePtr node,
|
|
||||||
const char* attributeName,
|
|
||||||
const char* defaultValue )
|
|
||||||
- throw ( Exception )
|
|
||||||
{
|
|
||||||
xmlChar* xmlStr = xmlGetProp( node, BAD_CAST( attributeName ) );
|
|
||||||
if ( xmlStr == NULL )
|
|
||||||
@@ -450,7 +449,7 @@
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
- bool parseBool( string boolStr ) throw ( Exception )
|
|
||||||
+ bool parseBool( string boolStr )
|
|
||||||
{
|
|
||||||
bool value = false;
|
|
||||||
if ( boolStr == "true" || boolStr == "1" )
|
|
||||||
@@ -462,7 +461,7 @@
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
- long parseInteger( string intStr ) throw ( Exception )
|
|
||||||
+ long parseInteger( string intStr )
|
|
||||||
{
|
|
||||||
char* end;
|
|
||||||
errno = 0;
|
|
||||||
@@ -481,7 +480,7 @@
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
- double parseDouble( string doubleStr ) throw ( Exception )
|
|
||||||
+ double parseDouble( string doubleStr )
|
|
||||||
{
|
|
||||||
char* end;
|
|
||||||
errno = 0;
|
|
||||||
--- src/libcmis/xml-utils.hxx
|
|
||||||
+++ src/libcmis/xml-utils.hxx
|
|
||||||
@@ -132,8 +132,7 @@
|
|
||||||
*/
|
|
||||||
std::string getXmlNodeAttributeValue( xmlNodePtr node,
|
|
||||||
const char* attributeName,
|
|
||||||
- const char* defaultValue = NULL )
|
|
||||||
- throw ( Exception );
|
|
||||||
+ const char* defaultValue = NULL );
|
|
||||||
|
|
||||||
/** Parse a xsd:dateTime string and return the corresponding UTC posix time.
|
|
||||||
*/
|
|
||||||
@@ -142,11 +141,11 @@
|
|
||||||
/// Write a UTC time object to an xsd:dateTime string
|
|
||||||
std::string writeDateTime( boost::posix_time::ptime time );
|
|
||||||
|
|
||||||
- bool parseBool( std::string str ) throw ( Exception );
|
|
||||||
+ bool parseBool( std::string str );
|
|
||||||
|
|
||||||
- long parseInteger( std::string str ) throw ( Exception );
|
|
||||||
+ long parseInteger( std::string str );
|
|
||||||
|
|
||||||
- double parseDouble( std::string str ) throw ( Exception );
|
|
||||||
+ double parseDouble( std::string str );
|
|
||||||
|
|
||||||
/** Trim spaces on the left and right of a string.
|
|
||||||
*/
|
|
@@ -1,32 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
|
|
125
external/libcmis/libcmis-fix-google-drive-2.patch
vendored
125
external/libcmis/libcmis-fix-google-drive-2.patch
vendored
@@ -1,125 +0,0 @@
|
|||||||
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) )
|
|
||||||
|
|
106
external/libcmis/libcmis-fix-google-drive.patch
vendored
106
external/libcmis/libcmis-fix-google-drive.patch
vendored
@@ -1,106 +0,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~
|
|
@@ -1,177 +0,0 @@
|
|||||||
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
|
+#define HTML_PARSE_RECOVER 0
|
||||||
+#endif
|
+#endif
|
||||||
+
|
+
|
||||||
string OAuth2Providers::OAuth2Gdrive( HttpSession* session, const string& authUrl,
|
namespace {
|
||||||
const string& username, const string& password )
|
|
||||||
{
|
// Encodes the given data according to the application/x-www-form-urlencoded format, see
|
||||||
|
@@ -1,24 +0,0 @@
|
|||||||
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";
|
|
59
external/libcmis/xwwwformurlencoded.patch.0
vendored
59
external/libcmis/xwwwformurlencoded.patch.0
vendored
@@ -1,59 +0,0 @@
|
|||||||
--- 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"
|
"dest-filename": "external/tarballs/libcdr-0.1.4.tar.xz"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "https://dev-www.libreoffice.org/src/libcmis-0.5.1.tar.gz",
|
"url": "https://dev-www.libreoffice.org/src/libcmis-0.5.2.tar.xz",
|
||||||
"sha256": "6acbdf22ecdbaba37728729b75bfc085ee5a4b49a6024757cfb86ccd3da27b0e",
|
"sha256": "d7b18d9602190e10d437f8a964a32e983afd57e2db316a07d87477a79f5000a2",
|
||||||
"type": "file",
|
"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",
|
"url": "https://dev-www.libreoffice.org/src/libe-book-0.1.3.tar.xz",
|
||||||
|
Reference in New Issue
Block a user