Active Directory/Connect: Difference between revisions
Thundergnat (talk | contribs) (Rename Perl 6 -> Raku, alphabetize, minor clean-up) |
(Added FreeBASIC) |
||
(13 intermediate revisions by 4 users not shown) | |||
Line 1: | Line 1: | ||
[[Category:Active Directory]] |
|||
{{task|Programming environment operations}} |
{{task|Programming environment operations}} |
||
The task is to establish a connection to an Active Directory or Lightweight Directory Access Protocol server. |
The task is to establish a connection to an Active Directory or Lightweight Directory Access Protocol server. |
||
Line 6: | Line 8: | ||
{{works with|AutoHotkey_L}} |
{{works with|AutoHotkey_L}} |
||
{{trans|VBScript}} |
{{trans|VBScript}} |
||
< |
<syntaxhighlight lang="autohotkey">objConn := CreateObject("ADODB.Connection") |
||
objCmd := CreateObject("ADODB.Command") |
objCmd := CreateObject("ADODB.Command") |
||
objConn.Provider := "ADsDSOObject" |
objConn.Provider := "ADsDSOObject" |
||
objConn.Open()</ |
objConn.Open()</syntaxhighlight> |
||
=={{header|AutoIt}}== |
=={{header|AutoIt}}== |
||
{{works with|AutoIt}} |
{{works with|AutoIt}} |
||
< |
<syntaxhighlight lang="autoit"> #include <AD.au3> |
||
_AD_Open()</ |
_AD_Open()</syntaxhighlight> |
||
=={{header|C}}== |
=={{header|C}}== |
||
With OpenLDAP: |
With OpenLDAP: |
||
< |
<syntaxhighlight lang="c">#include <ldap.h> |
||
... |
... |
||
char *name, *password; |
char *name, *password; |
||
Line 25: | Line 27: | ||
ldap_simple_bind_s(ld, name, password); |
ldap_simple_bind_s(ld, name, password); |
||
... after done with it... |
... after done with it... |
||
ldap_unbind(ld);</ |
ldap_unbind(ld);</syntaxhighlight> |
||
=={{header|C sharp|C#}}== |
=={{header|C sharp|C#}}== |
||
< |
<syntaxhighlight lang="csharp"> |
||
// Requires adding a reference to System.DirectoryServices |
// Requires adding a reference to System.DirectoryServices |
||
var objDE = new System.DirectoryServices.DirectoryEntry("LDAP://DC=onecity,DC=corp,DC=fabrikam,DC=com"); |
var objDE = new System.DirectoryServices.DirectoryEntry("LDAP://DC=onecity,DC=corp,DC=fabrikam,DC=com"); |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|ColdFusion}}== |
=={{header|ColdFusion}}== |
||
< |
<syntaxhighlight lang="cfm"> |
||
<cfldap |
<cfldap |
||
server = "#someip#" |
server = "#someip#" |
||
Line 45: | Line 47: | ||
attributes = "#attributeslist#" |
attributes = "#attributeslist#" |
||
> |
> |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|D}}== |
=={{header|D}}== |
||
Based on dopenldap. |
Based on dopenldap. |
||
<syntaxhighlight lang="d"> |
|||
<lang d> |
|||
import openldap; |
import openldap; |
||
import std.stdio; |
import std.stdio; |
||
Line 68: | Line 70: | ||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Erlang}}== |
=={{header|Erlang}}== |
||
This needs a test case. Is there a LDAP server available? |
This needs a test case. Is there a LDAP server available? |
||
<syntaxhighlight lang="erlang"> |
|||
<lang Erlang> |
|||
-module(ldap_example). |
-module(ldap_example). |
||
-export( [main/1] ). |
-export( [main/1] ). |
||
Line 80: | Line 82: | ||
ok = eldap:simple_bind( Handle, DN, Password ), |
ok = eldap:simple_bind( Handle, DN, Password ), |
||
eldap:close( Handle ). |
eldap:close( Handle ). |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|F_Sharp|F#}}== |
=={{header|F_Sharp|F#}}== |
||
{{trans|C_sharp}} |
{{trans|C_sharp}} |
||
<p>For Active Directory we use the library System.DirectoryServices</p> |
<p>For Active Directory we use the library System.DirectoryServices</p> |
||
< |
<syntaxhighlight lang="fsharp">let adObject = new System.DirectoryServices.DirectoryEntry("LDAP://DC=onecity,DC=corp,DC=fabrikam,DC=com")</syntaxhighlight> |
||
<p>For your average LDAP server we use System.DirectoryServices.Protocol</p> |
<p>For your average LDAP server we use System.DirectoryServices.Protocol</p> |
||
<p>For a minimal example we make an anonymous connect to the local machine on the well-known LDAP port 389 |
<p>For a minimal example we make an anonymous connect to the local machine on the well-known LDAP port 389 |
||
< |
<syntaxhighlight lang="fsharp">let ldapServer = new System.DirectoryServices.Protocols.LdapDirectoryIdentifier("127.0.0.1") |
||
let connect = new System.DirectoryServices.Protocols.LdapConnection(ldapServer) |
let connect = new System.DirectoryServices.Protocols.LdapConnection(ldapServer) |
||
connect.Bind()</ |
connect.Bind()</syntaxhighlight> |
||
=={{header|FreeBASIC}}== |
|||
{{libheader|winldap}} |
|||
<syntaxhighlight lang="vbnet">#Include "win\winldap.bi" |
|||
Dim ldap As LDAP Ptr |
|||
Dim hostname As String |
|||
Dim port As Integer |
|||
Dim username As String |
|||
Dim password As String |
|||
Dim result As Integer |
|||
hostname = "ldap.example.com" |
|||
port = 389 ' Standard port for LDAP. Use 636 for LDAPS. |
|||
username = "cn=username,dc=example,dc=com" |
|||
password = "password" |
|||
' Initialize the LDAP connection |
|||
ldap = ldap_init(hostname, port) |
|||
If ldap = NULL Then |
|||
Print "Error initializing LDAP connection" |
|||
Sleep |
|||
End 1 |
|||
End If |
|||
' Authenticate with the LDAP server |
|||
result = ldap_simple_bind_s(ldap, username, password) |
|||
If result <> LDAP_SUCCESS Then |
|||
Print "Error authenticating with LDAP server: "; ldap_err2string(result) |
|||
Sleep |
|||
End 1 |
|||
End If |
|||
' Here you can perform LDAP operations |
|||
'... |
|||
' We close the connection when finished |
|||
ldap_unbind(ldap)</syntaxhighlight> |
|||
=={{header|Go}}== |
=={{header|Go}}== |
||
Line 96: | Line 136: | ||
<br> |
<br> |
||
There are a large number of third-party LDAP libraries for Go. This uses one of the simpler ones and the code below is largely taken from the example on its main page. |
There are a large number of third-party LDAP libraries for Go. This uses one of the simpler ones and the code below is largely taken from the example on its main page. |
||
< |
<syntaxhighlight lang="go">package main |
||
import ( |
import ( |
||
Line 121: | Line 161: | ||
} |
} |
||
// Do something |
// Do something |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
||
Line 127: | Line 167: | ||
Example uses the [https://hackage.haskell.org/package/ldap-client <tt>ldap-client</tt>] package: |
Example uses the [https://hackage.haskell.org/package/ldap-client <tt>ldap-client</tt>] package: |
||
< |
<syntaxhighlight lang="haskell">{-# LANGUAGE OverloadedStrings #-} |
||
module Main (main) where |
module Main (main) where |
||
Line 141: | Line 181: | ||
Ldap.search ldap (Ldap.Dn "o=example.com") (Ldap.typesOnly True) (Attr "uid" := Text.encodeUtf8 "user") [] |
Ldap.search ldap (Ldap.Dn "o=example.com") (Ldap.typesOnly True) (Attr "uid" := Text.encodeUtf8 "user") [] |
||
for_ entries $ \entry -> |
for_ entries $ \entry -> |
||
print entry</ |
print entry</syntaxhighlight> |
||
=={{header|Java}}== |
=={{header|Java}}== |
||
Line 147: | Line 187: | ||
This code uses the Apache Directory third-party library. |
This code uses the Apache Directory third-party library. |
||
< |
<syntaxhighlight lang="java">import java.io.IOException; |
||
import org.apache.directory.api.ldap.model.exception.LdapException; |
import org.apache.directory.api.ldap.model.exception.LdapException; |
||
import org.apache.directory.ldap.client.api.LdapConnection; |
import org.apache.directory.ldap.client.api.LdapConnection; |
||
Line 160: | Line 200: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Julia}}== |
|||
<syntaxhighlight lang="julia">using LDAPClient |
|||
conn = LDAPClient.LDAPConnection("ldap://localhost:10389") |
|||
LDAPClient.simple_bind(conn, "user", "password") |
|||
LDAPClient.unbind(conn) |
|||
</syntaxhighlight> |
|||
=={{header|Kotlin}}== |
=={{header|Kotlin}}== |
||
< |
<syntaxhighlight lang="scala"> |
||
import org.apache.directory.api.ldap.model.exception.LdapException |
import org.apache.directory.api.ldap.model.exception.LdapException |
||
import org.apache.directory.ldap.client.api.LdapNetworkConnection |
import org.apache.directory.ldap.client.api.LdapNetworkConnection |
||
Line 207: | Line 256: | ||
fun main(args: Array<String>) = LDAP(mapOf("hostname" to "localhost", "port" to "10389")).run() |
fun main(args: Array<String>) = LDAP(mapOf("hostname" to "localhost", "port" to "10389")).run() |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|NetRexx}}== |
=={{header|NetRexx}}== |
||
Uses the [http://directory.apache.org/api/ Apache LDAP API], connecting to a local [http://directory.apache.org/apacheds/1.5/ ApacheDS] LDAP directory server. |
Uses the [http://directory.apache.org/api/ Apache LDAP API], connecting to a local [http://directory.apache.org/apacheds/1.5/ ApacheDS] LDAP directory server. |
||
< |
<syntaxhighlight lang="netrexx">/* NetRexx */ |
||
options replace format comments java crossref symbols binary |
options replace format comments java crossref symbols binary |
||
Line 254: | Line 303: | ||
return |
return |
||
</syntaxhighlight> |
|||
</lang> |
|||
'''Sample <tt>log4j.xml</tt> configuration file:''' |
'''Sample <tt>log4j.xml</tt> configuration file:''' |
||
< |
<syntaxhighlight lang="xml"><?xml version="1.0" encoding="UTF-8" ?> |
||
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> |
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> |
||
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'> |
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'> |
||
Line 283: | Line 332: | ||
</root> |
</root> |
||
</log4j:configuration> |
</log4j:configuration> |
||
</syntaxhighlight> |
|||
</lang> |
|||
'''Output:''' |
'''Output:''' |
||
Line 292: | Line 341: | ||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
[http://search.cpan.org/dist/perl-ldap/|Perl LDAP Modules] |
[http://search.cpan.org/dist/perl-ldap/|Perl LDAP Modules] |
||
< |
<syntaxhighlight lang="perl"> |
||
use Net::LDAP; |
use Net::LDAP; |
||
my $ldap = Net::LDAP->new('ldap://ldap.example.com') or die $@; |
my $ldap = Net::LDAP->new('ldap://ldap.example.com') or die $@; |
||
my $mesg = $ldap->bind( $bind_dn, password => $bind_pass ); |
my $mesg = $ldap->bind( $bind_dn, password => $bind_pass ); |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Phix}}== |
|||
{{trans|C}} |
|||
Note that builtins\ldap.e is incomplete, windows-only (depends on wldap32.dll), and largely untested. |
|||
This has been tested against a random 7-year-old list of public ldap servers, getting mixed errors of |
|||
LDAP_SERVER_DOWN/LDAP_INVALID_CREDENTIALS/LDAP_INVALID_DN_SYNTAX/LDAP_CONFIDENTIALITY_REQUIRED. |
|||
<!--<syntaxhighlight lang="phix">--> |
|||
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">/</span><span style="color: #000000;">ldap</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span> |
|||
<span style="color: #008080;">constant</span> <span style="color: #000000;">servers</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span> |
|||
<span style="color: #008000;">"ldap.somewhere.com"</span><span style="color: #0000FF;">,</span> |
|||
<span style="color: #0000FF;">}</span> |
|||
<span style="color: #000080;font-style:italic;">--...</span> |
|||
<span style="color: #004080;">string</span> <span style="color: #000000;">name</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"name"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">password</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"passwd"</span> |
|||
<span style="color: #000080;font-style:italic;">--...</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">servers</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #004080;">atom</span> <span style="color: #000000;">ld</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ldap_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">servers</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span> |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ldap_simple_bind_s</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ld</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">name</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">password</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s: %d [%s]\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">servers</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ldap_err_desc</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)})</span> |
|||
<span style="color: #000080;font-style:italic;">--... after done with it...</span> |
|||
<span style="color: #000000;">ldap_unbind</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ld</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<!--</syntaxhighlight>--> |
|||
{{out}} |
|||
<pre> |
|||
ldap.somewhere.com: 81 [LDAP_SERVER_DOWN] |
|||
</pre> |
|||
=={{header|PHP}}== |
=={{header|PHP}}== |
||
[http://php.net/ldap PHP LDAP Reference] |
[http://php.net/ldap PHP LDAP Reference] |
||
< |
<syntaxhighlight lang="php"><?php |
||
$ldap = ldap_connect($hostname, $port); |
$ldap = ldap_connect($hostname, $port); |
||
$success = ldap_bind($ldap, $username, $password);</ |
$success = ldap_bind($ldap, $username, $password);</syntaxhighlight> |
||
=={{header|PicoLisp}}== |
=={{header|PicoLisp}}== |
||
< |
<syntaxhighlight lang="picolisp">(unless (=0 (setq Ldap (native "libldap.so" "ldap_open" 'N "example.com" 389))) |
||
(quit "Can't open LDAP") ) |
(quit "Can't open LDAP") ) |
||
(native "libldap.so" "ldap_simple_bind_s" 'I Ldap "user" "password")</ |
(native "libldap.so" "ldap_simple_bind_s" 'I Ldap "user" "password")</syntaxhighlight> |
||
=={{header|Python}}== |
=={{header|Python}}== |
||
Line 317: | Line 393: | ||
[http://www.python-ldap.org/doc/html/index.html python-ldap Documentation] |
[http://www.python-ldap.org/doc/html/index.html python-ldap Documentation] |
||
< |
<syntaxhighlight lang="python">import ldap |
||
l = ldap.initialize("ldap://ldap.example.com") |
l = ldap.initialize("ldap://ldap.example.com") |
||
Line 327: | Line 403: | ||
finally: |
finally: |
||
l.unbind() |
l.unbind() |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Racket}}== |
=={{header|Racket}}== |
||
This version uses the ldap package, and was tested against OpenLDAP (with real values): |
This version uses the ldap package, and was tested against OpenLDAP (with real values): |
||
< |
<syntaxhighlight lang="racket">#lang racket |
||
(require net/ldap) |
(require net/ldap) |
||
(ldap-authenticate "ldap.somewhere.com" 389 "uid=username,ou=people,dc=somewhere,dc=com" password)</ |
(ldap-authenticate "ldap.somewhere.com" 389 "uid=username,ou=people,dc=somewhere,dc=com" password)</syntaxhighlight> |
||
{{trans|C}} |
{{trans|C}} |
||
Line 339: | Line 415: | ||
This is a direct translation of the C code -- I have no idea how to try it out since I don't have a working ldap server... So take it as a stub that waits for someone who can try it to do so. (And it's a low level thing anyway, there's an ldap package for Racket which I can't try for a similar reason.) |
This is a direct translation of the C code -- I have no idea how to try it out since I don't have a working ldap server... So take it as a stub that waits for someone who can try it to do so. (And it's a low level thing anyway, there's an ldap package for Racket which I can't try for a similar reason.) |
||
< |
<syntaxhighlight lang="racket">#lang racket |
||
(require ffi/unsafe ffi/unsafe/define) |
(require ffi/unsafe ffi/unsafe/define) |
||
Line 354: | Line 430: | ||
(ldap_simple_bind_s ld name password) |
(ldap_simple_bind_s ld name password) |
||
(ldap_unbind ld)</ |
(ldap_unbind ld)</syntaxhighlight> |
||
=={{header|Raku}}== |
=={{header|Raku}}== |
||
(formerly Perl 6) |
(formerly Perl 6) |
||
Using module LMDB - bindings to the openLDAP library. Requires an LDAP instance. |
Using module LMDB - bindings to the openLDAP library. Requires an LDAP instance. |
||
<lang |
<syntaxhighlight lang="raku" line>use LMDB; |
||
my %DB := LMDB::DB.open(:path<some-dir>, %connection-parameters); |
my %DB := LMDB::DB.open(:path<some-dir>, %connection-parameters); |
||
</syntaxhighlight> |
|||
</lang> |
|||
%DB may be accessed, read from and written to like a native hash. |
%DB may be accessed, read from and written to like a native hash. |
||
Line 373: | Line 450: | ||
{{libheader|RubyGems}} |
{{libheader|RubyGems}} |
||
< |
<syntaxhighlight lang="ruby">require 'rubygems' |
||
require 'net/ldap' |
require 'net/ldap' |
||
ldap = Net::LDAP.new(:host => 'ldap.example.com', :base => 'o=companyname') |
ldap = Net::LDAP.new(:host => 'ldap.example.com', :base => 'o=companyname') |
||
ldap.authenticate('bind_dn', 'bind_pass')</ |
ldap.authenticate('bind_dn', 'bind_pass')</syntaxhighlight> |
||
=={{header|Run BASIC}}== |
=={{header|Run BASIC}}== |
||
{{incorrect|Run BASIC|Active Directory has nothing to do with the local file system}} |
{{incorrect|Run BASIC|Active Directory has nothing to do with the local file system}} |
||
< |
<syntaxhighlight lang="runbasic">print shell$("dir") ' shell out to the os and print it</syntaxhighlight> |
||
=={{header|Rust}}== |
=={{header|Rust}}== |
||
This solution uses the popular [https://crates.io/crates/ldap3 ldap3] crate. |
This solution uses the popular [https://crates.io/crates/ldap3 ldap3] crate. |
||
< |
<syntaxhighlight lang="rust"> |
||
let conn = ldap3::LdapConn::new("ldap://ldap.example.com")?; |
let conn = ldap3::LdapConn::new("ldap://ldap.example.com")?; |
||
conn.simple_bind("bind_dn", "bind_pass")?.success()?; |
conn.simple_bind("bind_dn", "bind_pass")?.success()?; |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Scala}}== |
=={{header|Scala}}== |
||
< |
<syntaxhighlight lang="scala">import java.io.IOException |
||
import org.apache.directory.api.ldap.model.exception.LdapException |
import org.apache.directory.api.ldap.model.exception.LdapException |
||
Line 407: | Line 484: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
=={{header|smart BASIC}}== |
=={{header|smart BASIC}}== |
||
Line 413: | Line 490: | ||
smart BASIC uses three separate commands to list the current directory, folder and files respectively. |
smart BASIC uses three separate commands to list the current directory, folder and files respectively. |
||
< |
<syntaxhighlight lang="qbasic">PRINT "Current directory: ";CURRENT_DIR$() |
||
PRINT |
PRINT |
||
PRINT "Folders:" |
PRINT "Folders:" |
||
Line 427: | Line 504: | ||
FOR n = 0 TO c-1 |
FOR n = 0 TO c-1 |
||
PRINT ,a$(n) |
PRINT ,a$(n) |
||
NEXT n</ |
NEXT n</syntaxhighlight> |
||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
This does not use SSPI/Kerberos yet, so your AD would need to allow simple ldap access. |
This does not use SSPI/Kerberos yet, so your AD would need to allow simple ldap access. |
||
< |
<syntaxhighlight lang="tcl">package require ldap |
||
set conn [ldap::connect $host $port] |
set conn [ldap::connect $host $port] |
||
ldap::bind $conn $user $password</ |
ldap::bind $conn $user $password</syntaxhighlight> |
||
=={{header|VBScript}}== |
=={{header|VBScript}}== |
||
Creating the normal connection to AD |
Creating the normal connection to AD |
||
< |
<syntaxhighlight lang="vbscript">Set objConn = CreateObject("ADODB.Connection") |
||
Set objCmd = CreateObject("ADODB.Command") |
Set objCmd = CreateObject("ADODB.Command") |
||
objConn.Provider = "ADsDSOObject" |
objConn.Provider = "ADsDSOObject" |
||
objConn.Open</ |
objConn.Open</syntaxhighlight> |
||
=={{header|Wren}}== |
|||
{{trans|C}} |
|||
{{libheader|OpenLDAP}} |
|||
As it's not currently possible for Wren-cli to access OpenLDAP directly, we embed a Wren script in a C application to complete this task. |
|||
<syntaxhighlight lang="wren">/* Active_Directory_Connect.wren */ |
|||
foreign class LDAP { |
|||
construct init(host, port) {} |
|||
foreign simpleBindS(name, password) |
|||
foreign unbind() |
|||
} |
|||
class C { |
|||
foreign static getInput(maxSize) |
|||
} |
|||
var name = "" |
|||
while (name == "") { |
|||
System.write("Enter name : ") |
|||
name = C.getInput(40) |
|||
} |
|||
var password = "" |
|||
while (password == "") { |
|||
System.write("Enter password : ") |
|||
password = C.getInput(40) |
|||
} |
|||
var ld = LDAP.init("ldap.somewhere.com", 389) |
|||
ld.simpleBindS(name, password) |
|||
// do something here |
|||
ld.unbind()</syntaxhighlight> |
|||
<br> |
|||
We now embed this in the following C program, compile and run it. |
|||
<syntaxhighlight lang="c">#include <stdio.h> |
|||
#include <stdio_ext.h> |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
#include <ldap.h> |
|||
#include "wren.h" |
|||
/* C <=> Wren interface functions */ |
|||
void C_ldapAllocate(WrenVM* vm) { |
|||
LDAP** pldap = (LDAP**)wrenSetSlotNewForeign(vm, 0, 0, sizeof(LDAP*)); |
|||
char *host = (char *)wrenGetSlotString(vm, 1); |
|||
int port = (int)wrenGetSlotDouble(vm, 2); |
|||
*pldap = ldap_init(host, port); |
|||
} |
|||
void C_simpleBindS(WrenVM* vm) { |
|||
LDAP* ldap = *(LDAP**)wrenGetSlotForeign(vm, 0); |
|||
const char *name = wrenGetSlotString(vm, 1); |
|||
const char *password = wrenGetSlotString(vm, 2); |
|||
ldap_simple_bind_s(ldap, name, password); |
|||
} |
|||
void C_unbind(WrenVM* vm) { |
|||
LDAP* ldap = *(LDAP**)wrenGetSlotForeign(vm, 0); |
|||
ldap_unbind(ldap); |
|||
} |
|||
void C_getInput(WrenVM* vm) { |
|||
int maxSize = (int)wrenGetSlotDouble(vm, 1) + 2; |
|||
char input[maxSize]; |
|||
fgets(input, maxSize, stdin); |
|||
__fpurge(stdin); |
|||
input[strcspn(input, "\n")] = 0; |
|||
wrenSetSlotString(vm, 0, (const char*)input); |
|||
} |
|||
WrenForeignClassMethods bindForeignClass(WrenVM* vm, const char* module, const char* className) { |
|||
WrenForeignClassMethods methods; |
|||
methods.finalize = NULL; |
|||
if (strcmp(className, "LDAP") == 0) { |
|||
methods.allocate = C_ldapAllocate; |
|||
} |
|||
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, "LDAP") == 0) { |
|||
if (!isStatic && strcmp(signature, "simpleBindS(_,_)") == 0) return C_simpleBindS; |
|||
if (!isStatic && strcmp(signature, "unbind()") == 0) return C_unbind; |
|||
} else if (strcmp(className, "C") == 0) { |
|||
if (isStatic && strcmp(signature, "getInput(_)") == 0) return C_getInput; |
|||
} |
|||
} |
|||
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 = "Active_Directory_Connect.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; |
|||
}</syntaxhighlight> |
|||
{{omit from|Active Directory}} |
{{omit from|Active Directory}} |
||
Line 449: | Line 684: | ||
{{omit from|Lilypond}} |
{{omit from|Lilypond}} |
||
{{omit from|Lingo}} |
{{omit from|Lingo}} |
||
{{omit from|TI-83 BASIC}} |
|||
{{omit from|TI-89 BASIC}} <!-- Does not have network access. --> |
|||
{{omit from|Mathematica}} |
{{omit from|Mathematica}} |
||
{{omit from|Maxima}} |
|||
{{omit from|MIPS Assembly|None of the commonly used implementations can access AD functions}} |
{{omit from|MIPS Assembly|None of the commonly used implementations can access AD functions}} |
||
{{omit from|ML/I}} |
{{omit from|ML/I}} |
||
Line 458: | Line 692: | ||
{{omit from|Retro}} |
{{omit from|Retro}} |
||
{{omit from|SNOBOL4|Does not have network access.}} |
{{omit from|SNOBOL4|Does not have network access.}} |
||
{{omit from|TI-83 BASIC}} |
|||
{{omit from|TI-89 BASIC}} <!-- Does not have network access. --> |
|||
{{omit from|Yorick|Does not have network access.}} |
{{omit from|Yorick|Does not have network access.}} |
||
{{omit from|ZX Spectrum Basic|Does not have network access.}} |
{{omit from|ZX Spectrum Basic|Does not have network access.}} |
||
{{omit from|Maxima}} |
|||
[[Category:Active Directory]] |
Latest revision as of 21:13, 14 March 2024
The task is to establish a connection to an Active Directory or Lightweight Directory Access Protocol server.
You are encouraged to solve this task according to the task description, using any language you may know.
AutoHotkey
objConn := CreateObject("ADODB.Connection")
objCmd := CreateObject("ADODB.Command")
objConn.Provider := "ADsDSOObject"
objConn.Open()
AutoIt
#include <AD.au3>
_AD_Open()
C
With OpenLDAP:
#include <ldap.h>
...
char *name, *password;
...
LDAP *ld = ldap_init("ldap.somewhere.com", 389);
ldap_simple_bind_s(ld, name, password);
... after done with it...
ldap_unbind(ld);
C#
// Requires adding a reference to System.DirectoryServices
var objDE = new System.DirectoryServices.DirectoryEntry("LDAP://DC=onecity,DC=corp,DC=fabrikam,DC=com");
ColdFusion
<cfldap
server = "#someip#"
action="query"
start="somestart#"
username = "#someusername#"
password = "#somepassowrd#"
name = "results"
scope="subtree"
attributes = "#attributeslist#"
>
D
Based on dopenldap.
import openldap;
import std.stdio;
void main() {
auto ldap = LDAP("ldap://localhost");
auto r = ldap.search_s("dc=example,dc=com", LDAP_SCOPE_SUBTREE, "(uid=%s)".format("test"));
int b = ldap.bind_s(r[0].dn, "password");
scope(exit) ldap.unbind;
if (b)
{
writeln("error on binding");
return;
}
// do something
...
}
Erlang
This needs a test case. Is there a LDAP server available?
-module(ldap_example).
-export( [main/1] ).
main( [Host, DN, Password] ) ->
{ok, Handle} = eldap:open( [Host] ),
ok = eldap:simple_bind( Handle, DN, Password ),
eldap:close( Handle ).
F#
For Active Directory we use the library System.DirectoryServices
let adObject = new System.DirectoryServices.DirectoryEntry("LDAP://DC=onecity,DC=corp,DC=fabrikam,DC=com")
For your average LDAP server we use System.DirectoryServices.Protocol
For a minimal example we make an anonymous connect to the local machine on the well-known LDAP port 389
let ldapServer = new System.DirectoryServices.Protocols.LdapDirectoryIdentifier("127.0.0.1")
let connect = new System.DirectoryServices.Protocols.LdapConnection(ldapServer)
connect.Bind()
FreeBASIC
#Include "win\winldap.bi"
Dim ldap As LDAP Ptr
Dim hostname As String
Dim port As Integer
Dim username As String
Dim password As String
Dim result As Integer
hostname = "ldap.example.com"
port = 389 ' Standard port for LDAP. Use 636 for LDAPS.
username = "cn=username,dc=example,dc=com"
password = "password"
' Initialize the LDAP connection
ldap = ldap_init(hostname, port)
If ldap = NULL Then
Print "Error initializing LDAP connection"
Sleep
End 1
End If
' Authenticate with the LDAP server
result = ldap_simple_bind_s(ldap, username, password)
If result <> LDAP_SUCCESS Then
Print "Error authenticating with LDAP server: "; ldap_err2string(result)
Sleep
End 1
End If
' Here you can perform LDAP operations
'...
' We close the connection when finished
ldap_unbind(ldap)
Go
There are a large number of third-party LDAP libraries for Go. This uses one of the simpler ones and the code below is largely taken from the example on its main page.
package main
import (
"log"
"github.com/jtblin/go-ldap-client"
)
func main() {
client := &ldap.LDAPClient{
Base: "dc=example,dc=com",
Host: "ldap.example.com",
Port: 389,
UseSSL: false,
BindDN: "uid=readonlyuser,ou=People,dc=example,dc=com",
BindPassword: "readonlypassword",
UserFilter: "(uid=%s)",
GroupFilter: "(memberUid=%s)",
Attributes: []string{"givenName", "sn", "mail", "uid"},
}
defer client.Close()
err := client.Connect()
if err != nil {
log.Fatalf("Failed to connect : %+v", err)
}
// Do something
}
Haskell
Example uses the ldap-client package:
{-# LANGUAGE OverloadedStrings #-}
module Main (main) where
import Data.Foldable (for_)
import qualified Data.Text.Encoding as Text (encodeUtf8)
import Ldap.Client (Attr(..), Filter(..))
import qualified Ldap.Client as Ldap (Dn(..), Host(..), search, with, typesOnly)
main :: IO ()
main = do
entries <- Ldap.with (Ldap.Plain "localhost") 389 $ \ldap ->
Ldap.search ldap (Ldap.Dn "o=example.com") (Ldap.typesOnly True) (Attr "uid" := Text.encodeUtf8 "user") []
for_ entries $ \entry ->
print entry
Java
This code uses the Apache Directory third-party library.
import java.io.IOException;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.ldap.client.api.LdapConnection;
import org.apache.directory.ldap.client.api.LdapNetworkConnection;
public class LdapConnectionDemo {
public static void main(String[] args) throws LdapException, IOException {
try (LdapConnection connection = new LdapNetworkConnection("localhost", 10389)) {
connection.bind();
connection.unBind();
}
}
}
Julia
using LDAPClient
conn = LDAPClient.LDAPConnection("ldap://localhost:10389")
LDAPClient.simple_bind(conn, "user", "password")
LDAPClient.unbind(conn)
Kotlin
import org.apache.directory.api.ldap.model.exception.LdapException
import org.apache.directory.ldap.client.api.LdapNetworkConnection
import java.io.IOException
import java.util.logging.Level
import java.util.logging.Logger
class LDAP(map: Map<String, String>) {
fun run() {
var connection: LdapNetworkConnection? = null
try {
if (info) log.info("LDAP Connection to $hostname on port $port")
connection = LdapNetworkConnection(hostname, port.toInt())
try {
if (info) log.info("LDAP bind")
connection.bind()
} catch (e: LdapException) {
log.severe(e.toString())
}
try {
if (info) log.info("LDAP unbind")
connection.unBind()
} catch (e: LdapException) {
log.severe(e.toString())
}
} finally {
try {
if (info) log.info("LDAP close connection")
connection!!.close()
} catch (e: IOException) {
log.severe(e.toString())
}
}
}
private val log = Logger.getLogger(LDAP::class.java.name)
private val info = log.isLoggable(Level.INFO)
private val hostname: String by map
private val port: String by map
}
fun main(args: Array<String>) = LDAP(mapOf("hostname" to "localhost", "port" to "10389")).run()
NetRexx
Uses the Apache LDAP API, connecting to a local ApacheDS LDAP directory server.
/* NetRexx */
options replace format comments java crossref symbols binary
import org.apache.directory.ldap.client.api.LdapConnection
import org.apache.directory.ldap.client.api.LdapNetworkConnection
import org.apache.directory.shared.ldap.model.exception.LdapException
import org.slf4j.Logger
import org.slf4j.LoggerFactory
class RDirectoryLDAP public
properties constant
log_ = LoggerFactory.getLogger(RDirectoryLDAP.class)
properties private static
connection = LdapConnection null
method main(args = String[]) public static
ldapHostName = String "localhost"
ldapPort = int 10389
if log_.isInfoEnabled() then log_.info("LDAP Connection to" ldapHostName "on port" ldapPort)
connection = LdapNetworkConnection(ldapHostName, ldapPort)
do
if log_.isTraceEnabled() then log_.trace("LDAP bind")
connection.bind()
if log_.isTraceEnabled() then log_.trace("LDAP unbind")
connection.unBind()
catch lex = LdapException
log_.error("LDAP Error", Throwable lex)
catch iox = IOException
log_.error("I/O Error", Throwable iox)
finally
do
if connection \= null then connection.close()
catch iox = IOException
log_.error("I/O Error on connection.close()", Throwable iox)
end
end
return
Sample log4j.xml configuration file:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
<appender name="stdout" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{HH:mm:ss}] %-5p [%c] - %m%n" />
</layout>
</appender>
<!-- with these we'll not get innundated when switching to DEBUG -->
<logger name="org.apache.directory.shared.ldap.name">
<level value="warn" />
</logger>
<logger name="org.apache.directory.shared.codec">
<level value="warn" />
</logger>
<logger name="org.apache.directory.shared.asn1">
<level value="warn" />
</logger>
<root>
<level value="info" />
<appender-ref ref="stdout" />
</root>
</log4j:configuration>
Output:
[08:40:05] INFO [RDirectoryLDAP] - LDAP Connection to localhost on port 10389
Perl
use Net::LDAP;
my $ldap = Net::LDAP->new('ldap://ldap.example.com') or die $@;
my $mesg = $ldap->bind( $bind_dn, password => $bind_pass );
Phix
Note that builtins\ldap.e is incomplete, windows-only (depends on wldap32.dll), and largely untested. This has been tested against a random 7-year-old list of public ldap servers, getting mixed errors of LDAP_SERVER_DOWN/LDAP_INVALID_CREDENTIALS/LDAP_INVALID_DN_SYNTAX/LDAP_CONFIDENTIALITY_REQUIRED.
include builtins/ldap.e constant servers = { "ldap.somewhere.com", } --... string name="name", password="passwd" --... for i=1 to length(servers) do atom ld = ldap_init(servers[i]) integer res = ldap_simple_bind_s(ld, name, password) printf(1,"%s: %d [%s]\n",{servers[i],res,ldap_err_desc(res)}) --... after done with it... ldap_unbind(ld) end for
- Output:
ldap.somewhere.com: 81 [LDAP_SERVER_DOWN]
PHP
<?php
$ldap = ldap_connect($hostname, $port);
$success = ldap_bind($ldap, $username, $password);
PicoLisp
(unless (=0 (setq Ldap (native "libldap.so" "ldap_open" 'N "example.com" 389)))
(quit "Can't open LDAP") )
(native "libldap.so" "ldap_simple_bind_s" 'I Ldap "user" "password")
Python
import ldap
l = ldap.initialize("ldap://ldap.example.com")
try:
l.protocol_version = ldap.VERSION3
l.set_option(ldap.OPT_REFERRALS, 0)
bind = l.simple_bind_s("me@example.com", "password")
finally:
l.unbind()
Racket
This version uses the ldap package, and was tested against OpenLDAP (with real values):
#lang racket
(require net/ldap)
(ldap-authenticate "ldap.somewhere.com" 389 "uid=username,ou=people,dc=somewhere,dc=com" password)
This is a direct translation of the C code -- I have no idea how to try it out since I don't have a working ldap server... So take it as a stub that waits for someone who can try it to do so. (And it's a low level thing anyway, there's an ldap package for Racket which I can't try for a similar reason.)
#lang racket
(require ffi/unsafe ffi/unsafe/define)
(define-ffi-definer defldap (ffi-lib "libldap"))
(defldap ldap_init (_fun _string _int -> _pointer))
(defldap ldap_unbind (_fun _pointer -> _void))
(defldap ldap_simple_bind_s (_fun _pointer _string _string -> _int))
(defldap ldap_err2string (_fun _int -> _string))
(define name ...)
(define password ...)
(define ld (ldap_init "ldap.somewhere.com" 389))
(ldap_simple_bind_s ld name password)
(ldap_unbind ld)
Raku
(formerly Perl 6)
Using module LMDB - bindings to the openLDAP library. Requires an LDAP instance.
use LMDB;
my %DB := LMDB::DB.open(:path<some-dir>, %connection-parameters);
%DB may be accessed, read from and written to like a native hash.
Ruby
Similar to Tcl, assume the AD server talks LDAP.
There are many Ruby LDAP packages ([1]) -- this solution uses Net::LDAP ("Pure Ruby LDAP Tools" on RubyForge, gem name "ruby-net-ldap")
require 'rubygems'
require 'net/ldap'
ldap = Net::LDAP.new(:host => 'ldap.example.com', :base => 'o=companyname')
ldap.authenticate('bind_dn', 'bind_pass')
Run BASIC
print shell$("dir") ' shell out to the os and print it
Rust
This solution uses the popular ldap3 crate.
let conn = ldap3::LdapConn::new("ldap://ldap.example.com")?;
conn.simple_bind("bind_dn", "bind_pass")?.success()?;
Scala
import java.io.IOException
import org.apache.directory.api.ldap.model.exception.LdapException
import org.apache.directory.ldap.client.api.{LdapConnection, LdapNetworkConnection}
object LdapConnectionDemo {
@throws[LdapException]
@throws[IOException]
def main(args: Array[String]): Unit = {
try {
val connection: LdapConnection = new LdapNetworkConnection("localhost", 10389)
try {
connection.bind()
connection.unBind()
} finally if (connection != null) connection.close()
}
}
}
smart BASIC
smart BASIC uses three separate commands to list the current directory, folder and files respectively.
PRINT "Current directory: ";CURRENT_DIR$()
PRINT
PRINT "Folders:"
PRINT
DIR "/" LIST DIRS a$,c
FOR n = 0 TO c-1
PRINT ,a$(n)
NEXT n
PRINT
PRINT "Files:"
PRINT
DIR "/" LIST FILES a$,c
FOR n = 0 TO c-1
PRINT ,a$(n)
NEXT n
Tcl
This does not use SSPI/Kerberos yet, so your AD would need to allow simple ldap access.
package require ldap
set conn [ldap::connect $host $port]
ldap::bind $conn $user $password
VBScript
Creating the normal connection to AD
Set objConn = CreateObject("ADODB.Connection")
Set objCmd = CreateObject("ADODB.Command")
objConn.Provider = "ADsDSOObject"
objConn.Open
Wren
As it's not currently possible for Wren-cli to access OpenLDAP directly, we embed a Wren script in a C application to complete this task.
/* Active_Directory_Connect.wren */
foreign class LDAP {
construct init(host, port) {}
foreign simpleBindS(name, password)
foreign unbind()
}
class C {
foreign static getInput(maxSize)
}
var name = ""
while (name == "") {
System.write("Enter name : ")
name = C.getInput(40)
}
var password = ""
while (password == "") {
System.write("Enter password : ")
password = C.getInput(40)
}
var ld = LDAP.init("ldap.somewhere.com", 389)
ld.simpleBindS(name, password)
// do something here
ld.unbind()
We now embed this in the following C program, compile and run it.
#include <stdio.h>
#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
#include <ldap.h>
#include "wren.h"
/* C <=> Wren interface functions */
void C_ldapAllocate(WrenVM* vm) {
LDAP** pldap = (LDAP**)wrenSetSlotNewForeign(vm, 0, 0, sizeof(LDAP*));
char *host = (char *)wrenGetSlotString(vm, 1);
int port = (int)wrenGetSlotDouble(vm, 2);
*pldap = ldap_init(host, port);
}
void C_simpleBindS(WrenVM* vm) {
LDAP* ldap = *(LDAP**)wrenGetSlotForeign(vm, 0);
const char *name = wrenGetSlotString(vm, 1);
const char *password = wrenGetSlotString(vm, 2);
ldap_simple_bind_s(ldap, name, password);
}
void C_unbind(WrenVM* vm) {
LDAP* ldap = *(LDAP**)wrenGetSlotForeign(vm, 0);
ldap_unbind(ldap);
}
void C_getInput(WrenVM* vm) {
int maxSize = (int)wrenGetSlotDouble(vm, 1) + 2;
char input[maxSize];
fgets(input, maxSize, stdin);
__fpurge(stdin);
input[strcspn(input, "\n")] = 0;
wrenSetSlotString(vm, 0, (const char*)input);
}
WrenForeignClassMethods bindForeignClass(WrenVM* vm, const char* module, const char* className) {
WrenForeignClassMethods methods;
methods.finalize = NULL;
if (strcmp(className, "LDAP") == 0) {
methods.allocate = C_ldapAllocate;
}
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, "LDAP") == 0) {
if (!isStatic && strcmp(signature, "simpleBindS(_,_)") == 0) return C_simpleBindS;
if (!isStatic && strcmp(signature, "unbind()") == 0) return C_unbind;
} else if (strcmp(className, "C") == 0) {
if (isStatic && strcmp(signature, "getInput(_)") == 0) return C_getInput;
}
}
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 = "Active_Directory_Connect.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;
}