1 #ifdef FOSSIL_ENABLE_JSON
2 /*
3 ** Copyright (c) 2011 D. Richard Hipp
4 **
5 ** This program is free software; you can redistribute it and/or
6 ** modify it under the terms of the Simplified BSD License (also
7 ** known as the "2-Clause License" or "FreeBSD License".)
8 **
9 ** This program is distributed in the hope that it will be useful,
10 ** but without any warranty; without even the implied warranty of
11 ** merchantability or fitness for a particular purpose.
12 **
13 ** Author contact information:
14 **   drh@hwaci.com
15 **   http://www.hwaci.com/drh/
16 **
17 */
18 
19 #include "config.h"
20 #include "json_diff.h"
21 
22 #if INTERFACE
23 #include "json_detail.h"
24 #endif
25 
26 
27 
28 /*
29 ** Generates a diff between two versions (zFrom and zTo), using nContext
30 ** content lines in the output. On success, returns a new JSON String
31 ** object. On error it sets g.json's error state and returns NULL.
32 **
33 ** If fSbs is true (non-0) them side-by-side diffs are used.
34 **
35 ** If fHtml is true then HTML markup is added to the diff.
36 */
json_generate_diff(const char * zFrom,const char * zTo,int nContext,char fSbs,char fHtml)37 cson_value * json_generate_diff(const char *zFrom, const char *zTo,
38                                 int nContext, char fSbs,
39                                 char fHtml){
40   int fromid;
41   int toid;
42   int outLen;
43   DiffConfig DCfg;
44   Blob from = empty_blob, to = empty_blob, out = empty_blob;
45   cson_value * rc = NULL;
46   int flags = (fSbs ? DIFF_SIDEBYSIDE : 0)
47     | (fHtml ? DIFF_HTML : 0);
48   fromid = name_to_typed_rid(zFrom, "*");
49   if(fromid<=0){
50       json_set_err(FSL_JSON_E_UNRESOLVED_UUID,
51                    "Could not resolve 'from' ID.");
52       return NULL;
53   }
54   toid = name_to_typed_rid(zTo, "*");
55   if(toid<=0){
56       json_set_err(FSL_JSON_E_UNRESOLVED_UUID,
57                    "Could not resolve 'to' ID.");
58       return NULL;
59   }
60   content_get(fromid, &from);
61   content_get(toid, &to);
62   blob_zero(&out);
63   diff_config_init(&DCfg, flags);
64   text_diff(&from, &to, &out, &DCfg);
65   blob_reset(&from);
66   blob_reset(&to);
67   outLen = blob_size(&out);
68   if(outLen>=0){
69     rc = cson_value_new_string(blob_buffer(&out),
70                                (unsigned int)blob_size(&out));
71   }
72   blob_reset(&out);
73   return rc;
74 }
75 
76 /*
77 ** Implementation of the /json/diff page.
78 **
79 ** Arguments:
80 **
81 ** v1=1st version to diff
82 ** v2=2nd version to diff
83 **
84 ** Can come from GET, POST.payload, CLI -v1/-v2 or as positional
85 ** parameters following the command name (in HTTP and CLI modes).
86 **
87 */
json_page_diff()88 cson_value * json_page_diff(){
89   cson_object * pay = NULL;
90   cson_value * v = NULL;
91   char const * zFrom;
92   char const * zTo;
93   int nContext = 0;
94   char doSBS;
95   char doHtml;
96   if(!g.perm.Read){
97     json_set_err(FSL_JSON_E_DENIED,
98                  "Requires 'o' permissions.");
99     return NULL;
100   }
101   zFrom = json_find_option_cstr("v1",NULL,NULL);
102   if(!zFrom){
103     zFrom = json_command_arg(2);
104   }
105   if(!zFrom){
106     json_set_err(FSL_JSON_E_MISSING_ARGS,
107                  "Required 'v1' parameter is missing.");
108     return NULL;
109   }
110   zTo = json_find_option_cstr("v2",NULL,NULL);
111   if(!zTo){
112     zTo = json_command_arg(3);
113   }
114   if(!zTo){
115     json_set_err(FSL_JSON_E_MISSING_ARGS,
116                  "Required 'v2' parameter is missing.");
117     return NULL;
118   }
119   nContext = json_find_option_int("context",NULL,"c",5);
120   doSBS = json_find_option_bool("sbs",NULL,"y",0);
121   doHtml = json_find_option_bool("html",NULL,"h",0);
122   v = json_generate_diff(zFrom, zTo, nContext, doSBS, doHtml);
123   if(!v){
124     if(!g.json.resultCode){
125       json_set_err(FSL_JSON_E_UNKNOWN,
126                    "Generating diff failed for unknown reason.");
127     }
128     return NULL;
129   }
130   pay = cson_new_object();
131   cson_object_set(pay, "from", json_new_string(zFrom));
132   cson_object_set(pay, "to", json_new_string(zTo));
133   cson_object_set(pay, "diff", v);
134   v = 0;
135 
136   return pay ? cson_object_value(pay) : NULL;
137 }
138 
139 #endif /* FOSSIL_ENABLE_JSON */
140