vortex_client 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +10 -0
- data/VERSION +1 -1
- data/examples/convert_faq.rb +298 -0
- data/examples/publish_event.rb +1 -1
- data/examples/sitemap.rb +106 -0
- data/lib/vortex_client.rb +30 -101
- data/test/test_acl.rb +36 -0
- data/test/test_vortex_pic.rb +32 -0
- data/test/test_vortex_tags_flymake.rb +29 -0
- data/test/test_vortex_utils_flymake.rb +20 -0
- metadata +42 -17
data/README.rdoc
CHANGED
@@ -40,6 +40,16 @@ To create a folder named "2010" in the "/news/" folder.
|
|
40
40
|
|
41
41
|
RDoc: http://rdoc.info/projects/thomasfl/vortex_client/
|
42
42
|
|
43
|
+
= Installation
|
44
|
+
|
45
|
+
On most setups you simply do:
|
46
|
+
|
47
|
+
sudo gem install vortex_client
|
48
|
+
|
49
|
+
If your'e having problems installing the xml parser nokogiri on is x: http://wiki.github.com/tenderlove/nokogiri/what-to-do-if-libxml2-is-being-a-jerk
|
50
|
+
Also how to compile ruby 1.9.1 on os x http://wonko.com/post/how-to-compile-ruby-191
|
51
|
+
On ubuntu openssl can be an issue http://blog.maxaller.name/2009/02/ruby-19-and-openssl-on-ubuntu/
|
52
|
+
|
43
53
|
== Note on Patches/Pull Requests
|
44
54
|
|
45
55
|
* Fork the project.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.1
|
@@ -0,0 +1,298 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'rubygems'
|
3
|
+
require 'open-uri'
|
4
|
+
require 'hpricot'
|
5
|
+
# require 'webdavtools'
|
6
|
+
require 'vortex_client'
|
7
|
+
include Vortex
|
8
|
+
|
9
|
+
# Convert vortex xml faq til html faq:
|
10
|
+
# Example:
|
11
|
+
#
|
12
|
+
# ruby convert_faq.rb https://www-dav.uio.no/faq/studier/fronter.xml https://www-dav.usit.uio.no/it/fronter/faq.html
|
13
|
+
#
|
14
|
+
# Author: Thomas Flemming, 2010
|
15
|
+
#
|
16
|
+
|
17
|
+
ARTICLE_HEADER = <<EOF
|
18
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
19
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
20
|
+
<head>
|
21
|
+
<title>##title##</title>
|
22
|
+
<meta http-equiv="Content-type" content="text/html;charset=utf-8" />
|
23
|
+
|
24
|
+
</head>
|
25
|
+
<body>
|
26
|
+
<style type="text/css">
|
27
|
+
.vrtx-published-date {
|
28
|
+
display: none;
|
29
|
+
}
|
30
|
+
</style>
|
31
|
+
<br />
|
32
|
+
${resource:toc}
|
33
|
+
EOF
|
34
|
+
|
35
|
+
ARTICLE_FOOTER = <<EOF
|
36
|
+
</body>
|
37
|
+
</html>
|
38
|
+
EOF
|
39
|
+
|
40
|
+
|
41
|
+
# Parsing av HTML koden til FAQ med 2 nivåer
|
42
|
+
def scrape_faq_2_levels(url)
|
43
|
+
html = ""
|
44
|
+
doc = Hpricot(open(url))
|
45
|
+
doc.search(".faqOverskrift") do |item|
|
46
|
+
html += "<h2 class=\"faqOverskrift\">" + item.inner_html + "</h2>\n"
|
47
|
+
item = item.next_sibling
|
48
|
+
while item and item.name != "h2" and item.name != "br"
|
49
|
+
|
50
|
+
if item.attributes["class"] and item.attributes["class"] =~ /faqOverskrift/ then
|
51
|
+
puts "Parse error: Unwanted item: " + item.to_s
|
52
|
+
end
|
53
|
+
|
54
|
+
if not( item.name == "a" and item.inner_text == "") then
|
55
|
+
if item.attributes["class"] and item.attributes["class"] =~ /faqSporsmal/ then
|
56
|
+
html += "<h3 class=\"faqSporsmal\">" + item.inner_html + "</h3>\n"
|
57
|
+
else
|
58
|
+
html += item.to_s + "\n"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
item = item.next_sibling
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
return html
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
def scrape_faq_1_level(url)
|
70
|
+
doc = Hpricot(open(url))
|
71
|
+
html = ""
|
72
|
+
doc.search(".faqSporsmal") do |item|
|
73
|
+
html += "<h2 class=\"faqSporsmal\">" + item.inner_html + "</h2>\n"
|
74
|
+
item = item.next_sibling
|
75
|
+
while item and ((item.attributes["class"] =~ /faqSporsmal/) == nil) and item.name != "h2" and item.name != "br"
|
76
|
+
item = item.next_sibling if(item.name == "a" and item.inner_html == "")
|
77
|
+
if(item.attributes["class"] =~ /faqSvar/) then
|
78
|
+
html += item.inner_html.to_s + "\n"
|
79
|
+
else
|
80
|
+
html += item.to_s + "\n"
|
81
|
+
end
|
82
|
+
|
83
|
+
item = item.next_sibling
|
84
|
+
end
|
85
|
+
end
|
86
|
+
return html
|
87
|
+
end
|
88
|
+
|
89
|
+
# Skrap html kode til faq og konverter til nytt format
|
90
|
+
def scrape_faq_html(url)
|
91
|
+
|
92
|
+
doc = Hpricot(open(url))
|
93
|
+
|
94
|
+
if( doc.search(".faqOverskrift").size == 0 ) then
|
95
|
+
puts "Konverting FAQ with 1 level..."
|
96
|
+
return scrape_faq_1_level(url)
|
97
|
+
else
|
98
|
+
puts "Konverting FAQ with 2 levels..."
|
99
|
+
return scrape_faq_2_levels(url)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def davUrl2webUrl(url)
|
104
|
+
if(url =~ /^https:\/\/([^\/]*)-dav(\..*)/)then
|
105
|
+
return "http://" + $1 + $2
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Extracts introduction from FAQ
|
110
|
+
def scrape_faq_introduction(url)
|
111
|
+
introduction = ""
|
112
|
+
doc = Hpricot(open(url))
|
113
|
+
|
114
|
+
doc.search("h1") do |item|
|
115
|
+
|
116
|
+
item = item.next_sibling
|
117
|
+
|
118
|
+
while item and item.name != "h2" and item.name != "h3"
|
119
|
+
introduction = introduction + item.inner_html # text
|
120
|
+
item = item.next_sibling
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
introduction = introduction.gsub(/</,"<").gsub(/>/,">")
|
126
|
+
introduction = introduction.gsub("ø","ø").gsub("å","å").gsub("æ","æ")
|
127
|
+
introduction = introduction.gsub("Ø","Ø").gsub("Å","Å").gsub("&Aelig;","Æ")
|
128
|
+
introduction = introduction.gsub(/"/m,""")
|
129
|
+
introduction = introduction.gsub(/'/m,"") #’")
|
130
|
+
introduction = introduction.sub(/\n/m," ").sub(/\r/m," ")
|
131
|
+
introduction = introduction.sub(/^\s*/, "").chop!
|
132
|
+
return introduction
|
133
|
+
end
|
134
|
+
|
135
|
+
# Konverterter WebDAV properties fra managed-xml dokumenter til article dokumenter.
|
136
|
+
def convert_dav_propes(dav_url)
|
137
|
+
props_arr = []
|
138
|
+
unwanted_properties =
|
139
|
+
["v:guessedcharacterencoding",
|
140
|
+
"v:schema",
|
141
|
+
# Example: <customdefined xmlns="http://www.uio.no/visual-profile">true</..
|
142
|
+
# "customdefined",
|
143
|
+
# Derived properties that dont' need to be set:
|
144
|
+
"d:displayname",
|
145
|
+
"d:getcontentlength",
|
146
|
+
"d:getetag",
|
147
|
+
"v:collection",
|
148
|
+
"v:propertieslastmodified",
|
149
|
+
"v:propertiesmodifiedby",
|
150
|
+
"d:resourcetype",
|
151
|
+
"v:title"
|
152
|
+
]
|
153
|
+
props = Hpricot( @vortex_source.propfind(dav_url).to_s )
|
154
|
+
props.search("d:resourcetype/*") do |item|
|
155
|
+
if item.is_a?(Hpricot::Elem) and (unwanted_properties.grep(item.name) == [] )
|
156
|
+
prop =
|
157
|
+
case item.name
|
158
|
+
when "v:managedxmltitle"
|
159
|
+
title = item.inner_html
|
160
|
+
"<v:userTitle xmlns:v=\"vrtx\">#{title}</v:userTitle>"
|
161
|
+
when "v:characterencoding"
|
162
|
+
item.to_s.gsub(/UTF-/,"utf-") +
|
163
|
+
"<v:userSpecifiedCharacterEncoding xmlns:v=\"vrtx\">utf-8</v:userSpecifiedCharacterEncoding>"
|
164
|
+
when "v:resourcetype"
|
165
|
+
"<v:resourceType xmlns:v=\"vrtx\">article</v:resourceType>" +
|
166
|
+
"<v:xhtml10-type xmlns:v=\"vrtx\">article</v:xhtml10-type>"
|
167
|
+
when "v:contentlastmodified"
|
168
|
+
lastModifiedDate = item.inner_html
|
169
|
+
# Articles needs published-date to be visible. Use lastModified:
|
170
|
+
props_arr << "<v:published-date xmlns:v=\"vrtx\">#{lastModifiedDate}</v:published-date>"
|
171
|
+
item.to_s
|
172
|
+
when "customdefined"
|
173
|
+
item.to_s.gsub(/customdefined/, "customDefined") # attribute name is camelCase in article
|
174
|
+
when "editoremail"
|
175
|
+
item.to_s.gsub(/editoremail/, "editorEmail") # attribute name is camelCase in article
|
176
|
+
when "editorname"
|
177
|
+
item.to_s.gsub(/editorname/, "editorName") # attribute name is camelCase in article
|
178
|
+
else
|
179
|
+
item.to_s
|
180
|
+
end
|
181
|
+
props_arr << prop
|
182
|
+
end
|
183
|
+
end
|
184
|
+
return props_arr.sort().join("\n")
|
185
|
+
end
|
186
|
+
|
187
|
+
def convert_faq(dav_url, new_dav_url)
|
188
|
+
url = davUrl2webUrl(dav_url)
|
189
|
+
puts "Scraping html from: " + url
|
190
|
+
|
191
|
+
# Scrape document title
|
192
|
+
begin
|
193
|
+
doc = Hpricot(open(url))
|
194
|
+
rescue
|
195
|
+
puts "Kunne ikke åpne url: " + url
|
196
|
+
return
|
197
|
+
end
|
198
|
+
title = doc.search("title").inner_text
|
199
|
+
new_html = ARTICLE_HEADER.gsub(/##title##/, title) + scrape_faq_html(url) + ARTICLE_FOOTER
|
200
|
+
|
201
|
+
new_props = convert_dav_propes(dav_url)
|
202
|
+
|
203
|
+
introduction = scrape_faq_introduction(url)
|
204
|
+
if(introduction != nil and introduction != "") then
|
205
|
+
new_props = new_props + "<introduction>#{introduction}</introduction>"
|
206
|
+
end
|
207
|
+
|
208
|
+
# WebDAV.delete(new_dav_url)
|
209
|
+
# WebDAV.publish(new_dav_url, new_html, new_props)
|
210
|
+
begin
|
211
|
+
@vortex_dest.delete(new_dav_url)
|
212
|
+
rescue
|
213
|
+
end
|
214
|
+
# puts "DEBUG: " + new_dav_url + new_html + new_props
|
215
|
+
@vortex_dest.put_string(new_dav_url, new_html)
|
216
|
+
@vortex_dest.proppatch(new_dav_url, new_props)
|
217
|
+
|
218
|
+
end
|
219
|
+
|
220
|
+
|
221
|
+
#
|
222
|
+
# Generer rapport med oversikt over alle FAQ'er
|
223
|
+
#
|
224
|
+
HEADER = <<EOF
|
225
|
+
<table border="1">
|
226
|
+
<tbody>
|
227
|
+
<tr>
|
228
|
+
<th bgcolor="#c0c0c0" align="left" bordercolor="#FFFFFF">Tittel</th>
|
229
|
+
<th bgcolor="#c0c0c0" align="left" bordercolor="#FFFFFF">Orginal plassering</th>
|
230
|
+
<th bgcolor="#c0c0c0" align="left" bordercolor="#FFFFFF">Epost</th>
|
231
|
+
<th bgcolor="#c0c0c0" align="left" bordercolor="#FFFFFF">Status</th>
|
232
|
+
<th bgcolor="#c0c0c0" align="left" bordercolor="#FFFFFF">Skal konverteres til</th>
|
233
|
+
<th bgcolor="#c0c0c0" align="left" bordercolor="#FFFFFF">Er konvertert</th>
|
234
|
+
</tr>
|
235
|
+
EOF
|
236
|
+
|
237
|
+
def print_status_report(dav_url)
|
238
|
+
arr = []
|
239
|
+
count = 0
|
240
|
+
@vortex_source.find(dav_url, :recursive => true) do |item|
|
241
|
+
|
242
|
+
if( item.basename =~ /.xml$/ and (not(item.basename =~ /index.xml$/ )))then
|
243
|
+
url = item.href
|
244
|
+
url = url.sub(/^https/, "http").sub(/-dav\.uio\.no/,".uio.no")
|
245
|
+
arr.push([item.title, url, item.basename])
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
puts HEADER
|
250
|
+
arr.sort.each do |item|
|
251
|
+
# puts item[0] + item[1] + item[2]
|
252
|
+
puts "<tr>"
|
253
|
+
puts " <td>" + item[0] + "</td><td><a href=\"#{item[1]}\">#{item[2]}</a></td>"
|
254
|
+
puts " <td> </td><td> </td><td> </td><td> </td>"
|
255
|
+
puts "</tr>"
|
256
|
+
end
|
257
|
+
puts "</table>"
|
258
|
+
end
|
259
|
+
|
260
|
+
# Konverter alle FAQ dokumentene
|
261
|
+
def convert_recursively(url)
|
262
|
+
@vortex_source.find(dav_url, :recursive => true) do |item|
|
263
|
+
if( item.basename =~ /.xml$/ and (not(item.basename =~ /index.xml$/ )))then
|
264
|
+
puts "Converterting: " + item.basename.ljust(40) + item.title
|
265
|
+
dav_url = item.href
|
266
|
+
new_dav_url = dav_url.sub(/\.xml$/,".html")
|
267
|
+
convert_faq(dav_url, new_dav_url)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
|
273
|
+
# Usage:
|
274
|
+
#
|
275
|
+
# convert_faq()
|
276
|
+
#
|
277
|
+
# convert_faq("https://www-dav.usit.uio.no/it/epost/faq/thunderbird-itansv.xml",
|
278
|
+
# "https://vortex-dav.uio.no/brukere/thomasfl/thunderbird-itansv-faq.html")
|
279
|
+
# convert_faq("https://www-dav.uio.no/faq/studier/teologi-studentinfo.xml", "https://www-dav.tf.uio.no/studier/faq.html")
|
280
|
+
# convert_faq("https://www-dav.uio.no/faq/for_ansatte/usit-nyansatte.xml",
|
281
|
+
# "https://www-dav.usit.uio.no/for-ansatte/ny-usit/nyansatt.html")
|
282
|
+
# exit
|
283
|
+
|
284
|
+
|
285
|
+
|
286
|
+
# Les inn gammel og ny url
|
287
|
+
src_url = ARGV[0]
|
288
|
+
dest_url = ARGV[1]
|
289
|
+
if(not(src_url and dest_url))
|
290
|
+
puts "Usage: ruby convert src_dav_url destinatio_dav_url"
|
291
|
+
exit
|
292
|
+
end
|
293
|
+
|
294
|
+
@vortex_source = Vortex::Connection.new(src_url, ENV['DAVUSER'], ENV['DAVPASS'])
|
295
|
+
@vortex_dest = Vortex::Connection.new(dest_url, ENV['DAVUSER'], ENV['DAVPASS'])
|
296
|
+
|
297
|
+
convert_faq(src_url, dest_url)
|
298
|
+
puts "Published FAQ article to: " + dest_url
|
data/examples/publish_event.rb
CHANGED
@@ -12,7 +12,7 @@ event = HtmlEvent.new(:title => "My Sample Event 1",
|
|
12
12
|
:location => "Forskningsveien 3B",
|
13
13
|
:mapUrl => "http://maps.google.com/123",
|
14
14
|
:tags => ["vortex","testing","ruby"],
|
15
|
-
:publishedDate =>
|
15
|
+
:publishedDate => Time.now )
|
16
16
|
path = vortex.publish(event)
|
17
17
|
puts "published " + path
|
18
18
|
|
data/examples/sitemap.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# Generate sitemap from WebDAV tree:
|
3
|
+
#
|
4
|
+
# Example:
|
5
|
+
#
|
6
|
+
# $ruby generate_vortex_sitemap.rb http://www.iss.uio.no/
|
7
|
+
#
|
8
|
+
# Author: Thomas Flemming, thomas.flemming@usit.uio.no 2010
|
9
|
+
#
|
10
|
+
require "net/https"
|
11
|
+
require "uri"
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'vortex_client'
|
15
|
+
require 'open-uri'
|
16
|
+
|
17
|
+
user = ask("Username : ") {|q| q.echo = true}
|
18
|
+
pwd = ask("Pssword : ") {|q| q.echo = false}
|
19
|
+
|
20
|
+
|
21
|
+
# Returns "200" if everything's ok.
|
22
|
+
def responseCode(url)
|
23
|
+
uri = URI.parse(url)
|
24
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
25
|
+
if(uri.scheme == "https")
|
26
|
+
http.use_ssl = true
|
27
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
28
|
+
end
|
29
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
30
|
+
response = http.request(request)
|
31
|
+
return response.code
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
def property(item, xpath)
|
36
|
+
namespaces = {'v' => "vrtx",'d' => "DAV:"}
|
37
|
+
xml = item.propfind
|
38
|
+
xml.xpath(xpath, namespaces).inner_text
|
39
|
+
end
|
40
|
+
|
41
|
+
def dav_url2http_url(url)
|
42
|
+
if(url =~ /\/vortex-dav\./)
|
43
|
+
url = url.sub( /\/vortex-dav\./, '/vortex.' )
|
44
|
+
else
|
45
|
+
url = url.sub(/https:\/\/www-dav\./,'http://www.')
|
46
|
+
end
|
47
|
+
return url
|
48
|
+
end
|
49
|
+
|
50
|
+
def http_url2dav_url(url)
|
51
|
+
url = url.sub(/^http:\/\//i,'https://')
|
52
|
+
url = url.sub(/^https?:\/\/www\./i,'https://www-dav.')
|
53
|
+
return url
|
54
|
+
end
|
55
|
+
|
56
|
+
def outline_number(url)
|
57
|
+
@numbering = [] if(@numbering == nil)
|
58
|
+
@prev_url = "" if(@prev_url == nil)
|
59
|
+
|
60
|
+
size = url.split(/\//).size
|
61
|
+
prev_size = @prev_url.split(/\//).size
|
62
|
+
|
63
|
+
if(size > prev_size)
|
64
|
+
@numbering << 1
|
65
|
+
end
|
66
|
+
|
67
|
+
if(size < prev_size)
|
68
|
+
index = size - 1
|
69
|
+
# index = @numbering.size - 2
|
70
|
+
@numbering = @numbering[0..index]
|
71
|
+
@numbering[index] = @numbering.last + 1
|
72
|
+
end
|
73
|
+
|
74
|
+
if(prev_size == size)
|
75
|
+
index = @numbering.size - 1
|
76
|
+
@numbering[index] = @numbering.last + 1
|
77
|
+
end
|
78
|
+
|
79
|
+
@prev_url = url
|
80
|
+
return @numbering.join(".")
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
url = ARGV[0]
|
85
|
+
dav_url = http_url2dav_url(url)
|
86
|
+
|
87
|
+
vortex = Vortex::Connection.new(dav_url,user,pwd)
|
88
|
+
|
89
|
+
vortex.find('.',:recursive => true,:suppress_errors => true) do |item|
|
90
|
+
url = item.url.to_s
|
91
|
+
if(url =~ /\/$/ ) # Print folders onlye
|
92
|
+
collectionTitle = property(item,'.//v:collectionTitle') # Vortex folder title
|
93
|
+
resourceType = property(item,'.//v:resourceType') # Vortex folder type
|
94
|
+
http_url = dav_url2http_url(url)
|
95
|
+
responseCode = responseCode(http_url)
|
96
|
+
path = URI.parse(url).path
|
97
|
+
foldername = path[/\/([^\/]*)\/$/,1]
|
98
|
+
|
99
|
+
if(responseCode == "200" and not(foldername =~ /^[\.|_]/ or path =~ /^\/vrtx\// ) )
|
100
|
+
number = outline_number(path)
|
101
|
+
puts "#{number};#{foldername};#{http_url};#{collectionTitle}"
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
data/lib/vortex_client.rb
CHANGED
@@ -63,7 +63,7 @@ module Vortex
|
|
63
63
|
def publish(object)
|
64
64
|
if(object.is_a? HtmlArticle or object.is_a? HtmlEvent)
|
65
65
|
uri = @uri.merge(object.url)
|
66
|
-
# puts "DEBUG: '" + object.properties
|
66
|
+
# puts "DEBUG: '" + object.class.to_s + "=" + object.properties
|
67
67
|
self.put_string(uri, object.content)
|
68
68
|
self.proppatch(uri, object.properties)
|
69
69
|
return uri.to_s
|
@@ -82,7 +82,6 @@ module Vortex
|
|
82
82
|
def create(object)
|
83
83
|
if(object.is_a? Collection)
|
84
84
|
uri = @uri.merge(object.url)
|
85
|
-
# puts "DEBUG: uri: " + uri.to_s
|
86
85
|
self.mkdir(uri)
|
87
86
|
self.proppatch(uri, object.properties)
|
88
87
|
return uri.to_s
|
@@ -106,7 +105,6 @@ module Vortex
|
|
106
105
|
# Named PlainFile so it won't get mixed up with standard File class.
|
107
106
|
end
|
108
107
|
|
109
|
-
|
110
108
|
# Plain HTML files with title, introduction and keywords set as webdav properties.
|
111
109
|
#
|
112
110
|
# Examples:
|
@@ -117,13 +115,17 @@ module Vortex
|
|
117
115
|
# vortex.publish(article)
|
118
116
|
class HtmlArticle < PlainFile
|
119
117
|
|
120
|
-
attr_accessor :title, :introduction, :body, :filename, :modifiedDate, :publishedDate, :owner, :url, :author, :date, :tags
|
118
|
+
attr_accessor :title, :introduction, :body, :filename, :modifiedDate, :publishedDate, :owner, :url, :author, :date, :tags, :picture
|
121
119
|
|
122
120
|
# Create a new article of type html-article: plain html file with introduction stored as a webdav property.
|
123
121
|
def initialize(options={})
|
124
122
|
options.each{|k,v|send("#{k}=",v)}
|
125
123
|
end
|
126
124
|
|
125
|
+
def to_s
|
126
|
+
"#<Vortex::HtmlArticle "+instance_variables.collect{|var|var+": "+instance_variable_get(var).to_s}.join(",")+">"
|
127
|
+
end
|
128
|
+
|
127
129
|
def url
|
128
130
|
if(@url)
|
129
131
|
@url
|
@@ -163,106 +165,11 @@ module Vortex
|
|
163
165
|
'<v:propertiesLastModified xmlns:v="vrtx">' + date + '</v:propertiesLastModified>' +
|
164
166
|
'<v:creationTime xmlns:v="vrtx">' + date + '</v:creationTime>'
|
165
167
|
end
|
166
|
-
if(title)
|
167
|
-
props += '<v:userTitle xmlns:v="vrtx">' + title + '</v:userTitle>'
|
168
|
-
end
|
169
|
-
if(owner)
|
170
|
-
props += '<owner xmlns="vrtx">' + owner + '</owner>'
|
171
|
-
end
|
172
|
-
if(introduction and introduction != "")
|
173
|
-
props += '<introduction xmlns="vrtx">' + introduction + '</introduction>'
|
174
|
-
end
|
175
|
-
if(author and author != "")
|
176
|
-
props += '<v:authors xmlns:v="vrtx">' +
|
177
|
-
'<vrtx:values xmlns:vrtx="http://vortikal.org/xml-value-list">' +
|
178
|
-
'<vrtx:value>' + author + '</vrtx:value>' +
|
179
|
-
'</vrtx:values>' +
|
180
|
-
'</v:authors>'
|
181
|
-
end
|
182
|
-
|
183
|
-
if(tags and tags.kind_of?(Array) and tags.size > 0)
|
184
|
-
props += '<v:tags xmlns:v="vrtx">' +
|
185
|
-
'<vrtx:values xmlns:vrtx="http://vortikal.org/xml-value-list">'
|
186
|
-
tags.each do |tag|
|
187
|
-
props += "<vrtx:value>#{tag}</vrtx:value>"
|
188
|
-
end
|
189
|
-
props += '</vrtx:values></v:tags>'
|
190
|
-
end
|
191
|
-
|
192
|
-
return props
|
193
|
-
end
|
194
168
|
|
195
|
-
|
196
|
-
|
197
|
-
'"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' +
|
198
|
-
'<html xmlns="http://www.w3.org/1999/xhtml"><head><title>' + title + '</title>' +
|
199
|
-
' <link href="http://www.uio.no/profil/kupu/kupucontentstyles.css" type="text/css" rel="stylesheet"/>' +
|
200
|
-
'</head><body>'
|
201
|
-
if(body)
|
202
|
-
content += body
|
169
|
+
if(picture)
|
170
|
+
props += '<v:picture xmlns:v="vrtx">' + picture + '</v:picture>'
|
203
171
|
end
|
204
|
-
content += '</body></html>'
|
205
|
-
end
|
206
|
-
|
207
|
-
end
|
208
|
-
|
209
|
-
|
210
|
-
# Plain HTML files with title, introduction and keywords set as webdav properties.
|
211
|
-
#
|
212
|
-
# Examples:
|
213
|
-
#
|
214
|
-
# article = HtmlArticle.new(:title => "Sample Title",
|
215
|
-
# :introduction => "Introduction",
|
216
|
-
# :body => "<p>Hello world</p>")
|
217
|
-
# vortex.publish(article)
|
218
|
-
class HtmlArticle < PlainFile
|
219
172
|
|
220
|
-
attr_accessor :title, :introduction, :body, :filename, :modifiedDate, :publishedDate, :owner, :url, :author, :date, :tags
|
221
|
-
|
222
|
-
# Create a new article of type html-article: plain html file with introduction stored as a webdav property.
|
223
|
-
def initialize(options={})
|
224
|
-
options.each{|k,v|send("#{k}=",v)}
|
225
|
-
end
|
226
|
-
|
227
|
-
def url
|
228
|
-
if(@url)
|
229
|
-
@url
|
230
|
-
else
|
231
|
-
if(filename)
|
232
|
-
filename
|
233
|
-
end
|
234
|
-
if(title)
|
235
|
-
StringUtils.create_filename(title) + ".html"
|
236
|
-
else
|
237
|
-
warn "Article must have either a full url or title. "
|
238
|
-
end
|
239
|
-
end
|
240
|
-
end
|
241
|
-
|
242
|
-
def properties
|
243
|
-
props = '<v:resourceType xmlns:v="vrtx">article</v:resourceType>' +
|
244
|
-
'<v:xhtml10-type xmlns:v="vrtx">article</v:xhtml10-type>' +
|
245
|
-
'<v:userSpecifiedCharacterEncoding xmlns:v="vrtx">utf-8</v:userSpecifiedCharacterEncoding>'
|
246
|
-
|
247
|
-
if(@publishedDate and @publishedDate != "")
|
248
|
-
if(@publishedDate.kind_of? Time)
|
249
|
-
@publishedDate = @publishedDate.httpdate.to_s
|
250
|
-
end
|
251
|
-
props += '<v:published-date xmlns:v="vrtx">' + @publishedDate + '</v:published-date>'
|
252
|
-
end
|
253
|
-
|
254
|
-
if(date and date != "")
|
255
|
-
if(date.kind_of? Time)
|
256
|
-
date = @date.httpdate.to_s
|
257
|
-
end
|
258
|
-
if(@publishedDate == nil or @publishedDate != "")
|
259
|
-
props += '<v:published-date xmlns:v="vrtx">' + date + '</v:published-date>'
|
260
|
-
end
|
261
|
-
props += '<d:getlastmodified>' + date + '</d:getlastmodified>' +
|
262
|
-
'<v:contentLastModified xmlns:v="vrtx">' + date + '</v:contentLastModified>' +
|
263
|
-
'<v:propertiesLastModified xmlns:v="vrtx">' + date + '</v:propertiesLastModified>' +
|
264
|
-
'<v:creationTime xmlns:v="vrtx">' + date + '</v:creationTime>'
|
265
|
-
end
|
266
173
|
if(title)
|
267
174
|
props += '<v:userTitle xmlns:v="vrtx">' + title + '</v:userTitle>'
|
268
175
|
end
|
@@ -333,6 +240,10 @@ module Vortex
|
|
333
240
|
options.each{|k,v|send("#{k}=",v)}
|
334
241
|
end
|
335
242
|
|
243
|
+
def to_s
|
244
|
+
"#<Vortex::HtmlEvent "+instance_variables.collect{|var|var+": "+instance_variable_get(var).to_s}.join(",")+">"
|
245
|
+
end
|
246
|
+
|
336
247
|
def url
|
337
248
|
if(@url)
|
338
249
|
@url
|
@@ -445,6 +356,10 @@ module Vortex
|
|
445
356
|
options.each{|k,v|send("#{k}=",v)}
|
446
357
|
end
|
447
358
|
|
359
|
+
def to_s
|
360
|
+
"#<Vortex::StructuredArticle "+instance_variables.collect{|var|var+": "+instance_variable_get(var).to_s}.join(",")+">"
|
361
|
+
end
|
362
|
+
|
448
363
|
def dav_properties
|
449
364
|
"<xml todo>"
|
450
365
|
end
|
@@ -481,6 +396,10 @@ module Vortex
|
|
481
396
|
options.each{|k,v|send("#{k}=",v)}
|
482
397
|
end
|
483
398
|
|
399
|
+
def to_s
|
400
|
+
"#<Vortex::Collection "+instance_variables.collect{|var|var+": "+instance_variable_get(var).to_s}.join(",")+">"
|
401
|
+
end
|
402
|
+
|
484
403
|
def properties()
|
485
404
|
# props = "<v:resourceType xmlns:v=\"vrtx\">collection</v:resourceType>" +
|
486
405
|
# "<v:collection-type xmlns:v=\"vrtx\">article-listing</v:collection-type>"
|
@@ -499,6 +418,16 @@ module Vortex
|
|
499
418
|
|
500
419
|
end
|
501
420
|
|
421
|
+
# Article listing collection
|
422
|
+
#
|
423
|
+
# Examaple:
|
424
|
+
#
|
425
|
+
# collection = ArticleListingCollection(:url => 'news')
|
426
|
+
# collection = ArticleListingCollection(:foldername => 'news')
|
427
|
+
# collection = ArticleListingCollection(:title => 'My articles')
|
428
|
+
# collection = ArticleListingCollection(:title => 'My articles',
|
429
|
+
# :foldername => 'articles',
|
430
|
+
# :navigationTitle => 'Read articles')
|
502
431
|
class ArticleListingCollection < Collection
|
503
432
|
|
504
433
|
def properties()
|
data/test/test_acl.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
# Extensions to Net::DAV::Item class:
|
5
|
+
class Net::DAV::Item
|
6
|
+
|
7
|
+
def method_missing(sym, *args, &block)
|
8
|
+
require 'pp'
|
9
|
+
pp sym.to_s
|
10
|
+
pp args[0]
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
class TestVortexTags < Test::Unit::TestCase
|
16
|
+
include Vortex
|
17
|
+
|
18
|
+
def setup
|
19
|
+
if(not(@vortex))
|
20
|
+
user = ENV['DAVUSER']
|
21
|
+
pass = ENV['DAVPASS']
|
22
|
+
@vortex = Vortex::Connection.new("https://vortex-dav.uio.no/",user, pass)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
should "read access control lists for resource" do
|
27
|
+
|
28
|
+
@vortex.cd('/brukere/thomasfl/nyheter/')
|
29
|
+
@vortex.find('.', :filename => "my-sample-title.html") do |item|
|
30
|
+
require 'pp'
|
31
|
+
pp item
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
class TestVortexPictures < Test::Unit::TestCase
|
5
|
+
include Vortex
|
6
|
+
|
7
|
+
def setup
|
8
|
+
if(not(@vortex))
|
9
|
+
user = ENV['DAVUSER']
|
10
|
+
pass = ENV['DAVPASS']
|
11
|
+
@vortex = Vortex::Connection.new("https://vortex-dav.uio.no/",user, pass)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
should "publish articles with main image" do
|
16
|
+
url = 'https://vortex-dav.uio.no/brukere/thomasfl/nyheter/my-sample-title.html'
|
17
|
+
if(@vortex.exists?(url))
|
18
|
+
@vortex.delete(url)
|
19
|
+
end
|
20
|
+
|
21
|
+
@vortex.cd('/brukere/thomasfl/nyheter/')
|
22
|
+
article = Vortex::HtmlArticle.new(:title => "My Sample Title", :introduction => "Introduction",
|
23
|
+
:body => "<p>Hello world</p>", :picture => "/brukere/thomasfl/nyheter/fysikkstand.jpg")
|
24
|
+
published_url = @vortex.publish(article)
|
25
|
+
assert @vortex.exists?(published_url)
|
26
|
+
assert published_url == url
|
27
|
+
|
28
|
+
props = @vortex.propfind(published_url)
|
29
|
+
# assert props =~ /v:picture/
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
class TestVortexTags < Test::Unit::TestCase
|
5
|
+
include Vortex
|
6
|
+
|
7
|
+
def setup
|
8
|
+
if(not(@vortex))
|
9
|
+
user = ENV['DAVUSER']
|
10
|
+
pass = ENV['DAVPASS']
|
11
|
+
@vortex = Vortex::Connection.new("https://vortex-dav.uio.no/",user, pass)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
should "publish articles with tags" do
|
16
|
+
url = 'https://vortex-dav.uio.no/brukere/thomasfl/nyheter/my-sample-title.html'
|
17
|
+
if(@vortex.exists?(url))
|
18
|
+
@vortex.delete(url)
|
19
|
+
end
|
20
|
+
|
21
|
+
@vortex.cd('/brukere/thomasfl/nyheter/')
|
22
|
+
article = Vortex::HtmlArticle.new(:title => "My Sample Title", :introduction => "Introduction",
|
23
|
+
:body => "<p>Hello world</p>", :tags => ['tag 1','tag 2','tag 3'])
|
24
|
+
published_url = @vortex.publish(article)
|
25
|
+
assert @vortex.exists?(published_url)
|
26
|
+
assert published_url == url
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
class TestVortexClientUtils < Test::Unit::TestCase
|
5
|
+
include Vortex
|
6
|
+
|
7
|
+
should "make sentence in to valid url withthout any url encoding" do
|
8
|
+
assert_equal "hei-pa-deg", StringUtils.create_filename("Hei på deg")
|
9
|
+
assert StringUtils.create_filename('áàâäãÃÄÂÀ') =~ /^a*$/
|
10
|
+
assert StringUtils.create_filename('éèêëËÉÈÊ') =~ /^e*$/
|
11
|
+
assert StringUtils.create_filename('íìîïIÎÌ') => /^i*$/
|
12
|
+
assert StringUtils.create_filename('óòôöõÕÖÔÒ') => /^o*$/
|
13
|
+
|
14
|
+
# 0000000001111111111222222222233333333334
|
15
|
+
# 1234567890123456789012345678901234567890
|
16
|
+
str = 'start! to ()[]{}__@__\/?/.,"§_»_%##!!!end;:stripped'
|
17
|
+
assert_equal 'start-to-end', StringUtils.create_filename(str)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vortex_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 5
|
8
|
+
- 1
|
9
|
+
version: 0.5.1
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Thomas Flemming
|
@@ -9,39 +14,49 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date: 2010-
|
17
|
+
date: 2010-03-03 00:00:00 +01:00
|
13
18
|
default_executable: vrtx-sync
|
14
19
|
dependencies:
|
15
20
|
- !ruby/object:Gem::Dependency
|
16
21
|
name: net_dav
|
17
|
-
|
18
|
-
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
24
|
requirements:
|
21
25
|
- - ">="
|
22
26
|
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
- 4
|
30
|
+
- 1
|
23
31
|
version: 0.4.1
|
24
|
-
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
25
34
|
- !ruby/object:Gem::Dependency
|
26
35
|
name: highline
|
27
|
-
|
28
|
-
|
29
|
-
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
38
|
requirements:
|
31
39
|
- - ">="
|
32
40
|
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 1
|
43
|
+
- 5
|
44
|
+
- 1
|
33
45
|
version: 1.5.1
|
34
|
-
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id002
|
35
48
|
- !ruby/object:Gem::Dependency
|
36
49
|
name: thoughtbot-shoulda
|
37
|
-
|
38
|
-
|
39
|
-
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
40
52
|
requirements:
|
41
53
|
- - ">="
|
42
54
|
- !ruby/object:Gem::Version
|
55
|
+
segments:
|
56
|
+
- 0
|
43
57
|
version: "0"
|
44
|
-
|
58
|
+
type: :development
|
59
|
+
version_requirements: *id003
|
45
60
|
description: Utility for managing content on Vortex web content management system through webdav
|
46
61
|
email: thomas.flemming@usit.uio.no
|
47
62
|
executables:
|
@@ -59,9 +74,11 @@ files:
|
|
59
74
|
- Rakefile
|
60
75
|
- VERSION
|
61
76
|
- bin/vrtx-sync
|
77
|
+
- examples/convert_faq.rb
|
62
78
|
- examples/create_collection.rb
|
63
79
|
- examples/publish_article.rb
|
64
80
|
- examples/publish_event.rb
|
81
|
+
- examples/sitemap.rb
|
65
82
|
- lib/vortex_client.rb
|
66
83
|
- lib/vortex_client/string_utils.rb
|
67
84
|
- test/helper.rb
|
@@ -85,30 +102,38 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
85
102
|
requirements:
|
86
103
|
- - ">="
|
87
104
|
- !ruby/object:Gem::Version
|
105
|
+
segments:
|
106
|
+
- 0
|
88
107
|
version: "0"
|
89
|
-
version:
|
90
108
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
109
|
requirements:
|
92
110
|
- - ">="
|
93
111
|
- !ruby/object:Gem::Version
|
112
|
+
segments:
|
113
|
+
- 0
|
94
114
|
version: "0"
|
95
|
-
version:
|
96
115
|
requirements: []
|
97
116
|
|
98
117
|
rubyforge_project:
|
99
|
-
rubygems_version: 1.3.
|
118
|
+
rubygems_version: 1.3.6
|
100
119
|
signing_key:
|
101
120
|
specification_version: 3
|
102
121
|
summary: Vortex CMS client
|
103
122
|
test_files:
|
104
123
|
- test/helper.rb
|
124
|
+
- test/test_acl.rb
|
105
125
|
- test/test_date_conversion.rb
|
106
126
|
- test/test_vortex_article_publish.rb
|
107
127
|
- test/test_vortex_client.rb
|
108
128
|
- test/test_vortex_collection.rb
|
109
129
|
- test/test_vortex_event.rb
|
130
|
+
- test/test_vortex_pic.rb
|
110
131
|
- test/test_vortex_tags.rb
|
132
|
+
- test/test_vortex_tags_flymake.rb
|
111
133
|
- test/test_vortex_utils.rb
|
134
|
+
- test/test_vortex_utils_flymake.rb
|
135
|
+
- examples/convert_faq.rb
|
112
136
|
- examples/create_collection.rb
|
113
137
|
- examples/publish_article.rb
|
114
138
|
- examples/publish_event.rb
|
139
|
+
- examples/sitemap.rb
|