Try to replace avhttp by Curl
This commit is contained in:
parent
5127a6bd09
commit
981fddc649
|
@ -569,6 +569,10 @@ if( NOT GLEW_FOUND )
|
|||
check_find_package_result( GLEW_FOUND "GLEW" )
|
||||
endif()
|
||||
|
||||
# Find CURL library
|
||||
find_package( CURL REQUIRED )
|
||||
|
||||
|
||||
######################
|
||||
# Find Cairo library #
|
||||
######################
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
# This program source code file is part of KICAD, a free EDA CAD application.
|
||||
#
|
||||
# Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
# Copyright (C) 2013 Kicad Developers, see AUTHORS.txt for contributors.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, you may find one here:
|
||||
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
# or you may search the http://www.gnu.org website for the version 2 license,
|
||||
# or you may write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
|
||||
|
||||
# Download av_http and install into ${PREFIX}, typically in our KiCad source tree.
|
||||
# Assumes include( ExternalProject ) was done inline previous to this file
|
||||
# and that set( DOWNLOAD_DIR ... ) was set in a higher context.
|
||||
|
||||
#-----<configure>-------------------------------------------------------------------------------------
|
||||
|
||||
# soon cmake will have https support, switch to a true download then:
|
||||
#set( AVHTTP_RELEASE ??? )
|
||||
#set( AVHTTP_MD5 ???? ) # re-calc this on every RELEASE change
|
||||
|
||||
#-----</configure>-----------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# Where the library is to be installed.
|
||||
set( PREFIX ${DOWNLOAD_DIR}/avhttp )
|
||||
|
||||
if( KICAD_SKIP_BOOST )
|
||||
set( AVHTTP_DEPEND "" )
|
||||
else()
|
||||
set( AVHTTP_DEPEND "boost" )
|
||||
endif()
|
||||
|
||||
|
||||
# Install the AVHTTP header only library ${PREFIX}
|
||||
ExternalProject_Add( avhttp
|
||||
PREFIX ${PREFIX}
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR} # no true download yet
|
||||
|
||||
# grab it from a local zip file for now, cmake caller's source dir
|
||||
URL ${CMAKE_CURRENT_SOURCE_DIR}/avhttp-master.zip
|
||||
DEPENDS ${AVHTTP_DEPEND}
|
||||
|
||||
CONFIGURE_COMMAND ""
|
||||
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory <SOURCE_DIR> <INSTALL_DIR>
|
||||
)
|
||||
|
||||
|
||||
set( AVHTTP_INCLUDE_DIR "${PREFIX}/include" CACHE FILEPATH "AVHTTP include directory" )
|
||||
mark_as_advanced( AVHTTP_INCLUDE_DIR )
|
|
@ -78,14 +78,6 @@ specific patches required to build a working Boost library. These patches can b
|
|||
[patches folder][] in the KiCad source. These patches are named by the platform name they should
|
||||
be applied against.
|
||||
|
||||
## OpenSSL Secure Socket Layer Library ## {#openssl}
|
||||
|
||||
The [OpenSSL][] library is only required when the KiCad build is configured with the Github plugin
|
||||
enabled. See the [KiCad Build Configuration Options](#build_opts)` section for more information.
|
||||
Please note that KiCad will download and build version 1.0.1e of OpenSSL by default. You should
|
||||
probably use the version of OpenSSL installed on your system as it will most likely be more up to
|
||||
date and contain the latest security fixes.
|
||||
|
||||
## GLEW OpenGL Extension Wrangler Library ## {#glew}
|
||||
|
||||
The [OpenGL Extension Wrangler][GLEW] is an OpenGL helper library used by the KiCad graphics
|
||||
|
@ -299,7 +291,7 @@ the following commands:
|
|||
mingw-w64-x86_64-boost \
|
||||
mingw-w64-x86_64-cairo \
|
||||
mingw-w64-x86_64-glew \
|
||||
mingw-w64-x86_64-openssl \
|
||||
mingw-w64-x86_64-curl \
|
||||
mingw-w64-x86_64-wxPython \
|
||||
mingw-w64-x86_64-wxWidgets
|
||||
cd kicad-source
|
||||
|
@ -311,7 +303,6 @@ the following commands:
|
|||
-DCMAKE_PREFIX_PATH=/mingw64 \
|
||||
-DCMAKE_INSTALL_PREFIX=/mingw64 \
|
||||
-DDEFAULT_INSTALL_PATH=/mingw64 \
|
||||
-DOPENSSL_ROOT_DIR=/mingw64 \
|
||||
-DKICAD_SKIP_BOOST=ON \
|
||||
-DKICAD_SCRIPTING=ON \
|
||||
-DKICAD_SCRIPTING_MODULES=ON \
|
||||
|
@ -408,7 +399,6 @@ Boost patches in the KiCad source [patch folder][].
|
|||
[wxWidgets]: http://wxwidgets.org/
|
||||
[patches folder]: http://bazaar.launchpad.net/~kicad-product-committers/kicad/product/files/head:/patches/
|
||||
[Boost]: http://www.boost.org/
|
||||
[OpenSSL]: https://www.openssl.org/
|
||||
[GLEW]: http://glew.sourceforge.net/
|
||||
[GLUT]: https://www.opengl.org/resources/libraries/glut/
|
||||
[Cairo]: http://cairographics.org/
|
||||
|
|
|
@ -10,6 +10,12 @@ include_directories(
|
|||
${INC_AFTER}
|
||||
)
|
||||
|
||||
|
||||
if( NOT APPLE ) # windows and linux use openssl under curl
|
||||
find_package( OpenSSL REQUIRED )
|
||||
endif()
|
||||
|
||||
|
||||
# Generate header files containing shader programs
|
||||
# Order of input files is significant
|
||||
add_custom_command(
|
||||
|
@ -257,6 +263,9 @@ endif()
|
|||
|
||||
set( COMMON_SRCS
|
||||
${COMMON_SRCS}
|
||||
kicad_curl/kicad_curl.cpp
|
||||
kicad_curl/kicad_curl_easy.cpp
|
||||
|
||||
view/view.cpp
|
||||
view/view_item.cpp
|
||||
view/view_group.cpp
|
||||
|
@ -282,7 +291,11 @@ set( COMMON_SRCS
|
|||
add_library( common STATIC ${COMMON_SRCS} )
|
||||
add_dependencies( common lib-dependencies )
|
||||
add_dependencies( common version_header )
|
||||
target_link_libraries( common ${Boost_LIBRARIES} )
|
||||
target_link_libraries( common
|
||||
${Boost_LIBRARIES}
|
||||
${CURL_LIBRARIES}
|
||||
${OPENSSL_LIBRARIES} # empty on Apple
|
||||
)
|
||||
|
||||
|
||||
set( PCB_COMMON_SRCS
|
||||
|
|
|
@ -27,6 +27,14 @@
|
|||
* @file basicframe.cpp
|
||||
* @brief EDA_BASE_FRAME class implementation.
|
||||
*/
|
||||
#include <config.h>
|
||||
|
||||
// kicad_curl.h must be included before wx headers, to avoid
|
||||
// conflicts for some defines, at least on Windows
|
||||
#ifdef BUILD_GITHUB_PLUGIN
|
||||
#include <curl/curlver.h>
|
||||
#include <kicad_curl/kicad_curl.h>
|
||||
#endif
|
||||
|
||||
#include <wx/aboutdlg.h>
|
||||
#include <wx/fontdlg.h>
|
||||
|
@ -580,6 +588,11 @@ void EDA_BASE_FRAME::CopyVersionInfoToClipboard( wxCommandEvent& event )
|
|||
<< ( BOOST_VERSION / 100 % 1000 ) << wxT( "." )
|
||||
<< ( BOOST_VERSION % 100 ) << wxT( "\n" );
|
||||
|
||||
#ifdef BUILD_GITHUB_PLUGIN
|
||||
// Shows the Curl library version in use:
|
||||
msg_version << "Curl version: " << KICAD_CURL::GetVersion() << "\n";
|
||||
#endif
|
||||
|
||||
msg_version << wxT( " USE_WX_GRAPHICS_CONTEXT=" );
|
||||
#ifdef USE_WX_GRAPHICS_CONTEXT
|
||||
msg_version << wxT( "ON\n" );
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2011 Jean-Pierre Charras, <jp.charras@wanadoo.fr>
|
||||
* Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 2013-2016 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -28,7 +28,12 @@
|
|||
*/
|
||||
|
||||
|
||||
#define USE_WORKER_THREADS 1 // 1:yes, 0:no. use worker thread to load libraries
|
||||
/**
|
||||
No. concurrent threads doing "http(s) GET". More than 6 is not significantly
|
||||
faster, less than 6 is likely slower. Main thread is in this count, so if
|
||||
set to 1 then no temp threads are created.
|
||||
*/
|
||||
#define READER_THREADS 6
|
||||
|
||||
/*
|
||||
* Functions to read footprint libraries and fill m_footprints by available footprints names
|
||||
|
@ -120,13 +125,6 @@ void FOOTPRINT_INFO::load()
|
|||
}
|
||||
|
||||
|
||||
#define JOBZ 6 // no. libraries per worker thread. It takes about
|
||||
// a second to load a GITHUB library, so assigning
|
||||
// this no. libraries to each thread should give a little
|
||||
// over this no. seconds total time if the original delay
|
||||
// were caused by latencies alone.
|
||||
// (If https://github.com does not mind.)
|
||||
|
||||
void FOOTPRINT_LIST::loader_job( const wxString* aNicknameList, int aJobZ )
|
||||
{
|
||||
for( int i=0; i<aJobZ; ++i )
|
||||
|
@ -204,8 +202,6 @@ bool FOOTPRINT_LIST::ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* a
|
|||
// do all of them
|
||||
nicknames = aTable->GetLogicalLibs();
|
||||
|
||||
#if USE_WORKER_THREADS
|
||||
|
||||
// Even though the PLUGIN API implementation is the place for the
|
||||
// locale toggling, in order to keep LOCAL_IO::C_count at 1 or greater
|
||||
// for the duration of all helper threads, we increment by one here via instantiation.
|
||||
|
@ -221,22 +217,23 @@ bool FOOTPRINT_LIST::ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* a
|
|||
|
||||
MYTHREADS threads;
|
||||
|
||||
unsigned jobz = (nicknames.size() + READER_THREADS - 1) / READER_THREADS;
|
||||
|
||||
// Give each thread JOBZ nicknames to process. The last portion of, or if the entire
|
||||
// size() is small, I'll do myself.
|
||||
for( unsigned i=0; i<nicknames.size(); )
|
||||
{
|
||||
int jobz = JOBZ;
|
||||
|
||||
if( i + jobz >= nicknames.size() ) // on the last iteration of this for(;;)
|
||||
{
|
||||
jobz = nicknames.size() - i;
|
||||
|
||||
// Only a little bit to do, I'll do it myself, on current thread.
|
||||
// Only a little bit to do, I'll do it myself on current thread.
|
||||
// I am part of the READER_THREADS count.
|
||||
loader_job( &nicknames[i], jobz );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Delegate the job to a worker thread created here.
|
||||
// Delegate the job to a temporary thread created here.
|
||||
threads.push_back( new boost::thread( &FOOTPRINT_LIST::loader_job,
|
||||
this, &nicknames[i], jobz ) );
|
||||
}
|
||||
|
@ -251,9 +248,6 @@ bool FOOTPRINT_LIST::ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* a
|
|||
{
|
||||
threads[i].join();
|
||||
}
|
||||
#else
|
||||
loader_job( &nicknames[0], nicknames.size() );
|
||||
#endif
|
||||
|
||||
m_list.sort();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mark Roszko <mark.roszko@gmail.com>
|
||||
* Copyright (C) 2016 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 2015 KiCad Developers, see CHANGELOG.TXT for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 3
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
// kicad_curl.h must be included before wx headers, to avoid
|
||||
// conflicts for some defines, at least on Windows
|
||||
#include <kicad_curl/kicad_curl.h>
|
||||
|
||||
#include <wx/log.h>
|
||||
#include <wx/dynlib.h>
|
||||
|
||||
#include <macros.h>
|
||||
#include <fctsys.h>
|
||||
#include <ki_mutex.h> // MUTEX and MUTLOCK
|
||||
#include <richio.h>
|
||||
|
||||
|
||||
|
||||
// These are even more private than class members, and since there is only
|
||||
// one instance of KICAD_CURL ever, these statics are hidden here to simplify the
|
||||
// client (API) header file.
|
||||
static volatile bool s_initialized;
|
||||
|
||||
static MUTEX s_lock; // for s_initialized
|
||||
|
||||
// Assume that on these platforms libcurl uses OpenSSL
|
||||
#if defined(__linux__) || defined(__MINGW32__)
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
static MUTEX* s_crypto_locks;
|
||||
|
||||
static void lock_callback( int mode, int type, const char* file, int line )
|
||||
{
|
||||
(void)file;
|
||||
(void)line;
|
||||
|
||||
wxASSERT( s_crypto_locks && unsigned( type ) < unsigned( CRYPTO_num_locks() ) );
|
||||
|
||||
//DBG( printf( "%s: mode=0x%x type=%d file=%s line=%d\n", __func__, mode, type, file, line );)
|
||||
|
||||
if( mode & CRYPTO_LOCK )
|
||||
{
|
||||
s_crypto_locks[ type ].lock();
|
||||
}
|
||||
else
|
||||
{
|
||||
s_crypto_locks[ type ].unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void init_locks()
|
||||
{
|
||||
s_crypto_locks = new MUTEX[ CRYPTO_num_locks() ];
|
||||
|
||||
// From http://linux.die.net/man/3/crypto_set_id_callback:
|
||||
|
||||
/*
|
||||
|
||||
OpenSSL can safely be used in multi-threaded applications provided that at
|
||||
least two callback functions are set, locking_function and threadid_func.
|
||||
|
||||
locking_function(int mode, int n, const char *file, int line) is needed to
|
||||
perform locking on shared data structures. (Note that OpenSSL uses a number
|
||||
of global data structures that will be implicitly shared whenever multiple
|
||||
threads use OpenSSL.) Multi-threaded applications will crash at random if it
|
||||
is not set.
|
||||
|
||||
threadid_func( CRYPTO_THREADID *id) is needed to record the
|
||||
currently-executing thread's identifier into id. The implementation of this
|
||||
callback should not fill in id directly, but should use
|
||||
CRYPTO_THREADID_set_numeric() if thread IDs are numeric, or
|
||||
CRYPTO_THREADID_set_pointer() if they are pointer-based. If the application
|
||||
does not register such a callback using CRYPTO_THREADID_set_callback(), then
|
||||
a default implementation is used - on Windows and BeOS this uses the
|
||||
system's default thread identifying APIs, and on all other platforms it uses
|
||||
the address of errno. The latter is satisfactory for thread-safety if and
|
||||
only if the platform has a thread-local error number facility.
|
||||
|
||||
Dick: "sounds like CRYPTO_THREADID_set_callback() is not mandatory on our
|
||||
2 OpenSSL platforms."
|
||||
|
||||
*/
|
||||
|
||||
CRYPTO_set_locking_callback( &lock_callback );
|
||||
}
|
||||
|
||||
|
||||
static void kill_locks()
|
||||
{
|
||||
CRYPTO_set_locking_callback( NULL );
|
||||
|
||||
delete[] s_crypto_locks;
|
||||
|
||||
s_crypto_locks = NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline void init_locks() { /* dummy */ }
|
||||
inline void kill_locks() { /* dummy */ }
|
||||
|
||||
#endif
|
||||
|
||||
/// At process termination, using atexit() keeps the CURL stuff out of the
|
||||
/// singletops and PGM_BASE.
|
||||
static void at_terminate()
|
||||
{
|
||||
KICAD_CURL::Cleanup();
|
||||
}
|
||||
|
||||
|
||||
void KICAD_CURL::Init()
|
||||
{
|
||||
// We test s_initialized twice in an effort to avoid
|
||||
// unnecessarily locking s_lock. This understands that the common case
|
||||
// will not need to lock.
|
||||
if( !s_initialized )
|
||||
{
|
||||
MUTLOCK lock( s_lock );
|
||||
|
||||
if( !s_initialized )
|
||||
{
|
||||
if( curl_global_init( CURL_GLOBAL_ALL ) != CURLE_OK )
|
||||
{
|
||||
THROW_IO_ERROR( "curl_global_init() failed." );
|
||||
}
|
||||
|
||||
init_locks();
|
||||
|
||||
wxLogDebug( "Using %s", GetVersion() );
|
||||
|
||||
s_initialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void KICAD_CURL::Cleanup()
|
||||
{
|
||||
/*
|
||||
|
||||
Calling MUTLOCK() from a static destructor will typically be bad, since the
|
||||
s_lock may already have been statically destroyed itself leading to a boost
|
||||
exception. (Remember C++ does not provide certain sequencing of static
|
||||
destructor invocation.)
|
||||
|
||||
To prevent this we test s_initialized twice, which ensures that the MUTLOCK
|
||||
is only instantiated on the first call, which should be from
|
||||
PGM_BASE::destroy() which is first called earlier than static destruction.
|
||||
Then when called again from the actual PGM_BASE::~PGM_BASE() function,
|
||||
MUTLOCK will not be instantiated because s_initialized will be false.
|
||||
|
||||
*/
|
||||
|
||||
if( s_initialized )
|
||||
{
|
||||
MUTLOCK lock( s_lock );
|
||||
|
||||
if( s_initialized )
|
||||
{
|
||||
curl_global_cleanup();
|
||||
|
||||
kill_locks();
|
||||
|
||||
atexit( &at_terminate );
|
||||
|
||||
s_initialized = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string KICAD_CURL::GetSimpleVersion()
|
||||
{
|
||||
if( !s_initialized )
|
||||
Init();
|
||||
|
||||
curl_version_info_data* info = curl_version_info( CURLVERSION_NOW );
|
||||
|
||||
std::string res;
|
||||
|
||||
if( info->version )
|
||||
{
|
||||
res += "libcurl version: " + std::string( info->version );
|
||||
}
|
||||
|
||||
res += " (";
|
||||
|
||||
if( info->features & CURL_VERSION_SSL )
|
||||
{
|
||||
res += "with SSL - ";
|
||||
res += std::string( info->ssl_version );
|
||||
}
|
||||
else
|
||||
{
|
||||
res += "without SSL";
|
||||
}
|
||||
res += ")";
|
||||
|
||||
return res;
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mark Roszko <mark.roszko@gmail.com>
|
||||
* Copyright (C) 2015 KiCad Developers, see CHANGELOG.TXT for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 3
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <kicad_curl/kicad_curl_easy.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <stdarg.h>
|
||||
#include <sstream>
|
||||
#include <richio.h>
|
||||
|
||||
|
||||
static size_t write_callback( void* contents, size_t size, size_t nmemb, void* userp )
|
||||
{
|
||||
size_t realsize = size * nmemb;
|
||||
|
||||
std::string* p = (std::string*) userp;
|
||||
|
||||
p->append( (const char*) contents, realsize );
|
||||
|
||||
return realsize;
|
||||
}
|
||||
|
||||
|
||||
KICAD_CURL_EASY::KICAD_CURL_EASY() :
|
||||
m_headers( NULL )
|
||||
{
|
||||
// Call KICAD_CURL::Init() from in here everytime, but only the first time
|
||||
// will incur any overhead. This strategy ensures that libcurl is never loaded
|
||||
// unless it is needed.
|
||||
|
||||
KICAD_CURL::Init();
|
||||
|
||||
m_CURL = curl_easy_init();
|
||||
|
||||
if( !m_CURL )
|
||||
{
|
||||
THROW_IO_ERROR( "Unable to initialize CURL session" );
|
||||
}
|
||||
|
||||
curl_easy_setopt( m_CURL, CURLOPT_WRITEFUNCTION, write_callback );
|
||||
curl_easy_setopt( m_CURL, CURLOPT_WRITEDATA, (void*) &m_buffer );
|
||||
}
|
||||
|
||||
|
||||
KICAD_CURL_EASY::~KICAD_CURL_EASY()
|
||||
{
|
||||
if( m_headers )
|
||||
curl_slist_free_all( m_headers );
|
||||
|
||||
curl_easy_cleanup( m_CURL );
|
||||
}
|
||||
|
||||
|
||||
void KICAD_CURL_EASY::Perform()
|
||||
{
|
||||
if( m_headers )
|
||||
{
|
||||
curl_easy_setopt( m_CURL, CURLOPT_HTTPHEADER, m_headers );
|
||||
}
|
||||
|
||||
// bonus: retain worst case memory allocation, should re-use occur
|
||||
m_buffer.clear();
|
||||
|
||||
CURLcode res = curl_easy_perform( m_CURL );
|
||||
|
||||
if( res != CURLE_OK )
|
||||
{
|
||||
std::string msg = StrPrintf( "curl_easy_perform()=%d: %s",
|
||||
res, GetErrorText( res ).c_str() );
|
||||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mark Roszko <mark.roszko@gmail.com>
|
||||
* Copyright (C) 2015 KiCad Developers, see CHANGELOG.TXT for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 3
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
#ifndef KICAD_CURL_H_
|
||||
#define KICAD_CURL_H_
|
||||
|
||||
/*
|
||||
* KICAD_CURL.h must be included before wxWidgets because on Windows,
|
||||
* wxWidgets ends up including windows.h before winsocks2.h inside curl
|
||||
* this causes build warnings
|
||||
* Because we are before wx, we must explicitly define we are building with unicode.
|
||||
* wxWidgets defaults to supporting unicode now, so this should be safe.
|
||||
*/
|
||||
#if defined(WIN32)
|
||||
#ifndef UNICODE
|
||||
# define UNICODE
|
||||
#endif
|
||||
|
||||
#ifndef _UNICODE
|
||||
# define _UNICODE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <string>
|
||||
|
||||
// CURL_EXTERN expands to dllimport on MinGW which causes gcc warnings. This really should
|
||||
// expand to nothing on MinGW.
|
||||
#if defined( __MINGW32__)
|
||||
# if defined( CURL_EXTERN )
|
||||
# undef CURL_EXTERN
|
||||
# define CURL_EXTERN
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
struct DYN_LOOKUP;
|
||||
|
||||
|
||||
/**
|
||||
* Class KICAD_CURL
|
||||
* simple wrapper class to call curl_global_init and curl_global_cleanup for KiCad.
|
||||
*/
|
||||
class KICAD_CURL
|
||||
{
|
||||
friend class KICAD_CURL_EASY;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Function Init
|
||||
* calls curl_global_init for the application. It must be used only once
|
||||
* and before any curl functions that perform requests.
|
||||
*
|
||||
* @return bool - True if successful, false if CURL returned an error
|
||||
* @throw IO_ERROR on failure, hopefully with helpful text in it.
|
||||
*/
|
||||
static void Init();
|
||||
|
||||
/**
|
||||
* Function Cleanup
|
||||
* calls curl_global_cleanup for the application. It must be used only after
|
||||
* curl_global_init was called.
|
||||
*/
|
||||
static void Cleanup();
|
||||
|
||||
/**
|
||||
* Function GetVersion
|
||||
* wrapper for curl_version(). Reports back a short string of loaded libraries.
|
||||
*
|
||||
* @return const char* - String reported by libcurl and owned by it.
|
||||
* @throw IO_ERROR on failure, hopefully with helpful text in it.
|
||||
*/
|
||||
static const char* GetVersion()
|
||||
{
|
||||
return curl_version();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function GetSimpleVersion
|
||||
* Reports back curl version only and SSL library support
|
||||
*
|
||||
* @return std::string - Generated version string
|
||||
*/
|
||||
static std::string GetSimpleVersion();
|
||||
};
|
||||
|
||||
#endif // KICAD_CURL_H_
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mark Roszko <mark.roszko@gmail.com>
|
||||
* Copyright (C) 2015 KiCad Developers, see CHANGELOG.TXT for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 3
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
#ifndef KICAD_CURL_EASY_H_
|
||||
#define KICAD_CURL_EASY_H_
|
||||
|
||||
/*
|
||||
* KICAD_CURL_EASY.h must included before wxWidgets because on Windows,
|
||||
* wxWidgets ends up including windows.h before winsocks2.h inside curl
|
||||
* this causes build warnings
|
||||
* Because we are before wx, we must explicitly define we are building with unicode
|
||||
* wxWidgets defaults to supporting unicode now, so this should be safe.
|
||||
*/
|
||||
#if defined(WIN32)
|
||||
#ifndef UNICODE
|
||||
# define UNICODE
|
||||
#endif
|
||||
|
||||
#ifndef _UNICODE
|
||||
# define _UNICODE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <curl/curl.h>
|
||||
#include <kicad_curl/kicad_curl.h>
|
||||
|
||||
|
||||
/**
|
||||
* Class KICAD_CURL_EASY
|
||||
* wrapper interface around the curl_easy API
|
||||
*
|
||||
* Handling of using the curl_easy API to make a request and save the response to
|
||||
* a memory buffer
|
||||
*
|
||||
* Here is a small example usage:
|
||||
* @code
|
||||
* KICAD_CURL_EASY curl;
|
||||
*
|
||||
* curl.SetURL( "http://github.com" );
|
||||
* curl.SetUserAgent( <http-client-indentifier> );
|
||||
* curl.SetHeader( "Accept", "application/json" );
|
||||
* curl.Perform();
|
||||
* @endcode
|
||||
*/
|
||||
class KICAD_CURL_EASY
|
||||
{
|
||||
public:
|
||||
KICAD_CURL_EASY();
|
||||
~KICAD_CURL_EASY();
|
||||
|
||||
/**
|
||||
* Function perform
|
||||
* equivalent to curl_easy_perform. Executes the request
|
||||
* that was previously setup.
|
||||
*
|
||||
* @throw IO_ERROR, if there is a CURL request error
|
||||
*/
|
||||
void Perform();
|
||||
|
||||
/**
|
||||
* Function SetHeader
|
||||
* sets an arbitrary header for the HTTP(s) request.
|
||||
*
|
||||
* @param aName is the left hand side of the header, i.e. Accept without the colon
|
||||
* @param aValue is the right hand side of the header, i.e. application/json
|
||||
*/
|
||||
void SetHeader( const std::string& aName, const std::string& aValue )
|
||||
{
|
||||
std::string header = aName + ':' + aValue;
|
||||
m_headers = curl_slist_append( m_headers, header.c_str() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Function SetUserAgent
|
||||
* sets the request user agent
|
||||
*
|
||||
* @param aAgent is the string to set for the user agent
|
||||
* @return bool - True if successful, false if not
|
||||
*/
|
||||
bool SetUserAgent( const std::string& aAgent )
|
||||
{
|
||||
if( SetOption<const char*>( CURLOPT_USERAGENT, aAgent.c_str() ) == CURLE_OK )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function SetURL
|
||||
* sets the request URL
|
||||
*
|
||||
* @param aURL is the URL
|
||||
* @return bool - True if successful, false if not
|
||||
*/
|
||||
bool SetURL( const std::string& aURL )
|
||||
{
|
||||
if( SetOption<const char *>( CURLOPT_URL, aURL.c_str() ) == CURLE_OK )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function SetFollowRedirects
|
||||
* enables the following of HTTP(s) and other redirects, by default curl
|
||||
* does not follow redirects.
|
||||
*
|
||||
* @param aFollow is a boolean where true will enable following redirects
|
||||
* @return bool - True if successful, false if not
|
||||
*/
|
||||
bool SetFollowRedirects( bool aFollow )
|
||||
{
|
||||
if( SetOption<long>( CURLOPT_FOLLOWLOCATION , (aFollow ? 1 : 0) ) == CURLE_OK )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function GetErrorText
|
||||
* fetches CURL's "friendly" error string for a given error code
|
||||
*
|
||||
* @param aCode is CURL error code
|
||||
* @return const std::string - the corresponding error string for the given code
|
||||
*/
|
||||
const std::string GetErrorText( CURLcode aCode )
|
||||
{
|
||||
return curl_easy_strerror( aCode );
|
||||
}
|
||||
|
||||
/**
|
||||
* Function SetOption
|
||||
* sets a curl option, only supports single parameter curl options
|
||||
*
|
||||
* @param aOption is CURL option, see CURL manual for options
|
||||
* @param aArg is the argument being passed to CURL, ensure it is the right type per manual
|
||||
* @return CURLcode - CURL error code, will return CURLE_OK unless a problem was encountered
|
||||
*/
|
||||
template <typename T> CURLcode SetOption( CURLoption aOption, T aArg )
|
||||
{
|
||||
return curl_easy_setopt( m_CURL, aOption, aArg );
|
||||
}
|
||||
|
||||
/**
|
||||
* Function GetBuffer
|
||||
* returns a const reference to the recevied data buffer
|
||||
*/
|
||||
const std::string& GetBuffer()
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
private:
|
||||
CURL* m_CURL;
|
||||
curl_slist* m_headers;
|
||||
std::string m_buffer;
|
||||
};
|
||||
|
||||
#endif // KICAD_CURL_EASY_H_
|
|
@ -424,11 +424,11 @@ if( KICAD_SCRIPTING_MODULES )
|
|||
pcad2kicadpcb
|
||||
lib_dxf
|
||||
idf3
|
||||
${GITHUB_PLUGIN_LIBRARIES}
|
||||
polygon
|
||||
bitmaps
|
||||
gal
|
||||
${wxWidgets_LIBRARIES}
|
||||
${GITHUB_PLUGIN_LIBRARIES}
|
||||
${GDI_PLUS_LIBRARIES}
|
||||
${PYTHON_LIBRARIES}
|
||||
${PCBNEW_EXTRA_LIBS}
|
||||
|
@ -594,8 +594,8 @@ target_link_libraries( pcbnew_kiface
|
|||
gal
|
||||
lib_dxf
|
||||
idf3
|
||||
${GITHUB_PLUGIN_LIBRARIES}
|
||||
${wxWidgets_LIBRARIES}
|
||||
${GITHUB_PLUGIN_LIBRARIES}
|
||||
${GDI_PLUS_LIBRARIES}
|
||||
${PYTHON_LIBRARIES}
|
||||
${Boost_LIBRARIES} # must follow GITHUB
|
||||
|
|
|
@ -22,44 +22,21 @@
|
|||
|
||||
|
||||
|
||||
# Download avhttp and install the headers, not actually compiled
|
||||
#################################################
|
||||
include( download_avhttp )
|
||||
|
||||
if( MINGW AND NOT OPENSSL_ROOT_DIR )
|
||||
# download, compile and install to scratch dir a recent OPENSSL library and headers
|
||||
include( download_openssl )
|
||||
else()
|
||||
find_package( OpenSSL REQUIRED )
|
||||
#message( STATUS "OPENSSL_FOUND:${OPENSSL_FOUND} OPENSSL_LIBRARIES:${OPENSSL_LIBRARIES}" )
|
||||
|
||||
# FindOpenSSL.cmake does not set this var into cache, so is not globally visible,
|
||||
# do it here incase some other link image needs these libraries
|
||||
set( OPENSSL_LIBRARIES "${OPENSSL_LIBRARIES}" CACHE FILEPATH "OpenSSL link libraries" )
|
||||
set( OPENSSL_INCLUDE_DIR "${OPENSSL_INCLUDE_DIR}" CACHE FILEPATH "OpenSSL include dir" )
|
||||
endif()
|
||||
|
||||
|
||||
# These are additions to any inherited from pcbnew dir:
|
||||
include_directories( . ${OPENSSL_INCLUDE_DIR} ${AVHTTP_INCLUDE_DIR} )
|
||||
include_directories( . )
|
||||
|
||||
# Tell AVHTTP we have SSL.
|
||||
add_definitions( -DAVHTTP_ENABLE_OPENSSL )
|
||||
|
||||
# tone down the compiler warnings for avhttp header library:
|
||||
set( CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -Wno-sign-compare -Wno-reorder -Wno-unused-variable -Wno-unused-function -Wno-strict-aliasing" )
|
||||
include_directories( ${CURL_INCLUDE_DIRS} )
|
||||
|
||||
set( GITHUB_PLUGIN_SRCS
|
||||
github_plugin.cpp github_getliblist.cpp html_link_parser.cpp
|
||||
github_plugin.cpp
|
||||
github_getliblist.cpp
|
||||
html_link_parser.cpp
|
||||
)
|
||||
|
||||
add_library( github_plugin STATIC ${GITHUB_PLUGIN_SRCS} )
|
||||
|
||||
# No, you don't get github without boost and openssl. Boost_LIBRARIES now moved up
|
||||
# into CMakeLists.txt for pcbnew and cvpcb:
|
||||
target_link_libraries( github_plugin
|
||||
${OPENSSL_LIBRARIES}
|
||||
common
|
||||
)
|
||||
|
||||
if( MINGW )
|
||||
|
@ -70,9 +47,4 @@ if( MINGW )
|
|||
endif()
|
||||
|
||||
add_dependencies( github_plugin boost )
|
||||
add_dependencies( github_plugin avhttp )
|
||||
|
||||
if( MINGW AND NOT OPENSSL_ROOT_DIR )
|
||||
add_dependencies( github_plugin openssl )
|
||||
endif()
|
||||
|
||||
|
|
|
@ -41,35 +41,7 @@
|
|||
* JP Charras.
|
||||
*/
|
||||
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* FIX ME
|
||||
* I do not include avhttp.hpp here, because it is already included in
|
||||
* github_plugin.cpp
|
||||
* and if it is also included in this file, the link fails (double definiton of modules)
|
||||
* therefore, the GITHUB_GETLIBLIST method which uses avhttp to download dats from gitub
|
||||
* is in github_plugin.cpp
|
||||
*/
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
// when WIN32_LEAN_AND_MEAN is defined, some useless includes in <window.h>
|
||||
// are skipped, and this avoid some compil issues
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
// defines needed by avhttp
|
||||
// Minimal Windows version is XP: Google for _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#define WINVER 0x0501
|
||||
#endif
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <avhttp.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
#include <kicad_curl/kicad_curl_easy.h> // Include before any wx file
|
||||
#include <wx/uri.h>
|
||||
|
||||
#include <github_getliblist.h>
|
||||
|
@ -90,6 +62,7 @@ bool GITHUB_GETLIBLIST::Get3DshapesLibsList( wxArrayString* aList,
|
|||
bool (*aFilter)( const wxString& aData ) )
|
||||
{
|
||||
std::string fullURLCommand;
|
||||
|
||||
strcpy( m_option_string, "text/html" );
|
||||
|
||||
wxString repoURL = m_repoURL;
|
||||
|
@ -97,7 +70,7 @@ bool GITHUB_GETLIBLIST::Get3DshapesLibsList( wxArrayString* aList,
|
|||
wxString errorMsg;
|
||||
|
||||
fullURLCommand = repoURL.utf8_str();
|
||||
bool success = remote_get_json( &fullURLCommand, &errorMsg );
|
||||
bool success = remoteGetJSON( fullURLCommand, &errorMsg );
|
||||
|
||||
if( !success )
|
||||
{
|
||||
|
@ -123,6 +96,7 @@ bool GITHUB_GETLIBLIST::GetFootprintLibraryList( wxArrayString& aList )
|
|||
std::string fullURLCommand;
|
||||
int page = 1;
|
||||
int itemCountMax = 99; // Do not use a valu > 100, it does not work
|
||||
|
||||
strcpy( m_option_string, "application/json" );
|
||||
|
||||
// Github max items returned is 100 per page
|
||||
|
@ -147,7 +121,7 @@ bool GITHUB_GETLIBLIST::GetFootprintLibraryList( wxArrayString& aList )
|
|||
|
||||
while( 1 )
|
||||
{
|
||||
bool success = remote_get_json( &fullURLCommand, &errorMsg );
|
||||
bool success = remoteGetJSON( fullURLCommand, &errorMsg );
|
||||
|
||||
if( !success )
|
||||
{
|
||||
|
@ -235,3 +209,37 @@ bool GITHUB_GETLIBLIST::repoURL2listURL( const wxString& aRepoURL,
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool GITHUB_GETLIBLIST::remoteGetJSON( const std::string& aFullURLCommand, wxString* aMsgError )
|
||||
{
|
||||
KICAD_CURL_EASY kcurl;
|
||||
|
||||
wxLogDebug( wxT( "Attempting to download: " ) + aFullURLCommand );
|
||||
|
||||
kcurl.SetURL( aFullURLCommand );
|
||||
kcurl.SetUserAgent( "http://kicad-pcb.org" );
|
||||
kcurl.SetHeader( "Accept", m_option_string );
|
||||
kcurl.SetFollowRedirects( true );
|
||||
|
||||
try
|
||||
{
|
||||
kcurl.Perform();
|
||||
m_image = kcurl.GetBuffer();
|
||||
return true;
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
if( aMsgError )
|
||||
{
|
||||
UTF8 fmt( _( "Error fetching JSON data from URL '%s'.\nReason: '%s'" ) );
|
||||
|
||||
std::string msg = StrPrintf( fmt.c_str(),
|
||||
aFullURLCommand.c_str(),
|
||||
TO_UTF8( ioe.errorText ) );
|
||||
|
||||
*aMsgError = FROM_UTF8( msg.c_str() );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ protected:
|
|||
int aItemCountMax, int aPage = 1 );
|
||||
|
||||
/**
|
||||
* Function remote_get_json
|
||||
* Function remoteGetJSON
|
||||
* Download a json text from a github repo. The text image
|
||||
* is received into the m_input_stream.
|
||||
* @param aFullURLCommand the full command, i.e. the url with options like
|
||||
|
@ -111,7 +111,7 @@ protected:
|
|||
* @param aMsgError a pointer to a wxString which can store an error message
|
||||
* @return true if OK, false if error (which an error message in *aMsgError
|
||||
*/
|
||||
bool remote_get_json( std::string* aFullURLCommand, wxString* aMsgError );
|
||||
bool remoteGetJSON( const std::string& aFullURLCommand, wxString* aMsgError );
|
||||
|
||||
wxString m_github_path; ///< Something like https://api.github.com/orgs/KiCad
|
||||
std::string m_image; ///< image of the downloaded data in its entirety.
|
||||
|
|
|
@ -38,8 +38,7 @@ I have lost my enthusiasm for local caching until a faster time stamp retrieval
|
|||
mechanism can be found, or github gets more servers. But note that the occasionally
|
||||
slow response is the exception rather than the norm. Normally the response is
|
||||
down around a 1/3 of a second. The information we would use is in the header
|
||||
named "Last-Modified" as seen below. This would need parsing, but avhttp may
|
||||
offer some help there, if not, then boost async probably does.
|
||||
named "Last-Modified" as seen below.
|
||||
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
|
@ -62,23 +61,9 @@ Access-Control-Expose-Headers: ETag, Link, X-RateLimit-Limit, X-RateLimit-Remain
|
|||
Access-Control-Allow-Origin: *
|
||||
X-GitHub-Request-Id: 411087C2:659E:50FD6E6:52E67F66
|
||||
Vary: Accept-Encoding
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
// when WIN32_LEAN_AND_MEAN is defined, some useless includes in <window.h>
|
||||
// are skipped, and this avoid some compil issues
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
// defines needed by avhttp
|
||||
// Minimal Windows version is XP: Google for _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#define WINVER 0x0501
|
||||
#endif
|
||||
|
||||
#include <kicad_curl/kicad_curl_easy.h> // Include before any wx file
|
||||
#include <sstream>
|
||||
#include <boost/ptr_container/ptr_map.hpp>
|
||||
#include <set>
|
||||
|
@ -88,10 +73,6 @@ Vary: Accept-Encoding
|
|||
#include <wx/uri.h>
|
||||
|
||||
#include <fctsys.h>
|
||||
// Under Windows Mingw/msys, avhttp.hpp should be included after fctsys.h
|
||||
// in fact after wx/wx.h, included by fctsys.h,
|
||||
// to avoid issues (perhaps due to incompatible defines)
|
||||
#include <avhttp.hpp> // chinese SSL magic
|
||||
|
||||
#include <io_mgr.h>
|
||||
#include <richio.h>
|
||||
|
@ -103,6 +84,7 @@ Vary: Accept-Encoding
|
|||
#include <fp_lib_table.h> // ExpandSubstitutions()
|
||||
#include <github_getliblist.h>
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
|
@ -139,7 +121,7 @@ GITHUB_PLUGIN::~GITHUB_PLUGIN()
|
|||
|
||||
const wxString GITHUB_PLUGIN::PluginName() const
|
||||
{
|
||||
return wxT( "Github" );
|
||||
return "Github";
|
||||
}
|
||||
|
||||
|
||||
|
@ -212,7 +194,8 @@ MODULE* GITHUB_PLUGIN::FootprintLoad( const wxString& aLibraryPath,
|
|||
|
||||
if( it != m_gh_cache->end() ) // fp_name is present
|
||||
{
|
||||
wxMemoryInputStream mis( &m_zip_image[0], m_zip_image.size() );
|
||||
//std::string::data() ensures that the referenced data block is contiguous.
|
||||
wxMemoryInputStream mis( m_zip_image.data(), m_zip_image.size() );
|
||||
|
||||
// This decoder should always be UTF8, since it was saved that way by git.
|
||||
// That is, since pretty footprints are UTF8, and they were pushed to the
|
||||
|
@ -223,21 +206,17 @@ MODULE* GITHUB_PLUGIN::FootprintLoad( const wxString& aLibraryPath,
|
|||
if( zis.OpenEntry( *entry ) )
|
||||
{
|
||||
INPUTSTREAM_LINE_READER reader( &zis, aLibraryPath );
|
||||
#if 1
|
||||
|
||||
// I am a PCB_IO derivative with my own PCB_PARSER
|
||||
m_parser->SetLineReader( &reader ); // ownership not passed
|
||||
|
||||
MODULE* ret = (MODULE*) m_parser->Parse();
|
||||
#else
|
||||
PCB_PARSER parser( &reader );
|
||||
|
||||
MODULE* ret = (MODULE*) parser.Parse();
|
||||
#endif
|
||||
|
||||
// Dude, the footprint name comes from the file name in
|
||||
// a github library. Zero out the library name, we don't know it here.
|
||||
// Some caller may set the library nickname, one such instance is
|
||||
// FP_LIB_TABLE::FootprintLoad().
|
||||
// In a github library, (as well as in a "KiCad" library) the name of
|
||||
// the pretty file defines the footprint name. That filename trumps
|
||||
// any name found in the pretty file; any name in the pretty file
|
||||
// must be ignored here. Also, the library nickname is unknown in
|
||||
// this context so clear it just in case.
|
||||
ret->SetFPID( fp_name );
|
||||
|
||||
return ret;
|
||||
|
@ -408,7 +387,7 @@ void GITHUB_PLUGIN::cacheLib( const wxString& aLibraryPath, const PROPERTIES* aP
|
|||
|
||||
if( !wx_pretty_fn.IsOk() ||
|
||||
!wx_pretty_fn.IsDirWritable() ||
|
||||
wx_pretty_fn.GetExt() != wxT( "pretty" )
|
||||
wx_pretty_fn.GetExt() != "pretty"
|
||||
)
|
||||
{
|
||||
wxString msg = wxString::Format(
|
||||
|
@ -425,13 +404,13 @@ void GITHUB_PLUGIN::cacheLib( const wxString& aLibraryPath, const PROPERTIES* aP
|
|||
}
|
||||
|
||||
// operator==( wxString, wxChar* ) does not exist, construct wxString once here.
|
||||
const wxString kicad_mod( wxT( "kicad_mod" ) );
|
||||
const wxString kicad_mod( "kicad_mod" );
|
||||
|
||||
//D(printf("%s: this:%p m_lib_path:'%s' aLibraryPath:'%s'\n", __func__, this, TO_UTF8( m_lib_path), TO_UTF8(aLibraryPath) );)
|
||||
m_gh_cache = new GH_CACHE();
|
||||
|
||||
// INIT_LOGGER( "/tmp", "test.log" );
|
||||
remote_get_zip( aLibraryPath );
|
||||
remoteGetZip( aLibraryPath );
|
||||
// UNINIT_LOGGER();
|
||||
|
||||
m_lib_path = aLibraryPath;
|
||||
|
@ -460,7 +439,7 @@ void GITHUB_PLUGIN::cacheLib( const wxString& aLibraryPath, const PROPERTIES* aP
|
|||
}
|
||||
|
||||
|
||||
bool GITHUB_PLUGIN::repoURL_zipURL( const wxString& aRepoURL, string* aZipURL )
|
||||
bool GITHUB_PLUGIN::repoURL_zipURL( const wxString& aRepoURL, std::string* aZipURL )
|
||||
{
|
||||
// e.g. "https://github.com/liftoff-sr/pretty_footprints"
|
||||
//D(printf("aRepoURL:%s\n", TO_UTF8( aRepoURL ) );)
|
||||
|
@ -470,12 +449,12 @@ bool GITHUB_PLUGIN::repoURL_zipURL( const wxString& aRepoURL, string* aZipURL )
|
|||
if( repo.HasServer() && repo.HasPath() )
|
||||
{
|
||||
// scheme might be "http" or if truly github.com then "https".
|
||||
wxString zip_url = repo.GetScheme();
|
||||
|
||||
zip_url += "://";
|
||||
wxString zip_url;
|
||||
|
||||
if( repo.GetServer() == "github.com" )
|
||||
{
|
||||
//codeload.github.com only supports https
|
||||
zip_url = "https://";
|
||||
#if 0 // A proper code path would be this one, but it is not the fastest.
|
||||
zip_url += repo.GetServer();
|
||||
zip_url += repo.GetPath(); // path comes with a leading '/'
|
||||
|
@ -488,8 +467,6 @@ bool GITHUB_PLUGIN::repoURL_zipURL( const wxString& aRepoURL, string* aZipURL )
|
|||
|
||||
// In order to bypass this redirect, saving time, we use the
|
||||
// redirected URL on first attempt to save one HTTP GET hit.
|
||||
// avhttp would do the redirect behind the scenes normally, but that would
|
||||
// be slower than doing this bypass.
|
||||
zip_url += "codeload.github.com";
|
||||
zip_url += repo.GetPath(); // path comes with a leading '/'
|
||||
zip_url += "/zip/master";
|
||||
|
@ -498,9 +475,11 @@ bool GITHUB_PLUGIN::repoURL_zipURL( const wxString& aRepoURL, string* aZipURL )
|
|||
|
||||
else
|
||||
{
|
||||
zip_url = repo.GetScheme();
|
||||
zip_url += "://";
|
||||
|
||||
// This is the generic code path for any server which can serve
|
||||
// up zip files. The schemes tested include: http and https.
|
||||
// (I don't know what the avhttp library supports beyond that.)
|
||||
|
||||
// zip_url goal: "<scheme>://<server>[:<port>]/<path>"
|
||||
|
||||
|
@ -533,9 +512,9 @@ bool GITHUB_PLUGIN::repoURL_zipURL( const wxString& aRepoURL, string* aZipURL )
|
|||
}
|
||||
|
||||
|
||||
void GITHUB_PLUGIN::remote_get_zip( const wxString& aRepoURL ) throw( IO_ERROR )
|
||||
void GITHUB_PLUGIN::remoteGetZip( const wxString& aRepoURL ) throw( IO_ERROR )
|
||||
{
|
||||
string zip_url;
|
||||
std::string zip_url;
|
||||
|
||||
if( !repoURL_zipURL( aRepoURL, &zip_url ) )
|
||||
{
|
||||
|
@ -543,107 +522,48 @@ void GITHUB_PLUGIN::remote_get_zip( const wxString& aRepoURL ) throw( IO_ERROR )
|
|||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
|
||||
boost::asio::io_service io;
|
||||
avhttp::http_stream h( io );
|
||||
avhttp::request_opts options;
|
||||
wxLogDebug( wxT( "Attempting to download: " ) + zip_url );
|
||||
|
||||
options.insert( "Accept", "application/zip" );
|
||||
options.insert( "User-Agent", "http://kicad-pcb.org" ); // THAT WOULD BE ME.
|
||||
h.request_options( options );
|
||||
KICAD_CURL_EASY kcurl; // this can THROW_IO_ERROR
|
||||
|
||||
kcurl.SetURL( zip_url.c_str() );
|
||||
kcurl.SetUserAgent( "http://kicad-pcb.org" );
|
||||
kcurl.SetHeader( "Accept", "application/zip" );
|
||||
kcurl.SetFollowRedirects( true );
|
||||
|
||||
try
|
||||
{
|
||||
ostringstream os;
|
||||
|
||||
h.open( zip_url ); // only one file, therefore do it synchronously.
|
||||
os << &h;
|
||||
|
||||
// Keep zip file byte image in RAM. That plus the MODULE_MAP will constitute
|
||||
// the cache. We don't cache the MODULEs per se, we parse those as needed from
|
||||
// this zip file image.
|
||||
m_zip_image = os.str();
|
||||
|
||||
// 4 lines, using SSL, top that.
|
||||
kcurl.Perform();
|
||||
m_zip_image = kcurl.GetBuffer();
|
||||
}
|
||||
catch( const boost::system::system_error& e )
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
// https "GET" has faild, report this to API caller.
|
||||
// https "GET" has failed, report this to API caller.
|
||||
// Note: kcurl.Perform() does not return an error if the file to download is not found
|
||||
static const char errorcmd[] = "http GET command failed"; // Do not translate this message
|
||||
|
||||
UTF8 fmt( _( "%s\nCannot get/download Zip archive: '%s'\nfor library path: '%s'.\nReason: '%s'" ) );
|
||||
|
||||
string msg = StrPrintf( fmt.c_str(),
|
||||
errorcmd,
|
||||
// Report both secret zip_url and Lib Path, to user. The secret
|
||||
// zip_url may go bad at some point in future if github changes
|
||||
// their server architecture. Then fix repoURL_zipURL() to reflect
|
||||
// new architecture.
|
||||
zip_url.c_str(), TO_UTF8( aRepoURL ),
|
||||
e.what() );
|
||||
|
||||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
catch( const exception& exc )
|
||||
{
|
||||
UTF8 error( _( "Exception '%s' in avhttp while open()-ing URI:'%s'" ) );
|
||||
|
||||
string msg = StrPrintf( error.c_str(), exc.what(), zip_url.c_str() );
|
||||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This GITHUB_GETLIBLIST method should not be here, but in github_getliblist.cpp !
|
||||
// However it is here just because we need to include <avhttp.hpp> to compile it.
|
||||
// and when we include avhttp in two .cpp files, the link fails because it detects duplicate
|
||||
// avhttp functions.
|
||||
// So until it is fixed, this code is here.
|
||||
bool GITHUB_GETLIBLIST::remote_get_json( std::string* aFullURLCommand, wxString* aMsgError )
|
||||
{
|
||||
boost::asio::io_service io;
|
||||
avhttp::http_stream h( io );
|
||||
avhttp::request_opts options;
|
||||
|
||||
|
||||
options.insert( "Accept", m_option_string );
|
||||
options.insert( "User-Agent", "http://kicad-pcb.org" ); // THAT WOULD BE ME.
|
||||
h.request_options( options );
|
||||
|
||||
try
|
||||
{
|
||||
std::ostringstream os;
|
||||
|
||||
h.open( *aFullURLCommand ); // only one file, therefore do it synchronously.
|
||||
os << &h;
|
||||
|
||||
// Keep downloaded text file image in RAM.
|
||||
m_image = os.str();
|
||||
|
||||
// 4 lines, using SSL, top that.
|
||||
}
|
||||
catch( boost::system::system_error& e )
|
||||
{
|
||||
// https "GET" has faild, report this to API caller.
|
||||
static const char errorcmd[] = "https GET command failed"; // Do not translate this message
|
||||
|
||||
UTF8 fmt( _( "%s\nCannot get/download data from: '%s'\nReason: '%s'" ) );
|
||||
|
||||
std::string msg = StrPrintf( fmt.c_str(),
|
||||
errorcmd,
|
||||
// Report secret list_url to user. The secret
|
||||
// list_url may go bad at some point in future if github changes
|
||||
// their server architecture. Then fix repoURL_zipURL() to reflect
|
||||
// new architecture.
|
||||
aFullURLCommand->c_str(), e.what() );
|
||||
errorcmd,
|
||||
zip_url.c_str(),
|
||||
TO_UTF8( aRepoURL ),
|
||||
TO_UTF8( ioe.errorText )
|
||||
);
|
||||
|
||||
if( aMsgError )
|
||||
{
|
||||
*aMsgError = FROM_UTF8( msg.c_str() );
|
||||
return false;
|
||||
}
|
||||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
|
||||
return true;
|
||||
// If the zip archive is not existing, the received data is "Not Found" or "404: Not Found",
|
||||
// and no error is returned by kcurl.Perform().
|
||||
if( ( m_zip_image.compare( 0, 9, "Not Found", 9 ) == 0 ) ||
|
||||
( m_zip_image.compare( 0, 14, "404: Not Found", 14 ) == 0 ) )
|
||||
{
|
||||
UTF8 fmt( _( "Cannot download library '%s'.\nThe library does not exist on the server" ) );
|
||||
std::string msg = StrPrintf( fmt.c_str(), TO_UTF8( aRepoURL ) );
|
||||
|
||||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 && defined(STANDALONE)
|
||||
|
@ -657,7 +577,7 @@ int main( int argc, char** argv )
|
|||
try
|
||||
{
|
||||
wxArrayString fps = gh.FootprintEnumerate(
|
||||
wxT( "https://github.com/liftoff-sr/pretty_footprints" ),
|
||||
"https://github.com/liftoff-sr/pretty_footprints",
|
||||
NULL
|
||||
);
|
||||
|
||||
|
|
|
@ -213,11 +213,11 @@ protected:
|
|||
static bool repoURL_zipURL( const wxString& aRepoURL, std::string* aZipURL );
|
||||
|
||||
/**
|
||||
* Function remote_get_zip
|
||||
* Function remoteGetZip
|
||||
* fetches a zip file image from a github repo synchronously. The byte image
|
||||
* is received into the m_input_stream.
|
||||
*/
|
||||
void remote_get_zip( const wxString& aRepoURL ) throw( IO_ERROR );
|
||||
void remoteGetZip( const wxString& aRepoURL ) throw( IO_ERROR );
|
||||
|
||||
wxString m_lib_path; ///< from aLibraryPath, something like https://github.com/liftoff-sr/pretty_footprints
|
||||
std::string m_zip_image; ///< byte image of the zip file in its entirety.
|
||||
|
|
Loading…
Reference in New Issue