KiCad PCB EDA Suite
PLUGIN_CONTENT_MANAGER Class Reference

Main class of Plugin and Content Manager subsystem. More...

#include <pcm.h>

Public Member Functions

 PLUGIN_CONTENT_MANAGER (wxWindow *aParent)
 
 ~PLUGIN_CONTENT_MANAGER ()
 
bool FetchRepository (const wxString &aUrl, PCM_REPOSITORY &aRepository, WX_PROGRESS_REPORTER *aReporter)
 Fetches repository metadata from given url. More...
 
void ValidateJson (const nlohmann::json &aJson, const nlohmann::json_uri &aUri=nlohmann::json_uri("#")) const
 Validates json against a specific definition in the PCM schema. More...
 
bool VerifyHash (std::istream &aStream, const wxString &aHash) const
 Verifies SHA256 hash of a binary stream. More...
 
void SetRepositoryList (const STRING_PAIR_LIST &aRepositories)
 Set list of repositories. More...
 
void DiscardRepositoryCache (const wxString &aRepositoryId)
 Discard in-memory and on-disk cache of a repository. More...
 
void MarkInstalled (const PCM_PACKAGE &aPackage, const wxString &aVersion, const wxString &aRepositoryId)
 Mark package as installed. More...
 
void MarkUninstalled (const PCM_PACKAGE &aPackage)
 Mark package as uninstalled. More...
 
const STRING_TUPLE_LISTGetRepositoryList () const
 Get list of repositories. More...
 
const bool CacheRepository (const wxString &aRepositoryId)
 Cache specified repository packages and other metadata. More...
 
const std::vector< PCM_PACKAGE > & GetRepositoryPackages (const wxString &aRepositoryId) const
 Get the packages metadata from a previously cached repository. More...
 
const std::vector< PCM_INSTALLATION_ENTRYGetInstalledPackages () const
 Get list of installed packages. More...
 
const wxString & GetInstalledPackageVersion (const wxString &aPackageId) const
 Get the current version of an installed package. More...
 
const wxString & Get3rdPartyPath () const
 
PCM_PACKAGE_STATE GetPackageState (const wxString &aRepositoryId, const wxString &aPackageId)
 Get current state of the package. More...
 
bool DownloadToStream (const wxString &aUrl, std::ostream *aOutput, WX_PROGRESS_REPORTER *aReporter, const size_t aSizeLimit=DEFAULT_DOWNLOAD_MEM_LIMIT)
 Downloads url to an output stream. More...
 
int GetPackageSearchRank (const PCM_PACKAGE &aPackage, const wxString &aSearchTerm)
 Get the approximate measure of how much given package matches the search term. More...
 
std::unordered_map< wxString, wxBitmap > GetRepositoryPackageBitmaps (const wxString &aRepositoryId)
 Get the icon bitmaps for repository packages. More...
 
std::unordered_map< wxString, wxBitmap > GetInstalledPackageBitmaps ()
 Get the icon bitmaps for installed packages. More...
 

Private Member Functions

bool fetchPackages (const wxString &aUrl, const boost::optional< wxString > &aHash, std::vector< PCM_PACKAGE > &aPackages, WX_PROGRESS_REPORTER *aReporter)
 Downloads packages metadata to in memory stream, verifies hash and attempts to parse it. More...
 
const PCM_REPOSITORYgetCachedRepository (const wxString &aRepositoryId) const
 Get the cached repository metadata. More...
 
time_t getCurrentTimestamp () const
 

Static Private Member Functions

static void preparePackage (PCM_PACKAGE &aPackage)
 Parses version strings and calculates compatibility. More...
 

Private Attributes

wxWindow * m_dialog
 
nlohmann::json_schema::json_validator m_schema_validator
 
wxString m_3rdparty_path
 
wxString m_cache_path
 
std::unordered_map< wxString, PCM_REPOSITORYm_repository_cache
 
STRING_TUPLE_LIST m_repository_list
 
std::map< wxString, PCM_INSTALLATION_ENTRYm_installed
 

Static Private Attributes

static constexpr size_t DEFAULT_DOWNLOAD_MEM_LIMIT = 10 * 1024 * 1024
 < Default download limit of 10 Mb to not use too much memory More...
 
static const std::tuple< int, int > m_kicad_version
 

Detailed Description

Main class of Plugin and Content Manager subsystem.

This class handles logistics of repository management, caching, json validation, tracking installed packages and provides some utility methods.

Repository caching is done in $KICADX_3RD_PARTY/cache directory with each repository storing it's metadata, packages and optionally resource files under it's id subdirectory.

Repository id is a prefix of sha256 of it's main url.

JSON schema file is expected to be in $KICAD_DATA/schemas directory

Installed packages are stored in <user_settings>/installed_packages.json If that file is missing PCM will try to reconstruct it from existing directory structure inside $KICADX_3RD_PARTY but package descriptions and other metadata will be lost.

Definition at line 93 of file pcm.h.

Constructor & Destructor Documentation

◆ PLUGIN_CONTENT_MANAGER()

PLUGIN_CONTENT_MANAGER::PLUGIN_CONTENT_MANAGER ( wxWindow *  aParent)

Definition at line 63 of file pcm.cpp.

63  : m_dialog( aParent )
64 {
65  // Get 3rd party path
66  const ENV_VAR_MAP& env = Pgm().GetLocalEnvVariables();
67  auto it = env.find( wxT( "KICAD6_3RD_PARTY" ) );
68 
69  if( it != env.end() && !it->second.GetValue().IsEmpty() )
70  m_3rdparty_path = it->second.GetValue();
71  else
73 
74  // Read and store pcm schema
75  wxFileName schema_file( PATHS::GetStockDataPath( true ), wxT( "pcm.v1.schema.json" ) );
76  schema_file.Normalize();
77  schema_file.AppendDir( wxT( "schemas" ) );
78 
79  std::ifstream schema_stream( schema_file.GetFullPath().ToUTF8() );
80  nlohmann::json schema;
81 
82  try
83  {
84  schema_stream >> schema;
85  m_schema_validator.set_root_schema( schema );
86  }
87  catch( std::exception& e )
88  {
89  if( !schema_file.FileExists() )
90  wxLogError( wxString::Format( _( "schema file '%s' not found" ),
91  schema_file.GetFullPath() ) );
92  else
93  wxLogError( wxString::Format( _( "Error loading schema: %s" ), e.what() ) );
94  }
95 
96  // Load currently installed packages
97  wxFileName f( SETTINGS_MANAGER::GetUserSettingsPath(), wxT( "installed_packages.json" ) );
98 
99  if( f.FileExists() )
100  {
101  std::ifstream installed_stream( f.GetFullPath().ToUTF8() );
102  nlohmann::json installed;
103 
104  try
105  {
106  installed_stream >> installed;
107 
108  if( installed.contains( "packages" ) && installed["packages"].is_array() )
109  {
110  for( const auto& js_entry : installed["packages"] )
111  {
112  PCM_INSTALLATION_ENTRY entry = js_entry.get<PCM_INSTALLATION_ENTRY>();
113  m_installed.emplace( entry.package.identifier, entry );
114  }
115  }
116  }
117  catch( std::exception& e )
118  {
119  wxLogError( wxString::Format( _( "Error loading installed packages list: %s" ),
120  e.what() ) );
121  }
122  }
123 
124  // As a fall back populate installed from names of directories
125 
126  for( const wxString& dir : PCM_PACKAGE_DIRECTORIES )
127  {
128  wxFileName d( m_3rdparty_path, "" );
129  d.AppendDir( dir );
130 
131  if( d.DirExists() )
132  {
133  wxDir package_dir( d.GetPath() );
134 
135  if( !package_dir.IsOpened() )
136  continue;
137 
138  wxString subdir;
139  bool more = package_dir.GetFirst( &subdir, "", wxDIR_DIRS | wxDIR_HIDDEN );
140 
141  while( more )
142  {
143  wxString actual_package_id = subdir;
144  actual_package_id.Replace( '_', '.' );
145 
146  if( m_installed.find( actual_package_id ) == m_installed.end() )
147  {
149  wxFileName subdir_file( d.GetPath(), subdir );
150 
151  // wxFileModificationTime bugs out on windows for directories
152  wxStructStat stat;
153  int stat_code = wxStat( subdir_file.GetFullPath(), &stat );
154 
155  entry.package.name = subdir;
156  entry.package.identifier = actual_package_id;
157  entry.current_version = wxT( "0.0" );
158  entry.repository_name = wxT( "<unknown>" );
159 
160  if( stat_code == 0 )
161  entry.install_timestamp = stat.st_mtime;
162 
163  PACKAGE_VERSION version;
164  version.version = wxT( "0.0" );
165  version.status = PVS_STABLE;
166  version.kicad_version = KICAD_MAJOR_MINOR_VERSION;
167 
168  entry.package.versions.emplace_back( version );
169 
170  m_installed.emplace( actual_package_id, entry );
171  }
172 
173  more = package_dir.GetNext( &subdir );
174  }
175  }
176  }
177 
178  // Calculate package compatibility
179  std::for_each( m_installed.begin(), m_installed.end(),
180  [&]( auto& entry )
181  {
182  preparePackage( entry.second.package );
183  } );
184 }
< Package version metadata Package metadata
Definition: pcm_data.h:73
PCM_PACKAGE_VERSION_STATUS status
Definition: pcm_data.h:81
std::map< wxString, PCM_INSTALLATION_ENTRY > m_installed
Definition: pcm.h:315
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:106
nlohmann::json json
Definition: gerbview.cpp:41
static wxString GetStockDataPath(bool aRespectRunFromBuildDir=true)
Gets the stock (install) data path, which is the base path for things like scripting,...
Definition: paths.cpp:150
#define _(s)
wxString name
Definition: pcm_data.h:95
wxString m_3rdparty_path
Definition: pcm.h:310
wxWindow * m_dialog
Definition: pcm.h:308
std::vector< PACKAGE_VERSION > versions
Definition: pcm_data.h:105
uint64_t install_timestamp
Definition: pcm_data.h:139
static wxString GetUserSettingsPath()
Return the user configuration path used to store KiCad's configuration files.
static void preparePackage(PCM_PACKAGE &aPackage)
Parses version strings and calculates compatibility.
Definition: pcm.cpp:488
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
wxString current_version
Definition: pcm_data.h:136
std::map< wxString, ENV_VAR_ITEM > ENV_VAR_MAP
wxString identifier
Definition: pcm_data.h:98
wxString kicad_version
Definition: pcm_data.h:83
nlohmann::json_schema::json_validator m_schema_validator
Definition: pcm.h:309
static wxString GetDefault3rdPartyPath()
Gets the default path for PCM packages.
Definition: paths.cpp:129
const std::unordered_set< wxString > PCM_PACKAGE_DIRECTORIES({ wxT("plugins"), wxT("footprints"), wxT("3dmodels"), wxT("symbols"), wxT("resources"), wxT("colors"), })
< Contains list of all valid directories that get extracted from a package archive
PCM_PACKAGE package
Definition: pcm_data.h:135
wxString repository_name
Definition: pcm_data.h:138
Definition: pcm_data.h:133
wxString version
Definition: pcm_data.h:75

References _, PCM_INSTALLATION_ENTRY::current_version, Format(), PATHS::GetDefault3rdPartyPath(), PATHS::GetStockDataPath(), SETTINGS_MANAGER::GetUserSettingsPath(), PCM_PACKAGE::identifier, PCM_INSTALLATION_ENTRY::install_timestamp, PACKAGE_VERSION::kicad_version, m_3rdparty_path, m_installed, m_schema_validator, PCM_PACKAGE::name, PCM_INSTALLATION_ENTRY::package, PCM_PACKAGE_DIRECTORIES(), Pgm(), preparePackage(), PVS_STABLE, PCM_INSTALLATION_ENTRY::repository_name, PACKAGE_VERSION::status, PACKAGE_VERSION::version, and PCM_PACKAGE::versions.

◆ ~PLUGIN_CONTENT_MANAGER()

PLUGIN_CONTENT_MANAGER::~PLUGIN_CONTENT_MANAGER ( )

Definition at line 673 of file pcm.cpp.

674 {
675  // Save current installed packages list.
676 
677  try
678  {
679  nlohmann::json js;
680  js["packages"] = nlohmann::json::array();
681 
682  for( const auto& entry : m_installed )
683  {
684  js["packages"].emplace_back( entry.second );
685  }
686 
687  wxFileName f( SETTINGS_MANAGER::GetUserSettingsPath(), wxT( "installed_packages.json" ) );
688  std::ofstream stream( f.GetFullPath().ToUTF8() );
689 
690  stream << std::setw( 4 ) << js << std::endl;
691  }
692  catch( nlohmann::detail::exception& )
693  {
694  // Ignore
695  }
696 }
std::map< wxString, PCM_INSTALLATION_ENTRY > m_installed
Definition: pcm.h:315
nlohmann::json json
Definition: gerbview.cpp:41
static wxString GetUserSettingsPath()
Return the user configuration path used to store KiCad's configuration files.

References SETTINGS_MANAGER::GetUserSettingsPath(), and m_installed.

Member Function Documentation

◆ CacheRepository()

const bool PLUGIN_CONTENT_MANAGER::CacheRepository ( const wxString &  aRepositoryId)

Cache specified repository packages and other metadata.

This method fetches latest repository metadata, checks if there is cache on disk, compares it's last update timestamp to repository metadata and redownloads packages list if necessary. Then it checks sha256 if provided and parses the package list. Parsed packages metadata is stored in memory.

Process is repeated with resources file except it is just stored on disk and any errors at this stage are ignored.

Parameters
aRepositoryIdid of the repository to cache
Returns
true if packages metadata was cached successfully

Definition at line 345 of file pcm.cpp.

346 {
347  if( m_repository_cache.find( aRepositoryId ) != m_repository_cache.end() )
348  return true;
349 
350  const auto repository_tuple =
351  std::find_if( m_repository_list.begin(), m_repository_list.end(),
352  [&aRepositoryId]( const std::tuple<wxString, wxString, wxString>& t )
353  {
354  return std::get<0>( t ) == aRepositoryId;
355  } );
356 
357  if( repository_tuple == m_repository_list.end() )
358  return false;
359 
360  wxString url = std::get<2>( *repository_tuple );
361 
362  nlohmann::json js;
363  PCM_REPOSITORY current_repo;
364 
365  std::unique_ptr<WX_PROGRESS_REPORTER> reporter(
366  new WX_PROGRESS_REPORTER( m_dialog, wxEmptyString, 1 ) );
367 
368  if( !FetchRepository( url, current_repo, reporter.get() ) )
369  return false;
370 
371  bool packages_cache_exists = false;
372 
373  // First load repository data from local filesystem if available.
374  wxFileName repo_cache = wxFileName( m_3rdparty_path, wxT( "repository.json" ) );
375  repo_cache.AppendDir( wxT( "cache" ) );
376  repo_cache.AppendDir( aRepositoryId );
377  wxFileName packages_cache( repo_cache.GetPath(), wxT( "packages.json" ) );
378 
379  if( repo_cache.FileExists() && packages_cache.FileExists() )
380  {
381  std::ifstream repo_stream( repo_cache.GetFullPath().ToUTF8() );
382  repo_stream >> js;
383  PCM_REPOSITORY saved_repo = js.get<PCM_REPOSITORY>();
384 
385  if( saved_repo.packages.update_timestamp == current_repo.packages.update_timestamp )
386  {
387  // Cached repo is up to date, use data on disk
388  js.clear();
389  std::ifstream packages_cache_stream( packages_cache.GetFullPath().ToUTF8() );
390 
391  try
392  {
393  packages_cache_stream >> js;
394  saved_repo.package_list = js["packages"].get<std::vector<PCM_PACKAGE>>();
395 
396  std::for_each( saved_repo.package_list.begin(), saved_repo.package_list.end(),
397  &preparePackage );
398 
399  m_repository_cache[aRepositoryId] = std::move( saved_repo );
400 
401  packages_cache_exists = true;
402  }
403  catch( ... )
404  {
405  wxLogError( _( "Packages cache for current repository is "
406  "corrupted, it will be redownloaded." ) );
407  }
408  }
409  }
410 
411  if( !packages_cache_exists )
412  {
413  // Cache doesn't exist or is out of date
414  if( !fetchPackages( current_repo.packages.url, current_repo.packages.sha256,
415  current_repo.package_list, reporter.get() ) )
416  {
417  return false;
418  }
419 
420  std::for_each( current_repo.package_list.begin(), current_repo.package_list.end(),
421  &preparePackage );
422 
423  repo_cache.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
424 
425  std::ofstream repo_cache_stream( repo_cache.GetFullPath().ToUTF8() );
426  repo_cache_stream << std::setw( 4 ) << nlohmann::json( current_repo ) << std::endl;
427 
428  std::ofstream packages_cache_stream( packages_cache.GetFullPath().ToUTF8() );
429  js.clear();
430  js["packages"] = nlohmann::json( current_repo.package_list );
431  packages_cache_stream << std::setw( 4 ) << js << std::endl;
432 
433  m_repository_cache[aRepositoryId] = std::move( current_repo );
434  }
435 
436  if( current_repo.resources )
437  {
438  // Check resources file date, redownload if needed
439  PCM_RESOURCE_REFERENCE& resources = current_repo.resources.get();
440 
441  wxFileName resource_file( repo_cache.GetPath(), wxT( "resources.zip" ) );
442 
443  time_t mtime = 0;
444 
445  if( resource_file.FileExists() )
446  mtime = wxFileModificationTime( resource_file.GetFullPath() );
447 
448  if( mtime + 600 < getCurrentTimestamp() && mtime < (time_t) resources.update_timestamp )
449  {
450  std::ofstream resources_stream( resource_file.GetFullPath().ToUTF8(),
451  std::ios_base::binary );
452 
453  reporter->SetTitle( _( "Downloading resources" ) );
454 
455  // 100 Mb resource file limit
456  bool success = DownloadToStream( resources.url, &resources_stream, reporter.get(),
457  100 * 1024 * 1024 );
458 
459  resources_stream.close();
460 
461  if( success )
462  {
463  std::ifstream read_stream( resource_file.GetFullPath().ToUTF8(),
464  std::ios_base::binary );
465 
466 
467  if( resources.sha256 && !VerifyHash( read_stream, resources.sha256.get() ) )
468  {
469  read_stream.close();
470  wxLogError(
471  _( "Resources file hash doesn't match and will not be used. Repository "
472  "may be corrupted." ) );
473  wxRemoveFile( resource_file.GetFullPath() );
474  }
475  }
476  else
477  {
478  // Not critical, just clean up the file
479  wxRemoveFile( resource_file.GetFullPath() );
480  }
481  }
482  }
483 
484  return true;
485 }
PCM_RESOURCE_REFERENCE packages
Definition: pcm_data.h:122
uint64_t update_timestamp
Definition: pcm_data.h:114
boost::optional< PCM_RESOURCE_REFERENCE > resources
Definition: pcm_data.h:123
nlohmann::json json
Definition: gerbview.cpp:41
STRING_TUPLE_LIST m_repository_list
Definition: pcm.h:313
bool fetchPackages(const wxString &aUrl, const boost::optional< wxString > &aHash, std::vector< PCM_PACKAGE > &aPackages, WX_PROGRESS_REPORTER *aReporter)
Downloads packages metadata to in memory stream, verifies hash and attempts to parse it.
Definition: pcm.cpp:283
bool FetchRepository(const wxString &aUrl, PCM_REPOSITORY &aRepository, WX_PROGRESS_REPORTER *aReporter)
Fetches repository metadata from given url.
Definition: pcm.cpp:242
Multi-thread safe progress reporter dialog, intended for use of tasks that parallel reporting back of...
bool VerifyHash(std::istream &aStream, const wxString &aHash) const
Verifies SHA256 hash of a binary stream.
Definition: pcm.cpp:323
#define _(s)
wxString m_3rdparty_path
Definition: pcm.h:310
wxWindow * m_dialog
Definition: pcm.h:308
static void preparePackage(PCM_PACKAGE &aPackage)
Parses version strings and calculates compatibility.
Definition: pcm.cpp:488
boost::optional< wxString > sha256
Definition: pcm_data.h:113
std::vector< PCM_PACKAGE > package_list
Definition: pcm_data.h:128
Package installation entry.
Definition: pcm_data.h:119
bool DownloadToStream(const wxString &aUrl, std::ostream *aOutput, WX_PROGRESS_REPORTER *aReporter, const size_t aSizeLimit=DEFAULT_DOWNLOAD_MEM_LIMIT)
Downloads url to an output stream.
Definition: pcm.cpp:187
Repository metadata.
Definition: pcm_data.h:110
time_t getCurrentTimestamp() const
Definition: pcm.cpp:665
std::unordered_map< wxString, PCM_REPOSITORY > m_repository_cache
Definition: pcm.h:312

References _, DownloadToStream(), fetchPackages(), FetchRepository(), getCurrentTimestamp(), m_3rdparty_path, m_dialog, m_repository_cache, m_repository_list, PCM_REPOSITORY::package_list, PCM_REPOSITORY::packages, preparePackage(), PCM_REPOSITORY::resources, PCM_RESOURCE_REFERENCE::sha256, PCM_RESOURCE_REFERENCE::update_timestamp, PCM_RESOURCE_REFERENCE::url, and VerifyHash().

Referenced by GetPackageState().

◆ DiscardRepositoryCache()

void PLUGIN_CONTENT_MANAGER::DiscardRepositoryCache ( const wxString &  aRepositoryId)

Discard in-memory and on-disk cache of a repository.

Parameters
aRepositoryIdid of the repository

Definition at line 591 of file pcm.cpp.

592 {
593  if( m_repository_cache.count( aRepositoryId ) > 0 )
594  m_repository_cache.erase( aRepositoryId );
595 
596  wxFileName repo_cache( m_3rdparty_path, "" );
597  repo_cache.AppendDir( wxT( "cache" ) );
598  repo_cache.AppendDir( aRepositoryId );
599 
600  if( repo_cache.DirExists() )
601  repo_cache.Rmdir( wxPATH_RMDIR_RECURSIVE );
602 }
wxString m_3rdparty_path
Definition: pcm.h:310
std::unordered_map< wxString, PCM_REPOSITORY > m_repository_cache
Definition: pcm.h:312

References m_3rdparty_path, and m_repository_cache.

Referenced by SetRepositoryList().

◆ DownloadToStream()

bool PLUGIN_CONTENT_MANAGER::DownloadToStream ( const wxString &  aUrl,
std::ostream *  aOutput,
WX_PROGRESS_REPORTER aReporter,
const size_t  aSizeLimit = DEFAULT_DOWNLOAD_MEM_LIMIT 
)

Downloads url to an output stream.

Parameters
aUrlURL to download
aOutputoutput stream
aReporterprogress dialog to use
aSizeLimitmaximum download size, 0 for unlimited
Returns
true if download was successful
false if download failed or was too large

Definition at line 187 of file pcm.cpp.

190 {
191  bool size_exceeded = false;
192 
193  TRANSFER_CALLBACK callback = [&]( size_t dltotal, size_t dlnow, size_t ultotal, size_t ulnow )
194  {
195  if( aSizeLimit > 0 && ( dltotal > aSizeLimit || dlnow > aSizeLimit ) )
196  {
197  size_exceeded = true;
198 
199  // Non zero return means abort.
200  return true;
201  }
202 
203  if( dltotal > 1024 )
204  {
205  aReporter->SetCurrentProgress( dlnow / (double) dltotal );
206  aReporter->Report( wxString::Format( _( "Downloading %lld/%lld Kb" ), dlnow / 1024,
207  dltotal / 1024 ) );
208  }
209  else
210  {
211  aReporter->SetCurrentProgress( 0.0 );
212  }
213 
214  return !aReporter->KeepRefreshing();
215  };
216 
217  KICAD_CURL_EASY curl;
218  curl.SetOutputStream( aOutput );
219  curl.SetURL( aUrl.ToUTF8().data() );
220  curl.SetFollowRedirects( true );
221  curl.SetTransferCallback( callback, 250000L );
222 
223  int code = curl.Perform();
224 
225  if( !aReporter->IsCancelled() )
226  aReporter->SetCurrentProgress( 1.0 );
227 
228  if( code != CURLE_OK )
229  {
230  if( code == CURLE_ABORTED_BY_CALLBACK && size_exceeded )
231  wxMessageBox( _( "Download is too large." ) );
232  else if( code != CURLE_ABORTED_BY_CALLBACK )
233  wxLogError( wxString( curl.GetErrorText( code ) ) );
234 
235  return false;
236  }
237 
238  return true;
239 }
bool SetFollowRedirects(bool aFollow)
Enable the following of HTTP(s) and other redirects, by default curl does not follow redirects.
virtual void Report(const wxString &aMessage) override
Display aMessage in the progress bar dialog.
std::function< int(size_t, size_t, size_t, size_t)> TRANSFER_CALLBACK
Wrapper interface around the curl_easy API/.
bool KeepRefreshing(bool aWait=false) override
Update the UI dialog.
#define _(s)
int Perform()
Equivalent to curl_easy_perform.
const std::string GetErrorText(int aCode)
Fetch CURL's "friendly" error string for a given error code.
bool SetTransferCallback(const TRANSFER_CALLBACK &aCallback, size_t aInterval)
bool SetURL(const std::string &aURL)
Set the request URL.
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
bool IsCancelled() const override
bool SetOutputStream(const std::ostream *aOutput)
virtual void SetCurrentProgress(double aProgress) override
Set the progress value to aProgress (0..1).

References _, Format(), KICAD_CURL_EASY::GetErrorText(), PROGRESS_REPORTER_BASE::IsCancelled(), PROGRESS_REPORTER_BASE::KeepRefreshing(), KICAD_CURL_EASY::Perform(), PROGRESS_REPORTER_BASE::Report(), PROGRESS_REPORTER_BASE::SetCurrentProgress(), KICAD_CURL_EASY::SetFollowRedirects(), KICAD_CURL_EASY::SetOutputStream(), KICAD_CURL_EASY::SetTransferCallback(), and KICAD_CURL_EASY::SetURL().

Referenced by CacheRepository(), fetchPackages(), and FetchRepository().

◆ fetchPackages()

bool PLUGIN_CONTENT_MANAGER::fetchPackages ( const wxString &  aUrl,
const boost::optional< wxString > &  aHash,
std::vector< PCM_PACKAGE > &  aPackages,
WX_PROGRESS_REPORTER aReporter 
)
private

Downloads packages metadata to in memory stream, verifies hash and attempts to parse it.

Parameters
aUrlURL of the packages metadata
aHashoptional sha256 hash
aPackagesresulting packages metadata list
aReporterprogress dialog to use for download
Returns
true if packages were successfully downloaded, verified and parsed

Definition at line 283 of file pcm.cpp.

287 {
288  std::stringstream packages_stream;
289 
290  aReporter->SetTitle( _( "Fetching repository packages" ) );
291 
292  if( !DownloadToStream( aUrl, &packages_stream, aReporter ) )
293  {
294  wxLogError( _( "Unable to load repository packages url." ) );
295  return false;
296  }
297 
298  std::istringstream isstream( packages_stream.str() );
299 
300  if( aHash && !VerifyHash( isstream, aHash.get() ) )
301  {
302  wxLogError( _( "Packages hash doesn't match. Repository may be corrupted." ) );
303  return false;
304  }
305 
306  try
307  {
308  nlohmann::json packages_json = nlohmann::json::parse( packages_stream.str() );
309  ValidateJson( packages_json, nlohmann::json_uri( "#/definitions/PackageArray" ) );
310 
311  aPackages = packages_json["packages"].get<std::vector<PCM_PACKAGE>>();
312  }
313  catch( std::exception& e )
314  {
315  wxLogError( wxString::Format( _( "Unable to parse packages metadata:\n\n%s" ), e.what() ) );
316  return false;
317  }
318 
319  return true;
320 }
bool parse(std::istream &aStream, bool aVerbose)
Parse a PCB or footprint file from the given input stream.
nlohmann::json json
Definition: gerbview.cpp:41
bool VerifyHash(std::istream &aStream, const wxString &aHash) const
Verifies SHA256 hash of a binary stream.
Definition: pcm.cpp:323
void SetTitle(const wxString &aTitle) override
Change the title displayed on the window caption.
#define _(s)
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
void ValidateJson(const nlohmann::json &aJson, const nlohmann::json_uri &aUri=nlohmann::json_uri("#")) const
Validates json against a specific definition in the PCM schema.
Definition: pcm.cpp:275
bool DownloadToStream(const wxString &aUrl, std::ostream *aOutput, WX_PROGRESS_REPORTER *aReporter, const size_t aSizeLimit=DEFAULT_DOWNLOAD_MEM_LIMIT)
Downloads url to an output stream.
Definition: pcm.cpp:187

References _, DownloadToStream(), Format(), parse(), WX_PROGRESS_REPORTER::SetTitle(), ValidateJson(), and VerifyHash().

Referenced by CacheRepository().

◆ FetchRepository()

bool PLUGIN_CONTENT_MANAGER::FetchRepository ( const wxString &  aUrl,
PCM_REPOSITORY aRepository,
WX_PROGRESS_REPORTER aReporter 
)

Fetches repository metadata from given url.

Parameters
aUrlURL of the repository
aRepositoryfetched repository metadata
aReporterprogress reporter dialog to use for download
Returns
true if successful
false if URL could not be downloaded or result could not be parsed

Definition at line 242 of file pcm.cpp.

244 {
245  std::stringstream repository_stream;
246 
247  aReporter->SetTitle( _( "Fetching repository" ) );
248 
249  if( !DownloadToStream( aUrl, &repository_stream, aReporter, 20480 ) )
250  {
251  wxLogError( _( "Unable to load repository url" ) );
252  return false;
253  }
254 
255  nlohmann::json repository_json;
256 
257  try
258  {
259  repository_stream >> repository_json;
260 
261  ValidateJson( repository_json, nlohmann::json_uri( "#/definitions/Repository" ) );
262 
263  aRepository = repository_json.get<PCM_REPOSITORY>();
264  }
265  catch( const std::exception& e )
266  {
267  wxLogError( wxString::Format( _( "Unable to parse repository:\n\n%s" ), e.what() ) );
268  return false;
269  }
270 
271  return true;
272 }
nlohmann::json json
Definition: gerbview.cpp:41
void SetTitle(const wxString &aTitle) override
Change the title displayed on the window caption.
#define _(s)
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
void ValidateJson(const nlohmann::json &aJson, const nlohmann::json_uri &aUri=nlohmann::json_uri("#")) const
Validates json against a specific definition in the PCM schema.
Definition: pcm.cpp:275
Package installation entry.
Definition: pcm_data.h:119
bool DownloadToStream(const wxString &aUrl, std::ostream *aOutput, WX_PROGRESS_REPORTER *aReporter, const size_t aSizeLimit=DEFAULT_DOWNLOAD_MEM_LIMIT)
Downloads url to an output stream.
Definition: pcm.cpp:187

References _, DownloadToStream(), Format(), WX_PROGRESS_REPORTER::SetTitle(), and ValidateJson().

Referenced by CacheRepository().

◆ Get3rdPartyPath()

const wxString& PLUGIN_CONTENT_MANAGER::Get3rdPartyPath ( ) const
inline

Definition at line 216 of file pcm.h.

216 { return m_3rdparty_path; };
wxString m_3rdparty_path
Definition: pcm.h:310

References m_3rdparty_path.

◆ getCachedRepository()

const PCM_REPOSITORY & PLUGIN_CONTENT_MANAGER::getCachedRepository ( const wxString &  aRepositoryId) const
private

Get the cached repository metadata.

Parameters
aRepositoryIdid of the repository
Returns
const PCM_REPOSITORY&

Definition at line 336 of file pcm.cpp.

337 {
338  wxASSERT_MSG( m_repository_cache.find( aRepositoryId ) != m_repository_cache.end(),
339  wxT( "Repository is not cached." ) );
340 
341  return m_repository_cache.at( aRepositoryId );
342 }
std::unordered_map< wxString, PCM_REPOSITORY > m_repository_cache
Definition: pcm.h:312

References m_repository_cache.

Referenced by GetPackageState(), GetRepositoryPackages(), and MarkInstalled().

◆ getCurrentTimestamp()

time_t PLUGIN_CONTENT_MANAGER::getCurrentTimestamp ( ) const
private

Definition at line 665 of file pcm.cpp.

666 {
667  return std::chrono::duration_cast<std::chrono::seconds>(
668  std::chrono::system_clock::now().time_since_epoch() )
669  .count();
670 }

Referenced by CacheRepository(), and MarkInstalled().

◆ GetInstalledPackageBitmaps()

std::unordered_map< wxString, wxBitmap > PLUGIN_CONTENT_MANAGER::GetInstalledPackageBitmaps ( )

Get the icon bitmaps for installed packages.

Icons for installed packages are taken from package extracted files in $KICADX_3RD_PARTY/resources/<packageid> directories

Returns
map of package id -> bitmap

Definition at line 824 of file pcm.cpp.

825 {
826  std::unordered_map<wxString, wxBitmap> bitmaps;
827 
828  wxFileName resources_dir_fn( m_3rdparty_path, wxEmptyString );
829  resources_dir_fn.AppendDir( wxT( "resources" ) );
830  wxDir resources_dir( resources_dir_fn.GetPath() );
831 
832  if( !resources_dir.IsOpened() )
833  return bitmaps;
834 
835  wxString subdir;
836  bool more = resources_dir.GetFirst( &subdir, wxEmptyString, wxDIR_DIRS | wxDIR_HIDDEN );
837 
838  while( more )
839  {
840  wxFileName icon( resources_dir_fn.GetPath(), wxT( "icon.png" ) );
841  icon.AppendDir( subdir );
842 
843  if( icon.FileExists() )
844  {
845  wxString actual_package_id = subdir;
846  actual_package_id.Replace( '_', '.' );
847 
848  try
849  {
850  wxBitmap bitmap( icon.GetFullPath(), wxBITMAP_TYPE_PNG );
851  bitmaps.emplace( actual_package_id, bitmap );
852  }
853  catch( ... )
854  {
855  // Log and ignore
856  wxLogTrace( wxT( "Error loading png bitmap from %s" ), icon.GetFullPath() );
857  }
858  }
859 
860  more = resources_dir.GetNext( &subdir );
861  }
862 
863  return bitmaps;
864 }
wxString m_3rdparty_path
Definition: pcm.h:310

References m_3rdparty_path.

◆ GetInstalledPackages()

const std::vector< PCM_INSTALLATION_ENTRY > PLUGIN_CONTENT_MANAGER::GetInstalledPackages ( ) const

Get list of installed packages.

Returns
vector of PCM_INSTALLATION_ENTRY objects

Definition at line 699 of file pcm.cpp.

700 {
701  std::vector<PCM_INSTALLATION_ENTRY> v;
702 
703  std::for_each( m_installed.begin(), m_installed.end(),
704  [&v]( const auto& entry )
705  {
706  v.push_back( entry.second );
707  } );
708 
709  return v;
710 }
std::map< wxString, PCM_INSTALLATION_ENTRY > m_installed
Definition: pcm.h:315

References m_installed.

◆ GetInstalledPackageVersion()

const wxString & PLUGIN_CONTENT_MANAGER::GetInstalledPackageVersion ( const wxString &  aPackageId) const

Get the current version of an installed package.

Parameters
aPackageIdid of the package
Returns
current version
Exceptions
std::out_of_rangeif package with given id is not installedReturns current 3rd party directory path

Definition at line 714 of file pcm.cpp.

715 {
716  wxASSERT_MSG( m_installed.find( aPackageId ) != m_installed.end(),
717  wxT( "Installed package not found." ) );
718 
719  return m_installed.at( aPackageId ).current_version;
720 }
std::map< wxString, PCM_INSTALLATION_ENTRY > m_installed
Definition: pcm.h:315

References m_installed.

◆ GetPackageSearchRank()

int PLUGIN_CONTENT_MANAGER::GetPackageSearchRank ( const PCM_PACKAGE aPackage,
const wxString &  aSearchTerm 
)

Get the approximate measure of how much given package matches the search term.

Parameters
aPackagepackage metadata object
aSearchTermsearch term
Returns
int search rank, higher number means better match, 0 means no match

Definition at line 723 of file pcm.cpp.

725 {
726  wxArrayString terms = wxStringTokenize( aSearchTerm.Lower(), wxT( " " ), wxTOKEN_STRTOK );
727  int rank = 0;
728 
729  const auto find_term_matches = [&]( const wxString& str )
730  {
731  int result = 0;
732  wxString lower = str.Lower();
733 
734  for( const wxString& term : terms )
735  if( lower.Find( term ) != wxNOT_FOUND )
736  result += 1;
737 
738  return result;
739  };
740 
741  // Match on package id
742  if( terms.size() == 1 && terms[0] == aPackage.identifier )
743  rank += 10000;
744 
745  if( terms.size() == 1 && find_term_matches( aPackage.identifier ) )
746  rank += 1000;
747 
748  // Match on package name
749  rank += 500 * find_term_matches( aPackage.name );
750 
751  // Match on tags
752  for( const std::string& tag : aPackage.tags )
753  rank += 100 * find_term_matches( wxString( tag ) );
754 
755  // Match on package description
756  rank += 10 * find_term_matches( aPackage.description );
757  rank += 10 * find_term_matches( aPackage.description_full );
758 
759  // Match on author/maintainer
760  rank += find_term_matches( aPackage.author.name );
761 
762  if( aPackage.maintainer )
763  rank += 3 * find_term_matches( aPackage.maintainer.get().name );
764 
765  // Match on resources
766  for( const auto& entry : aPackage.resources )
767  {
768  rank += find_term_matches( entry.first );
769  rank += find_term_matches( entry.second );
770  }
771 
772  // Match on license
773  if( terms.size() == 1 && terms[0] == aPackage.license )
774  rank += 1;
775 
776  return rank;
777 }
boost::optional< PCM_CONTACT > maintainer
Definition: pcm_data.h:101
wxString description
Definition: pcm_data.h:96
wxString name
Definition: pcm_data.h:63
wxString description_full
Definition: pcm_data.h:97
std::vector< std::string > tags
Definition: pcm_data.h:104
wxString name
Definition: pcm_data.h:95
STRING_MAP resources
Definition: pcm_data.h:103
wxString identifier
Definition: pcm_data.h:98
PCM_CONTACT author
Definition: pcm_data.h:100
wxString license
Definition: pcm_data.h:102

References PCM_PACKAGE::author, PCM_PACKAGE::description, PCM_PACKAGE::description_full, PCM_PACKAGE::identifier, PCM_PACKAGE::license, PCM_PACKAGE::maintainer, PCM_CONTACT::name, PCM_PACKAGE::name, PCM_PACKAGE::resources, and PCM_PACKAGE::tags.

◆ GetPackageState()

PCM_PACKAGE_STATE PLUGIN_CONTENT_MANAGER::GetPackageState ( const wxString &  aRepositoryId,
const wxString &  aPackageId 
)

Get current state of the package.

Parameters
aRepositoryIdrepository id
aPackageIdpackage id
Returns
PCM_PACKAGE_STATE

Definition at line 630 of file pcm.cpp.

632 {
633  if( m_installed.find( aPackageId ) != m_installed.end() )
634  return PPS_INSTALLED;
635 
636  if( aRepositoryId.IsEmpty() || !CacheRepository( aRepositoryId ) )
637  return PPS_UNAVAILABLE;
638 
639  const PCM_REPOSITORY& repo = getCachedRepository( aRepositoryId );
640 
641  auto pkg_it = std::find_if( repo.package_list.begin(), repo.package_list.end(),
642  [&aPackageId]( const PCM_PACKAGE& pkg )
643  {
644  return pkg.identifier == aPackageId;
645  } );
646 
647  if( pkg_it == repo.package_list.end() )
648  return PPS_UNAVAILABLE;
649 
650  const PCM_PACKAGE& pkg = *pkg_it;
651 
652  auto ver_it = std::find_if( pkg.versions.begin(), pkg.versions.end(),
653  []( const PACKAGE_VERSION& ver )
654  {
655  return ver.compatible;
656  } );
657 
658  if( ver_it == pkg.versions.end() )
659  return PPS_UNAVAILABLE;
660  else
661  return PPS_AVAILABLE;
662 }
< Package version metadata Package metadata
Definition: pcm_data.h:73
std::map< wxString, PCM_INSTALLATION_ENTRY > m_installed
Definition: pcm.h:315
Repository reference to a resource.
Definition: pcm_data.h:93
const PCM_REPOSITORY & getCachedRepository(const wxString &aRepositoryId) const
Get the cached repository metadata.
Definition: pcm.cpp:336
const bool CacheRepository(const wxString &aRepositoryId)
Cache specified repository packages and other metadata.
Definition: pcm.cpp:345
std::vector< PACKAGE_VERSION > versions
Definition: pcm_data.h:105
std::vector< PCM_PACKAGE > package_list
Definition: pcm_data.h:128
Package installation entry.
Definition: pcm_data.h:119

References CacheRepository(), getCachedRepository(), m_installed, PCM_REPOSITORY::package_list, PPS_AVAILABLE, PPS_INSTALLED, PPS_UNAVAILABLE, and PCM_PACKAGE::versions.

◆ GetRepositoryList()

const STRING_TUPLE_LIST& PLUGIN_CONTENT_MANAGER::GetRepositoryList ( ) const
inline

Get list of repositories.

Returns
const STRING_TUPLE_LIST& list of repositories in <id, URL, name> tuple format

Definition at line 170 of file pcm.h.

170 { return m_repository_list; }
STRING_TUPLE_LIST m_repository_list
Definition: pcm.h:313

References m_repository_list.

◆ GetRepositoryPackageBitmaps()

std::unordered_map< wxString, wxBitmap > PLUGIN_CONTENT_MANAGER::GetRepositoryPackageBitmaps ( const wxString &  aRepositoryId)

Get the icon bitmaps for repository packages.

Repository package icons are taken from repository's resources zip file

Parameters
aRepositoryIdid of the repository
Returns
map of package id -> bitmap

Definition at line 781 of file pcm.cpp.

782 {
783  std::unordered_map<wxString, wxBitmap> bitmaps;
784 
785  wxFileName resources_file = wxFileName( m_3rdparty_path, wxT( "resources.zip" ) );
786  resources_file.AppendDir( wxT( "cache" ) );
787  resources_file.AppendDir( aRepositoryId );
788 
789  if( !resources_file.FileExists() )
790  return bitmaps;
791 
792  wxFFileInputStream stream( resources_file.GetFullPath() );
793  wxZipInputStream zip( stream );
794 
795  if( !zip.IsOk() || zip.GetTotalEntries() == 0 )
796  return bitmaps;
797 
798  for( wxArchiveEntry* entry = zip.GetNextEntry(); entry; entry = zip.GetNextEntry() )
799  {
800  wxArrayString path_parts =
801  wxSplit( entry->GetName(), wxFileName::GetPathSeparator(), (wxChar) 0 );
802 
803  if( path_parts.size() != 2 || path_parts[1] != wxT( "icon.png" ) )
804  continue;
805 
806  try
807  {
808  wxMemoryInputStream image_stream( zip, entry->GetSize() );
809  wxImage image( image_stream, wxBITMAP_TYPE_PNG );
810  bitmaps.emplace( path_parts[0], wxBitmap( image ) );
811  }
812  catch( ... )
813  {
814  // Log and ignore
815  wxLogTrace( wxT( "Error loading png bitmap for entry %s from %s" ), entry->GetName(),
816  resources_file.GetFullPath() );
817  }
818  }
819 
820  return bitmaps;
821 }
wxString m_3rdparty_path
Definition: pcm.h:310

References image, m_3rdparty_path, and zip.

◆ GetRepositoryPackages()

const std::vector< PCM_PACKAGE > & PLUGIN_CONTENT_MANAGER::GetRepositoryPackages ( const wxString &  aRepositoryId) const

Get the packages metadata from a previously cached repository.

This should only be called after a successful CacheRepository call

Parameters
aRepositoryIdid of the repository
Returns
list of package metadata objects

Definition at line 556 of file pcm.cpp.

557 {
558  return getCachedRepository( aRepositoryId ).package_list;
559 }
const PCM_REPOSITORY & getCachedRepository(const wxString &aRepositoryId) const
Get the cached repository metadata.
Definition: pcm.cpp:336
std::vector< PCM_PACKAGE > package_list
Definition: pcm_data.h:128

References getCachedRepository(), and PCM_REPOSITORY::package_list.

◆ MarkInstalled()

void PLUGIN_CONTENT_MANAGER::MarkInstalled ( const PCM_PACKAGE aPackage,
const wxString &  aVersion,
const wxString &  aRepositoryId 
)

Mark package as installed.

Parameters
aPackagepackage metadata
aVersioninstalled package version
aRepositoryIdid of the source repository or empty estring if installed from a local file

Definition at line 605 of file pcm.cpp.

607 {
609  entry.package = aPackage;
610  entry.current_version = aVersion;
611  entry.repository_id = aRepositoryId;
612 
613  if( !aRepositoryId.IsEmpty() )
614  entry.repository_name = getCachedRepository( aRepositoryId ).name;
615  else
616  entry.repository_name = _( "Local file" );
617 
619 
620  m_installed.emplace( aPackage.identifier, entry );
621 }
std::map< wxString, PCM_INSTALLATION_ENTRY > m_installed
Definition: pcm.h:315
wxString name
Definition: pcm_data.h:121
const PCM_REPOSITORY & getCachedRepository(const wxString &aRepositoryId) const
Get the cached repository metadata.
Definition: pcm.cpp:336
#define _(s)
uint64_t install_timestamp
Definition: pcm_data.h:139
wxString current_version
Definition: pcm_data.h:136
wxString identifier
Definition: pcm_data.h:98
wxString repository_id
Definition: pcm_data.h:137
PCM_PACKAGE package
Definition: pcm_data.h:135
wxString repository_name
Definition: pcm_data.h:138
Definition: pcm_data.h:133
time_t getCurrentTimestamp() const
Definition: pcm.cpp:665

References _, PCM_INSTALLATION_ENTRY::current_version, getCachedRepository(), getCurrentTimestamp(), PCM_PACKAGE::identifier, PCM_INSTALLATION_ENTRY::install_timestamp, m_installed, PCM_REPOSITORY::name, PCM_INSTALLATION_ENTRY::package, PCM_INSTALLATION_ENTRY::repository_id, and PCM_INSTALLATION_ENTRY::repository_name.

◆ MarkUninstalled()

void PLUGIN_CONTENT_MANAGER::MarkUninstalled ( const PCM_PACKAGE aPackage)

Mark package as uninstalled.

Parameters
aPackagepackage metadata

Definition at line 624 of file pcm.cpp.

625 {
626  m_installed.erase( aPackage.identifier );
627 }
std::map< wxString, PCM_INSTALLATION_ENTRY > m_installed
Definition: pcm.h:315
wxString identifier
Definition: pcm_data.h:98

References PCM_PACKAGE::identifier, and m_installed.

◆ preparePackage()

void PLUGIN_CONTENT_MANAGER::preparePackage ( PCM_PACKAGE aPackage)
staticprivate

Parses version strings and calculates compatibility.

This should be called after loading package metadata from repository or from installation entries

Parameters
aPackagepackage metadata objectReturns current UTC timestamp

Definition at line 488 of file pcm.cpp.

489 {
490  // Parse package version strings
491  for( PACKAGE_VERSION& ver : aPackage.versions )
492  {
493  int epoch = 0, major = 0, minor = 0, patch = 0;
494 
495  if( ver.version_epoch )
496  epoch = ver.version_epoch.get();
497 
498  wxStringTokenizer version_tokenizer( ver.version, wxT( "." ) );
499 
500  major = wxAtoi( version_tokenizer.GetNextToken() );
501 
502  if( version_tokenizer.HasMoreTokens() )
503  minor = wxAtoi( version_tokenizer.GetNextToken() );
504 
505  if( version_tokenizer.HasMoreTokens() )
506  patch = wxAtoi( version_tokenizer.GetNextToken() );
507 
508  ver.parsed_version = std::make_tuple( epoch, major, minor, patch );
509 
510  // Determine compatibility
511  ver.compatible = true;
512 
513  auto parse_major_minor = []( const wxString& version )
514  {
515  wxStringTokenizer tokenizer( version, wxT( "." ) );
516  int ver_major = wxAtoi( tokenizer.GetNextToken() );
517  int ver_minor = wxAtoi( tokenizer.GetNextToken() );
518  return std::tuple<int, int>( ver_major, ver_minor );
519  };
520 
521  if( parse_major_minor( ver.kicad_version ) > m_kicad_version )
522  ver.compatible = false;
523 
524  if( ver.kicad_version_max
525  && parse_major_minor( ver.kicad_version_max.get() ) < m_kicad_version )
526  ver.compatible = false;
527 
528 #ifdef __WXMSW__
529  wxString platform = wxT( "windows" );
530 #endif
531 #ifdef __WXOSX__
532  wxString platform = wxT( "macos" );
533 #endif
534 #ifdef __WXGTK__
535  wxString platform = wxT( "linux" );
536 #endif
537 
538  if( ver.platforms.size() > 0
539  && std::find( ver.platforms.begin(), ver.platforms.end(), platform )
540  == ver.platforms.end() )
541  {
542  ver.compatible = false;
543  }
544  }
545 
546  // Sort by descending version
547  std::sort( aPackage.versions.begin(), aPackage.versions.end(),
548  []( const PACKAGE_VERSION& a, const PACKAGE_VERSION& b )
549  {
550  return a.parsed_version > b.parsed_version;
551  } );
552 }
< Package version metadata Package metadata
Definition: pcm_data.h:73
std::vector< std::string > platforms
Definition: pcm_data.h:82
static const std::tuple< int, int > m_kicad_version
Definition: pcm.h:316
boost::optional< int > version_epoch
Definition: pcm_data.h:76
bool compatible
Definition: pcm_data.h:88
std::vector< PACKAGE_VERSION > versions
Definition: pcm_data.h:105
std::tuple< int, int, int, int > parsed_version
Definition: pcm_data.h:87
wxString kicad_version
Definition: pcm_data.h:83
boost::optional< wxString > kicad_version_max
Definition: pcm_data.h:84
wxString version
Definition: pcm_data.h:75

References PACKAGE_VERSION::compatible, PACKAGE_VERSION::kicad_version, PACKAGE_VERSION::kicad_version_max, m_kicad_version, PACKAGE_VERSION::parsed_version, PACKAGE_VERSION::platforms, PACKAGE_VERSION::version, PACKAGE_VERSION::version_epoch, and PCM_PACKAGE::versions.

Referenced by CacheRepository(), and PLUGIN_CONTENT_MANAGER().

◆ SetRepositoryList()

void PLUGIN_CONTENT_MANAGER::SetRepositoryList ( const STRING_PAIR_LIST aRepositories)

Set list of repositories.

Discards cache of repositories that were previously cached but are not on the new list of repositories.

Parameters
aRepositorieslist of <URL, name> pairs of repositories

Definition at line 562 of file pcm.cpp.

563 {
564  // Clean up cache folder if repository is not in new list
565  for( const auto& entry : m_repository_list )
566  {
567  auto it = std::find_if( aRepositories.begin(), aRepositories.end(),
568  [&]( const auto& new_entry )
569  {
570  return new_entry.first == std::get<1>( entry );
571  } );
572 
573  if( it == aRepositories.end() )
574  {
575  DiscardRepositoryCache( std::get<0>( entry ) );
576  }
577  }
578 
579  m_repository_list.clear();
580  m_repository_cache.clear();
581 
582  for( const auto& repo : aRepositories )
583  {
584  std::string url_sha = picosha2::hash256_hex_string( repo.second );
585  m_repository_list.push_back(
586  std::make_tuple( url_sha.substr( 0, 16 ), repo.first, repo.second ) );
587  }
588 }
void DiscardRepositoryCache(const wxString &aRepositoryId)
Discard in-memory and on-disk cache of a repository.
Definition: pcm.cpp:591
STRING_TUPLE_LIST m_repository_list
Definition: pcm.h:313
std::unordered_map< wxString, PCM_REPOSITORY > m_repository_cache
Definition: pcm.h:312

References DiscardRepositoryCache(), m_repository_cache, and m_repository_list.

◆ ValidateJson()

void PLUGIN_CONTENT_MANAGER::ValidateJson ( const nlohmann::json aJson,
const nlohmann::json_uri &  aUri = nlohmann::json_uri( "#" ) 
) const

Validates json against a specific definition in the PCM schema.

Parameters
aJsonJSON object to validate
aUriJSON URI of a definition to validate against, default is root
Exceptions
std::invalid_argumenton validation failure

Definition at line 275 of file pcm.cpp.

277 {
278  THROWING_ERROR_HANDLER error_handler;
279  m_schema_validator.validate( aJson, error_handler, aUri );
280 }
nlohmann::json_schema::json_validator m_schema_validator
Definition: pcm.h:309

References m_schema_validator.

Referenced by fetchPackages(), and FetchRepository().

◆ VerifyHash()

bool PLUGIN_CONTENT_MANAGER::VerifyHash ( std::istream &  aStream,
const wxString &  aHash 
) const

Verifies SHA256 hash of a binary stream.

Parameters
aStreaminput stream
aHashsha256 lowercase hex string
Returns
true if hash matches

Definition at line 323 of file pcm.cpp.

324 {
325  std::vector<unsigned char> bytes( picosha2::k_digest_size );
326 
327  picosha2::hash256( std::istreambuf_iterator<char>( aStream ), std::istreambuf_iterator<char>(),
328  bytes.begin(), bytes.end() );
329  std::string hex_str = picosha2::bytes_to_hex_string( bytes.begin(), bytes.end() );
330 
331  return aHash.compare( hex_str ) == 0;
332 }

Referenced by CacheRepository(), and fetchPackages().

Member Data Documentation

◆ DEFAULT_DOWNLOAD_MEM_LIMIT

constexpr size_t PLUGIN_CONTENT_MANAGER::DEFAULT_DOWNLOAD_MEM_LIMIT = 10 * 1024 * 1024
staticprivate

< Default download limit of 10 Mb to not use too much memory

Definition at line 273 of file pcm.h.

◆ m_3rdparty_path

wxString PLUGIN_CONTENT_MANAGER::m_3rdparty_path
private

◆ m_cache_path

wxString PLUGIN_CONTENT_MANAGER::m_cache_path
private

Definition at line 311 of file pcm.h.

◆ m_dialog

wxWindow* PLUGIN_CONTENT_MANAGER::m_dialog
private

Definition at line 308 of file pcm.h.

Referenced by CacheRepository().

◆ m_installed

std::map<wxString, PCM_INSTALLATION_ENTRY> PLUGIN_CONTENT_MANAGER::m_installed
private

◆ m_kicad_version

const std::tuple< int, int > PLUGIN_CONTENT_MANAGER::m_kicad_version
staticprivate
Initial value:
=
KICAD_MAJOR_MINOR_VERSION_TUPLE

Definition at line 316 of file pcm.h.

Referenced by preparePackage().

◆ m_repository_cache

std::unordered_map<wxString, PCM_REPOSITORY> PLUGIN_CONTENT_MANAGER::m_repository_cache
private

◆ m_repository_list

STRING_TUPLE_LIST PLUGIN_CONTENT_MANAGER::m_repository_list
private

Definition at line 313 of file pcm.h.

Referenced by CacheRepository(), GetRepositoryList(), and SetRepositoryList().

◆ m_schema_validator

nlohmann::json_schema::json_validator PLUGIN_CONTENT_MANAGER::m_schema_validator
private

Definition at line 309 of file pcm.h.

Referenced by PLUGIN_CONTENT_MANAGER(), and ValidateJson().


The documentation for this class was generated from the following files: