vortex_client 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|