HTTPS/Authenticated: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎{{header|Phix}}: fixed libheader)
(Added Wren)
Line 657: Line 657:
Debug.Print HttpReq.ResponseText
Debug.Print HttpReq.ResponseText
End Sub</lang>
End Sub</lang>

=={{header|Wren}}==
{{trans|C}}
{{libheader|libcurl}}
An embedded program so we can ask the C host to communicate with libcurl for us.
<lang ecmascript>/* https_authenticated.wren */

var CURLOPT_URL = 10002
var CURLOPT_FOLLOWLOCATION = 52
var CURLOPT_ERRORBUFFER = 10010

foreign class Curl {
construct easyInit() {}

foreign easySetOpt(opt, param)

foreign easyPerform()

foreign easyCleanup()
}

var curl = Curl.easyInit()
if (curl == 0) {
System.print("Error initializing cURL.")
return
}
curl.easySetOpt(CURLOPT_URL, "https://user:password@secure.example.com/")
curl.easySetOpt(CURLOPT_FOLLOWLOCATION, 1)
curl.easySetOpt(CURLOPT_ERRORBUFFER, 0) // buffer to be supplied by C

var status = curl.easyPerform()
if (status != 0) {
System.print("Failed to perform task.")
return
}
curl.easyCleanup()</lang>
<br>
We now embed this in the following C program, compile and run it.
<lang c>/* gcc https_authenticated.c -o https_authenticated -lcurl -lwren -lm */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include "wren.h"

/* C <=> Wren interface functions */

void C_curlAllocate(WrenVM* vm) {
CURL** pcurl = (CURL**)wrenSetSlotNewForeign(vm, 0, 0, sizeof(CURL*));
*pcurl = curl_easy_init();
}

void C_easyPerform(WrenVM* vm) {
CURL* curl = *(CURL**)wrenGetSlotForeign(vm, 0);
CURLcode cc = curl_easy_perform(curl);
wrenSetSlotDouble(vm, 0, (double)cc);
}

void C_easyCleanup(WrenVM* vm) {
CURL* curl = *(CURL**)wrenGetSlotForeign(vm, 0);
curl_easy_cleanup(curl);
}

void C_easySetOpt(WrenVM* vm) {
CURL* curl = *(CURL**)wrenGetSlotForeign(vm, 0);
CURLoption opt = (CURLoption)wrenGetSlotDouble(vm, 1);
if (opt < 10000) {
long lparam = (long)wrenGetSlotDouble(vm, 2);
curl_easy_setopt(curl, opt, lparam);
} else {
if (opt == CURLOPT_URL) {
const char *url = wrenGetSlotString(vm, 2);
curl_easy_setopt(curl, opt, url);
} else if (opt == CURLOPT_ERRORBUFFER) {
char buffer[CURL_ERROR_SIZE];
curl_easy_setopt(curl, opt, buffer);
}
}
}

WrenForeignClassMethods bindForeignClass(WrenVM* vm, const char* module, const char* className) {
WrenForeignClassMethods methods;
methods.allocate = NULL;
methods.finalize = NULL;
if (strcmp(module, "main") == 0) {
if (strcmp(className, "Curl") == 0) {
methods.allocate = C_curlAllocate;
}
}
return methods;
}

WrenForeignMethodFn bindForeignMethod(
WrenVM* vm,
const char* module,
const char* className,
bool isStatic,
const char* signature) {
if (strcmp(module, "main") == 0) {
if (strcmp(className, "Curl") == 0) {
if (!isStatic && strcmp(signature, "easySetOpt(_,_)") == 0) return C_easySetOpt;
if (!isStatic && strcmp(signature, "easyPerform()") == 0) return C_easyPerform;
if (!isStatic && strcmp(signature, "easyCleanup()") == 0) return C_easyCleanup;
}
}
return NULL;
}

static void writeFn(WrenVM* vm, const char* text) {
printf("%s", text);
}

void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) {
switch (errorType) {
case WREN_ERROR_COMPILE:
printf("[%s line %d] [Error] %s\n", module, line, msg);
break;
case WREN_ERROR_STACK_TRACE:
printf("[%s line %d] in %s\n", module, line, msg);
break;
case WREN_ERROR_RUNTIME:
printf("[Runtime Error] %s\n", msg);
break;
}
}

char *readFile(const char *fileName) {
FILE *f = fopen(fileName, "r");
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
rewind(f);
char *script = malloc(fsize + 1);
fread(script, 1, fsize, f);
fclose(f);
script[fsize] = 0;
return script;
}

int main(int argc, char **argv) {
WrenConfiguration config;
wrenInitConfiguration(&config);
config.writeFn = &writeFn;
config.errorFn = &errorFn;
config.bindForeignClassFn = &bindForeignClass;
config.bindForeignMethodFn = &bindForeignMethod;
WrenVM* vm = wrenNewVM(&config);
const char* module = "main";
const char* fileName = "https_authenticated.wren";
char *script = readFile(fileName);
WrenInterpretResult result = wrenInterpret(vm, module, script);
switch (result) {
case WREN_RESULT_COMPILE_ERROR:
printf("Compile Error!\n");
break;
case WREN_RESULT_RUNTIME_ERROR:
printf("Runtime Error!\n");
break;
case WREN_RESULT_SUCCESS:
break;
}
wrenFreeVM(vm);
free(script);
return 0;
}</lang>


=={{header|zkl}}==
=={{header|zkl}}==

Revision as of 15:02, 5 October 2021

Task
HTTPS/Authenticated
You are encouraged to solve this task according to the task description, using any language you may know.

The goal of this task is to demonstrate HTTPS requests with authentication. Implementations of this task should not use client certificates for this: that is the subject of another task.

AutoHotkey

Library: iweb
Library: COM

<lang AutoHotkey>iWeb_Init() pwb := iWeb_newGui(0, 0, 1000, 800) iWeb_nav(pwb, "http://www.facebook.com/login.php?ref=pf") iWeb_Term() iWeb_complete(pwb) inputbox, email, email inputbox, pass, password iWeb_setDomObj(pwb,"Email",email) iWeb_setDomObj(pwb,"pass",pass) iWeb_clickDomObj(pwb, "login") return

  1. Include iweb.ahk
  2. Include COM.ahk
  3. Include COMinvokeDeep.ahk</lang>

BaCon

<lang bacon>OPTION TLS TRUE

website$ = "website.com" username$ = "nobody" password$ = "ignore"

OPEN website$ & ":443" FOR NETWORK AS conn SEND "GET / HTTP/1.1\r\nHost: " & website$ & "\r\nAuthorization: Basic " & B64ENC$(username$ & ":" & password$) & "\r\n\r\n" TO conn

WHILE WAIT(conn, 2000)

   RECEIVE data$ FROM conn
   total$ = total$ & data$
   IF INSTR(data$, "</html>") THEN BREAK

WEND CLOSE NETWORK conn

PRINT total$</lang>

C

Library: libcurl

<lang c>#include <stdio.h>

  1. include <stdlib.h>
  2. include "curl/curl.h"

int main(void) {

       CURL *curl;
       char buffer[CURL_ERROR_SIZE];
       if ((curl = curl_easy_init()) != NULL) {
               curl_easy_setopt(curl, CURLOPT_URL, "https://user:password@secure.example.com/");
               curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
               curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, buffer);
               if (curl_easy_perform(curl) != CURLE_OK) {
                       fprintf(stderr, "%s\n", buffer);
                       return EXIT_FAILURE;
               }
               curl_easy_cleanup(curl);
       }
       return EXIT_SUCCESS;

}</lang>

C#

Works with: C sharp version 3.0

<lang csharp> using System; using System.Net;

class Program {

   static void Main(string[] args)
   {
       var client = new WebClient();
       // credentials of current user:
       client.Credentials = CredentialCache.DefaultCredentials;
       // or specify credentials manually:
       client.Credentials = new NetworkCredential("User", "Password");
       var data = client.DownloadString("https://example.com");
       Console.WriteLine(data);
   }

} </lang>

Clojure

Library: clj-http

<lang clojure>(clj-http.client/get "https://somedomain.com"

                    {:basic-auth ["user" "pass"]})</lang>

Delphi

<lang Delphi>program ShowHTTPSAuthenticated;

{$APPTYPE CONSOLE}

uses IdHttp, IdSSLOpenSSL;

var

 s: string;
 lHTTP: TIdHTTP;
 lIOHandler: TIdSSLIOHandlerSocketOpenSSL;

begin

 ReportMemoryLeaksOnShutdown := True;
 lHTTP := TIdHTTP.Create(nil);
 lIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
 try
   lHTTP.Request.Username := 'USERNAME';
   lHTTP.Request.Password := 'PASSWD';
   lHTTP.IOHandler := lIOHandler;
   lHTTP.HandleRedirects := True;
   s := lHTTP.Get('https://SomeSecureSite.net/');
   Writeln(s);
 finally
   lHTTP.Free;
   lIOHandler.Free;
 end;

end.</lang>

Go

The task solution is really the client program, but to test it I wrote a server and created a custom certificate. I won't describe the certificate, but this is the server: <lang go>package main

import (

   "encoding/base64"
   "io"
   "log"
   "net/http"
   "strings"

)

const userPass = "rosetta:code" const unauth = http.StatusUnauthorized

func hw(w http.ResponseWriter, req *http.Request) {

   auth := req.Header.Get("Authorization")
   if !strings.HasPrefix(auth, "Basic ") {
       log.Print("Invalid authorization:", auth)
       http.Error(w, http.StatusText(unauth), unauth)
       return
   }
   up, err := base64.StdEncoding.DecodeString(auth[6:])
   if err != nil {
       log.Print("authorization decode error:", err)
       http.Error(w, http.StatusText(unauth), unauth)
       return
   }
   if string(up) != userPass {
       log.Print("invalid username:password:", string(up))
       http.Error(w, http.StatusText(unauth), unauth)
       return
   }
   io.WriteString(w, "Goodbye, World!")

}

func main() {

   http.HandleFunc("/", hw)
   log.Fatal(http.ListenAndServeTLS(":8080", "cert.pem", "key.pem", nil))

}</lang> It is a "Hello world" server, but over TLS and with basic authentication required on the Get. Errors are logged to aid client debugging.

The client: <lang go>package main

import (

   "crypto/tls"
   "crypto/x509"
   "fmt"
   "io/ioutil"
   "log"
   "net/http"

)

const (

   userid   = "rosetta"
   password = "code"

)

func main() {

   // Use custom certificate for testing.  Not exactly required by task.
   b, err := ioutil.ReadFile("cert.pem")
   if err != nil {
       log.Fatal(err)
   }
   pool := x509.NewCertPool()
   if ok := pool.AppendCertsFromPEM(b); !ok {
       log.Fatal("Failed to append cert")
   }
   tc := &tls.Config{RootCAs: pool}
   tr := &http.Transport{TLSClientConfig: tc}
   client := &http.Client{Transport: tr}
   req, err := http.NewRequest("GET", "https://127.0.0.1:8080", nil)
   if err != nil {
       log.Fatal(err)
   }
   // This one line implements the authentication required for the task.
   req.SetBasicAuth(userid, password)
   // Make request and show output.
   resp, err := client.Do(req)
   if err != nil {
       log.Fatal(err)
   }
   b, err = ioutil.ReadAll(resp.Body)
   resp.Body.Close()
   if err != nil {
       log.Fatal(err)
   }
   fmt.Println(string(b))

}</lang>

Haskell

Example uses the req and aeson packages:

<lang haskell>{-# LANGUAGE OverloadedStrings #-}

module Main (main) where

import Data.Aeson (Value) import Data.Default.Class (def) import Network.HTTP.Req

                   ( (/:)
                   , GET(..)
                   , NoReqBody(..)
                   , basicAuth
                   , https
                   , jsonResponse
                   , req
                   , responseBody
                   , runReq
                   )

main :: IO () main = do

   response <- runReq def $ req
           GET
           (https "httpbin.org" /: "basic-auth" /: "someuser" /: "somepassword")
           NoReqBody
           jsonResponse
           (basicAuth "someuser" "somepassword")
   print (responseBody response :: Value)</lang>

Julia

An example using HTTP (see the source for HTTP.jl for the code below ) to access and play a song: <lang Julia> using HTTP, HTTP.IOExtras, JSON, MusicProcessing HTTP.open("POST", "http://music.com/play") do io

   write(io, JSON.json([
       "auth" => "12345XXXX",
       "song_id" => 7,
   ]))
   r = startread(io)
   @show r.status
   while !eof(io)
       bytes = readavailable(io)
       play(bytes)
   end

end </lang>

Kotlin

<lang scala>// version 1.2.0

import java.net.Authenticator import java.net.PasswordAuthentication import javax.net.ssl.HttpsURLConnection import java.net.URL import java.io.InputStreamReader import java.io.BufferedReader

object PasswordAuthenticator : Authenticator() {

   override fun getPasswordAuthentication() =
       PasswordAuthentication ("username", "password".toCharArray())

}

fun main(args: Array<String>) {

   val url = URL("https://somehost.com")
   val con = url.openConnection() as HttpsURLConnection
   Authenticator.setDefault(PasswordAuthenticator)
   con.allowUserInteraction = true
   con.connect()
   val isr = InputStreamReader(con.inputStream)
   val br = BufferedReader(isr)
   while (true) {
       val line = br.readLine()
       if (line == null) break
       println(line)
   }

}</lang>

Lasso

<lang Lasso>local(username = 'hello',password = 'world') local(x = curl('https://sourceforge.net'))

  1. x->set(CURLOPT_USERPWD, #username + ':' + #password)

local(y = #x->result)

  1. y->asString</lang>

LiveCode

HTTP Basic Auth as part of url <lang LiveCode>command getAuthWebResource

   libURLFollowHttpRedirects true
   libURLSetSSLVerification true
   put URL "https://user:passwd@example.basicauth.com/" into response
   put response

end getAuthWebResource</lang>

You can also set the headers for the basic auth requests <lang LiveCode>command getAuthWebResource

   libURLFollowHttpRedirects true
   libURLSetSSLVerification true
   set the httpHeaders to "Authorization: Basic " && base64Encode("user:passwd")
   put URL "https://example.basicauth.com" into response
   put response

end getAuthWebResource</lang>

Lua

Works with: Lua version 5.1 - 5.3
Library: lua-requests

<lang lua> local requests = require('requests') local auth = requests.HTTPBasicAuth('admin', 'admin') local resp, e = requests.get({

 url = 'https://httpbin.org/basic-auth/admin/admin',
 auth = auth

}) io.write(string.format('Status: %d', resp.status_code)) </lang>

Output:
Status: 200

Nim

Library: OpenSSL

<lang Nim>import httpclient, base64

const

 User = "admin"
 Password = "admin"

let headers = newHttpHeaders({"Authorization": "Basic " & base64.encode(User & ":" & Password)}) let client = newHttpClient(headers = headers) echo client.getContent("https://httpbin.org/basic-auth/admin/admin")</lang>

Mathematica / Wolfram Language

<lang Mathematica>a = RunThrough["curl -u JohnDoe:Password https://www.example.com", 1] For[ i=0, i < Length[a] , i++, SomeFunction[a]]</lang>

Perl

Library: LWP

<lang perl>use LWP::UserAgent qw(); my $ua = LWP::UserAgent->new; my $netloc = 'http://www.buddhism-dict.net/cgi-bin/xpr-dealt.pl:80'; $ua->credentials(

  $netloc,
  'CJK-E and Buddhist Dictionaries', # basic realm
  'guest',  # user
  ,       # empty pw

); my $response = $ua->get($netloc);

use WWW::Mechanize qw(); my $mech = WWW::Mechanize->new; $mech->get('https://login.yahoo.com/'); $mech->submit_form(with_fields => {

   login         => 'XXXXXX',
   passwd        => 'YYYYYY',
   '.persistent' => 'y',  # tick checkbox

});</lang>

Phix

Library: Phix/libcurl

Exactly the same as the HTTP#Phix task. You can of course use curl_easy_setopt(curl,CURLOPT_USERPWD,"user:password") rather than embed that in the url. <lang Phix>include builtins\libcurl.e curl_global_init() atom curl = curl_easy_init() curl_easy_setopt(curl, CURLOPT_URL, "https://user:password@example.com/") object res = curl_easy_perform_ex(curl) curl_easy_cleanup(curl) curl_global_cleanup()

puts(1,res)</lang>

PicoLisp

<lang PicoLisp>(let (User "Bill" Pass "T0p5ecRet" Url "https://www.example.com")

  (in (list 'curl "-u" (pack User ': Pass) Url)
     (while (line)
        (doSomeProcessingWithLine @) ) ) )</lang>

PowerShell

Translation of: C#

<lang PowerShell>$client = [Net.WebClient]::new()

  1. credentials of current user:

$client.Credentials = [Net.CredentialCache]::DefaultCredentials

  1. or specify credentials manually:
  2. $client.Credentials = [System.Net.NetworkCredential]::new("User", "Password")

$data = $client.DownloadString("https://example.com") Write-Host $data</lang>

Python

Works with: Python version 2.4 and 2.6

Note: You should install mechanize to run code below. Visit: http://wwwsearch.sourceforge.net/mechanize/

<lang python>#!/usr/bin/python

  1. -*- coding: utf-8 -*-

from mechanize import Browser

USER_AGENT = "Mozilla/5.0 (X11; U; Linux i686; tr-TR; rv:1.8.1.9) Gecko/20071102 Pardus/2007 Firefox/2.0.0.9"

br = Browser() br.addheaders = [("User-agent", USER_AGENT)]

  1. remove comment if you get debug output
  2. br.set_debug_redirects(True)
  3. br.set_debug_responses(True)
  4. br.set_debug_http(True)

br.open("https://www.facebook.com")

br.select_form("loginform") br['email'] = "xxxxxxx@xxxxx.com" br['pass'] = "xxxxxxxxx" br['persistent'] = ["1"]

response = br.submit() print response.read()</lang>

Library: Requests
Works with: Python version 2.7, 3.4–3.7

<lang python>import requests

username = "user" password = "pass" url = "https://www.example.com"

response = requests.get(url, auth=(username, password)

print(response.text)</lang>

Racket

<lang racket>

  1. lang racket

(require net/url net/url-connect openssl)

(module+ main

 (parameterize ([current-https-protocol (ssl-make-client-context)])
   (ssl-set-verify! (current-https-protocol) #t)
   ;; When this is #f, we correctly get an exception:
   ;; error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
   (when #t
     (ssl-load-verify-source! (current-https-protocol)
                              '(directory
                                ;; This location works on Debian 6;
                                ;; adjust as needed for your platform.
                                "/etc/ssl/certs"
                                )))
   (for ([l (in-port read-line (get-pure-port (string->url "https://www.google.com/")))])
     (displayln  l))))

</lang>

Raku

(formerly Perl 6)

Works with: Rakudo version 2017.09

Used here to connect to my local wireless router to a page that is password protected. Obviously not going to be generally publicly accessible but should be easily adaptable to other sites / devices.

<lang perl6>use HTTP::UserAgent;

my $username = 'username'; # my username my $password = 'password'; # my password my $address = 'http://192.168.1.1/Status_Router.asp'; # my local wireless router

my $ua = HTTP::UserAgent.new; $ua.auth( $username, $password ); my $response = $ua.get: $address; say $response.is-success ?? $response.content !! $response.status-line;</lang>

Ruby

<lang ruby>require 'uri' require 'net/http'

uri = URI.parse('https://www.example.com') response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|

 request = Net::HTTP::Get.new uri
 request.basic_auth('username', 'password')
 http.request request

end</lang>

Run BASIC

<lang runbasic>html "

LOGIN
UserName"
TEXTBOX #userName, "" 
html "
Password:"

PasswordBox #passWord, ""

html "
"

button #si, "Signin", [doSignin] html " " button #ex, "Exit", [exit]

html "
"

WAIT

[doSignin] loginUserName$ = trim$(#userName contents$()) loginPassWord$ = trim$(#passWord contents$()) if (loginUserName$ = "admin" and loginPassWord$ = "admin" then

  print "Login ok"
 else
  print "invalid User or Pass"
  cls
  goto [loop]

end if

print Platform$ ' OS where Run BASIC is being hosted print UserInfo$ ' Information about the user's web browser print UserAddress$ ' IP address of the user

[exit] end</lang>

Rust

<lang rust> extern crate reqwest;

use reqwest::blocking::Client; use reqwest::header::CONNECTION;

fn main() {

   let client = Client::new();
   // reqwest uses strongly-typed structs for creating headers
   let res = client
       .get("https://www.example.com")
       .basic_auth("user", Some("password"))
       .header(CONNECTION, "close")
       .send()
       .unwrap();
   let body = res.text().unwrap();
   println!("{}", body);

} </lang>

Output:


Scala

<lang Scala>import java.net.{Authenticator, PasswordAuthentication, URL}

import javax.net.ssl.HttpsURLConnection

import scala.io.BufferedSource


object Authenticated extends App {

 val con: HttpsURLConnection =
   new URL("https://somehost.com").openConnection().asInstanceOf[HttpsURLConnection]
 object PasswordAuthenticator extends Authenticator {
   override def getPasswordAuthentication = 
     new PasswordAuthentication("username", "password".toCharArray)
 }
 Authenticator.setDefault(PasswordAuthenticator)
 con.setAllowUserInteraction(true)
 con.connect()
 new BufferedSource(con.getInputStream).getLines.foreach(println(_))

}</lang>

Sidef

<lang ruby>require('WWW::Mechanize')

var mech = %s'WWW::Mechanize'.new(

   cookie_jar => Hash.new,
   agent => 'Mozilla/5.0',

)

mech.get('https://login.yahoo.com/') mech.submit_form(

   form_id => 'mbr-login-form',   # form id
   fields => Hash.new(
       'login'  => 'XXXXXX',
       'passwd' => 'YYYYYY',

))</lang>

Tcl

Works with: Tcl version 8.6
for the binary encode subcommand, otherwise uses
Library: Tcllib (Package: base64)

Uses the Tls package. <lang Tcl>package require http package require tls http::register https 443 ::tls::socket

  1. Generate the authentication

set user theUser set pass thePassword dict set auth Authenticate "Basic [binary encode base64 ${user}:${pass}]"

  1. Make a secure authenticated connection

set token [http::geturl https://secure.example.com/ -headers $auth]

  1. Now as for conventional use of the “http” package

set data [http::data $token] http::cleanup $token</lang>

Visual Basic

Works with: Visual Basic version 5
Works with: Visual Basic version 6
Works with: VBA version Access 97
Works with: VBA version 6.5
Works with: VBA version 7.1

<lang vb>Sub Main() ' in the "references" dialog of the IDE, check ' "Microsoft WinHTTP Services, version 5.1" (winhttp.dll) Dim HttpReq As WinHttp.WinHttpRequest Const WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 As Long = &H80& Const WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 As Long = &H200& Const WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 As Long = &H800& Const HTTPREQUEST_PROXYSETTING_PROXY As Long = 2

  1. Const USE_PROXY = 1
 Set HttpReq = New WinHttp.WinHttpRequest
 HttpReq.Open "GET", "https://www.abc.com/xyz/index.html"
 HttpReq.Option(WinHttpRequestOption_SecureProtocols) = WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 Or _
                                                        WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 Or _
                                                        WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2
 HttpReq.SetCredentials "<username>", "<password>", 0&
  1. If USE_PROXY Then
 HttpReq.SetProxy HTTPREQUEST_PROXYSETTING_PROXY, "10.167.1.1:80"
  1. End If
 HttpReq.SetTimeouts 1000, 1000, 1000, 1000
 HttpReq.Send
 Debug.Print HttpReq.ResponseText

End Sub</lang>

Wren

Translation of: C
Library: libcurl

An embedded program so we can ask the C host to communicate with libcurl for us. <lang ecmascript>/* https_authenticated.wren */

var CURLOPT_URL = 10002 var CURLOPT_FOLLOWLOCATION = 52 var CURLOPT_ERRORBUFFER = 10010

foreign class Curl {

   construct easyInit() {}
   foreign easySetOpt(opt, param)
   foreign easyPerform()
   foreign easyCleanup()

}

var curl = Curl.easyInit() if (curl == 0) {

   System.print("Error initializing cURL.")
   return

} curl.easySetOpt(CURLOPT_URL, "https://user:password@secure.example.com/") curl.easySetOpt(CURLOPT_FOLLOWLOCATION, 1) curl.easySetOpt(CURLOPT_ERRORBUFFER, 0) // buffer to be supplied by C

var status = curl.easyPerform() if (status != 0) {

   System.print("Failed to perform task.")
   return

} curl.easyCleanup()</lang>
We now embed this in the following C program, compile and run it. <lang c>/* gcc https_authenticated.c -o https_authenticated -lcurl -lwren -lm */

  1. include <stdio.h>
  2. include <stdlib.h>
  3. include <string.h>
  4. include <curl/curl.h>
  5. include "wren.h"

/* C <=> Wren interface functions */

void C_curlAllocate(WrenVM* vm) {

   CURL** pcurl = (CURL**)wrenSetSlotNewForeign(vm, 0, 0, sizeof(CURL*));
   *pcurl = curl_easy_init();

}

void C_easyPerform(WrenVM* vm) {

   CURL* curl = *(CURL**)wrenGetSlotForeign(vm, 0);
   CURLcode cc = curl_easy_perform(curl);
   wrenSetSlotDouble(vm, 0, (double)cc);

}

void C_easyCleanup(WrenVM* vm) {

   CURL* curl = *(CURL**)wrenGetSlotForeign(vm, 0);
   curl_easy_cleanup(curl);

}

void C_easySetOpt(WrenVM* vm) {

   CURL* curl = *(CURL**)wrenGetSlotForeign(vm, 0);
   CURLoption opt = (CURLoption)wrenGetSlotDouble(vm, 1);
   if (opt < 10000) {
       long lparam = (long)wrenGetSlotDouble(vm, 2);
       curl_easy_setopt(curl, opt, lparam);
   } else {
       if (opt == CURLOPT_URL) {
           const char *url = wrenGetSlotString(vm, 2);
           curl_easy_setopt(curl, opt, url);
       } else if (opt == CURLOPT_ERRORBUFFER) {
           char buffer[CURL_ERROR_SIZE];
           curl_easy_setopt(curl, opt, buffer);
       }
   }

}

WrenForeignClassMethods bindForeignClass(WrenVM* vm, const char* module, const char* className) {

   WrenForeignClassMethods methods;
   methods.allocate = NULL;
   methods.finalize = NULL;
   if (strcmp(module, "main") == 0) {
       if (strcmp(className, "Curl") == 0) {
           methods.allocate = C_curlAllocate;
       }
   }
   return methods;

}

WrenForeignMethodFn bindForeignMethod(

   WrenVM* vm,
   const char* module,
   const char* className,
   bool isStatic,
   const char* signature) {
   if (strcmp(module, "main") == 0) {
       if (strcmp(className, "Curl") == 0) {
           if (!isStatic && strcmp(signature, "easySetOpt(_,_)") == 0) return C_easySetOpt;
           if (!isStatic && strcmp(signature, "easyPerform()") == 0)   return C_easyPerform;
           if (!isStatic && strcmp(signature, "easyCleanup()") == 0)   return C_easyCleanup;
       }
   }
   return NULL;

}

static void writeFn(WrenVM* vm, const char* text) {

   printf("%s", text);

}

void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) {

   switch (errorType) {
       case WREN_ERROR_COMPILE:
           printf("[%s line %d] [Error] %s\n", module, line, msg);
           break;
       case WREN_ERROR_STACK_TRACE:
           printf("[%s line %d] in %s\n", module, line, msg);
           break;
       case WREN_ERROR_RUNTIME:
           printf("[Runtime Error] %s\n", msg);
           break;
   }

}

char *readFile(const char *fileName) {

   FILE *f = fopen(fileName, "r");
   fseek(f, 0, SEEK_END);
   long fsize = ftell(f);
   rewind(f);
   char *script = malloc(fsize + 1);
   fread(script, 1, fsize, f);
   fclose(f);
   script[fsize] = 0;
   return script;

}

int main(int argc, char **argv) {

   WrenConfiguration config;
   wrenInitConfiguration(&config);
   config.writeFn = &writeFn;
   config.errorFn = &errorFn;
   config.bindForeignClassFn = &bindForeignClass;
   config.bindForeignMethodFn = &bindForeignMethod;
   WrenVM* vm = wrenNewVM(&config);
   const char* module = "main";
   const char* fileName = "https_authenticated.wren";
   char *script = readFile(fileName);
   WrenInterpretResult result = wrenInterpret(vm, module, script);
   switch (result) {
       case WREN_RESULT_COMPILE_ERROR:
           printf("Compile Error!\n");
           break;
       case WREN_RESULT_RUNTIME_ERROR:
           printf("Runtime Error!\n");
           break;
       case WREN_RESULT_SUCCESS:
           break;
   }
   wrenFreeVM(vm);
   free(script);
   return 0;

}</lang>

zkl

Using cURL to do the heavy lifting, get a XML list of computers connected to my router. <lang zkl>zkl: var ZC=Import("zklCurl") zkl: var data=ZC().get("http://usr:pw@192.168.1.1/computer_list.xml") L(Data(1,049),121,0) zkl: data[0][121,*].text</lang>

Output:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<computers>
<ip_address0>192.168.1.100</ip_address0><host_name0>core-shot
...