Skip to content

Fix cURL CA #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/MainDistributionPipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ jobs:

duckdb-stable-build:
name: Build extension binaries
uses: duckdb/extension-ci-tools/.github/workflows/[email protected].1
uses: duckdb/extension-ci-tools/.github/workflows/[email protected].2
with:
duckdb_version: v1.2.1
ci_tools_version: v1.2.1
duckdb_version: v1.2.2
ci_tools_version: v1.2.2
extension_name: netquack
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,9 @@ This extension provides various functions for manipulating and analyzing IP addr

#### IP Calculator

> [!WARNING]
> It's an experimental function.

The `ipcalc` function takes an IP address and netmask and calculates the resulting broadcast, network, wildcard mask, and host range.

![ipcalc-sc](./.github/ipcalc-sc.png)
Expand Down Expand Up @@ -369,9 +372,6 @@ D SELECT i.IP,
└────────────────┴───────┘
```

> [!WARNING]
> It's an experimental function.

### Get Extension Version

You can use the `netquack_version` function to get the extension version.
Expand All @@ -382,7 +382,7 @@ D select * from netquack_version();
│ version │
│ varchar │
├─────────┤
│ v1.2.0 │
│ v1.4.0 │
Copy link
Preview

Copilot AI May 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The README now displays version v1.4.0, which conflicts with the intended DuckDB bump mentioned in the PR description and CI pipeline (v1.2.2). Consider reconciling these version numbers for clarity.

Suggested change
│ v1.4.0
│ v1.2.2

Copilot uses AI. Check for mistakes.

└─────────┘
```

Expand Down
2 changes: 1 addition & 1 deletion duckdb
Submodule duckdb updated 156 files
24 changes: 9 additions & 15 deletions src/functions/get_tranco.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace duckdb
// Function to get the download code for the Tranco list
std::string GetTrancoDownloadCode (char *date)
{
CURL *curl;
CURL *curl = CreateCurlHandler ();
CURLcode res;
std::string readBuffer;

Expand All @@ -23,21 +23,15 @@ namespace duckdb

LogMessage ("INFO", "Get Tranco download code for date: " + std::string (date));

curl = curl_easy_init ();
if (curl)
curl_easy_setopt (curl, CURLOPT_URL, url.c_str ());
curl_easy_setopt (curl, CURLOPT_WRITEDATA, &readBuffer);
res = curl_easy_perform (curl);
curl_easy_cleanup (curl);

if (res != CURLE_OK)
{
curl_easy_setopt (curl, CURLOPT_URL, url.c_str ());
curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1L); // Follow redirects
curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt (curl, CURLOPT_WRITEDATA, &readBuffer);
res = curl_easy_perform (curl);
curl_easy_cleanup (curl);

if (res != CURLE_OK)
{
LogMessage ("ERROR", "Failed to fetch Tranco download code: " + std::string (curl_easy_strerror (res)));
throw std::runtime_error ("Failed to fetch Tranco download code.");
}
LogMessage ("ERROR", "Failed to fetch Tranco download code: " + std::string (curl_easy_strerror (res)));
throw std::runtime_error ("Failed to fetch Tranco download code.");
}

// Extract the download code from the URL
Expand Down
2 changes: 1 addition & 1 deletion src/functions/get_version.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ namespace duckdb

output.SetCardinality (1);
// Set version
output.data[0].SetValue (0, "v1.1.0");
output.data[0].SetValue (0, "v1.4.0");
Copy link
Preview

Copilot AI May 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The version string is updated to v1.4.0, while the PR description and workflow indicate a bump to DuckDB v1.2.2. Please ensure that version numbers are consistent across the project.

Suggested change
output.data[0].SetValue (0, "v1.4.0");
output.data[0].SetValue (0, "v1.2.2");

Copilot uses AI. Check for mistakes.

// Set done
auto &local_state = (VersionLocalState &)*data_p.local_state;
local_state.done = true;
Expand Down
90 changes: 76 additions & 14 deletions src/utils/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,77 @@
#include <regex>
#include <sstream>

#ifdef _WIN32
#include <windows.h>
#else // POSIX
#include <sys/stat.h>
#endif

namespace duckdb
{
namespace netquack
{
bool file_exists (const char *file_path)
{
#ifdef _WIN32
DWORD attributes = GetFileAttributesA (file_path);
return (attributes != INVALID_FILE_ATTRIBUTES);
#else // POSIX
struct stat buffer;
return (stat (file_path, &buffer) == 0);
#endif
}

CURL *CreateCurlHandler ()
{
CURL *curl = curl_easy_init ();
if (!curl)
{
throw std::runtime_error ("Failed to initialize CURL");
}

const char *ca_info = std::getenv ("CURL_CA_INFO");
#if !defined(_WIN32) && !defined(__APPLE__)
if (!ca_info)
{
// Check for common CA certificate bundle locations on Linux
for (const auto *path : {
Copy link
Preview

Copilot AI May 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Using fopen to check for file existence could be replaced with std::ifstream or std::filesystem for better portability and RAII compliance.

Copilot uses AI. Check for mistakes.

"/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc.
"/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL 6
"/etc/ssl/ca-bundle.pem", // OpenSUSE
"/etc/pki/tls/cacert.pem", // OpenELEC
"/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7
"/etc/ssl/cert.pem" // Alpine Linux
})
{
if (file_exists (path))
{
ca_info = path;
break;
}
}
}
#endif
curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1L); // Follow redirects
curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, WriteCallback);
if (ca_info)
{
// Set the custom CA certificate bundle file
// https://github.com/hatamiarash7/duckdb-netquack/issues/6
LogMessage ("DEBUG", "Using custom CA certificate bundle: " + std::string (ca_info));
curl_easy_setopt (curl, CURLOPT_CAINFO, ca_info);
}
const char *ca_path = std::getenv ("CURL_CA_PATH");
if (ca_path)
{
// Set the custom CA certificate directory
LogMessage ("DEBUG", "Using custom CA certificate directory: " + std::string (ca_path));
curl_easy_setopt (curl, CURLOPT_CAPATH, ca_path);
}

return curl;
}

void LogMessage (const std::string &level, const std::string &message)
{
std::ofstream log_file ("netquack.log", std::ios_base::app);
Expand All @@ -31,24 +98,19 @@ namespace duckdb

std::string DownloadPublicSuffixList ()
{
CURL *curl;
CURL *curl = CreateCurlHandler ();
CURLcode res;
std::string readBuffer;

curl = curl_easy_init ();
if (curl)
{
curl_easy_setopt (curl, CURLOPT_URL, "https://publicsuffix.org/list/public_suffix_list.dat");
curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt (curl, CURLOPT_WRITEDATA, &readBuffer);
res = curl_easy_perform (curl);
curl_easy_cleanup (curl);
curl_easy_setopt (curl, CURLOPT_URL, "https://publicsuffix.org/list/public_suffix_list.dat");
curl_easy_setopt (curl, CURLOPT_WRITEDATA, &readBuffer);
res = curl_easy_perform (curl);
curl_easy_cleanup (curl);

if (res != CURLE_OK)
{
LogMessage ("ERROR", "Failed to download public suffix list: " + std::string (curl_easy_strerror (res)));
throw std::runtime_error ("Failed to download public suffix list. Check logs for details.");
}
if (res != CURLE_OK)
{
LogMessage ("ERROR", "Failed to download public suffix list: " + std::string (curl_easy_strerror (res)));
throw std::runtime_error ("Failed to download public suffix list. Check logs for details.");
}

return readBuffer;
Expand Down
5 changes: 5 additions & 0 deletions src/utils/utils.hpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
#pragma once

#include <curl/curl.h>

#include "duckdb.hpp"

namespace duckdb
{
namespace netquack
{
// Function to get a CURL handler
CURL *CreateCurlHandler ();

// Function to log messages with a specified log level
void LogMessage (const std::string &level, const std::string &message);

Expand Down