3 var Mustache = require("lib/mustache");
4 var List = require("vendor/couchapp/lib/list");
5 var path = require("vendor/couchapp/lib/path").init(req);
6 var Atom = require("vendor/couchapp/lib/atom");
9 if ( 'within' in req.query ) {
10 within = Number(req.query['within']);
11 log("within: " + within);
13 within = 60 * 60 * 3; // within three hours;
15 var ts = (new Date()).getTime()/1000 - within; // convert milliseconds to seconds
17 var indexPath = path.list('nodelist','node-status',{descending:true, limit:10});
18 var feedPath = path.list('nodelist','node-status',{descending:true, limit:10, format:"atom"});
19 var commentsFeed = path.list('comments','comments',{descending:true, limit:10, format:"atom"});
21 var path_parts = req.path;
31 function check_field(query, field, def) {
33 if ( field in query ) {
35 log(field + ": " + ret);
40 function token_get(sf) {
46 var f_le = /<=|%3C=|%3c=/;
47 var f_ge = />=|%3E=|%3e=/;
49 var f_not_match = /!~/;
51 if ( sf.match(f_eq) ) {
52 fields = sf.split("==");
53 ret = [fields[0], fields[1], EQ];
54 } else if ( sf.match(f_ne) ) {
55 fields = sf.split("!=");
56 ret = [fields[0], fields[1], NE] ;
57 } else if ( sf.match(f_le) ) {
58 fields = sf.split("<=");
59 ret = [fields[0], Number(fields[1]), LE] ;
60 } else if ( sf.match(f_ge) ) {
61 fields = sf.split(">=");
62 ret = [fields[0], Number(fields[1]), GE] ;
63 } else if ( sf.match(f_not_match) ) {
64 fields = sf.split("!~");
66 ret = [fields[0], r, NOT_MATCH] ;
68 } else if ( sf.match(f_match) ) {
70 fields = sf.split("=~");
72 log("fields: " + fields);
73 //r = RegExp(fields[1]);
76 ret = [fields[0], r, MATCH] ;
83 function token_conjunction_get(sf) {
84 var f_and = /AND|%%|&&/;
92 log("sfilter: " + sf);
93 if ( sf.match(f_and) ) {
94 fields = sf.split(f_and);
97 } else if ( sf.match(f_or) ) {
98 fields = sf.split(f_or);
106 for ( var i=0; i < fields.length ; i++)
108 var t = token_get(fields[i]);
115 log("tcg:" + JSON.stringify(tcg));
119 function token_test(token, row)
124 var result_minor = true;
127 result_minor &= val == row[prop];
128 } else if ( op == NE ) {
129 result_minor &= val != row[prop];
130 } else if ( op == LE && prop in row ) {
131 result_minor &= Number(row[prop]) <= val;
132 //result_minor &= parseFloat(row[prop]) <= val;
133 } else if ( op == GE && prop in row ) {
134 //#result_minor &= Number(row[prop]) >= val;
135 result_minor &= parseFloat(row[prop]) >= val;
136 } else if ( ( op == MATCH || op == NOT_MATCH ) && prop in row ) {
137 val = new RegExp(val);
138 if ( typeof(row[prop]) == "object" ) {
140 for (var i=0; i < row[prop].length ; i++ ) {
141 if ( val.test(row[prop][i]) ) {
146 result_minor &= found;
148 result_minor &= val.test(row[prop]);
150 if ( op == NOT_MATCH ) {
151 // reverse the result if we actually want a non-match
152 result_minor = !result_minor;
155 result_minor = false;
160 function parse_filter (sfilter) {
162 log("sfilter: " + sfilter);
163 if ( sfilter == "" ) { return null; }
164 var ret = token_conjunction_get(sfilter);
165 log("tcg2: " + JSON.stringify(ret));
169 function filter_matches (row, pfilter) {
170 var result_minor = true;
172 if ( pfilter != null ) {
174 // set defaults based on conjunction type
175 if ( pfilter['type'] == AND ) {
177 } else if ( pfilter['type'] == OR ) {
181 for ( var i=0; i < pfilter['list'].length ; i++ )
183 tok = pfilter['list'][i];
184 result_minor = token_test(tok, row);
186 if (pfilter['type'] == AND ) {
187 result &= result_minor;
188 } else if ( pfilter['type'] == OR ) {
189 result |= result_minor;
192 //log("filter:" + JSON.stringify(pfilter) + " result: " + result);
197 // The provides function serves the format the client requests.
198 // The first matching format is sent, so reordering functions changes
199 // thier priority. In this case HTML is the preferred format, so it comes first.
200 provides("text", function() {
201 var row, first_row = true;
202 var skip_header = false;
203 var skip_props = {'_id' : "", '_rev' : "", '_deleted_conflicts' : '',}; // 'hardware' : '', };
205 var more_props = true;
211 var prop_start = [ "hostname", 'ts' ];
212 var prop_list = {'hostname' : '', 'ts' : ''};
213 var show = check_field(req.query, 'show', null);
215 if ( show != null ) { show = Number(show); }
221 if ( 'filter' in req.query ) {
222 pfilter = parse_filter(req.query['filter']);
223 log("pf: " + JSON.stringify(pfilter));
226 if ( 'rpmpattern' in req.query ) {
227 pattern = req.query['rpmpattern'];
228 log("found pattern");
232 if ( 'prop_list' in req.query || 'fields' in req.query ) {
233 if ( 'prop_list' in req.query ) {
234 prop_start = req.query['prop_list'].split(',');
236 prop_start = req.query['fields'].split(',');
238 prop_list = {'hostname' : '', 'ts' : ''};
239 for ( var i=0; i < prop_start.length ; i++) {
240 prop_list[prop_start[i]] = "";
244 if ( 'skip_header' in req.query ) {
248 while (row = getRow()) {
249 if ( row.key[0] < ts ) { continue; }
250 if ( show != null && count >= show ) { break; }
252 if ( first_row == true )
255 // get a list of all properties
256 for (var prop in row.value ) {
257 if ( ! (prop in prop_list) && more_props ) {
258 prop_start.push(prop);
259 prop_list[prop] = "";
262 if ( ! skip_header ) {
263 // create a header for all the data to follow
264 for (var i=0 ; i < prop_start.length ; i++) {
265 prop = prop_start[i];
266 if ( ! (prop in skip_props) ) {
267 header += prop + ',';
270 send(header.substring(0,header.length-1) + '\n');
276 if ( filter_matches(row.value, pfilter) )
278 //send(header.substring(0,-1) + '\n');
279 // Send the data that matches the filter when present
280 for (var i=0 ; i < prop_start.length ; i++) {
281 prop = prop_start[i];
282 if ( ! (prop in skip_props) )
284 if ( (prop == 'rpm_versions') && (pattern != null) && ('rpm_versions' in prop_list) ) {
285 if ( typeof(row.value['rpm_versions']) == "object" ) {
286 for (var i; i < row.value['rpm_versions'].length ; i++ ) {
287 var rpm = row.value['rpm_versions'][i].match(pattern);
288 if ( rpm ) { break; }
292 rowstring += rpm.join(' ') + ',';
298 log(typeof(row.value['rpm_versions']));
304 if ( typeof(row.value[prop]) == "object" )
306 rowstring += row.value[prop].join(" ") + ',';
308 rowstring += row.value[prop] + ',';
313 send(rowstring.substring(0,rowstring.length-1) + '\n');
320 provides("3mtl", function() {
322 // render the html head using a template
326 blogName : ddoc.blog.title,
328 commentsFeed : commentsFeed
332 design : req.path[2],
334 newPostPath : path.show("edit"),
335 assets : path.asset(),
336 nodes : List.withRows(function(row) {
337 var node = row.value;
340 name : node.hostname,
342 date : node.date_created,
343 link : path.list('node','node-page', {startkey : [row.id]}),
349 return path.older(key);
352 "10" : path.limit(10),
353 "25" : path.limit(25)
355 return Mustache.to_html(ddoc.templates.nodelist, stash, ddoc.templates.partials, List.send);