1 /*
2 * http.c for owhttpd (1-wire web server)
3 * By Paul Alfille 2003, using libow
4 * offshoot of the owfs ( 1wire file system )
5 *
6 * GPL license ( Gnu Public Lincense )
7 *
8 * Based on chttpd. copyright(c) 0x7d0 greg olszewski <noop@nwonknu.org>
9 *
10 */
11
12 #include "owhttpd.h"
13
14 // #include <libgen.h> /* for dirname() */
15
16 /* --------------- Prototypes---------------- */
17 static void Show(struct OutputControl * oc, const struct parsedname *pn_entry);
18 static void ShowDirectory(struct OutputControl * oc, const struct parsedname *pn_entry);
19 static void ShowReadWrite(struct OutputControl * oc, struct one_wire_query *owq);
20 static void ShowReadonly(struct OutputControl * oc, struct one_wire_query *owq);
21 static void ShowWriteonly(struct OutputControl * oc, struct one_wire_query *owq);
22 static void ShowStructure(struct OutputControl * oc, struct one_wire_query *owq);
23 static void StructureDetail(struct OutputControl * oc, const char * structure_details );
24 static void Upload( struct OutputControl * oc, const struct parsedname * pn ) ;
25 static void Extension( struct OutputControl * oc, const struct parsedname * pn ) ;
26
27 static void ShowText(struct OutputControl * oc, const struct parsedname *pn_entry);
28 static void ShowTextDirectory(struct OutputControl * oc, const struct parsedname *pn_entry);
29 static void ShowTextReadWrite(struct OutputControl * oc, struct one_wire_query *owq);
30 static void ShowTextReadonly(struct OutputControl * oc, struct one_wire_query *owq);
31 static void ShowTextWriteonly(struct OutputControl * oc, struct one_wire_query *owq);
32 static void ShowTextStructure(struct OutputControl * oc, struct one_wire_query *owq);
33
34 static void ShowJson(struct OutputControl * oc, const struct parsedname *pn_entry);
35 static void ShowJsonDirectory(struct OutputControl * oc, const struct parsedname *pn_entry);
36 static void ShowJsonReadWrite(struct OutputControl * oc, struct one_wire_query *owq);
37 static void ShowJsonReadonly(struct OutputControl * oc, struct one_wire_query *owq);
38 static void ShowJsonWriteonly(struct OutputControl * oc, struct one_wire_query *owq);
39 static void ShowJsonStructure(struct OutputControl * oc, struct one_wire_query *owq);
40 static void StructureDetailJson(struct OutputControl * oc, const char * structure_details );
41
42 /* --------------- Functions ---------------- */
43
44 /* Device entry -- table line for a filetype */
Show(struct OutputControl * oc,const struct parsedname * pn_entry)45 static void Show(struct OutputControl * oc, const struct parsedname *pn_entry)
46 {
47 FILE * out = oc->out ;
48 struct one_wire_query *owq = OWQ_create_from_path(pn_entry->path); // for read or dir
49 struct filetype * ft = pn_entry->selected_filetype ;
50 /* Left column */
51 fprintf(out, "<TR><TD><B>%s</B></TD><TD>", FS_DirName(pn_entry));
52
53 if (owq == NO_ONE_WIRE_QUERY) {
54 fprintf(out, "<B>Memory exhausted</B>");
55 } else if ( BAD( OWQ_allocate_read_buffer(owq)) ) {
56 fprintf(out, "<B>Memory exhausted</B>");
57 } else if (ft == NO_FILETYPE) {
58 ShowDirectory(oc, pn_entry);
59 } else if (IsStructureDir(pn_entry)) {
60 ShowStructure(oc, owq);
61 } else if (ft->format == ft_directory || ft->format == ft_subdir) {
62 // Directory
63 ShowDirectory(oc, pn_entry);
64 } else if ( pn_entry->extension == EXTENSION_UNKNOWN && ft->ag != NON_AGGREGATE && ft->ag->combined == ag_sparse ) {
65 Extension(oc, pn_entry ) ; // flag as generic needing an extension chosen
66 } else if (ft->write == NO_WRITE_FUNCTION || Globals.readonly) {
67 // Unwritable
68 if (ft->read != NO_READ_FUNCTION) {
69 ShowReadonly(oc, owq);
70 } else {
71 // Property has no read or write ability
72 }
73 } else { // Writeable
74 if (ft->read == NO_READ_FUNCTION) {
75 ShowWriteonly(oc, owq);
76 } else {
77 ShowReadWrite(oc, owq);
78 }
79 }
80 fprintf(out, "</TD></TR>\r\n");
81 OWQ_destroy(owq);
82 }
83
84
85 /* Device entry -- table line for a filetype */
ShowReadWrite(struct OutputControl * oc,struct one_wire_query * owq)86 static void ShowReadWrite(struct OutputControl * oc, struct one_wire_query *owq)
87 {
88 FILE * out = oc->out ;
89 struct parsedname * pn = PN(owq) ;
90 const char *file = FS_DirName(pn);
91 SIZE_OR_ERROR read_return = FS_read_postparse(owq);
92 if (read_return < 0) {
93 fprintf(out, "Error: %s", strerror(-read_return));
94 return;
95 }
96
97 switch (pn->selected_filetype->format) {
98 case ft_binary:
99 {
100 int i = 0;
101 fprintf(out, "<CODE><FORM METHOD='GET' ACTION='http://%s%s'><TEXTAREA NAME='%s' COLS='64' ROWS='%-d'>", oc->host, oc->base_url, file, read_return >> 5);
102 while (i < read_return) {
103 fprintf(out, "%.2hhX", OWQ_buffer(owq)[i]);
104 if (((++i) < read_return) && (i & 0x1F) == 0) {
105 fprintf(out, "\r\n");
106 }
107 }
108 fprintf(out, "</TEXTAREA><INPUT TYPE='SUBMIT' VALUE='CHANGE'></FORM></CODE>");
109 Upload( oc, pn ) ;
110 break;
111 }
112 case ft_yesno:
113 case ft_bitfield:
114 if (pn->extension >= 0) {
115 fprintf(out,
116 "<FORM METHOD='GET' ACTION='http://%s%s'><INPUT TYPE='CHECKBOX' NAME='%s' %s><INPUT TYPE='SUBMIT' VALUE='CHANGE' NAME='%s'></FORM>",oc->host, oc->base_url,
117 file, (OWQ_buffer(owq)[0] == '0') ? "" : "CHECKED", file);
118 break;
119 }
120 // fall through
121 default:
122 fprintf(out,
123 "<FORM METHOD='GET' ACTION='http://%s%s'><INPUT TYPE='TEXT' NAME='%s' VALUE='%.*s'><INPUT TYPE='SUBMIT' VALUE='CHANGE'></FORM>",oc->host, oc->base_url,
124 file, read_return, OWQ_buffer(owq));
125 break;
126 }
127 }
128
Upload(struct OutputControl * oc,const struct parsedname * pn)129 static void Upload( struct OutputControl * oc, const struct parsedname * pn )
130 {
131 FILE * out = oc->out ;
132 fprintf(out,"<FORM METHOD='POST' ACTION='http://%s%s' ENCTYPE='multipart/form-data'>Load from file: <INPUT TYPE=FILE NAME='%s' SIZE=30><INPUT TYPE=SUBMIT VALUE='UPLOAD'></FORM>",oc->host, oc->base_url, pn->path);
133 }
134
Extension(struct OutputControl * oc,const struct parsedname * pn)135 static void Extension( struct OutputControl * oc, const struct parsedname * pn )
136 {
137 static regex_t rx_extension ;
138 FILE * out = oc->out ;
139 const char * file = FS_DirName(pn);
140 struct ow_regmatch orm ;
141 orm.number = 0 ;
142
143 ow_regcomp( &rx_extension, "\\.", 0 ) ;
144 if ( ow_regexec( &rx_extension, file, &orm ) == 0 ) {
145 fprintf(out, "<CODE><FORM METHOD='GET' ACTION='http://%s%s'><INPUT NAME='EXTENSION' TYPE='TEXT' SIZE='30' VALUE='%s.' ID='EXTENSION'><INPUT TYPE='SUBMIT' VALUE='EXTENSION'></FORM>", oc->host, oc->base_url, orm.pre[0] );
146 ow_regexec_free( &orm ) ;
147 }
148 }
149
150 /* Device entry -- table line for a filetype */
ShowReadonly(struct OutputControl * oc,struct one_wire_query * owq)151 static void ShowReadonly(struct OutputControl * oc, struct one_wire_query *owq)
152 {
153 FILE * out = oc->out ;
154 SIZE_OR_ERROR read_return = FS_read_postparse(owq);
155 struct parsedname * pn = PN(owq) ;
156 if (read_return < 0) {
157 fprintf(out, "Error: %s", strerror(-read_return));
158 return;
159 }
160
161 switch (pn->selected_filetype->format) {
162 case ft_binary:
163 {
164 int i = 0;
165 fprintf(out, "<PRE>");
166 while (i < read_return) {
167 fprintf(out, "%.2hhX", OWQ_buffer(owq)[i]);
168 if (((++i) < read_return) && (i & 0x1F) == 0) {
169 fprintf(out, "\r\n");
170 }
171 }
172 fprintf(out, "</PRE>");
173 break;
174 }
175 case ft_yesno:
176 case ft_bitfield:
177 if (pn->extension >= 0) {
178 switch (OWQ_buffer(owq)[0]) {
179 case '0':
180 fprintf(out, "NO (0)");
181 break;
182 case '1':
183 fprintf(out, "YES (1)");
184 break;
185 }
186 break;
187 }
188 // fall through
189 default:
190 fprintf(out, "%.*s", read_return, OWQ_buffer(owq));
191 break;
192 }
193 }
194
195 /* Structure entry */
ShowStructure(struct OutputControl * oc,struct one_wire_query * owq)196 static void ShowStructure(struct OutputControl * oc, struct one_wire_query *owq)
197 {
198 FILE * out = oc->out ;
199 SIZE_OR_ERROR read_return = FS_read_postparse(owq);
200 if (read_return < 0) {
201 fprintf(out, "Error: %s", strerror(-read_return));
202 return;
203 }
204
205 fprintf(out, "%.*s", read_return, OWQ_buffer(owq));
206
207 // Optional structure details
208 StructureDetail(oc,OWQ_buffer(owq)) ;
209 }
210
211 /* Detailed (parsed) structure entry */
StructureDetail(struct OutputControl * oc,const char * structure_details)212 static void StructureDetail(struct OutputControl * oc, const char * structure_details )
213 {
214 FILE * out = oc->out ;
215 char format_type ;
216 int extension ;
217 int elements ;
218 char rw[4] ;
219 int size ;
220
221 if ( sscanf( structure_details, "%c,%d,%d,%2s,%d,", &format_type, &extension, &elements, rw, &size ) < 5 ) {
222 return ;
223 }
224
225 fprintf(out, "<br>");
226 switch( format_type ) {
227 case 'b':
228 fprintf(out, "Binary string");
229 break ;
230 case 'a':
231 fprintf(out, "Ascii string");
232 break ;
233 case 'D':
234 fprintf(out, "Directory");
235 break ;
236 case 'i':
237 fprintf(out, "Integer value");
238 break ;
239 case 'u':
240 fprintf(out, "Unsigned integer value");
241 break ;
242 case 'f':
243 fprintf(out, "Floating point value");
244 break ;
245 case 'l':
246 fprintf(out, "Alias");
247 break ;
248 case 'y':
249 fprintf(out, "Yes/No value");
250 break ;
251 case 'd':
252 fprintf(out, "Date value");
253 break ;
254 case 't':
255 fprintf(out, "Temperature value");
256 break ;
257 case 'g':
258 fprintf(out, "Delta temperature value");
259 break ;
260 case 'p':
261 fprintf(out, "Pressure value");
262 break ;
263 default:
264 fprintf(out, "Unknown value type");
265 }
266
267 fprintf(out, ", ");
268
269 if ( elements == 1 ) {
270 fprintf(out, "Singleton");
271 } else if ( extension == EXTENSION_BYTE ) {
272 fprintf(out, "Array of %d bits as a BYTE",elements);
273 } else if ( extension == EXTENSION_ALL ) {
274 fprintf(out, "Array of %d elements combined",elements);
275 } else {
276 fprintf(out, "Element %d (of %d)",extension,elements);
277 }
278
279 fprintf(out, ", ");
280
281 if ( strncasecmp( rw, "rw", 2 ) == 0 ) {
282 fprintf(out, "Read/Write");
283 } else if ( strncasecmp( rw, "ro", 2 ) == 0 ) {
284 fprintf(out, "Read only");
285 } else if ( strncasecmp( rw, "wo", 2 ) == 0 ) {
286 fprintf(out, "Write only");
287 } else{
288 fprintf(out, "No access");
289 }
290
291 fprintf(out, ", ");
292
293 if ( format_type == 'b' ) {
294 fprintf(out, "%d bytes",size);
295 } else {
296 fprintf(out, "%d characters",size);
297 }
298 }
299
300 /* Device entry -- table line for a filetype */
ShowWriteonly(struct OutputControl * oc,struct one_wire_query * owq)301 static void ShowWriteonly(struct OutputControl * oc, struct one_wire_query *owq)
302 {
303 FILE * out = oc->out ;
304 struct parsedname * pn = PN(owq) ;
305 const char *file = FS_DirName(pn);
306
307 switch (pn->selected_filetype->format) {
308 case ft_binary:
309 fprintf(out,
310 "<CODE><FORM METHOD='GET' ACTION='http://%s%s'><TEXTAREA NAME='%s' COLS='64' ROWS='%-d'></TEXTAREA><INPUT TYPE='SUBMIT' VALUE='CHANGE'></FORM></CODE>",oc->host, oc->base_url,
311 file, (int) (OWQ_size(owq) >> 5));
312 Upload(oc,pn) ;
313 break;
314 case ft_yesno:
315 case ft_bitfield:
316 if (pn->extension >= 0) {
317 fprintf(out,
318 "<FORM METHOD='GET' ACTION='http://%s%s'><INPUT TYPE='SUBMIT' NAME='%s' VALUE='ON'><INPUT TYPE='SUBMIT' NAME='%s' VALUE='OFF'></FORM>", oc->host, oc->base_url, file, file);
319 break;
320 }
321 // fall through
322 default:
323 fprintf(out, "<FORM METHOD='GET' ACTION='http://%s%s'><INPUT TYPE='TEXT' NAME='%s'><INPUT TYPE='SUBMIT' VALUE='CHANGE'></FORM>", oc->host, oc->base_url, file);
324 break;
325 }
326 }
327
ShowDirectory(struct OutputControl * oc,const struct parsedname * pn_entry)328 static void ShowDirectory(struct OutputControl * oc, const struct parsedname *pn_entry)
329 {
330 FILE * out = oc->out ;
331 fprintf(out, "<A HREF='%s'>%s</A>", pn_entry->path, FS_DirName(pn_entry));
332 }
333
334 /* Device entry -- table line for a filetype */
ShowText(struct OutputControl * oc,const struct parsedname * pn_entry)335 static void ShowText(struct OutputControl * oc, const struct parsedname *pn_entry)
336 {
337 FILE * out = oc->out ;
338 struct one_wire_query *owq = OWQ_create_from_path(pn_entry->path); // for read or dir
339 struct filetype * ft = pn_entry->selected_filetype ;
340
341 /* Left column */
342 fprintf(out, "%s ", FS_DirName(pn_entry));
343
344 if (owq == NO_ONE_WIRE_QUERY) {
345 } else if ( BAD( OWQ_allocate_read_buffer(owq)) ) {
346 //fprintf(out, "(memory exhausted)");
347 } else if (ft == NO_FILETYPE) {
348 ShowTextDirectory(oc, pn_entry);
349 } else if (ft->format == ft_directory || ft->format == ft_subdir) {
350 ShowTextDirectory(oc, pn_entry);
351 } else if (IsStructureDir(pn_entry)) {
352 ShowTextStructure(oc, owq);
353 } else if (ft->write == NO_WRITE_FUNCTION || Globals.readonly) {
354 // Unwritable
355 if (ft->read != NO_READ_FUNCTION) {
356 ShowTextReadonly(oc, owq);
357 }
358 } else { // Writeable
359 if (ft->read == NO_READ_FUNCTION) {
360 ShowTextWriteonly(oc, owq);
361 } else {
362 ShowTextReadWrite(oc, owq);
363 }
364 }
365 fprintf(out, "\r\n");
366 OWQ_destroy(owq);
367 }
368
369 /* Device entry -- table line for a filetype */
ShowTextStructure(struct OutputControl * oc,struct one_wire_query * owq)370 static void ShowTextStructure(struct OutputControl * oc, struct one_wire_query *owq)
371 {
372 FILE * out = oc->out ;
373 SIZE_OR_ERROR read_return = FS_read_postparse(owq);
374 if (read_return < 0) {
375 //fprintf(out, "error: %s", strerror(-read_return));
376 return;
377 }
378
379 fprintf(out, "%.*s", read_return, OWQ_buffer(owq));
380 }
381
382 /* Device entry -- table line for a filetype */
ShowTextReadWrite(struct OutputControl * oc,struct one_wire_query * owq)383 static void ShowTextReadWrite(struct OutputControl * oc, struct one_wire_query *owq)
384 {
385 FILE * out = oc->out ;
386 SIZE_OR_ERROR read_return = FS_read_postparse(owq);
387 if (read_return < 0) {
388 //fprintf(out, "error: %s", strerror(-read_return));
389 return;
390 }
391
392 switch (PN(owq)->selected_filetype->format) {
393 case ft_binary:
394 {
395 int i;
396 for (i = 0; i < read_return; ++i) {
397 fprintf(out, "%.2hhX", OWQ_buffer(owq)[i]);
398 }
399 break;
400 }
401 case ft_yesno:
402 case ft_bitfield:
403 if (PN(owq)->extension >= 0) {
404 fprintf(out, "%c", OWQ_buffer(owq)[0]);
405 break;
406 }
407 // fall through
408 default:
409 fprintf(out, "%.*s", read_return, OWQ_buffer(owq));
410 break;
411 }
412 }
413
414 /* Device entry -- table line for a filetype */
ShowTextReadonly(struct OutputControl * oc,struct one_wire_query * owq)415 static void ShowTextReadonly(struct OutputControl * oc, struct one_wire_query *owq)
416 {
417 ShowTextReadWrite(oc, owq);
418 }
419
420 /* Device entry -- table line for a filetype */
ShowTextWriteonly(struct OutputControl * oc,struct one_wire_query * owq)421 static void ShowTextWriteonly(struct OutputControl * oc, struct one_wire_query *owq)
422 {
423 FILE * out = oc->out ;
424 (void) owq;
425 fprintf(out, "(writeonly)");
426 }
427
ShowTextDirectory(struct OutputControl * oc,const struct parsedname * pn_entry)428 static void ShowTextDirectory(struct OutputControl * oc, const struct parsedname *pn_entry)
429 {
430 (void) oc;
431 (void) pn_entry;
432 }
433
434 /* Now show the device */
ShowDeviceTextCallback(void * v,const struct parsedname * pn_entry)435 static void ShowDeviceTextCallback(void *v, const struct parsedname * pn_entry)
436 {
437 struct OutputControl * oc = v;
438 ShowText(oc, pn_entry);
439 }
440
ShowDeviceCallback(void * v,const struct parsedname * pn_entry)441 static void ShowDeviceCallback(void *v, const struct parsedname * pn_entry)
442 {
443 struct OutputControl * oc = v;
444 Show(oc, pn_entry);
445 }
446
ShowDeviceText(struct OutputControl * oc,struct parsedname * pn)447 static void ShowDeviceText(struct OutputControl * oc, struct parsedname *pn)
448 {
449 HTTPstart(oc, "200 OK", ct_text);
450
451 if (pn->selected_filetype == NO_DEVICE) { /* whole device */
452 //printf("whole directory path=%s \n", pn->path);
453 FS_dir(ShowDeviceTextCallback, oc, pn);
454 } else { /* Single item */
455 //printf("single item path=%s\n", pn->path);
456 ShowText(oc, pn);
457 }
458 }
459
460 /* Device entry -- table line for a filetype */
ShowJson(struct OutputControl * oc,const struct parsedname * pn_entry)461 static void ShowJson(struct OutputControl * oc, const struct parsedname *pn_entry)
462 {
463 FILE * out = oc->out ;
464 struct one_wire_query *owq = OWQ_create_from_path(pn_entry->path); // for read or dir
465 struct filetype * ft = pn_entry->selected_filetype ;
466
467 if (owq == NO_ONE_WIRE_QUERY) {
468 fprintf(out, "null");
469 } else if ( BAD( OWQ_allocate_read_buffer(owq)) ) {
470 fprintf(out, "null");
471 } else if (ft == NO_FILETYPE) {
472 ShowJsonDirectory(oc, pn_entry);
473 } else if (IsStructureDir(pn_entry)) {
474 ShowJsonStructure(oc, owq);
475 } else if (ft->format == ft_directory || ft->format == ft_subdir) {
476 ShowJsonDirectory(oc, pn_entry);
477 } else if (ft->write == NO_WRITE_FUNCTION || Globals.readonly) {
478 // Unwritable
479 if (ft->read != NO_READ_FUNCTION) {
480 ShowJsonReadonly(oc, owq);
481 }
482 } else { // Writeable
483 if (ft->read == NO_READ_FUNCTION) {
484 ShowJsonWriteonly(oc, owq);
485 } else {
486 ShowJsonReadWrite(oc, owq);
487 }
488 }
489 OWQ_destroy(owq);
490 }
491
492 /* Device entry -- table line for a filetype */
ShowJsonStructure(struct OutputControl * oc,struct one_wire_query * owq)493 static void ShowJsonStructure(struct OutputControl * oc, struct one_wire_query *owq)
494 {
495 FILE * out = oc->out ;
496 SIZE_OR_ERROR read_return = FS_read_postparse(owq);
497 if (read_return < 0) {
498 fprintf(out, "null");
499 return;
500 }
501 fprintf(out, "\"%.*s\":", read_return, OWQ_buffer(owq));
502 StructureDetailJson( oc, OWQ_buffer(owq) ) ;
503 }
504
505 /* Detailed (parsed) structure entry */
StructureDetailJson(struct OutputControl * oc,const char * structure_details)506 static void StructureDetailJson(struct OutputControl * oc, const char * structure_details )
507 {
508 FILE * out = oc->out ;
509 char format_type ;
510 int extension ;
511 int elements ;
512 char rw[4] ;
513 int size ;
514
515 if ( sscanf( structure_details, "[\"%c\",\"%d\",\"%d\",\"%2s\",\"%d\",", &format_type, &extension, &elements, rw, &size ) < 5 ) {
516 return ;
517 }
518
519 fprintf(out, "\"");
520 switch( format_type ) {
521 case 'b':
522 fprintf(out, "Binary string");
523 break ;
524 case 'a':
525 fprintf(out, "Ascii string");
526 break ;
527 case 'D':
528 fprintf(out, "Directory");
529 break ;
530 case 'i':
531 fprintf(out, "Integer value");
532 break ;
533 case 'u':
534 fprintf(out, "Unsigned integer value");
535 break ;
536 case 'f':
537 fprintf(out, "Floating point value");
538 break ;
539 case 'l':
540 fprintf(out, "Alias");
541 break ;
542 case 'y':
543 fprintf(out, "Yes/No value");
544 break ;
545 case 'd':
546 fprintf(out, "Date value");
547 break ;
548 case 't':
549 fprintf(out, "Temperature value");
550 break ;
551 case 'g':
552 fprintf(out, "Delta temperature value");
553 break ;
554 case 'p':
555 fprintf(out, "Pressure value");
556 break ;
557 default:
558 fprintf(out, "Unknown value type");
559 }
560
561 fprintf(out, "\", \"");
562
563 if ( elements == 1 ) {
564 fprintf(out, "Singleton");
565 } else if ( extension == EXTENSION_BYTE ) {
566 fprintf(out, "Array of %d bits as a BYTE",elements);
567 } else if ( extension == EXTENSION_ALL ) {
568 fprintf(out, "Array of %d elements combined",elements);
569 } else {
570 fprintf(out, "Element %d (of %d)",extension,elements);
571 }
572
573 fprintf(out, "\", \"");
574
575 if ( strncasecmp( rw, "rw", 2 ) == 0 ) {
576 fprintf(out, "Read/Write");
577 } else if ( strncasecmp( rw, "ro", 2 ) == 0 ) {
578 fprintf(out, "Read only");
579 } else if ( strncasecmp( rw, "wo", 2 ) == 0 ) {
580 fprintf(out, "Write only");
581 } else{
582 fprintf(out, "No access");
583 }
584
585 fprintf(out, "\", \"");
586
587 if ( format_type == 'b' ) {
588 fprintf(out, "%d bytes",size);
589 } else {
590 fprintf(out, "%d characters",size);
591 }
592 fprintf( out, "\"]" );
593 }
594
595 /* Device entry -- table line for a filetype */
ShowJsonReadWrite(struct OutputControl * oc,struct one_wire_query * owq)596 static void ShowJsonReadWrite(struct OutputControl * oc, struct one_wire_query *owq)
597 {
598 FILE * out = oc->out ;
599 struct parsedname * pn = PN(owq) ;
600 SIZE_OR_ERROR read_return = FS_read_postparse(owq);
601
602 if (read_return < 0) {
603 fprintf(out, "null");
604 return;
605 }
606
607 switch (pn->selected_filetype->format) {
608 case ft_binary:
609 {
610 int i;
611 fprintf(out,"\"");
612 for (i = 0; i < read_return; ++i) {
613 fprintf(out, "%.2hhX", OWQ_buffer(owq)[i]);
614 }
615 fprintf(out,"\"");
616 break;
617 }
618 case ft_yesno:
619 case ft_bitfield:
620 if (pn->extension >= 0) {
621 fprintf(out, "\"%s\"", OWQ_buffer(owq)[0]=='0'?"false":"true");
622 break;
623 }
624 // fall through
625 default:
626 fprintf(out, "\"%.*s\"", read_return, OWQ_buffer(owq));
627 break;
628 }
629 }
630
631 /* Device entry -- table line for a filetype */
ShowJsonReadonly(struct OutputControl * oc,struct one_wire_query * owq)632 static void ShowJsonReadonly(struct OutputControl * oc, struct one_wire_query *owq)
633 {
634 ShowJsonReadWrite(oc, owq);
635 }
636
637 /* Device entry -- table line for a filetype */
ShowJsonWriteonly(struct OutputControl * oc,struct one_wire_query * owq)638 static void ShowJsonWriteonly(struct OutputControl * oc, struct one_wire_query *owq)
639 {
640 FILE * out = oc->out ;
641 (void) owq ;
642 fprintf(out,"null") ;
643 }
ShowJsonDirectory(struct OutputControl * oc,const struct parsedname * pn_entry)644 static void ShowJsonDirectory(struct OutputControl * oc, const struct parsedname *pn_entry)
645 {
646 FILE * out = oc->out ;
647 (void) pn_entry;
648 fprintf(out,"[]") ;
649 }
650
651 /* Now show the device */
ShowDeviceJsonCallback(void * v,const struct parsedname * pn_entry)652 static void ShowDeviceJsonCallback(void *v, const struct parsedname * pn_entry)
653 {
654 struct OutputControl * oc = v ;
655 JSON_dir_entry(oc, "\"%s\":",FS_DirName(pn_entry) ) ;
656 ShowJson(oc, pn_entry);
657 }
658
ShowDeviceJson(struct OutputControl * oc,struct parsedname * pn)659 static void ShowDeviceJson(struct OutputControl * oc, struct parsedname *pn)
660 {
661 FILE * out = oc->out ;
662
663 HTTPstart(oc, "200 OK", ct_json);
664
665 if (pn->selected_filetype == NO_DEVICE) { /* whole device */
666 JSON_dir_init( oc ) ;
667 fprintf(out, "{\n" ) ;
668 FS_dir(ShowDeviceJsonCallback, oc, pn);
669 JSON_dir_finish(oc) ;
670 fprintf(out, "}" );
671 } else { /* Single item */
672 //printf("single item path=%s\n", pn->path);
673 fprintf(out, "[ " ) ;
674 ShowJson(oc, pn);
675 fprintf(out, " ]" ) ;
676 }
677 }
678
679
ShowDevice(struct OutputControl * oc,struct parsedname * pn)680 void ShowDevice(struct OutputControl * oc, struct parsedname *pn)
681 {
682 FILE * out = oc->out ;
683 if (pn->state & ePS_text) {
684 ShowDeviceText(oc, pn);
685 return;
686 } else if (pn->state & ePS_json) {
687 ShowDeviceJson(oc, pn);
688 return;
689 }
690
691 HTTPstart(oc, "200 OK", ct_html);
692
693 HTTPtitle(oc, &pn->path[1]);
694 HTTPheader(oc, &pn->path[1]);
695
696 if (NotUncachedDir(pn) && IsRealDir(pn)) {
697 fprintf(out, "<BR><small><A href='/uncached%s'>uncached version</A></small>", pn->path);
698 }
699 fprintf(out, "<TABLE BGCOLOR=\"#DDDDDD\" BORDER=1>");
700 fprintf(out, "<TR><TD><A HREF='%.*s'><CODE><B><BIG>up</BIG></B></CODE></A></TD><TD>directory</TD></TR>", Backup(pn->path), pn->path);
701
702
703 if (pn->selected_filetype == NO_FILETYPE) { /* whole device */
704 FS_dir(ShowDeviceCallback, oc, pn);
705 } else { /* single item */
706 Show(oc, pn);
707 }
708 fprintf(out, "</TABLE>");
709 HTTPfoot(oc);
710 }
711