LCOV - code coverage report
Current view: top level - src/client/monitor - json_input.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 189 234 80.8 %
Date: 2017-01-01 Functions: 13 14 92.9 %

          Line data    Source code
       1             : #include "../../burp.h"
       2             : #include "../../alloc.h"
       3             : #include "../../asfd.h"
       4             : #include "../../async.h"
       5             : #include "../../bu.h"
       6             : #include "../../cstat.h"
       7             : #include "../../handy.h"
       8             : #include "../../iobuf.h"
       9             : #include "../../log.h"
      10             : #include "json_input.h"
      11             : #include "lline.h"
      12             : #include "sel.h"
      13             : #ifdef HAVE_WIN32
      14             : #include <yajl/yajl_parse.h>
      15             : #else
      16             : #include "../../yajl/api/yajl_parse.h"
      17             : #endif
      18             : 
      19             : static int map_depth=0;
      20             : 
      21             : // FIX THIS: should pass around a ctx instead of keeping track of a bunch
      22             : // of globals.
      23             : static unsigned long number=0;
      24             : static char *timestamp=NULL;
      25             : static uint16_t flags=0;
      26             : static struct cstat *cnew=NULL;
      27             : static struct cstat *current=NULL;
      28             : static struct cstat **cslist=NULL;
      29             : static struct cntr_ent *cntr_ent=NULL;
      30             : static char lastkey[32]="";
      31             : static int in_backups=0;
      32             : static int in_flags=0;
      33             : static int in_counters=0;
      34             : static int in_logslist=0;
      35             : static int in_log_content=0;
      36             : static struct bu **sselbu=NULL;
      37             : // For server side log files.
      38             : static struct lline *ll_list=NULL;
      39             : static struct lline **sllines=NULL;
      40             : // For recording 'loglines' in json input.
      41             : static struct lline *jsll_list=NULL;
      42             : 
      43             : static int is_wrap(const char *val, const char *key, uint16_t bit)
      44             : {
      45         899 :         if(!strcmp(val, key))
      46             :         {
      47         204 :                 flags|=bit;
      48             :                 return 1;
      49             :         }
      50             :         return 0;
      51             : }
      52             : 
      53         406 : static int input_integer(__attribute__ ((unused)) void *ctx, long long val)
      54             : {
      55         406 :         if(in_counters)
      56             :         {
      57          60 :                 if(!strcmp(lastkey, "count"))
      58             :                 {
      59          60 :                         if(!cntr_ent) goto error;
      60          60 :                         cntr_ent->count=(uint64_t)val;
      61             :                 }
      62           0 :                 else if(!strcmp(lastkey, "changed"))
      63             :                 {
      64           0 :                         if(!cntr_ent) goto error;
      65           0 :                         cntr_ent->changed=(uint64_t)val;
      66             :                 }
      67           0 :                 else if(!strcmp(lastkey, "same"))
      68             :                 {
      69           0 :                         if(!cntr_ent) goto error;
      70           0 :                         cntr_ent->same=(uint64_t)val;
      71             :                 }
      72           0 :                 else if(!strcmp(lastkey, "deleted"))
      73             :                 {
      74           0 :                         if(!cntr_ent) goto error;
      75           0 :                         cntr_ent->deleted=(uint64_t)val;
      76             :                 }
      77           0 :                 else if(!strcmp(lastkey, "scanned"))
      78             :                 {
      79           0 :                         if(!cntr_ent) goto error;
      80           0 :                         cntr_ent->phase1=(uint64_t)val;
      81             :                 }
      82             :                 else
      83             :                 {
      84             :                         goto error;
      85             :                 }
      86             :                 return 1;
      87             :         }
      88         346 :         else if(in_backups && !in_flags && !in_counters && !in_logslist)
      89             :         {
      90         254 :                 if(!current) goto error;
      91         254 :                 if(!strcmp(lastkey, "number"))
      92             :                 {
      93         127 :                         number=(unsigned long)val;
      94         127 :                         return 1;
      95             :                 }
      96         127 :                 else if(!strcmp(lastkey, "timestamp"))
      97             :                 {
      98             :                         time_t t;
      99         127 :                         t=(unsigned long)val;
     100         127 :                         free_w(&timestamp);
     101         127 :                         if(!(timestamp=strdup_w(getdatestr(t), __func__)))
     102             :                                 return 0;
     103         127 :                         return 1;
     104             :                 }
     105             :         }
     106             :         else
     107             :         {
     108          92 :                 if(!strcmp(lastkey, "protocol"))
     109             :                 {
     110             :                         return 1;
     111             :                 }
     112             :         }
     113             : error:
     114           0 :         logp("Unexpected integer: '%s' %"PRIu64"\n", lastkey, (uint64_t)val);
     115           0 :         return 0;
     116             : }
     117             : 
     118         543 : static int input_string(__attribute__ ((unused)) void *ctx,
     119             :         const unsigned char *val, size_t len)
     120             : {
     121             :         char *str;
     122         543 :         if(!(str=(char *)malloc_w(len+1, __func__)))
     123             :                 return 0;
     124         543 :         snprintf(str, len+1, "%s", val);
     125         543 :         str[len]='\0';
     126             : 
     127         543 :         if(in_counters)
     128             :         {
     129         120 :                 if(!strcmp(lastkey, "name"))
     130             :                 {
     131             :                         // Ignore 'name' in a counters object. We use 'type'
     132             :                         // instead.
     133             :                 }
     134          60 :                 else if(!strcmp(lastkey, "type"))
     135             :                 {
     136          60 :                         if(!current) goto error;
     137          60 :                         cntr_ent=current->cntr->ent[(uint8_t)*str];
     138             :                 }
     139             :                 else
     140             :                 {
     141             :                         goto error;
     142             :                 }
     143             :                 goto end;
     144             :         }
     145         423 :         else if(!strcmp(lastkey, "name"))
     146             :         {
     147          92 :                 if(cnew) goto error;
     148          92 :                 if(!(current=cstat_get_by_name(*cslist, str)))
     149             :                 {
     150          44 :                         if(!(cnew=cstat_alloc())
     151          44 :                           || cstat_init_with_cntr(cnew, str, NULL))
     152             :                                 goto error;
     153          44 :                         current=cnew;
     154             :                 }
     155             :                 goto end;
     156             :         }
     157         331 :         else if(!strcmp(lastkey, "labels"))
     158             :         {
     159          30 :                 if(!current) goto error;
     160             :                 goto end;
     161             :         }
     162         301 :         else if(!strcmp(lastkey, "run_status"))
     163             :         {
     164          92 :                 if(!current) goto error;
     165          92 :                 current->run_status=run_str_to_status(str);
     166          92 :                 goto end;
     167             :         }
     168         209 :         else if(!strcmp(lastkey, "phase"))
     169             :         {
     170           0 :                 if(!current) goto error;
     171           0 :                 current->cntr->cntr_status=cntr_str_to_status(str);
     172           0 :                 goto end;
     173             :         }
     174         209 :         else if(!strcmp(lastkey, "flags"))
     175             :         {
     176         204 :                 if(!current) goto error;
     177         408 :                 if(is_wrap(str, "hardlinked", BU_HARDLINKED)
     178         398 :                   || is_wrap(str, "deletable", BU_DELETABLE)
     179         324 :                   || is_wrap(str, "working", BU_WORKING)
     180         294 :                   || is_wrap(str, "finishing", BU_FINISHING)
     181         264 :                   || is_wrap(str, "current", BU_CURRENT)
     182         110 :                   || is_wrap(str, "manifest", BU_MANIFEST))
     183             :                         goto end;
     184             :         }
     185           5 :         else if(!strcmp(lastkey, "counters")) // Do we need this?
     186             :         {
     187             :                 goto end;
     188             :         }
     189           5 :         else if(!strcmp(lastkey, "list"))
     190             :         {
     191           0 :                 if(is_wrap(str, "backup", BU_LOG_BACKUP)
     192           0 :                   || is_wrap(str, "restore", BU_LOG_RESTORE)
     193           0 :                   || is_wrap(str, "verify", BU_LOG_VERIFY)
     194           0 :                   || is_wrap(str, "backup_stats", BU_STATS_BACKUP)
     195           0 :                   || is_wrap(str, "restore_stats", BU_STATS_RESTORE)
     196           0 :                   || is_wrap(str, "verify_stats", BU_STATS_VERIFY))
     197             :                         goto end;
     198             :         }
     199           5 :         else if(!strcmp(lastkey, "logs"))
     200             :         {
     201             :                 goto end;
     202             :         }
     203           5 :         else if(!strcmp(lastkey, "logline"))
     204             :         {
     205           0 :                 if(lline_add(&jsll_list, str))
     206             :                         goto error;
     207             :                 goto end;
     208             :         }
     209           5 :         else if(!strcmp(lastkey, "backup")
     210           5 :           || !strcmp(lastkey, "restore")
     211           5 :           || !strcmp(lastkey, "verify")
     212           5 :           || !strcmp(lastkey, "backup_stats")
     213           5 :           || !strcmp(lastkey, "restore_stats")
     214           5 :           || !strcmp(lastkey, "verify_stats"))
     215             :         {
     216             :                 // Log file contents.
     217           0 :                 if(lline_add(&ll_list, str))
     218             :                         goto error;
     219             :                 goto end;
     220             :         }
     221           5 :         else if(!strcmp(lastkey, "warning")) 
     222             :         {
     223             :                 goto end;
     224             :         }
     225             : error:
     226           0 :         logp("Unexpected string: '%s' '%s'\n", lastkey, str);
     227           0 :         free_w(&str);
     228           0 :         return 0;
     229             : end:
     230         543 :         free_w(&str);
     231         543 :         return 1;
     232             : }
     233             : 
     234        1018 : static int input_map_key(__attribute__((unused)) void *ctx,
     235             :         const unsigned char *val, size_t len)
     236             : {
     237        1018 :         snprintf(lastkey, len+1, "%s", val);
     238        1018 :         lastkey[len]='\0';
     239             : //      logp("mapkey: %s\n", lastkey);
     240        1018 :         return 1;
     241             : }
     242             : 
     243             : static struct bu *bu_list=NULL;
     244             : 
     245         219 : static int add_to_bu_list(void)
     246             : {
     247             :         struct bu *bu;
     248             :         struct bu *last;
     249         219 :         if(!number) return 0;
     250         127 :         if(!(bu=bu_alloc())) return -1;
     251         127 :         bu->bno=number;
     252         127 :         bu->flags=flags;
     253         127 :         bu->timestamp=timestamp;
     254             : 
     255             :         // FIX THIS: Inefficient to find the end each time.
     256         127 :         for(last=bu_list; last && last->next; last=last->next) { }
     257         127 :         if(last)
     258             :         {
     259          50 :                 last->next=bu;
     260          50 :                 bu->prev=last;
     261             :         }
     262             :         else
     263             :         {
     264          77 :                 bu_list=bu;
     265          77 :                 bu_list->prev=NULL;
     266             :         }
     267             :         
     268         127 :         number=0;
     269         127 :         flags=0;
     270         127 :         timestamp=NULL;
     271         127 :         return 0;
     272             : }
     273             : 
     274         326 : static int input_start_map(__attribute__ ((unused)) void *ctx)
     275             : {
     276         326 :         map_depth++;
     277             :         //logp("startmap: %d\n", map_depth);
     278         326 :         return 1;
     279             : }
     280             : 
     281         325 : static int input_end_map(__attribute__ ((unused)) void *ctx)
     282             : {
     283         325 :         map_depth--;
     284             :         //logp("endmap: %d\n", map_depth);
     285         325 :         if(in_backups && !in_flags && !in_counters && !in_logslist)
     286             :         {
     287         127 :                 if(add_to_bu_list()) return 0;
     288             :         }
     289             :         return 1;
     290             : }
     291             : 
     292         303 : static int input_start_array(__attribute__ ((unused)) void *ctx)
     293             : {
     294             :         //logp("start arr\n");
     295         303 :         if(!strcmp(lastkey, "backups"))
     296             :         {
     297          92 :                 in_backups=1;
     298             :         }
     299         211 :         else if(!strcmp(lastkey, "flags"))
     300             :         {
     301         127 :                 in_flags=1;
     302             :         }
     303          84 :         else if(!strcmp(lastkey, "counters"))
     304             :         {
     305          30 :                 in_counters=1;
     306             :         }
     307          54 :         else if(!strcmp(lastkey, "list"))
     308             :         {
     309           0 :                 in_logslist=1;
     310             :         }
     311          54 :         else if(!strcmp(lastkey, "backup")
     312          54 :           || !strcmp(lastkey, "restore")
     313          54 :           || !strcmp(lastkey, "verify")
     314          54 :           || !strcmp(lastkey, "backup_stats")
     315          54 :           || !strcmp(lastkey, "restore_stats")
     316          54 :           || !strcmp(lastkey, "verify_stats"))
     317             :         {
     318           0 :                 in_log_content=1;
     319             :         }
     320         303 :         return 1;
     321             : }
     322             : 
     323          92 : static void merge_bu_lists(void)
     324             : {
     325             :         struct bu *n;
     326             :         struct bu *o;
     327          92 :         struct bu *lastn=NULL;
     328          92 :         struct bu *lasto=NULL;
     329             : 
     330         253 :         for(o=current->bu; o; )
     331             :         {
     332          69 :                 int found_in_new=0;
     333          69 :                 lastn=NULL;
     334          87 :                 for(n=bu_list; n; n=n->next)
     335             :                 {
     336          87 :                         if(o->bno==n->bno)
     337             :                         {
     338             :                                 // Found o in new list.
     339             :                                 // Copy the fields from new to old.
     340          69 :                                 found_in_new=1;
     341          69 :                                 o->flags=n->flags;
     342          69 :                                 free_w(&o->timestamp);
     343          69 :                                 o->timestamp=n->timestamp;
     344          69 :                                 n->timestamp=NULL;
     345             : 
     346             :                                 // Remove it from new list.
     347          69 :                                 if(lastn)
     348             :                                 {
     349          18 :                                         lastn->next=n->next;
     350          18 :                                         if(n->next) n->next->prev=lastn;
     351             :                                 }
     352             :                                 else
     353             :                                 {
     354          51 :                                         bu_list=n->next;
     355          51 :                                         if(bu_list) bu_list->prev=NULL;
     356             :                                 }
     357          69 :                                 bu_free(&n);
     358          69 :                                 n=lastn;
     359          69 :                                 break;
     360             :                         }
     361          18 :                         lastn=n;
     362             :                 }
     363          69 :                 if(!found_in_new)
     364             :                 {
     365             :                         // Could not find o in new list.
     366             :                         // Remove it from old list.
     367           0 :                         if(lasto)
     368             :                         {
     369           0 :                                 lasto->next=o->next;
     370           0 :                                 if(o->next) o->next->prev=lasto;
     371             :                         }
     372             :                         else
     373             :                         {
     374           0 :                                 current->bu=o->next;
     375           0 :                                 if(current->bu) current->bu->prev=NULL;
     376             :                         }
     377             :                         // Need to reset if the one that was removed was
     378             :                         // selected in ncurses.
     379           0 :                         if(o==*sselbu) *sselbu=NULL;
     380           0 :                         bu_free(&o);
     381           0 :                         o=lasto;
     382             :                 }
     383          69 :                 lasto=o;
     384          69 :                 if(o) o=o->next;
     385             :         }
     386             : 
     387             :         // Now, new list only has entries missing from old list.
     388          92 :         n=bu_list;
     389          92 :         lastn=NULL;
     390         242 :         while(n)
     391             :         {
     392          58 :                 o=current->bu;
     393          58 :                 lasto=NULL;
     394         136 :                 while(o && n->bno < o->bno)
     395             :                 {
     396          20 :                         lasto=o;
     397          20 :                         o=o->next;
     398             :                 }
     399             :                 // Found the place to insert it.
     400          58 :                 if(lasto)
     401             :                 {
     402           8 :                         lasto->next=n;
     403           8 :                         n->prev=lasto;
     404             :                 }
     405             :                 else
     406             :                 {
     407          50 :                         if(current->bu) current->bu->prev=n;
     408          50 :                         current->bu=n;
     409          50 :                         current->bu->prev=NULL;
     410             :                 }
     411          58 :                 lastn=n->next;
     412          58 :                 n->next=o;
     413          58 :                 n=lastn;
     414             :         }
     415          92 : }
     416             : 
     417         303 : static int input_end_array(__attribute__ ((unused)) void *ctx)
     418             : {
     419         303 :         if(in_backups && !in_flags && !in_counters && !in_logslist)
     420             :         {
     421          92 :                 in_backups=0;
     422          92 :                 if(add_to_bu_list()) return 0;
     423             :                 // Now may have two lists. Want to keep the old one is intact
     424             :                 // as possible, so that we can keep a pointer to its entries
     425             :                 // in the ncurses stuff.
     426             :                 // Merge the new list into the old.
     427          92 :                 merge_bu_lists();
     428          92 :                 bu_list=NULL;
     429          92 :                 if(cnew)
     430             :                 {
     431          44 :                         cstat_add_to_list(cslist, cnew);
     432          44 :                         cnew=NULL;
     433             :                 }
     434          92 :                 current=NULL;
     435             :         }
     436         211 :         else if(in_flags)
     437             :         {
     438         127 :                 in_flags=0;
     439             :         }
     440          84 :         else if(in_counters)
     441             :         {
     442          30 :                 in_counters=0;
     443             :         }
     444          54 :         else if(in_logslist)
     445             :         {
     446           0 :                 in_logslist=0;
     447             :         }
     448          54 :         else if(in_log_content)
     449             :         {
     450           0 :                 in_log_content=0;
     451           0 :                 llines_free(sllines);
     452           0 :                 *sllines=ll_list;
     453           0 :                 ll_list=NULL;
     454             :         }
     455             :         return 1;
     456             : }
     457             : 
     458             : static yajl_callbacks callbacks = {
     459             :         NULL,
     460             :         NULL,
     461             :         input_integer,
     462             :         NULL,
     463             :         NULL,
     464             :         input_string,
     465             :         input_start_map,
     466             :         input_map_key,
     467             :         input_end_map,
     468             :         input_start_array,
     469             :         input_end_array
     470             : };
     471             : 
     472           2 : static void do_yajl_error(yajl_handle yajl, struct asfd *asfd)
     473             : {
     474             :         unsigned char *str;
     475           4 :         str=yajl_get_error(yajl, 1,
     476           4 :                 (const unsigned char *)asfd->rbuf->buf, asfd->rbuf->len);
     477           2 :         logp("yajl error: %s\n", str?(const char *)str:"unknown");
     478           2 :         if(str) yajl_free_error(yajl, str);
     479           2 : }
     480             : 
     481             : static yajl_handle yajl=NULL;
     482             : 
     483          48 : int json_input_init(void)
     484             : {
     485          48 :         if(!(yajl=yajl_alloc(&callbacks, NULL, NULL)))
     486             :                 return -1;
     487          48 :         yajl_config(yajl, yajl_dont_validate_strings, 1);
     488          48 :         return 0;
     489             : }
     490             : 
     491          25 : void json_input_free(void)
     492             : {
     493          98 :         if(!yajl) return;
     494          48 :         yajl_free(yajl);
     495          48 :         yajl=NULL;
     496             : }
     497             : 
     498           0 : struct lline *json_input_get_loglines(void)
     499             : {
     500           0 :         return jsll_list;
     501             : }
     502             : 
     503             : // Client records will be coming through in alphabetical order.
     504             : // FIX THIS: If a client is deleted on the server, it is not deleted from
     505             : // clist.
     506        5287 : int json_input(struct asfd *asfd, struct sel *sel)
     507             : {
     508        5285 :         cslist=&sel->clist;
     509        5285 :         sselbu=&sel->backup;
     510        5285 :         sllines=&sel->llines;
     511             : 
     512        5285 :         if(!yajl && json_input_init()) goto error;
     513             : 
     514       10570 :         if(yajl_parse(yajl, (const unsigned char *)asfd->rbuf->buf,
     515       10570 :                 asfd->rbuf->len)!=yajl_status_ok)
     516             :         {
     517           2 :                 do_yajl_error(yajl, asfd);
     518           1 :                 goto error;
     519             :         }
     520             : 
     521        5284 :         if(!map_depth)
     522             :         {
     523             :                 // Got to the end of the JSON object.
     524          47 :                 if(yajl_complete_parse(yajl)!=yajl_status_ok)
     525             :                 {
     526           2 :                         do_yajl_error(yajl, asfd);
     527           1 :                         goto error;
     528             :                 }
     529             :                 json_input_free();
     530             :                 return 1;
     531             :         }
     532             : 
     533             :         return 0;
     534             : error:
     535             :         json_input_free();
     536             :         return -1;
     537             : }

Generated by: LCOV version 1.10