// Network integration test hitting a live PrivateBin instance (optional) // Server under test: https://privatebin.medisoftware.org/ // Enable by setting environment variable PRIVATEBIN_IT=1 #include "privatebinapi.h" #include #include #include #include static bool extract_paste_id_and_key(const std::string& full_url, std::string& paste_id, std::string& key) { // Expected format: https://host/path?PASTEID#BASE58_KEY const std::size_t qpos = full_url.find('?'); const std::size_t hpos = full_url.find('#'); if (qpos == std::string::npos || hpos == std::string::npos || hpos <= qpos + 1) { return false; } paste_id = full_url.substr(qpos + 1, hpos - (qpos + 1)); key = full_url.substr(hpos + 1); return !paste_id.empty() && !key.empty(); } int main() { char* it = nullptr; size_t len = 0; _dupenv_s(&it, &len, "PRIVATEBIN_IT"); if (!it || std::string(it) == "0") { std::cout << "[test] PRIVATEBIN_IT not set; skipping integration test." << std::endl; free(it); return 0; // treat as success when integration testing is disabled } const char* server = "https://privatebin.medisoftware.org/"; const char* password = nullptr; // no password const char* expiration = "5min"; // short-lived const int burn_after_reading = 0; const int open_discussion = 0; std::cout << "[test] Testing different text formats..." << std::endl; // Test 1: Plaintext format std::cout << "[test] 1. Testing plaintext format..." << std::endl; const char* plaintext_content = "Integration test from lib-privatebin - plaintext"; const char* plaintext_format = "plaintext"; char* paste_url = nullptr; char* delete_token = nullptr; int rc = create_paste(server, plaintext_content, password, expiration, plaintext_format, burn_after_reading, open_discussion, &paste_url, &delete_token); if (rc != 0 || paste_url == nullptr || delete_token == nullptr) { std::cerr << "[test][ERROR] plaintext create_paste failed, rc=" << rc << std::endl; if (paste_url) free_string(paste_url); if (delete_token) free_string(delete_token); return 1; } std::string full_url = paste_url; std::string paste_id; std::string key; const bool ok_parse = extract_paste_id_and_key(full_url, paste_id, key); if (!ok_parse) { std::cerr << "[test][ERROR] failed to parse paste id/key from URL: " << full_url << std::endl; free_string(paste_url); free_string(delete_token); return 1; } std::cout << "[test] get_paste... id=" << paste_id << std::endl; char* fetched = nullptr; rc = get_paste(server, paste_id.c_str(), key.c_str(), &fetched); if (rc != 0 || fetched == nullptr) { std::cerr << "[test][ERROR] get_paste failed, rc=" << rc << std::endl; free_string(paste_url); free_string(delete_token); return 1; } std::string fetched_str = fetched; assert(fetched_str == plaintext_content && "fetched plaintext content mismatch"); std::cout << "[test] delete_paste..." << std::endl; rc = delete_paste(server, paste_id.c_str(), delete_token); if (rc != 0) { std::cerr << "[test][ERROR] delete_paste failed, rc=" << rc << std::endl; free_string(paste_url); free_string(delete_token); free_string(fetched); return 1; } // cleanup plaintext test free_string(paste_url); free_string(delete_token); free_string(fetched); // Test 2: Syntax highlighting format std::cout << "[test] 2. Testing syntax highlighting format..." << std::endl; const char* code_content = R"( #include int main() { std::cout << "Hello, World!" << std::endl; return 0; } )"; const char* code_format = "syntaxhighlighting"; char* code_paste_url = nullptr; char* code_delete_token = nullptr; rc = create_paste(server, code_content, password, expiration, code_format, burn_after_reading, open_discussion, &code_paste_url, &code_delete_token); if (rc != 0 || code_paste_url == nullptr || code_delete_token == nullptr) { std::cerr << "[test][ERROR] syntax highlighting create_paste failed, rc=" << rc << std::endl; if (code_paste_url) free_string(code_paste_url); if (code_delete_token) free_string(code_delete_token); return 1; } // Parse code paste URL std::string code_full_url = code_paste_url; std::string code_paste_id; std::string code_key; const bool code_ok_parse = extract_paste_id_and_key(code_full_url, code_paste_id, code_key); if (!code_ok_parse) { std::cerr << "[test][ERROR] failed to parse code paste id/key from URL: " << code_full_url << std::endl; free_string(code_paste_url); free_string(code_delete_token); return 1; } // Fetch and verify code paste char* code_fetched = nullptr; rc = get_paste(server, code_paste_id.c_str(), code_key.c_str(), &code_fetched); if (rc != 0 || code_fetched == nullptr) { std::cerr << "[test][ERROR] code get_paste failed, rc=" << rc << std::endl; free_string(code_paste_url); free_string(code_delete_token); return 1; } std::string code_fetched_str = code_fetched; assert(code_fetched_str == code_content && "fetched code content mismatch"); // Delete code paste rc = delete_paste(server, code_paste_id.c_str(), code_delete_token); if (rc != 0) { std::cerr << "[test][ERROR] code delete_paste failed, rc=" << rc << std::endl; free_string(code_paste_url); free_string(code_delete_token); free_string(code_fetched); return 1; } // cleanup code test free_string(code_paste_url); free_string(code_delete_token); free_string(code_fetched); // Test 3: Markdown format std::cout << "[test] 3. Testing markdown format..." << std::endl; const char* markdown_content = R"( # Test Header This is a **bold** and *italic* text. ## Code Block ```cpp int x = 42; std::cout << x << std::endl; ``` > This is a blockquote. )"; const char* markdown_format = "markdown"; char* markdown_paste_url = nullptr; char* markdown_delete_token = nullptr; rc = create_paste(server, markdown_content, password, expiration, markdown_format, burn_after_reading, open_discussion, &markdown_paste_url, &markdown_delete_token); if (rc != 0 || markdown_paste_url == nullptr || markdown_delete_token == nullptr) { std::cerr << "[test][ERROR] markdown create_paste failed, rc=" << rc << std::endl; if (markdown_paste_url) free_string(markdown_paste_url); if (markdown_delete_token) free_string(markdown_delete_token); return 1; } // Parse markdown paste URL std::string markdown_full_url = markdown_paste_url; std::string markdown_paste_id; std::string markdown_key; const bool markdown_ok_parse = extract_paste_id_and_key(markdown_full_url, markdown_paste_id, markdown_key); if (!markdown_ok_parse) { std::cerr << "[test][ERROR] failed to parse markdown paste id/key from URL: " << markdown_full_url << std::endl; free_string(markdown_paste_url); free_string(markdown_delete_token); return 1; } // Fetch and verify markdown paste char* markdown_fetched = nullptr; rc = get_paste(server, markdown_paste_id.c_str(), markdown_key.c_str(), &markdown_fetched); if (rc != 0 || markdown_fetched == nullptr) { std::cerr << "[test][ERROR] markdown get_paste failed, rc=" << rc << std::endl; free_string(markdown_paste_url); free_string(markdown_delete_token); return 1; } std::string markdown_fetched_str = markdown_fetched; assert(markdown_fetched_str == markdown_content && "fetched markdown content mismatch"); // Delete markdown paste rc = delete_paste(server, markdown_paste_id.c_str(), markdown_delete_token); if (rc != 0) { std::cerr << "[test][ERROR] markdown delete_paste failed, rc=" << rc << std::endl; free_string(markdown_paste_url); free_string(markdown_delete_token); free_string(markdown_fetched); return 1; } // cleanup markdown test free_string(markdown_paste_url); free_string(markdown_delete_token); free_string(markdown_fetched); std::cout << "[test] All format tests passed successfully!" << std::endl; return 0; }