Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 525 lines (457 sloc) 18.96 kB
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
1 %%%----------------------------------------------------------------------
2 %%% File : yaws_rss.erl
3 %%% Created : 15 Dec 2004 by Torbjorn Tornkvist <tobbe@tornkvist.org>
4 %%%
5 %%% @doc A Yaws RSS feed interface.
6 %%%
558e525 Minor Edoc fixes.
Tobbe Tornquist authored
7 %%% @author Torbjorn Tornkvist <tobbe@tornkvist.org>
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
8 %%% @end
9 %%%
10 %%% $Id$
11 %%%----------------------------------------------------------------------
12 -module(yaws_rss).
13
14 -behaviour(gen_server).
15
16 %% External exports
30d2427 Added RSS config parameters ro config parser and some more documentat…
Tobbe Tornquist authored
17 -export([start/0, start_link/0, open/1, open/2, close/0, close/2,
0be3c7e @klacke untabified all of yaws
authored
18 insert/5, insert/6, insert/7, retrieve/2]).
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
19
20 -export([t_setup/0, t_exp/0, t_xopen/0]).
21
22 %% gen_server callbacks
ca1c8b1 @karlsson Fixed a number of compiler warnings and html validation errors
karlsson authored
23 -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
6e96a14 @klacke indendation cleanup
authored
24 code_change/3]).
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
25
26 -record(s, {
0be3c7e @klacke untabified all of yaws
authored
27 open_apps = [], % activated applications
28 expire = false, % false | days
29 rm_exp = false, % remove expired items
30 max=infinite, % maximum number of elements in DB
31 days=7, % maximum number of days in DB
32 counter}). % item counter
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
33
34 -define(SERVER, ?MODULE).
35 -define(DB, ?MODULE).
36 -define(DB_FNAME, "yaws_rss.dets").
30d2427 Added RSS config parameters ro config parser and some more documentat…
Tobbe Tornquist authored
37 -define(ITEM(App, Tag, Counter, Item), {{App, Tag, Counter}, Item}).
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
38
39 %%%----------------------------------------------------------------------
40 %%% API
41 %%%----------------------------------------------------------------------
42 start_link() ->
43 gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
44
45 start() ->
46 gen_server:start({local, ?SERVER}, ?MODULE, [], []).
47
48 %%%
455578a @vinoski major trailing whitespace cleanup
vinoski authored
49 %%% @spec open(App::atom()) ->
30d2427 Added RSS config parameters ro config parser and some more documentat…
Tobbe Tornquist authored
50 %%% {ok, DB::db()} | {error, string()}
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
51 %%%
52 %%% @type db(). An opaque handle leading to an RSS database.
53 %%%
455578a @vinoski major trailing whitespace cleanup
vinoski authored
54 %%% @doc See {@link open/2}
558e525 Minor Edoc fixes.
Tobbe Tornquist authored
55 %%% @end
30d2427 Added RSS config parameters ro config parser and some more documentat…
Tobbe Tornquist authored
56 open(App) ->
57 open(App, []).
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
58
59 %%%
455578a @vinoski major trailing whitespace cleanup
vinoski authored
60 %%% @spec open(App::atom(), Opts::list()) ->
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
61 %%% {ok, DB::db()} | {error, string()}
62 %%%
8af1e99 Fixing the yaws-rss functionality. Adding configure parameter rss_dir…
Tobbe Tornquist authored
63 %%% @doc Open a RSS database.
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
64 %%% Per default <em>dets</em> is used as database,
65 %%% but by using the <em>db_mod</em> option it is
558e525 Minor Edoc fixes.
Tobbe Tornquist authored
66 %%% possible to use your own database.<br/>
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
67 %%% These are the options:
68 %%% <p><dl>
69 %%%
70 %%% <dt>{db_mod, Module}</dt>
71 %%% <dd>If specified, the following functions will be
72 %%% called:<ul>
73 %%% <li>Module:open(Opts)</li>
30d2427 Added RSS config parameters ro config parser and some more documentat…
Tobbe Tornquist authored
74 %%% <li>Module:insert(App,Tag,Title,Link,Desc,Creator,GregSec)</li>
75 %%% <li>Module:retrieve(App,Tag) -&gt; {Title, Link, Desc, Creator, GregSecs}</li>
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
76 %%% <li>Module:close(DbName)</li></ul>
77 %%% This means that the default DB won't be used, and
78 %%% no expiration handling will be done. Only the producing of
79 %%% XML will thus be done. Also, the whole <em>Opts</em> will be
80 %%% passed un-interpreted to the other DB module.</dd>
81 %%%
8af1e99 Fixing the yaws-rss functionality. Adding configure parameter rss_dir…
Tobbe Tornquist authored
82 %%% <dt>{db_dir, Dir}</dt>
83 %%% <dd>Specifies the directory where the database will be created.
84 %%% Default is: /tmp</dd>
455578a @vinoski major trailing whitespace cleanup
vinoski authored
85 %%%
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
86 %%% <dt>{expire, Expire}</dt>
87 %%% <dd>Specifies what method to use to expire items. Possible values
88 %%% are: <em>false</em>, <em>days</em>, meaning
455578a @vinoski major trailing whitespace cleanup
vinoski authored
89 %%% never expire, expire after a number of days.
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
90 %%% Default is to never expire items.</dd>
455578a @vinoski major trailing whitespace cleanup
vinoski authored
91 %%%
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
92 %%% <dt>{days, Number}</dt>
93 %%% <dd>Specifies the number of days befor an item is expired.
94 %%% Default is 7 days.</dd>
95 %%%
96 %%% <dt>{rm_exp, Bool}</dt>
97 %%% <dd>Specifies if expired items should be removed from
98 %%% the database. Default is to not remove any items.</dd>
99 %%%
100 %%% <dt>{max, Number}</dt>
101 %%% <dd>Specifies the maximum number of items that should
102 %%% be stored in the database. The default in <em>infinite</em></dd>
103 %%% </dl></p>
71af10e @vinoski in open, ensure the gen_server is up before calling it
vinoski authored
104 %%% <p>If no database exist, a new one will be created.
558e525 Minor Edoc fixes.
Tobbe Tornquist authored
105 %%% The returned database handle is to be used with {@link close/1}.</p>
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
106 %%% @end
107 %%%
30d2427 Added RSS config parameters ro config parser and some more documentat…
Tobbe Tornquist authored
108 open(App, Opts) ->
71af10e @vinoski in open, ensure the gen_server is up before calling it
vinoski authored
109 %% This is called during read of yaws.conf during startup, so make sure this
110 %% server is up and running before invoking it
111 ok = wait_for_server(?SERVER),
30d2427 Added RSS config parameters ro config parser and some more documentat…
Tobbe Tornquist authored
112 gen_server:call(?SERVER, {open, App, Opts}, infinity).
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
113
114 %%%
115 %%% @spec close() -> ok | {error, string()}
116 %%%
117 %%% @doc Close the RSS database.
558e525 Minor Edoc fixes.
Tobbe Tornquist authored
118 %%% @end
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
119 close() ->
120 gen_server:call(?SERVER, {close, ?DB}, infinity).
121
122 %%%
455578a @vinoski major trailing whitespace cleanup
vinoski authored
123 %%% @spec close(DbMod::atom(), DbName::atom()) ->
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
124 %%% ok | {error, string()}
125 %%%
126 %%% @doc Close the user provided RSS database.
127 %%% A call to; <em>DbMod:close(DbName)</em> will be made.
558e525 Minor Edoc fixes.
Tobbe Tornquist authored
128 %%% @end
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
129 close(DBmod, DBname) ->
130 gen_server:call(?SERVER, {close, DBmod, DBname}, infinity).
131
132 %%%
455578a @vinoski major trailing whitespace cleanup
vinoski authored
133 %%% @spec insert(App::atom(), Tag::atom(), Title::string(),
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
134 %%% Link::string(), Desc::string()) ->
135 %%% ok | {error, string()}
136 %%%
30d2427 Added RSS config parameters ro config parser and some more documentat…
Tobbe Tornquist authored
137 %%% @doc Insert an RSS item into the <em>{App,Tag}</em> RSS feed.
138 %%% An application (App) can maintain several feeds each
139 %%% one refered to with a symbolic name (Tag).
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
140 %%% <em>Link</em> should be a URL pointing to the item.
455578a @vinoski major trailing whitespace cleanup
vinoski authored
141 %%% <p>In case another database backend is used, the
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
142 %%% <em>Tag</em> has the format: <em>{DbModule, OpaqueTag}</em>
143 %%% where <em>DbModule</em> is the database backend module
144 %%% to be called, and <em>OpaqueTag</em> the Tag that is
145 %%% used in <em>DbModule:insert(Tag, ...)</em></p>
146 %%% @end
147 %%%
30d2427 Added RSS config parameters ro config parser and some more documentat…
Tobbe Tornquist authored
148 insert(App, Tag, Title, Link, Desc) ->
149 insert(App, Tag, Title, Link, Desc, "").
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
150
151 %%%
455578a @vinoski major trailing whitespace cleanup
vinoski authored
152 %%% @spec insert(App::atom(), Tag::atom(), Title::string(),
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
153 %%% Link::string(), Desc::string(),
154 %%% Creator::string()) ->
155 %%% ok | {error, string()}
156 %%%
30d2427 Added RSS config parameters ro config parser and some more documentat…
Tobbe Tornquist authored
157 %%% @doc Works as {@link insert/5} but takes an extra argument
158 %%% <em>Creator</em> which may contains an identification
159 %%% of who created the item.
558e525 Minor Edoc fixes.
Tobbe Tornquist authored
160 %%% @end
30d2427 Added RSS config parameters ro config parser and some more documentat…
Tobbe Tornquist authored
161 insert(App, Tag, Title, Link, Desc, Creator) ->
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
162 GregSecs = calendar:datetime_to_gregorian_seconds({date(),time()}),
30d2427 Added RSS config parameters ro config parser and some more documentat…
Tobbe Tornquist authored
163 insert(App, Tag, Title, Link, Desc, Creator, GregSecs).
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
164
165 %%%
455578a @vinoski major trailing whitespace cleanup
vinoski authored
166 %%% @spec insert(App::atom(), Tag::atom(), Title::string(),
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
167 %%% Link::string(), Desc::string(),
168 %%% Creator::string(), GregSecs::integer()) ->
169 %%% ok | {error, string()}
170 %%%
30d2427 Added RSS config parameters ro config parser and some more documentat…
Tobbe Tornquist authored
171 %%% @doc Works as {@link insert/6} but takes an extra argument
172 %%% <em>GregSecs</em> which is the creation time of the item
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
173 %%% in Gregorian Seconds.
558e525 Minor Edoc fixes.
Tobbe Tornquist authored
174 %%% @end
30d2427 Added RSS config parameters ro config parser and some more documentat…
Tobbe Tornquist authored
175 insert(App, Tag, Title, Link, Desc, Creator, GregSecs) ->
176 Args = {App, Tag, Title, Link, Desc, Creator, GregSecs},
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
177 gen_server:call(?SERVER, {insert, Args}, infinity).
178
179
180 %%%
30d2427 Added RSS config parameters ro config parser and some more documentat…
Tobbe Tornquist authored
181 %%% @spec retrieve(App::atom(), Tag::atom()) ->
558e525 Minor Edoc fixes.
Tobbe Tornquist authored
182 %%% {ok, RSSContent::iolist()} |{error, string()}
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
183 %%%
558e525 Minor Edoc fixes.
Tobbe Tornquist authored
184 %%% @type ioList(). A deep list of strings and/or binaries.
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
185 %%%
186 %%% @doc Retrieve the <em>RSScontent</em> (in XML and all...)
455578a @vinoski major trailing whitespace cleanup
vinoski authored
187 %%% to be delivered to a RSS client.
188 %%% <p>In case another database backend is used, the
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
189 %%% <em>Tag</em> has the format: <em>{DbModule, OpaqueTag}</em>
190 %%% where <em>DbModule</em> is the database backend module
191 %%% to be called, and <em>OpaqueTag</em> the Tag that is
192 %%% used in <em>DbModule:retrieve(Tag)</em> which must return
193 %%% a list of tuples: <em>{Title, Link, Desc, Creator, GregSecs}</em></p>
558e525 Minor Edoc fixes.
Tobbe Tornquist authored
194 %%% @end
30d2427 Added RSS config parameters ro config parser and some more documentat…
Tobbe Tornquist authored
195 retrieve(App, Tag) ->
196 gen_server:call(?SERVER, {retrieve, App, Tag}, infinity).
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
197
198 %%%----------------------------------------------------------------------
199 %%% Callback functions from gen_server
200 %%%----------------------------------------------------------------------
201
202 %%----------------------------------------------------------------------
203 %% Func: init/1
204 %% Returns: {ok, State} |
205 %% {ok, State, Timeout} |
206 %% ignore |
207 %% {stop, Reason}
208 %%----------------------------------------------------------------------
209 init([]) ->
210 {ok, #s{}}.
211
212 %%----------------------------------------------------------------------
213 %% Func: handle_call/3
214 %% Returns: {reply, Reply, State} |
215 %% {reply, Reply, State, Timeout} |
216 %% {noreply, State} |
217 %% {noreply, State, Timeout} |
218 %% {stop, Reason, Reply, State} | (terminate/2 is called)
219 %% {stop, Reason, State} (terminate/2 is called)
220 %%----------------------------------------------------------------------
30d2427 Added RSS config parameters ro config parser and some more documentat…
Tobbe Tornquist authored
221 handle_call({open, App, Opts}, _From, State) ->
222 {NewState, Res} = do_open_dir(State, App, Opts),
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
223 {reply, Res, NewState};
224 %%
225 handle_call({close, DB}, _From, State) ->
226 dets:close(DB),
227 {reply, ok, State};
228 %%
229 handle_call({close, DBMod, DBname}, _From, State) ->
230 catch apply(DBMod, close, [DBname]),
231 {reply, ok, State};
232 %%
233 handle_call({insert, Args}, _From, State) ->
234 {NewState, Res} = do_insert(State, Args),
235 {reply, Res, NewState};
236 %%
30d2427 Added RSS config parameters ro config parser and some more documentat…
Tobbe Tornquist authored
237 handle_call({retrieve, App, Tag}, _From, State) ->
238 {NewState, Res} = do_retrieve(State, App, Tag),
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
239 {reply, Res, NewState}.
240
241 %%----------------------------------------------------------------------
242 %% Func: handle_cast/2
243 %% Returns: {noreply, State} |
244 %% {noreply, State, Timeout} |
245 %% {stop, Reason, State} (terminate/2 is called)
246 %%----------------------------------------------------------------------
247 handle_cast(_Msg, State) ->
248 {noreply, State}.
249
250 %%----------------------------------------------------------------------
251 %% Func: handle_info/2
252 %% Returns: {noreply, State} |
253 %% {noreply, State, Timeout} |
254 %% {stop, Reason, State} (terminate/2 is called)
255 %%----------------------------------------------------------------------
256 handle_info(_Info, State) ->
257 {noreply, State}.
258
259 %%----------------------------------------------------------------------
260 %% Func: terminate/2
261 %% Purpose: Shutdown the server
262 %% Returns: any (ignored by gen_server)
263 %%----------------------------------------------------------------------
264 terminate(_Reason, _State) ->
265 ok.
266
ca1c8b1 @karlsson Fixed a number of compiler warnings and html validation errors
karlsson authored
267 %%----------------------------------------------------------------------
268 %% Func: code_change/3
269 %% Purpose: Handle upgrade
270 %% Returns: new State data
271 %%----------------------------------------------------------------------
272 code_change(_OldVsn, Data, _Extra) ->
273 {ok, Data}.
274
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
275 %%%----------------------------------------------------------------------
276 %%% Internal functions
277 %%%----------------------------------------------------------------------
278
455578a @vinoski major trailing whitespace cleanup
vinoski authored
279 %%%
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
280 %%% Check what database store that should be used.
281 %%% Per default 'dets' is used.
282 %%%
455578a @vinoski major trailing whitespace cleanup
vinoski authored
283 do_open_dir(State, App, Opts) ->
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
284 case get_db_mod(Opts, dets) of
455578a @vinoski major trailing whitespace cleanup
vinoski authored
285 dets ->
0be3c7e @klacke untabified all of yaws
authored
286 File = get_db_file(Opts),
455578a @vinoski major trailing whitespace cleanup
vinoski authored
287 Expire = get_expire(Opts, #s.expire),
288 Max = get_max(Opts, #s.max),
289 Days = get_days(Opts, #s.days),
290 RmExp = get_rm_exp(Opts, #s.rm_exp),
0be3c7e @klacke untabified all of yaws
authored
291 case dets:is_dets_file(File) of
455578a @vinoski major trailing whitespace cleanup
vinoski authored
292 false ->
0be3c7e @klacke untabified all of yaws
authored
293 {State, {error, "not a proper dets file"}};
294 _ ->
295 case catch dets:open_file(?DB, [{file, File}]) of
455578a @vinoski major trailing whitespace cleanup
vinoski authored
296 {ok,DB} = Res ->
0be3c7e @klacke untabified all of yaws
authored
297 {State#s{
298 open_apps = u_insert(App, State#s.open_apps),
455578a @vinoski major trailing whitespace cleanup
vinoski authored
299 expire = Expire,
0be3c7e @klacke untabified all of yaws
authored
300 days = Days,
301 rm_exp = RmExp,
302 max = Max,
455578a @vinoski major trailing whitespace cleanup
vinoski authored
303 counter = init_counter(DB)},
0be3c7e @klacke untabified all of yaws
authored
304 Res};
455578a @vinoski major trailing whitespace cleanup
vinoski authored
305 {error, _Reason} ->
0be3c7e @klacke untabified all of yaws
authored
306 {State, {error, "open dets file"}}
307 end
308 end;
309 DBmod ->
310 {State, catch apply(DBmod, open, Opts)}
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
311 end.
312
8af1e99 Fixing the yaws-rss functionality. Adding configure parameter rss_dir…
Tobbe Tornquist authored
313 get_db_file(Opts) ->
314 Dir = get_db_dir(Opts, "/tmp"),
315 Dir ++ "/" ++ a2l(?DB) ++ ".dets".
316
fbf6580 Yaws is now RSS capable, see doc/README.rss
Tobbe Tornquist authored
317 init_counter(DB) ->
318 case dets:lookup(DB, counter) of
0be3c7e @klacke untabified all of yaws
authored
319 [] -> dets:insert(DB, {counter, 0}), 0;
320 [{counter,N}] -> N
fbf6580 Yaws is now RSS capable, see doc/README.rss
Tobbe Tornquist authored
321 end.
322
323 set_counter(DB, N) ->
324 dets:insert(DB, {counter, N}).
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
325
30d2427 Added RSS config parameters ro config parser and some more documentat…
Tobbe Tornquist authored
326 do_insert(State, {App, {DbMod,Tag}, Title, Link, Desc, Creator, GregSecs}) ->
327 {State, catch apply(DbMod, insert, [App, Tag,Title,Link,Desc,Creator,GregSecs])};
328 do_insert(State, {App, Tag, Title, Link, Desc, Creator, GregSecs}) ->
329 case lists:member(App, State#s.open_apps) of
0be3c7e @klacke untabified all of yaws
authored
330 true ->
455578a @vinoski major trailing whitespace cleanup
vinoski authored
331 Counter = if (State#s.max > 0) ->
0be3c7e @klacke untabified all of yaws
authored
332 (State#s.counter + 1) rem State#s.max;
455578a @vinoski major trailing whitespace cleanup
vinoski authored
333 true ->
0be3c7e @klacke untabified all of yaws
authored
334 State#s.counter + 1
335 end,
336 Item = {Title, Link, Desc, Creator, GregSecs},
337 Res = dets:insert(?DB, ?ITEM(App, Tag, Counter, Item)),
338 set_counter(?DB, Counter),
339 {State#s{counter = Counter}, Res};
340 false ->
341 {State, {error, "no open DB"}}
30d2427 Added RSS config parameters ro config parser and some more documentat…
Tobbe Tornquist authored
342 end.
343
344
345 do_retrieve(State, App, {DbMod,Tag}) ->
346 {State, catch apply(DbMod, retrieve, [App, Tag])};
347 do_retrieve(State, App, Tag) ->
348 case lists:member(App, State#s.open_apps) of
0be3c7e @klacke untabified all of yaws
authored
349 true ->
455578a @vinoski major trailing whitespace cleanup
vinoski authored
350 F = fun(?ITEM(Xa, Xt, _Counter, Item), Acc) when Xa == App, Xt == Tag ->
0be3c7e @klacke untabified all of yaws
authored
351 [Item|Acc];
455578a @vinoski major trailing whitespace cleanup
vinoski authored
352 (_, Acc) ->
0be3c7e @klacke untabified all of yaws
authored
353 Acc
354 end,
355 Items = sort_items(expired(State, dets:foldl(F, [], ?DB))),
356 Xml = to_xml(Items),
357 {State, {ok, Xml}};
358 false ->
359 {State, {error, "no open DB"}}
30d2427 Added RSS config parameters ro config parser and some more documentat…
Tobbe Tornquist authored
360 end.
6e96a14 @klacke indendation cleanup
authored
361
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
362
363
364 -define(ONE_DAY, 86400). % 24*60*60 seconds
365 -define(X(GregSecs), {Title, Link, Desc, Creator, GregSecs}).
366
367 %%% Filter away expired items !!
368 expired(State, List) when State#s.expire == days ->
369 Gs = calendar:datetime_to_gregorian_seconds({date(),time()}),
370 Old = Gs - (?ONE_DAY * State#s.days),
371 F = fun(?X(GregSecs), Acc) when GregSecs > Old ->
0be3c7e @klacke untabified all of yaws
authored
372 [?X(GregSecs) | Acc];
373 (_, Acc) ->
374 Acc
375 end,
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
376 lists:foldl(F, [], List);
377 expired(_State, List) ->
378 List.
379
380 -undef(X).
381
382
383
384 %%%
385 %%% Sort on creation date !!
386 %%% Item = {Title, Link, Desc, Creator, GregSecs},
387 %%%
388 sort_items(Is) ->
389 lists:keysort(5,Is).
390
391
392 to_xml([{Title, Link, Desc, Creator, GregSecs}|Tail]) ->
b6717e7 Fixed the RSS date format, as suggested by Daniel Kaminski.
Tobbe Tornquist authored
393 Date = w3cdtf(GregSecs),
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
394 [["<item>\n",
6938f5c The generated content was not valid RSS 2.0 content. This is fixed now.
Tobbe Tornquist authored
395 "<title>", yaws_api:htmlize(Title), "</title>\n",
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
396 "<link>", Link, "</link>\n",
6938f5c The generated content was not valid RSS 2.0 content. This is fixed now.
Tobbe Tornquist authored
397 "<guid>", Link, "</guid>\n",
398 "<description>", yaws_api:htmlize(Desc), "</description>\n",
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
399 "<dc:creator>", Creator, "</dc:creator>\n",
400 "<dc:date>", Date, "</dc:date>\n",
455578a @vinoski major trailing whitespace cleanup
vinoski authored
401 "</item>\n"] |
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
402 to_xml(Tail)];
455578a @vinoski major trailing whitespace cleanup
vinoski authored
403 to_xml([]) ->
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
404 [].
405
9ea2690 Cleaned up w3cdtf-date function by Daniel Kaminski.
Tobbe Tornquist authored
406 %%%
407 %%% Create W3CDTF (http://www.w3.org/TR/NOTE-datetime) formatted date
408 %%% w3cdtf(GregSecs) -> "YYYY-MM-DDThh:mm:ssTZD"
409 %%%
410 w3cdtf(GregSecs) -> Date = calendar:gregorian_seconds_to_datetime(GregSecs),
6e96a14 @klacke indendation cleanup
authored
411 {{Y, Mo, D},{H, Mi, S}} = Date,
412 [UDate|_] = calendar:local_time_to_universal_time_dst(Date),
413 {DiffD,{DiffH,DiffMi,_}}=calendar:time_difference(UDate,Date),
455578a @vinoski major trailing whitespace cleanup
vinoski authored
414 w3cdtf_diff(Y, Mo, D, H, Mi, S, DiffD, DiffH, DiffMi).
9ea2690 Cleaned up w3cdtf-date function by Daniel Kaminski.
Tobbe Tornquist authored
415
416 %%% w3cdtf's helper function
417 w3cdtf_diff(Y, Mo, D, H, Mi, S, _DiffD, DiffH, DiffMi) when DiffH < 12, DiffH /= 0 ->
418 i2l(Y) ++ "-" ++ add_zero(Mo) ++ "-" ++ add_zero(D) ++ "T" ++
419 add_zero(H) ++ ":" ++ add_zero(Mi) ++ ":" ++
420 add_zero(S) ++ "+" ++ add_zero(DiffH) ++ ":" ++ add_zero(DiffMi);
421
422 w3cdtf_diff(Y, Mo, D, H, Mi, S, DiffD, DiffH, DiffMi) when DiffH > 12, DiffD == 0 ->
423 i2l(Y) ++ "-" ++ add_zero(Mo) ++ "-" ++ add_zero(D) ++ "T" ++
424 add_zero(H) ++ ":" ++ add_zero(Mi) ++ ":" ++
425 add_zero(S) ++ "+" ++ add_zero(DiffH) ++ ":" ++
426 add_zero(DiffMi);
427
428 w3cdtf_diff(Y, Mo, D, H, Mi, S, DiffD, DiffH, DiffMi) when DiffH > 12, DiffD /= 0, DiffMi /= 0 ->
429 i2l(Y) ++ "-" ++ add_zero(Mo) ++ "-" ++ add_zero(D) ++ "T" ++
430 add_zero(H) ++ ":" ++ add_zero(Mi) ++ ":" ++
431 add_zero(S) ++ "-" ++ add_zero(23-DiffH) ++
432 ":" ++ add_zero(60-DiffMi);
433
434 w3cdtf_diff(Y, Mo, D, H, Mi, S, DiffD, DiffH, DiffMi) when DiffH > 12, DiffD /= 0, DiffMi == 0 ->
6e96a14 @klacke indendation cleanup
authored
435 i2l(Y) ++ "-" ++ add_zero(Mo) ++ "-" ++ add_zero(D) ++ "T" ++
9ea2690 Cleaned up w3cdtf-date function by Daniel Kaminski.
Tobbe Tornquist authored
436 add_zero(H) ++ ":" ++ add_zero(Mi) ++ ":" ++
437 add_zero(S) ++ "-" ++ add_zero(24-DiffH) ++
455578a @vinoski major trailing whitespace cleanup
vinoski authored
438 ":" ++ add_zero(DiffMi);
9ea2690 Cleaned up w3cdtf-date function by Daniel Kaminski.
Tobbe Tornquist authored
439
440 w3cdtf_diff(Y, Mo, D, H, Mi, S, _DiffD, DiffH, _DiffMi) when DiffH == 0 ->
441 i2l(Y) ++ "-" ++ add_zero(Mo) ++ "-" ++ add_zero(D) ++ "T" ++
442 add_zero(H) ++ ":" ++ add_zero(Mi) ++ ":" ++
443 add_zero(S) ++ "Z".
444
f44be6a @klacke all calls to old deprecated guard tests removed
authored
445 add_zero(I) when is_integer(I) -> add_zero(i2l(I));
9ea2690 Cleaned up w3cdtf-date function by Daniel Kaminski.
Tobbe Tornquist authored
446 add_zero([A]) -> [$0,A];
455578a @vinoski major trailing whitespace cleanup
vinoski authored
447 add_zero(L) when is_list(L) -> L.
081c135 Updated the RSS date format, as suggested by Daniel Kaminski.
Tobbe Tornquist authored
448
b6717e7 Fixed the RSS date format, as suggested by Daniel Kaminski.
Tobbe Tornquist authored
449
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
450
451 get_db_mod(Opts, Def) -> lkup(db_mod, Opts, Def).
8af1e99 Fixing the yaws-rss functionality. Adding configure parameter rss_dir…
Tobbe Tornquist authored
452 get_db_dir(Opts, Def) -> lkup(db_dir, Opts, Def).
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
453 get_expire(Opts, Def) -> lkup(expire, Opts, Def).
454 get_max(Opts, Def) -> lkup(max, Opts, Def).
455578a @vinoski major trailing whitespace cleanup
vinoski authored
455 get_days(Opts, Def) -> lkup(days, Opts, Def).
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
456 get_rm_exp(Opts, Def ) -> lkup(rm_exp, Opts, Def).
457
458 lkup(Key, List, Def) ->
459 case lists:keysearch(Key, 1, List) of
0be3c7e @klacke untabified all of yaws
authored
460 {value,{_,Value}} -> Value;
461 _ -> Def
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
462 end.
463
464
30d2427 Added RSS config parameters ro config parser and some more documentat…
Tobbe Tornquist authored
465 u_insert(H, [H|T]) -> T;
466 u_insert(E, [H|T]) -> [H|u_insert(E,T)];
467 u_insert(E, []) -> [E].
468
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
469
2f8a8c6 @tuncer Fix unused clause Dialyzer warnings in yaws_rss
tuncer authored
470 i2l(I) when is_integer(I) -> integer_to_list(I).
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
471
2f8a8c6 @tuncer Fix unused clause Dialyzer warnings in yaws_rss
tuncer authored
472 a2l(A) when is_atom(A) -> atom_to_list(A).
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
473
6e96a14 @klacke indendation cleanup
authored
474
475
476
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
477 t_setup() ->
fbf6580 Yaws is now RSS capable, see doc/README.rss
Tobbe Tornquist authored
478 %%open([{db_file, "yaws_rss.dets"}, {max,7}]),
30d2427 Added RSS config parameters ro config parser and some more documentat…
Tobbe Tornquist authored
479 insert(test,xml,"Normalizing XML, Part 2",
0be3c7e @klacke untabified all of yaws
authored
480 "http://www.xml.com/pub/a/2002/12/04/normalizing.html",
481 "In this second and final look at applying relational "
482 "normalization techniques to W3C XML Schema data modeling, "
483 "Will Provost discusses when not to normalize, the scope "
484 "of uniqueness and the fourth and fifth normal forms."),
30d2427 Added RSS config parameters ro config parser and some more documentat…
Tobbe Tornquist authored
485 insert(test,xml,"The .NET Schema Object Model",
0be3c7e @klacke untabified all of yaws
authored
486 "http://www.xml.com/pub/a/2002/12/04/som.html",
487 "Priya Lakshminarayanan describes in detail the use of "
488 "the .NET Schema Object Model for programmatic manipulation "
489 "of W3C XML Schemas."),
30d2427 Added RSS config parameters ro config parser and some more documentat…
Tobbe Tornquist authored
490 insert(test,xml,"SVG's Past and Promising Future",
0be3c7e @klacke untabified all of yaws
authored
491 "http://www.xml.com/pub/a/2002/12/04/svg.html",
492 "In this month's SVG column, Antoine Quint looks back at "
493 "SVG's journey through 2002 and looks forward to 2003.").
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
494
495
496 t_exp() ->
497 %%open([{db_file, "yaws_rss.dets"}, {expire,days}]),
30d2427 Added RSS config parameters ro config parser and some more documentat…
Tobbe Tornquist authored
498 insert(test,xml,"Expired article",
0be3c7e @klacke untabified all of yaws
authored
499 "http://www.xml.com/pub/a/2002/12/04/normalizing.html",
500 "In this second and final look at applying relational "
501 "normalization techniques to W3C XML Schema data modeling, "
502 "Will Provost discusses when not to normalize, the scope "
503 "of uniqueness and the fourth and fifth normal forms.",
6e96a14 @klacke indendation cleanup
authored
504 "tobbe",
505 63269561882). % 6/12-2004
6e45786 Added RSS store/interface.
Tobbe Tornquist authored
506
507 t_xopen() ->
455578a @vinoski major trailing whitespace cleanup
vinoski authored
508 open([{db_file, "yaws_rss.dets"},
0be3c7e @klacke untabified all of yaws
authored
509 {expire,days},
510 {days, 20}]).
71af10e @vinoski in open, ensure the gen_server is up before calling it
vinoski authored
511
512 wait_for_server(Server) ->
513 wait_for_server(Server, 20).
514
515 wait_for_server(_Server, 0) ->
516 {error, timeout};
517 wait_for_server(Server, N) ->
518 case erlang:whereis(Server) of
519 undefined ->
520 receive after 500 -> ok end,
521 wait_for_server(Server, N-1);
522 _ ->
523 ok
524 end.
Something went wrong with that request. Please try again.