| | 1 | === Using XMLRPC from Ruby === |
|---|
| | 2 | |
|---|
| | 3 | You can either use the XMLRPC functionality included in the [http://ruby-doc.org/stdlib/libdoc/xmlrpc/rdoc/index.html Ruby Standard Library] or [/attachment/wiki/XmlRpcPlugin/trac4r.tar.gz download the trac4r library] which does all the trivial stuff for you. |
|---|
| | 4 | |
|---|
| | 5 | please refer to the '''SSL Support''' section if you need one. |
|---|
| | 6 | |
|---|
| | 7 | ==== trac4r Example ==== |
|---|
| | 8 | This example uses trac4r: |
|---|
| | 9 | {{{ |
|---|
| | 10 | #!ruby |
|---|
| | 11 | require 'trac4r/trac' |
|---|
| | 12 | # initialize the connection (username and password can be ommitted if not needed, but most of the time you will need them if anonymous doesn't have XMLRPC permissions) |
|---|
| | 13 | trac = Trac.new "https://dev.example.com/trac/my_awesome_project", "myusername", "mypassword" |
|---|
| | 14 | # get a list of all tickets (as an array of numbers) |
|---|
| | 15 | trac.tickets.list :include_closed => true # this is the default anyway |
|---|
| | 16 | # get all the tickets |
|---|
| | 17 | # NOTE: the results here are cached, so you can call it as often as you want without producing traffic more than once. |
|---|
| | 18 | # use ":cached_results => false" to get the latest version |
|---|
| | 19 | trac.tickets.get_all :include_closed => true |
|---|
| | 20 | # get a single ticket |
|---|
| | 21 | ticket = trac.tickets.get 5 |
|---|
| | 22 | # print the data |
|---|
| | 23 | puts "Title: #{ticket.summary}" |
|---|
| | 24 | puts "Description: #{ticket.description}" |
|---|
| | 25 | puts "Milestone: #{ticket.milestone}" |
|---|
| | 26 | puts "Status: #{ticket.status}" |
|---|
| | 27 | puts "Type: #{ticket.type}" |
|---|
| | 28 | puts "Priority: #{ticket.priority}" |
|---|
| | 29 | # get a list of all wiki pages |
|---|
| | 30 | trac.wiki.list |
|---|
| | 31 | # download one page |
|---|
| | 32 | trac.wiki.get_html "SomeRandomPageName" # HTML version |
|---|
| | 33 | trac.wiki.get_raw "AnotherRandomPageName" # trac syntax version (e.g. for editing) |
|---|
| | 34 | # for previews use |
|---|
| | 35 | trac.wiki.raw_to_html "content of a page in [wiki:WikiFormatting Trac syntax] as a ''String''" |
|---|
| | 36 | # to post a page use |
|---|
| | 37 | trac.wiki.put "NameOfThePage", "content in Trac syntax" |
|---|
| | 38 | # list the attachments of a wiki page |
|---|
| | 39 | trac.wiki.attachments "NameOfThePage" |
|---|
| | 40 | # save an attachment |
|---|
| | 41 | File.new("my_cool_document","w") do |f| |
|---|
| | 42 | f.write trac.wiki.get_attachment "NameOfThePage", "my_cool_document.pdf" |
|---|
| | 43 | end |
|---|
| | 44 | |
|---|
| | 45 | # upload an attachment to the page above |
|---|
| | 46 | page = "NameOfThePage" |
|---|
| | 47 | fn = "my_nice_doc.pdf" |
|---|
| | 48 | fh = File.new(fn, "rb") |
|---|
| | 49 | sdata = fh.read |
|---|
| | 50 | data = XMLRPC::Base64.new(sdata) |
|---|
| | 51 | result = trac.wiki.put_attachment(page, name, "uploaded via ruby script", data) |
|---|
| | 52 | # the correct result should be the name of the file: |
|---|
| | 53 | puts "ERROR: uploading #{name} didn't work properly!" if result != name |
|---|
| | 54 | }}} |
|---|
| | 55 | |
|---|
| | 56 | Also see the included Documentation in trac4r/doc |
|---|
| | 57 | |
|---|
| | 58 | If you need to do a custom query do |
|---|
| | 59 | {{{ |
|---|
| | 60 | #!ruby |
|---|
| | 61 | trac.query("system.getAPIVersion") |
|---|
| | 62 | }}} |
|---|
| | 63 | The first argument is the method name, all other arguments are directly passed to XMLRPC. |
|---|
| | 64 | For this example of cause you could do `trac.api_version` instead ;) |
|---|
| | 65 | |
|---|
| | 66 | If you have any problems with trac4r you can email me: niklas.cathor (eat) gmail dot com |
|---|
| | 67 | |
|---|
| | 68 | ==== xmlrpc Example ==== |
|---|
| | 69 | |
|---|
| | 70 | An example using XML-RPC directly with Ruby to append to a wiki page: |
|---|
| | 71 | {{{ |
|---|
| | 72 | #!ruby |
|---|
| | 73 | require 'xmlrpc/client' |
|---|
| | 74 | user = "username" |
|---|
| | 75 | password = "password" |
|---|
| | 76 | page_name = "SandBoxRPC" |
|---|
| | 77 | new_content = "\n\nMy new content" |
|---|
| | 78 | new_comment = "Adding new content from ruby" |
|---|
| | 79 | |
|---|
| | 80 | server = XMLRPC::Client.new2("https://#{user}:#{password}@trac.server.com/trac/login/xmlrpc") |
|---|
| | 81 | content = server.call("wiki.getPage", page_name) + new_content |
|---|
| | 82 | server.call("wiki.putPage", page_name, content, {"comment" => new_comment}) |
|---|
| | 83 | }}} |
|---|
| | 84 | |
|---|
| | 85 | ==== SSL Support + X509 ==== |
|---|
| | 86 | The standard ruby xmlrpc client for some reason does not support SSL at all. |
|---|
| | 87 | In order to be able to use the XMLRPC over SSL with both |
|---|
| | 88 | * Client Certificate authentication |
|---|
| | 89 | * Basic Authentication |
|---|
| | 90 | One must do as follows. |
|---|
| | 91 | |
|---|
| | 92 | in order to proceed, you should have: |
|---|
| | 93 | * ca certificate in .pem format |
|---|
| | 94 | * personal certificate + RSA key in .p12 format (and its password, of course) |
|---|
| | 95 | * patched version of xmlrpc/client.rb |
|---|
| | 96 | * patched version of trac4r |
|---|
| | 97 | * username/password (for basic authentication) |
|---|
| | 98 | |
|---|
| | 99 | Assuming you have the above, and your ca and user certificates are respectively: |
|---|
| | 100 | {{{ |
|---|
| | 101 | ~/.openssl/cacert.pem |
|---|
| | 102 | ~/.openssl/certkey.p12 |
|---|
| | 103 | }}} |
|---|
| | 104 | ===== The Instructions ===== |
|---|
| | 105 | 1. apply the patches: |
|---|
| | 106 | 1. to the [attachment:"xmlrpc-client.SSL.patch" xmlrpc client] |
|---|
| | 107 | {{{ |
|---|
| | 108 | sudo su - |
|---|
| | 109 | cd /usr/lib/ruby/1.8/ |
|---|
| | 110 | patch -p0 < /path/to/xmlrpc-client.SSL.patch |
|---|
| | 111 | }}} |
|---|
| | 112 | 1. to the [attachment:"trac4r-1.2.3.SSL.patch" trac4r gem] |
|---|
| | 113 | {{{ |
|---|
| | 114 | sudo su - |
|---|
| | 115 | cd /var/lib/gems/1.8/gems/ |
|---|
| | 116 | patch -p0 < /path/to/trac4r-1.2.3.SSL.patch |
|---|
| | 117 | }}} |
|---|
| | 118 | 1. create a .yml file called {{{~/.trac/creds.yml}}} of the following structure: |
|---|
| | 119 | {{{ |
|---|
| | 120 | --- |
|---|
| | 121 | tracurl: https://yourserver.yourdomain/yourproject |
|---|
| | 122 | tracuser: yourwebuser |
|---|
| | 123 | tracpass: yourwebpassword |
|---|
| | 124 | certkey: /home/youruser/.openssl/certkey.p12 |
|---|
| | 125 | cacert: /home/youruser/.openssl/cacert.pem |
|---|
| | 126 | keypass: yourkeypassword |
|---|
| | 127 | }}} |
|---|
| | 128 | * do not forget to chmod the personal files to 600 or 400 |
|---|
| | 129 | 1. use the data in the code |
|---|
| | 130 | {{{ |
|---|
| | 131 | #!ruby |
|---|
| | 132 | require 'yaml' |
|---|
| | 133 | require 'openssl' |
|---|
| | 134 | require 'xmlrpc/client' |
|---|
| | 135 | require 'trac4r' |
|---|
| | 136 | |
|---|
| | 137 | ## read the data from yaml: |
|---|
| | 138 | $ymlname= "#{ENV['HOME']}/.trac/creds.yml" |
|---|
| | 139 | if !File.exists?($ymlname) |
|---|
| | 140 | raise "Cannot open credentials file!" |
|---|
| | 141 | end |
|---|
| | 142 | begin |
|---|
| | 143 | $vars = YAML::load_file($ymlname) |
|---|
| | 144 | rescue Exception => e |
|---|
| | 145 | raise "Cannot load credentials file #{$ymlname}: #{e.message}\nTrace: #{e.stacktrace}" |
|---|
| | 146 | end |
|---|
| | 147 | |
|---|
| | 148 | ## extract the certificate, and the key from the fles. |
|---|
| | 149 | pkcs = OpenSSL::PKCS12.new(File.open($vars['certkey']),$vars['keypass']) |
|---|
| | 150 | cert = pkcs.cert |
|---|
| | 151 | key = pkcs.key |
|---|
| | 152 | ## connect to the server |
|---|
| | 153 | trac = Trac.new($vars['tracurl'], $vars['tracuser'], $vars['tracpass'], $vars['cacert'], cert, key) |
|---|
| | 154 | ## from now you can refer to the connection as open (or query it) |
|---|
| | 155 | ## use the API as explained above. |
|---|
| | 156 | }}} |
|---|
| | 157 | |
|---|
| | 158 | '''NOTE:''' The working environment of the code (trac4r + ssl) is: |
|---|
| | 159 | * Debian/GNU system: {{{Linux hostname 2.6.26-2-686 #1 SMP Mon Jun 21 05:58:44 UTC 2010 i686 GNU/Linux}}} |
|---|
| | 160 | * OpenSSL: {{{OpenSSL 0.9.8g 19 Oct 2007}}} |
|---|
| | 161 | * Ruby: {{{ruby 1.8.7 (2008-08-11 patchlevel 72) [i486-linux]}}} |
|---|
| | 162 | * The certificates have been issued by the above OpenSSL setup. |