23#include <wx/translation.h> 
   26#include <boost/algorithm/string.hpp> 
   43    if( aTestConnectionNow )
 
 
   60        res = curl->GetBuffer();
 
   65        if( 
res.length() == 0 )
 
   67            m_lastError += wxString::Format( 
_( 
"KiCad received an empty response!" ) + 
"\n" );
 
   71            nlohmann::json response = nlohmann::json::parse( 
res );
 
   74            if( !response.at( 
"categories" ).empty() && !response.at( 
"parts" ).empty() )
 
   78    catch( 
const std::exception& e )
 
   80        m_lastError += wxString::Format( 
_( 
"Error: %s" ) + 
"\n" + 
_( 
"API Response:  %s" ) + 
"\n",
 
   83        wxLogTrace( 
traceHTTPLib, wxT( 
"validateHttpLibraryEndpoints: Exception while testing API connection: %s" ),
 
 
  100        wxLogTrace( 
traceHTTPLib, wxT( 
"syncCategories: without valid connection!" ) );
 
  104    std::string 
res = 
"";
 
  107    curl->SetURL( 
m_source.root_url + 
"categories.json" );
 
  113        res = curl->GetBuffer();
 
  118        nlohmann::json response = nlohmann::json::parse( 
res );
 
  121        for( 
const auto& item : response.items() )
 
  125            auto& value = item.value();
 
  126            category.
id = value[
"id"].get<std::string>();
 
  127            category.
name = value[
"name"].get<std::string>();
 
  129            if( value.contains( 
"description" ) )
 
  131                category.
description = value[
"description"].get<std::string>();
 
  138    catch( 
const std::exception& e )
 
  140        m_lastError += wxString::Format( 
_( 
"Error: %s" ) + 
"\n" + 
_( 
"API Response:  %s" ) + 
"\n",
 
 
  158        wxString strval( std::any_cast<std::string>( aVal ).c_str(), wxConvUTF8 );
 
  160        if( strval.IsEmpty() )
 
  161            return aDefaultValue;
 
  165        for( 
const auto& trueVal : { wxS( 
"true" ), wxS( 
"yes" ), wxS( 
"y" ), wxS( 
"1" ) } )
 
  167            if( strval.Matches( trueVal ) )
 
  171        for( 
const auto& falseVal : { wxS( 
"false" ), wxS( 
"no" ), wxS( 
"n" ), wxS( 
"0" ) } )
 
  173            if( strval.Matches( falseVal ) )
 
  177    catch( 
const std::bad_any_cast& )
 
  181    return aDefaultValue;
 
 
  189    aPart.
id = aPart_json.at( 
"id" );
 
  192    if( aPart_json.contains( 
"name" ) )
 
  193        aPart.
name = aPart_json.at( 
"name" );
 
  199    if( aPart_json.contains( 
"description" ) )
 
  200        aPart.
desc = aPart_json.at( 
"description" );
 
  202    if( aPart_json.contains( 
"keywords" ) )
 
  203        aPart.
keywords = aPart_json.at( 
"keywords" );
 
  205    if( aPart_json.contains( 
"footprint_filters" ) )
 
  207        nlohmann::json filters_json = aPart_json.at( 
"footprint_filters" );
 
  209        if( filters_json.is_array() )
 
  211            for( 
const auto& val : filters_json )
 
 
  226        wxLogTrace( 
traceHTTPLib, wxT( 
"SelectOne: without valid connection!" ) );
 
  234        if( std::difftime( std::time( 
nullptr ), 
m_cachedParts[aPartID].lastCached ) < 
m_source.timeout_parts )
 
  241    std::string 
res = 
"";
 
  244    std::string url = 
m_source.root_url + fmt::format( 
"parts/{}.json", aPartID );
 
  251        res = curl->GetBuffer();
 
  256        nlohmann::ordered_json response = nlohmann::ordered_json::parse( 
res );
 
  257        std::string    key = 
"";
 
  258        std::string    value = 
"";
 
  261        aFetchedPart.
lastCached = std::time( 
nullptr );
 
  265        aFetchedPart.
symbolIdStr = response.at( 
"symbolIdStr" );
 
  270        if( response.contains( 
"exclude_from_bom" ) )
 
  273            exclude = response.at( 
"exclude_from_bom" );
 
  278        if( response.contains( 
"exclude_from_board" ) )
 
  281            exclude = response.at( 
"exclude_from_board" );
 
  286        if( response.contains( 
"exclude_from_sim" ) )
 
  289            exclude = response.at( 
"exclude_from_sim" );
 
  294        aFetchedPart.
fields.clear();
 
  297        for( 
const auto& field : response.at( 
"fields" ).items() )
 
  305            auto& properties = field.value();
 
  307            value = properties.at( 
"value" );
 
  310            if( properties.contains( 
"visible" ) )
 
  312                std::string vis = properties.at( 
"visible" );
 
  317            aFetchedPart.
fields.push_back( std::make_pair( key, std::make_tuple( value, visible ) ) );
 
  320    catch( 
const std::exception& e )
 
  322        m_lastError += wxString::Format( 
_( 
"Error: %s" ) + 
"\n" + 
_( 
"API Response: %s" ) + 
"\n",
 
 
  340        wxLogTrace( 
traceHTTPLib, wxT( 
"SelectAll: without valid connection!" ) );
 
  344    std::string 
res = 
"";
 
  348    curl->SetURL( 
m_source.root_url + fmt::format( 
"parts/category/{}.json", aCategory.
id ) );
 
  354        res = curl->GetBuffer();
 
  356        nlohmann::json response = nlohmann::json::parse( 
res );
 
  358        for( nlohmann::json& item : response )
 
  368            aParts.emplace_back( std::move( part ) );
 
  371    catch( 
const std::exception& e )
 
  373        m_lastError += wxString::Format( 
_( 
"Error: %s" ) + 
"\n" + 
_( 
"API Response: %s" ) + 
"\n",
 
 
  387    int statusCode = aCurl->GetResponseStatusCode();
 
  389    if( statusCode != 200 )
 
  391        m_lastError += wxString::Format( 
_( 
"API responded with error code: %s" ) + 
"\n",
 
 
  402    auto codeDescription =
 
  403            []( uint16_t aCode ) -> wxString
 
  407                case 100: 
return wxS( 
"Continue" );
 
  408                case 101: 
return wxS( 
"Switching Protocols" );
 
  409                case 102: 
return wxS( 
"Processing" );
 
  410                case 103: 
return wxS( 
"Early Hints" );
 
  412                case 200: 
return wxS( 
"OK" );
 
  413                case 201: 
return wxS( 
"Created" );
 
  414                case 203: 
return wxS( 
"Non-Authoritative Information" );
 
  415                case 204: 
return wxS( 
"No Content" );
 
  416                case 205: 
return wxS( 
"Reset Content" );
 
  417                case 206: 
return wxS( 
"Partial Content" );
 
  418                case 207: 
return wxS( 
"Multi-Status" );
 
  419                case 208: 
return wxS( 
"Already Reported" );
 
  420                case 226: 
return wxS( 
"IM Used" );
 
  422                case 300: 
return wxS( 
"Multiple Choices" );
 
  423                case 301: 
return wxS( 
"Moved Permanently" );
 
  424                case 302: 
return wxS( 
"Found" );
 
  425                case 303: 
return wxS( 
"See Other" );
 
  426                case 304: 
return wxS( 
"Not Modified" );
 
  427                case 305: 
return wxS( 
"Use Proxy (Deprecated)" );
 
  428                case 306: 
return wxS( 
"Unused" );
 
  429                case 307: 
return wxS( 
"Temporary Redirect" );
 
  430                case 308: 
return wxS( 
"Permanent Redirect" );
 
  432                case 400: 
return wxS( 
"Bad Request" );
 
  433                case 401: 
return wxS( 
"Unauthorized" );
 
  434                case 402: 
return wxS( 
"Payment Required (Experimental)" );
 
  435                case 403: 
return wxS( 
"Forbidden" );
 
  436                case 404: 
return wxS( 
"Not Found" );
 
  437                case 405: 
return wxS( 
"Method Not Allowed" );
 
  438                case 406: 
return wxS( 
"Not Acceptable" );
 
  439                case 407: 
return wxS( 
"Proxy Authentication Required" );
 
  440                case 408: 
return wxS( 
"Request Timeout" );
 
  441                case 409: 
return wxS( 
"Conflict" );
 
  442                case 410: 
return wxS( 
"Gone" );
 
  443                case 411: 
return wxS( 
"Length Required" );
 
  444                case 412: 
return wxS( 
"Payload Too Large" );
 
  445                case 414: 
return wxS( 
"URI Too Long" );
 
  446                case 415: 
return wxS( 
"Unsupported Media Type" );
 
  447                case 416: 
return wxS( 
"Range Not Satisfiable" );
 
  448                case 417: 
return wxS( 
"Expectation Failed" );
 
  449                case 418: 
return wxS( 
"I'm a teapot" );
 
  450                case 421: 
return wxS( 
"Misdirected Request" );
 
  451                case 422: 
return wxS( 
"Unprocessable Content" );
 
  452                case 423: 
return wxS( 
"Locked" );
 
  453                case 424: 
return wxS( 
"Failed Dependency" );
 
  454                case 425: 
return wxS( 
"Too Early (Experimental)" );
 
  455                case 426: 
return wxS( 
"Upgrade Required" );
 
  456                case 428: 
return wxS( 
"Precondition Required" );
 
  457                case 429: 
return wxS( 
"Too Many Requests" );
 
  458                case 431: 
return wxS( 
"Request Header Fields Too Large" );
 
  459                case 451: 
return wxS( 
"Unavailable For Legal Reasons" );
 
  461                case 500: 
return wxS( 
"Internal Server Error" );
 
  462                case 501: 
return wxS( 
"Not Implemented" );
 
  463                case 502: 
return wxS( 
"Bad Gateway" );
 
  464                case 503: 
return wxS( 
"Service Unavailable" );
 
  465                case 504: 
return wxS( 
"Gateway Timeout" );
 
  466                case 505: 
return wxS( 
"HTTP Version Not Supported" );
 
  467                case 506: 
return wxS( 
"Variant Also Negotiates" );
 
  468                case 507: 
return wxS( 
"Insufficient Storage" );
 
  469                case 508: 
return wxS( 
"Loop Detected" );
 
  470                case 510: 
return wxS( 
"Not Extended" );
 
  471                case 511: 
return wxS( 
"Network Authentication Required" );
 
  472                default:  
return wxS( 
"Unknown" );
 
  476    return wxString::Format( wxS( 
"%d: %s" ), aHttpCode, codeDescription( aHttpCode ) );
 
 
bool checkServerResponse(std::unique_ptr< KICAD_CURL_EASY > &aCurl)
 
bool validateHttpLibraryEndpoints()
 
std::map< std::string, HTTP_LIB_PART > m_cachedParts
 
std::unique_ptr< KICAD_CURL_EASY > createCurlEasyObject()
 
std::map< std::string, std::string > m_categoryDescriptions
 
bool SelectAll(const HTTP_LIB_CATEGORY &aCategory, std::vector< HTTP_LIB_PART > &aParts)
Retrieve all parts from a specific category from the HTTP library.
 
HTTP_LIB_CONNECTION(const HTTP_LIB_SOURCE &aSource, bool aTestConnectionNow)
 
std::map< std::string, std::tuple< std::string, std::string > > m_cache
 
std::vector< HTTP_LIB_CATEGORY > m_categories
 
bool IsValidEndpoint() const
 
bool SelectOne(const std::string &aPartID, HTTP_LIB_PART &aFetchedPart)
Retrieve a single part with full details from the HTTP library.
 
wxString httpErrorCodeDescription(uint16_t aHttpCode)
HTTP response status codes indicate whether a specific HTTP request has been successfully completed.
 
static UTF8 FixIllegalChars(const UTF8 &aLibItemName, bool aLib)
Replace illegal LIB_ID item name characters with underscores '_'.
 
const char * c_str() const
 
void setPartIdNameAndMetadata(const nlohmann::json &aPart_json, HTTP_LIB_PART &aPart)
 
const char *const traceHTTPLib
 
bool boolFromString(const std::any &aVal, bool aDefaultValue)
 
const char *const traceHTTPLib
 
std::string id
id of category
 
std::string name
name of category
 
std::string description
description of category
 
std::vector< std::string > fp_filters
 
std::vector< std::pair< std::string, std::tuple< std::string, bool > > > fields