diff options
Diffstat (limited to 'docs')
-rw-r--r-- | docs/applications.md | 24 | ||||
-rw-r--r-- | docs/architecture.md | 15 | ||||
-rw-r--r-- | docs/build-steps.md | 84 | ||||
-rw-r--r-- | docs/configuration-logic.md | 87 | ||||
-rw-r--r-- | docs/libproxy.svg | 1 | ||||
-rw-r--r-- | docs/meson.build | 47 | ||||
-rw-r--r-- | docs/perl.md | 21 | ||||
-rw-r--r-- | docs/proxy-authentication.md | 7 | ||||
-rw-r--r-- | docs/px.toml.in | 71 | ||||
-rw-r--r-- | docs/python.md | 30 | ||||
-rw-r--r-- | docs/ruby.md | 20 | ||||
-rw-r--r-- | docs/samples.md | 4 | ||||
-rw-r--r-- | docs/samples/dotnet/Makefile | 8 | ||||
-rw-r--r-- | docs/samples/dotnet/proxy.cs | 38 | ||||
-rw-r--r-- | docs/samples/libcurl/Makefile | 9 | ||||
-rw-r--r-- | docs/samples/libcurl/curlget.c | 108 | ||||
-rw-r--r-- | docs/samples/perl/sample.pl | 7 | ||||
-rw-r--r-- | docs/samples/vala/Makefile | 7 | ||||
-rw-r--r-- | docs/samples/vala/sample.vala | 9 | ||||
-rw-r--r-- | docs/vala.md | 32 | ||||
-rw-r--r-- | docs/version.xml.in | 1 |
21 files changed, 630 insertions, 0 deletions
diff --git a/docs/applications.md b/docs/applications.md new file mode 100644 index 0000000..79fe046 --- /dev/null +++ b/docs/applications.md @@ -0,0 +1,24 @@ +Title: Applications - Who is using Libproxy? +Slug: ApplicationMatrix + +# Applications - Who is using Libproxy? + + +| Application | Upstream | Patches | +| --- | -- | -- | +| apt | NO | AVAILABLE | +| cURL | NO | AVAILABLE | +| eid-viewer | YES | - | +| glib-networking | YES | - | +| libQt5Network | YES | - | +| libzypp | YES | - | +| Mozilla Firefox | YES | - | +| neon | YES | - | +| openconnect | YES | - | +| python-requests | NO | AVAILABLE | +| seamonkey | YES | - | +| signond | YES | - | +| signond_ui | YES | - | +| vagalume | YES | - | +| wget | NO | [Patch](https://build.opensuse.org/package/show/openSUSE:Factory/wget) | + diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..35c3596 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,15 @@ +Title: Architecture - Difference between library and D-Bus service +Slug: Architecture + + +# Architecture + +Starting with release 0.5.0 Libproxy is making use of glib. glib has many +advantages and helps to get rid of one of the major issues we have had with +previous versions of Libproxy. To name a few advantages: + +- Testing Framework +- Make use of existing plugin loader +- Automatic documentation out of code +- Gobject Introspection bindings for almost every programming language + diff --git a/docs/build-steps.md b/docs/build-steps.md new file mode 100644 index 0000000..2590c4e --- /dev/null +++ b/docs/build-steps.md @@ -0,0 +1,84 @@ +Title: Build steps - How to compile libproxy +Slug: building + +# Build steps - How to compile libproxy + +## Fedora + +### Dependencies + +``` +sudo dnf install glib2-devel duktape-devel libsoup3-devel meson gcovr gi-docgen libcurl-devel vala gsettings-desktop-schemas-devel gobject-introspection-devel +``` + +### Build Setup + +``` +meson setup build +``` + +### Compilation + +``` +ninja -C build +``` + +### Installation + +``` +ninja -C build install +``` + +## OS X + +### Dependencies + +``` +pip install meson ninja +brew install libsoup icu4c gobject-introspection duktape gcovr gi-docgen curl vala +``` + +### Build Setup + +``` +meson setup build +``` + +### Compilation + +``` +ninja -C build +``` + +### Installation + +``` +ninja -C build install +``` + +## Windows (MSYS2) + +### Dependencies + +``` +pacman -S base-devel git mingw-w64-x86_64-toolchain mingw-w64-x86_64-ccache mingw-w64-x86_64-pkg-config mingw-w64-x86_64-gobject-introspection mingw-w64-x86_64-python-gobject mingw-w64-x86_64-meson mingw-w64-x86_64-glib mingw-w64-x86_64-duktape mingw-w64-x86_64-gi-docgen mingw-w64-x86_64-libsoup3 mingw-w64-x86_64-curl mingw-w64-x86_64-vala +``` + +### Build Setup + +``` +meson setup build +``` + +### Compilation + +``` +ninja -C build +``` + +### Installation + +``` +ninja -C build install +``` + diff --git a/docs/configuration-logic.md b/docs/configuration-logic.md new file mode 100644 index 0000000..783a8db --- /dev/null +++ b/docs/configuration-logic.md @@ -0,0 +1,87 @@ +Title: Configuration Logic +Slug: Design + +# Configuration Logic + +## Introduction +As the proxy configuration predates libproxy, we need to consider previous +implementation behavior to ensure consistency with user expectations. This page +presents analyses of well known implementation base on the platform they run on. + +## Linux +On Linux the pioneer of proxy support is Mozilla browsers (former Netscape). +But other browsers do support proxy and has it's own proxy configuration +interpretation logic. Current GNOME proxy settings is a copy of Firefox +settings. + +### Firefox +When using Firefox internal manual settings, the proxy is selected base on the +most specific proxy (e.g. HTTP before SOCKS). Only one proxy is selected, if +connection to that proxy fails, then connection fails. + +``` + IF protocol specific proxy is set THEN use it + ELSE IF SOCKS proxy is set THEN use it + ELSE use direct connection. +``` + +### Firefox and Chromium (with GNOME settings) +After some testing we found that Chromium mimics perfectly Firefox behavior +when using system settings. When using manual proxy configuration mode, those +browsers chooses a proxy base on the most generic solution (SOCKS) to the most +specific (per protocol proxies), with an exception when a single proxy is set +for all protocols. Only one protocol is selected and no fallback will occur in +the case of failures. Those browsers support SOCKS, HTTP, HTTPS, FTP and +Firefox also support Gopher. You can also set the configuration to use a +specific PAC file or to automatically discover one (WPAD) but those does not +contain any special logic. Next is the logic represent as pseudo code: + +``` + IF not using same proxy for all protocols THEN + IF SOCKS is set THEN use it + ELSE IF protocol specific proxy is set THEN use it + ELSE IF using same proxy for all protocols THEN + IF SOCKS is set THEN use it + IF no proxy has been set THEN use direct connection +``` + +## OS X +OS X uses it's own way for proxy settings. It supports protocols including +SOCKS, HTTP, HTTPS, FTP, Gopher, RTSP, and automatic configuration through PAC +files. For sake of simplicity, we have tested the logic with the default browser +Safari. + +### Safari +Safari interpret proxy logic differently from Firefox. If multiple proxy are +configured, it try each of them until a connection is established. From our +testing the order seems to be from most specific to most generic (starting with +manual configuration). Next is the logic represented as pseudo code: + +``` + DEFINE proxy_list as list + IF protocol specific proxy is set THEN add it to proxy_list + IF SOCKS proxy is set THEN append it to proxy_list + IF PAC auto-configuration is set THEN append it to proxy_list + FOREACH proxy in proxy_list + connect to proxy + IF connection failed THEN continue + ELSE stop +``` + +## Windows +Windows user most often use Internet Explorer, Firefox or Opera for browsing. +Analyses as shown that Firefox acts exactly the same as on Linux, except that +same logic is applied for internal settings and system setting (IE settings). +Internet explorer also act the same way, and Opera only support protocol +specific proxies (no SOCKS). So essentially, if chooses choose the most +specific proxy, and if that one fails the own connection fails. + +## Conclusion +Base on current result, we see that the most common logic is to select a proxy +starting from the most specific (HTTP, FTP, etc.) to the least specific +(SOCKS, PAC then WPAD). OS X pushes a bit further by trying all the configure +proxy that match the protocol. This technique is interesting for libproxy +since it warranty that connection will be possible for all cases covered by +the others. The only difference with the GNOME environment is that OS X may +connect through an HTTP server while Firefox and Chromium (on Gnome) would +connect to a SOCKS server if both are available. diff --git a/docs/libproxy.svg b/docs/libproxy.svg new file mode 100644 index 0000000..70d3793 --- /dev/null +++ b/docs/libproxy.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><g fill="#2a488c"><path d="M4.96 8.635V11H1.367c-.206 0-.368.205-.368.467v1.058c0 .262.162.467.368.467h10.264c.206 0 .368-.205.368-.467v-1.058c0-.262-.162-.467-.368-.467H7.977V8.635z"/><path d="M3.8 0C2.849 0 2 .793 2 1.746v6.613c0 .953.849 1.746 1.868 1.746h5.264c1.02 0 1.868-.793 1.868-1.746V1.746C11 .793 10.151 0 9.132 0zM4 2h5c0 .317 0-.316 0 0v6H4s0 .044 0 0V2c0-.044 0 0 0 0z" style="line-height:normal;-inkscape-font-specification:'Bitstream Vera Sans';text-indent:0;text-align:start;text-decoration-line:none;text-transform:none;marker:none" color="#fff" font-weight="400" font-family="Bitstream Vera Sans" overflow="visible"/><path d="M5 2.971h3v1.003H5zm2 2.005h1v1.002H7z" style="marker:none" color="#fff" overflow="visible"/><path d="M9.229 3c.07 0 0 .209 0 .476v1.078c0 .267.07.476.16.476h4.451c.09 0 .16-.209.16-.476V3.476c0-.267-.07-.476-.16-.476-.16 0-4.585.063-4.611 0zm-3.256 8.624c.08-.06.253.039.394.223l.573.747c.142.184.191.375.112.435l-3.935 2.954c-.08.059-.253-.039-.395-.224l-.573-.746c-.141-.184-.19-.376-.111-.435 0 0 3.946-2.893 3.935-2.954z"/><path d="M7.027 11.624c-.08-.06-.253.039-.394.223l-.573.747c-.142.184-.191.375-.112.435l3.935 2.954c.08.059.253-.039.395-.224l.573-.746c.141-.184.19-.376.111-.435 0 0-3.946-2.893-3.935-2.954z"/></g></svg>
\ No newline at end of file diff --git a/docs/meson.build b/docs/meson.build new file mode 100644 index 0000000..3c2fae9 --- /dev/null +++ b/docs/meson.build @@ -0,0 +1,47 @@ +if get_option('docs') + +expand_content_md_files = [ + 'architecture.md', + 'applications.md', + 'build-steps.md', + 'configuration-logic.md', + 'perl.md', + 'python.md', + 'ruby.md', + 'vala.md', +] + +toml_data = configuration_data() +toml_data.set('VERSION', meson.project_version()) + +px_toml = configure_file( + input: 'px.toml.in', + output: 'px.toml', + configuration: toml_data +) + +gidocgen = find_program('gi-docgen') + +docs_dir = datadir / 'doc' + +custom_target('px-doc', + input: [ px_toml, libproxy_gir[0] ], + output: 'libproxy-@0@'.format(api_version), + command: [ + gidocgen, + 'generate', + '--quiet', + '--add-include-path=@0@'.format(meson.current_source_dir() + '/src'), + '--config=@INPUT0@', + '--output-dir=@OUTPUT@', + '--no-namespace-dir', + '--content-dir=@0@'.format(meson.current_source_dir()), + '@INPUT1@', + ], + depend_files: [ expand_content_md_files ], + build_by_default: true, + install: true, + install_dir: docs_dir, +) + +endif diff --git a/docs/perl.md b/docs/perl.md new file mode 100644 index 0000000..eee6bbe --- /dev/null +++ b/docs/perl.md @@ -0,0 +1,21 @@ +Title: How to use libproxy in Perl +Slug: snippets + +# How to use libproxy in Perl + +``` +#!/usr/bin/perl +use warnings; +use Glib::Object::Introspection; +Glib::Object::Introspection->setup( + basename => 'Px', + version => '1.0', + package => 'Px'); + +my $pf = new Px::ProxyFactory; + +$proxies = $pf->get_proxies("https://github.com/libproxy/libproxy"); +foreach my $proxy (@$proxies) { + print $proxy."\n"; +} +``` diff --git a/docs/proxy-authentication.md b/docs/proxy-authentication.md new file mode 100644 index 0000000..de7a905 --- /dev/null +++ b/docs/proxy-authentication.md @@ -0,0 +1,7 @@ +Title: Proxy Authentication +Slug: ProxyAuthentication + + +# Proxy Authentication +Because proxy authentication is protocol specific, it is outside the scope of this library. libproxy tells you WHICH proxy servers to try to use, +not HOW to use them. diff --git a/docs/px.toml.in b/docs/px.toml.in new file mode 100644 index 0000000..8cab536 --- /dev/null +++ b/docs/px.toml.in @@ -0,0 +1,71 @@ +[library] +version = "@VERSION@" +description = "Simplifyed proxy handling" +authors = "libproxy Team" +license = "LGPL-2.1-or-later" +browse_url = "https://github.com/libproxy/libproxy" +repository_url = "https://github.com/libproxy/libproxy" +website_url = "https://libproxy.github.io/libproxy/" +# logo_url = "libproxy.svg" +dependencies = [ + "GObject-2.0", + "Gio-2.0", + "GLib-2.0", + "Soup-3.0", + "curl-1.0", +] +devhelp = true +search_index = true + +[dependencies."GObject-2.0"] +name = "GObject" +description = "The base type system library" +docs_url = "https://developer.gnome.org/gobject/stable" + +[dependencies."Gio-2.0"] +name = "Gio" +description = "Gio is a library providing useful classes for general purpose I/O, networking, IPC, settings, and other high level application functionality" +docs_url = "https://developer.gnome.org/gio/stable" + +[dependencies."GLib-2.0"] +name = "GLib" +description = "The base utility library" +docs_url = "https://developer.gnome.org/glib/stable" + +[dependencies."Soup-3.0"] +name = "Soup" +description = "HTTP client/server library for GNOME" +docs_url = "https://libsoup.org/libsoup-3.0/index.html" + +[dependencies."curl-1.0"] +name = "cURL" +description = "Library for transferring data" +docs_url = "https://github.com/curl/curl" + +[theme] +name = "basic" +show_index_summary = false +show_class_hierarchy = false + +[source-location] +# The base URL for the web UI +base_url = "https://gitlab.gnome.org/jbrummer/libproxy/-/blob/main/" +# The format for links, using "filename" and "line" for the format +file_format = "{filename}#L{line}" + +[extra] +content_files = [ + "architecture.md", + "applications.md", + "build-steps.md", + "configuration-logic.md", + "proxy-authentication.md", + "perl.md", + "python.md", + "ruby.md", + "vala.md", +] + +content_images = [ + "libproxy.svg" +] diff --git a/docs/python.md b/docs/python.md new file mode 100644 index 0000000..8094e0b --- /dev/null +++ b/docs/python.md @@ -0,0 +1,30 @@ +Title: How to use libproxy in Python +Slug: snippets + +# How to use libproxy in Python + +``` +import gi +gi.require_version('Libproxy', '1.0') +from gi.repository import Libproxy +import requests + +url = 'https://github.com/libproxy/libproxy' + +pf = Libproxy.ProxyFactory() +proxies = pf.get_proxies(url) + +success = False +for proxy in proxies: + response = requests.get(url) #, proxies=proxies) + + if response.status_code == 200: + success = True + break + +if success: + print(f"The requested URL {url} could be retrieved using the current setup!") +else: + print(f"The requested URL {url} could *NOT* be retrieved using the current setup") +``` + diff --git a/docs/ruby.md b/docs/ruby.md new file mode 100644 index 0000000..ceddbd8 --- /dev/null +++ b/docs/ruby.md @@ -0,0 +1,20 @@ +Title: How to use libproxy in Ruby +Slug: snippets + +# How to use libproxy in Ruby + +``` +#!/usr/bin/ruby + +require 'gir_ffi' +GirFFI.setup :Libproxy + +pf = Libproxy::ProxyFactory.new() + +proxies = pf.get_proxies("https://github.com/libproxy/libproxy") +proxies.each do |proxy| + puts proxy +end + +pf.free() +``` diff --git a/docs/samples.md b/docs/samples.md new file mode 100644 index 0000000..f73aa0f --- /dev/null +++ b/docs/samples.md @@ -0,0 +1,4 @@ +Title: How to use libproxy in language X? +Slug: building + +# Samples - How to use libproxy in language X? diff --git a/docs/samples/dotnet/Makefile b/docs/samples/dotnet/Makefile new file mode 100644 index 0000000..587f83b --- /dev/null +++ b/docs/samples/dotnet/Makefile @@ -0,0 +1,8 @@ + +all: proxy.exe + +proxy.exe: proxy.cs + gmcs -pkg:libproxy-sharp-1.0 proxy.cs + +clean: + rm proxy.exe diff --git a/docs/samples/dotnet/proxy.cs b/docs/samples/dotnet/proxy.cs new file mode 100644 index 0000000..a8ce5e4 --- /dev/null +++ b/docs/samples/dotnet/proxy.cs @@ -0,0 +1,38 @@ +/******************************************************************************* + * libproxy - A library for proxy configuration + * Copyright (C) 2009 Dominique Leuenberger <dominique@leuenberger.net> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ******************************************************************************/ + +using System; +using libproxy; + +public class proxy { + public static int Main (string[] args) + { + if (args.Length > 0) { + ProxyFactory pf = new ProxyFactory(); + string[] Proxies = pf.GetProxies(args[0]); + Console.WriteLine(Proxies[0]); + pf = null; + return 0; + } else { + Console.WriteLine("Please start the program with one parameter"); + Console.WriteLine("Example: proxy.exe http://libproxy.googlecode.com/"); + return 1; + } + } +} diff --git a/docs/samples/libcurl/Makefile b/docs/samples/libcurl/Makefile new file mode 100644 index 0000000..35b4597 --- /dev/null +++ b/docs/samples/libcurl/Makefile @@ -0,0 +1,9 @@ + + +all: curlget + +curlget: curlget.c + gcc curlget.c -o curlget -Wall -lcurl -std=c99 $(shell pkg-config --libs libproxy-1.0) + +clean: + rm curlget diff --git a/docs/samples/libcurl/curlget.c b/docs/samples/libcurl/curlget.c new file mode 100644 index 0000000..00954e9 --- /dev/null +++ b/docs/samples/libcurl/curlget.c @@ -0,0 +1,108 @@ +/******************************************************************************* + * libproxy - A library for proxy configuration + * Copyright (C) 2006 Nathaniel McCallum <nathaniel@natemccallum.com> + * Copyright (C) 2008 Dominique Leuenberger <dominique-libproxy@leuenberger.net> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ******************************************************************************/ + +#include "proxy.h" +#include "curl/curl.h" +#include <string.h> +#include <stdlib.h> + +int main(int argc, char * argv[]) { + pxProxyFactory *pf = NULL; + CURL *curl = NULL; + CURLcode result = 1; + + /* Check if we have a parameter passed, otherwise bail out... I need one */ + if (argc < 2) + { + printf("libcurl / libproxy example implementation\n"); + printf("=========================================\n"); + printf("The program has to be started with one parameter\n"); + printf("Defining the URL that should be downloaded\n\n"); + printf("Example: %s http://code.google.com/p/libproxy/\n", argv[0]); + return -1; + } + + /* Initializing curl... has to happen exactly once in the program */ + if (curl_global_init( CURL_GLOBAL_ALL )) return -4; + + /* Create pxProxyFactory object */ + if (!(pf = px_proxy_factory_new())) + { + printf("Unable to create pxProxyFactory object!\n"); + curl_global_cleanup(); + return -2; + } + + /* Create curl handle */ + if (!(curl = curl_easy_init())) + { + printf("Unable to get libcurl handle!\n"); + px_proxy_factory_free(pf); + curl_global_cleanup(); + return -3; + } + + /* Get the array of proxies to try */ + char **proxies = px_proxy_factory_get_proxies(pf, argv[1]); + + /* Set the URL into the curl handle */ + curl_easy_setopt(curl, CURLOPT_URL, argv[1]); + + /* Try to fetch our url using each proxy */ + for (int i=0 ; proxies[i] ; i++) + { + if (result != 0) + { + /* Setup our proxy's config into curl */ + curl_easy_setopt(curl, CURLOPT_PROXY, proxies[i]); + + /* HTTP Proxy */ + if (!strncmp("http", proxies[i], 4)) + curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); + + /* SOCKS Proxy, is this correct??? */ + /* What about SOCKS 4A, 5 and 5_HOSTNAME??? */ + else if (!strncmp("socks", proxies[i], 4)) + curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); + + /* Attempt to fetch the page */ + result = curl_easy_perform(curl); + } + + /* If we reached the end of the proxies array and still did not + succeed to conntect, let's inform the user that we failed. */ + if (proxies[i+1] == NULL && result != 0) + printf ("The requested URL (%s) could not be retrieved using the current setup\n", argv[1]); + + } + + /* Free the proxy array */ + px_proxy_factory_free_proxies(proxies); + + /* Free the curl and libproxy handles */ + px_proxy_factory_free(pf); + curl_easy_cleanup(curl); + + /* Cleanup the libcurl library */ + curl_global_cleanup(); + return 0; + +} + diff --git a/docs/samples/perl/sample.pl b/docs/samples/perl/sample.pl new file mode 100644 index 0000000..e8850fc --- /dev/null +++ b/docs/samples/perl/sample.pl @@ -0,0 +1,7 @@ +use Net::Libproxy; + +$p = new Net::Libproxy; +$proxies = $p->getProxies('http://www.google.com'); +foreach my $proxy (@$proxies) { + print $proxy."\n"; +} diff --git a/docs/samples/vala/Makefile b/docs/samples/vala/Makefile new file mode 100644 index 0000000..3e42a34 --- /dev/null +++ b/docs/samples/vala/Makefile @@ -0,0 +1,7 @@ +all: sample + +sample: sample.vala + valac --pkg libproxy-1.0 sample.vala + +clean: + rm sample diff --git a/docs/samples/vala/sample.vala b/docs/samples/vala/sample.vala new file mode 100644 index 0000000..1cec8cf --- /dev/null +++ b/docs/samples/vala/sample.vala @@ -0,0 +1,9 @@ +using Libproxy; + +void main () { + var pf = new ProxyFactory (); + string[] proxies = pf.get_proxies ("http://www.google.com"); + foreach (string proxy in proxies) { + stdout.printf ("%s\n", proxy); + } +} diff --git a/docs/vala.md b/docs/vala.md new file mode 100644 index 0000000..b1332ac --- /dev/null +++ b/docs/vala.md @@ -0,0 +1,32 @@ +Title: How to use libproxy in Vala +Slug: snippets + +# How to use libproxy in Vala + + +## Makefile + +``` +all: sample + +sample: sample.vala + valac --pkg libproxy-1.0 sample.vala + +clean: + rm sample +``` + +## Source + +``` +using px; + +void main() { + var pf = new px.ProxyFactory(); + string[] proxies = pf.get_proxies("https://github.com/libproxy/libproxy"); + + foreach (string proxy in proxies) { + stdout.printf ("%s\n", proxy); + } +} +``` diff --git a/docs/version.xml.in b/docs/version.xml.in new file mode 100644 index 0000000..d78bda9 --- /dev/null +++ b/docs/version.xml.in @@ -0,0 +1 @@ +@VERSION@ |