Fossil SCM

Finish implementing the configuration command by adding method implementations for "import", "reset", and "pull".

drh 2008-05-23 19:21 trunk
Commit 28e56282c91556de4dde4860cf2618e5fca42314
+1 -1
--- src/clone.c
+++ src/clone.c
@@ -75,11 +75,11 @@
7575
}
7676
db_finalize(&q);
7777
}else{
7878
url_enable_proxy(0);
7979
g.xlinkClusterOnly = 1;
80
- client_sync(0,0,1);
80
+ client_sync(0,0,1,CONFIGSET_ALL);
8181
g.xlinkClusterOnly = 0;
8282
}
8383
verify_cancel();
8484
db_end_transaction(0);
8585
db_close();
8686
--- src/clone.c
+++ src/clone.c
@@ -75,11 +75,11 @@
75 }
76 db_finalize(&q);
77 }else{
78 url_enable_proxy(0);
79 g.xlinkClusterOnly = 1;
80 client_sync(0,0,1);
81 g.xlinkClusterOnly = 0;
82 }
83 verify_cancel();
84 db_end_transaction(0);
85 db_close();
86
--- src/clone.c
+++ src/clone.c
@@ -75,11 +75,11 @@
75 }
76 db_finalize(&q);
77 }else{
78 url_enable_proxy(0);
79 g.xlinkClusterOnly = 1;
80 client_sync(0,0,1,CONFIGSET_ALL);
81 g.xlinkClusterOnly = 0;
82 }
83 verify_cancel();
84 db_end_transaction(0);
85 db_close();
86
+59 -14
--- src/configure.c
+++ src/configure.c
@@ -61,29 +61,50 @@
6161
** transfer.
6262
*/
6363
static struct {
6464
const char *zName; /* Name of the configuration parameter */
6565
int groupMask; /* Which config groups is it part of */
66
-} aSafeConfig[] = {
66
+} aConfig[] = {
6767
{ "css", CONFIGSET_SKIN },
6868
{ "header", CONFIGSET_SKIN },
6969
{ "footer", CONFIGSET_SKIN },
7070
{ "project-name", CONFIGSET_PROJ },
7171
{ "project-description", CONFIGSET_PROJ },
7272
{ "index-page", CONFIGSET_SKIN },
7373
{ "timeline-block-markup", CONFIGSET_SKIN },
7474
{ "timeline-max-comment", CONFIGSET_SKIN },
7575
};
76
+static int iConfig = 0;
77
+
78
+/*
79
+** Return name of first configuration property matching the given mask.
80
+*/
81
+const char *configure_first_name(int iMask){
82
+ iConfig = 0;
83
+ return configure_next_name(iMask);
84
+}
85
+const char *configure_next_name(int iMask){
86
+ while( iConfig<count(aConfig) ){
87
+ if( aConfig[iConfig].groupMask & iMask ){
88
+ return aConfig[iConfig++].zName;
89
+ }else{
90
+ iConfig++;
91
+ }
92
+ }
93
+ return 0;
94
+}
7695
7796
/*
7897
** Return TRUE if a particular configuration parameter zName is
7998
** safely exportable.
8099
*/
81100
int configure_is_exportable(const char *zName){
82101
int i;
83
- for(i=0; i<count(aSafeConfig); i++){
84
- if( strcmp(zName, aSafeConfig[i].zName)==0 ) return 1;
102
+ for(i=0; i<count(aConfig); i++){
103
+ if( strcmp(zName, aConfig[i].zName)==0 ){
104
+ return aConfig[i].groupMask;
105
+ }
85106
}
86107
return 0;
87108
}
88109
89110
/*
@@ -102,39 +123,39 @@
102123
return 0;
103124
}
104125
105126
106127
/*
107
-** COMMAND: configure
128
+** COMMAND: configuration
108129
**
109130
** Usage: %fossil configure METHOD ...
110131
**
111132
** Where METHOD is one of: export import pull reset. All methods
112133
** accept the -R or --repository option to specific a repository.
113134
**
114
-** %fossil config export AREA FILENAME
135
+** %fossil configuration export AREA FILENAME
115136
**
116137
** Write to FILENAME exported configuraton information for AREA.
117138
** AREA can be one of: all ticket skin project
118139
**
119
-** %fossil config import FILENAME
140
+** %fossil configuration import FILENAME
120141
**
121142
** Read a configuration from FILENAME, overwriting the current
122143
** configuration. Warning: Do not read a configuration from
123144
** an untrusted source since the configuration is not checked
124145
** for safety and can introduce security threats.
125146
**
126
-** %fossil config pull AREA URL
147
+** %fossil configuration pull AREA URL
127148
**
128149
** Pull and install the configuration from a different server
129150
** identified by URL. AREA is as in "export".
130151
**
131
-** %fossil configure reset AREA
152
+** %fossil configuration reset AREA
132153
**
133154
** Restore the configuration to the default. AREA as above.
134155
*/
135
-void configure_cmd(void){
156
+void configuration_cmd(void){
136157
int n;
137158
const char *zMethod;
138159
if( g.argc<3 ){
139160
usage("METHOD ...");
140161
}
@@ -158,39 +179,63 @@
158179
"SELECT 'REPLACE INTO config(name,value) VALUES('''"
159180
" || name || ''',' || quote(value) || ');'"
160181
" FROM config WHERE name IN "
161182
);
162183
zSep = "(";
163
- for(i=0; i<count(aSafeConfig); i++){
164
- if( aSafeConfig[i].groupMask & mask ){
165
- blob_appendf(&sql, "%s'%s'", zSep, aSafeConfig[i].zName);
184
+ for(i=0; i<count(aConfig); i++){
185
+ if( aConfig[i].groupMask & mask ){
186
+ blob_appendf(&sql, "%s'%s'", zSep, aConfig[i].zName);
166187
zSep = ",";
167188
}
168189
}
169190
blob_appendf(&sql, ") ORDER BY name");
170191
db_prepare(&q, blob_str(&sql));
171192
blob_reset(&sql);
172193
blob_appendf(&out,
173194
"-- The \"%s\" configuration exported from\n"
174195
"-- repository \"%s\"\n"
175
- "-- on %s\nBEGIN;\n",
196
+ "-- on %s\n",
176197
g.argv[3], g.zRepositoryName,
177198
db_text(0, "SELECT datetime('now')")
178199
);
179200
while( db_step(&q)==SQLITE_ROW ){
180201
blob_appendf(&out, "%s\n", db_column_text(&q, 0));
181202
}
182203
db_finalize(&q);
183
- blob_appendf(&out, "COMMIT;\n");
184204
blob_write_to_file(&out, g.argv[4]);
185205
blob_reset(&out);
186206
}else
187207
if( strncmp(zMethod, "import", n)==0 ){
208
+ Blob in;
209
+ if( g.argc!=4 ) usage("import FILENAME");
210
+ blob_read_from_file(&in, g.argv[3]);
211
+ db_begin_transaction();
212
+ db_multi_exec("%s", blob_str(&in));
213
+ db_end_transaction(0);
188214
}else
189215
if( strncmp(zMethod, "pull", n)==0 ){
216
+ int mask;
217
+ url_proxy_options();
218
+ if( g.argc!=5 ) usage("pull AREA URL");
219
+ mask = find_area(g.argv[3]);
220
+ url_parse(g.argv[4]);
221
+ if( g.urlIsFile ){
222
+ fossil_fatal("network sync only");
223
+ }
224
+ user_select();
225
+ client_sync(0,0,0,mask);
190226
}else
191227
if( strncmp(zMethod, "reset", n)==0 ){
228
+ int mask, i;
229
+ if( g.argc!=4 ) usage("reset AREA");
230
+ mask = find_area(g.argv[3]);
231
+ db_begin_transaction();
232
+ for(i=0; i<count(aConfig); i++){
233
+ if( (aConfig[i].groupMask & mask)==0 ) continue;
234
+ db_multi_exec("DELETE FROM config WHERE name=%Q", aConfig[i].zName);
235
+ }
236
+ db_end_transaction(0);
192237
}else
193238
{
194239
fossil_fatal("METHOD should be one of: export import pull reset");
195240
}
196241
}
197242
--- src/configure.c
+++ src/configure.c
@@ -61,29 +61,50 @@
61 ** transfer.
62 */
63 static struct {
64 const char *zName; /* Name of the configuration parameter */
65 int groupMask; /* Which config groups is it part of */
66 } aSafeConfig[] = {
67 { "css", CONFIGSET_SKIN },
68 { "header", CONFIGSET_SKIN },
69 { "footer", CONFIGSET_SKIN },
70 { "project-name", CONFIGSET_PROJ },
71 { "project-description", CONFIGSET_PROJ },
72 { "index-page", CONFIGSET_SKIN },
73 { "timeline-block-markup", CONFIGSET_SKIN },
74 { "timeline-max-comment", CONFIGSET_SKIN },
75 };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
77 /*
78 ** Return TRUE if a particular configuration parameter zName is
79 ** safely exportable.
80 */
81 int configure_is_exportable(const char *zName){
82 int i;
83 for(i=0; i<count(aSafeConfig); i++){
84 if( strcmp(zName, aSafeConfig[i].zName)==0 ) return 1;
 
 
85 }
86 return 0;
87 }
88
89 /*
@@ -102,39 +123,39 @@
102 return 0;
103 }
104
105
106 /*
107 ** COMMAND: configure
108 **
109 ** Usage: %fossil configure METHOD ...
110 **
111 ** Where METHOD is one of: export import pull reset. All methods
112 ** accept the -R or --repository option to specific a repository.
113 **
114 ** %fossil config export AREA FILENAME
115 **
116 ** Write to FILENAME exported configuraton information for AREA.
117 ** AREA can be one of: all ticket skin project
118 **
119 ** %fossil config import FILENAME
120 **
121 ** Read a configuration from FILENAME, overwriting the current
122 ** configuration. Warning: Do not read a configuration from
123 ** an untrusted source since the configuration is not checked
124 ** for safety and can introduce security threats.
125 **
126 ** %fossil config pull AREA URL
127 **
128 ** Pull and install the configuration from a different server
129 ** identified by URL. AREA is as in "export".
130 **
131 ** %fossil configure reset AREA
132 **
133 ** Restore the configuration to the default. AREA as above.
134 */
135 void configure_cmd(void){
136 int n;
137 const char *zMethod;
138 if( g.argc<3 ){
139 usage("METHOD ...");
140 }
@@ -158,39 +179,63 @@
158 "SELECT 'REPLACE INTO config(name,value) VALUES('''"
159 " || name || ''',' || quote(value) || ');'"
160 " FROM config WHERE name IN "
161 );
162 zSep = "(";
163 for(i=0; i<count(aSafeConfig); i++){
164 if( aSafeConfig[i].groupMask & mask ){
165 blob_appendf(&sql, "%s'%s'", zSep, aSafeConfig[i].zName);
166 zSep = ",";
167 }
168 }
169 blob_appendf(&sql, ") ORDER BY name");
170 db_prepare(&q, blob_str(&sql));
171 blob_reset(&sql);
172 blob_appendf(&out,
173 "-- The \"%s\" configuration exported from\n"
174 "-- repository \"%s\"\n"
175 "-- on %s\nBEGIN;\n",
176 g.argv[3], g.zRepositoryName,
177 db_text(0, "SELECT datetime('now')")
178 );
179 while( db_step(&q)==SQLITE_ROW ){
180 blob_appendf(&out, "%s\n", db_column_text(&q, 0));
181 }
182 db_finalize(&q);
183 blob_appendf(&out, "COMMIT;\n");
184 blob_write_to_file(&out, g.argv[4]);
185 blob_reset(&out);
186 }else
187 if( strncmp(zMethod, "import", n)==0 ){
 
 
 
 
 
 
188 }else
189 if( strncmp(zMethod, "pull", n)==0 ){
 
 
 
 
 
 
 
 
 
 
190 }else
191 if( strncmp(zMethod, "reset", n)==0 ){
 
 
 
 
 
 
 
 
 
192 }else
193 {
194 fossil_fatal("METHOD should be one of: export import pull reset");
195 }
196 }
197
--- src/configure.c
+++ src/configure.c
@@ -61,29 +61,50 @@
61 ** transfer.
62 */
63 static struct {
64 const char *zName; /* Name of the configuration parameter */
65 int groupMask; /* Which config groups is it part of */
66 } aConfig[] = {
67 { "css", CONFIGSET_SKIN },
68 { "header", CONFIGSET_SKIN },
69 { "footer", CONFIGSET_SKIN },
70 { "project-name", CONFIGSET_PROJ },
71 { "project-description", CONFIGSET_PROJ },
72 { "index-page", CONFIGSET_SKIN },
73 { "timeline-block-markup", CONFIGSET_SKIN },
74 { "timeline-max-comment", CONFIGSET_SKIN },
75 };
76 static int iConfig = 0;
77
78 /*
79 ** Return name of first configuration property matching the given mask.
80 */
81 const char *configure_first_name(int iMask){
82 iConfig = 0;
83 return configure_next_name(iMask);
84 }
85 const char *configure_next_name(int iMask){
86 while( iConfig<count(aConfig) ){
87 if( aConfig[iConfig].groupMask & iMask ){
88 return aConfig[iConfig++].zName;
89 }else{
90 iConfig++;
91 }
92 }
93 return 0;
94 }
95
96 /*
97 ** Return TRUE if a particular configuration parameter zName is
98 ** safely exportable.
99 */
100 int configure_is_exportable(const char *zName){
101 int i;
102 for(i=0; i<count(aConfig); i++){
103 if( strcmp(zName, aConfig[i].zName)==0 ){
104 return aConfig[i].groupMask;
105 }
106 }
107 return 0;
108 }
109
110 /*
@@ -102,39 +123,39 @@
123 return 0;
124 }
125
126
127 /*
128 ** COMMAND: configuration
129 **
130 ** Usage: %fossil configure METHOD ...
131 **
132 ** Where METHOD is one of: export import pull reset. All methods
133 ** accept the -R or --repository option to specific a repository.
134 **
135 ** %fossil configuration export AREA FILENAME
136 **
137 ** Write to FILENAME exported configuraton information for AREA.
138 ** AREA can be one of: all ticket skin project
139 **
140 ** %fossil configuration import FILENAME
141 **
142 ** Read a configuration from FILENAME, overwriting the current
143 ** configuration. Warning: Do not read a configuration from
144 ** an untrusted source since the configuration is not checked
145 ** for safety and can introduce security threats.
146 **
147 ** %fossil configuration pull AREA URL
148 **
149 ** Pull and install the configuration from a different server
150 ** identified by URL. AREA is as in "export".
151 **
152 ** %fossil configuration reset AREA
153 **
154 ** Restore the configuration to the default. AREA as above.
155 */
156 void configuration_cmd(void){
157 int n;
158 const char *zMethod;
159 if( g.argc<3 ){
160 usage("METHOD ...");
161 }
@@ -158,39 +179,63 @@
179 "SELECT 'REPLACE INTO config(name,value) VALUES('''"
180 " || name || ''',' || quote(value) || ');'"
181 " FROM config WHERE name IN "
182 );
183 zSep = "(";
184 for(i=0; i<count(aConfig); i++){
185 if( aConfig[i].groupMask & mask ){
186 blob_appendf(&sql, "%s'%s'", zSep, aConfig[i].zName);
187 zSep = ",";
188 }
189 }
190 blob_appendf(&sql, ") ORDER BY name");
191 db_prepare(&q, blob_str(&sql));
192 blob_reset(&sql);
193 blob_appendf(&out,
194 "-- The \"%s\" configuration exported from\n"
195 "-- repository \"%s\"\n"
196 "-- on %s\n",
197 g.argv[3], g.zRepositoryName,
198 db_text(0, "SELECT datetime('now')")
199 );
200 while( db_step(&q)==SQLITE_ROW ){
201 blob_appendf(&out, "%s\n", db_column_text(&q, 0));
202 }
203 db_finalize(&q);
 
204 blob_write_to_file(&out, g.argv[4]);
205 blob_reset(&out);
206 }else
207 if( strncmp(zMethod, "import", n)==0 ){
208 Blob in;
209 if( g.argc!=4 ) usage("import FILENAME");
210 blob_read_from_file(&in, g.argv[3]);
211 db_begin_transaction();
212 db_multi_exec("%s", blob_str(&in));
213 db_end_transaction(0);
214 }else
215 if( strncmp(zMethod, "pull", n)==0 ){
216 int mask;
217 url_proxy_options();
218 if( g.argc!=5 ) usage("pull AREA URL");
219 mask = find_area(g.argv[3]);
220 url_parse(g.argv[4]);
221 if( g.urlIsFile ){
222 fossil_fatal("network sync only");
223 }
224 user_select();
225 client_sync(0,0,0,mask);
226 }else
227 if( strncmp(zMethod, "reset", n)==0 ){
228 int mask, i;
229 if( g.argc!=4 ) usage("reset AREA");
230 mask = find_area(g.argv[3]);
231 db_begin_transaction();
232 for(i=0; i<count(aConfig); i++){
233 if( (aConfig[i].groupMask & mask)==0 ) continue;
234 db_multi_exec("DELETE FROM config WHERE name=%Q", aConfig[i].zName);
235 }
236 db_end_transaction(0);
237 }else
238 {
239 fossil_fatal("METHOD should be one of: export import pull reset");
240 }
241 }
242
+5 -5
--- src/sync.c
+++ src/sync.c
@@ -61,20 +61,20 @@
6161
printf("Autosync: http://%s:%d%s\n", g.urlName, g.urlPort, g.urlPath);
6262
}else{
6363
printf("Autosync: http://%s%s\n", g.urlName, g.urlPath);
6464
}
6565
url_enable_proxy("via proxy: ");
66
- client_sync((flags & AUTOSYNC_PUSH)!=0, 1, 0);
66
+ client_sync((flags & AUTOSYNC_PUSH)!=0, 1, 0, 0);
6767
}
6868
6969
/*
7070
** This routine processes the command-line argument for push, pull,
7171
** and sync. If a command-line argument is given, that is the URL
7272
** of a server to sync against. If no argument is given, use the
7373
** most recently synced URL. Remember the current URL for next time.
7474
*/
75
-static void process_sync_args(void){
75
+void process_sync_args(void){
7676
const char *zUrl = 0;
7777
url_proxy_options();
7878
db_find_and_open_repository(1);
7979
if( g.argc==2 ){
8080
zUrl = db_get("last-sync-url", 0);
@@ -122,11 +122,11 @@
122122
** specifies the TCP port of the server. The default port is
123123
** 80.
124124
*/
125125
void pull_cmd(void){
126126
process_sync_args();
127
- client_sync(0,1,0);
127
+ client_sync(0,1,0,0);
128128
}
129129
130130
/*
131131
** COMMAND: push
132132
**
@@ -135,11 +135,11 @@
135135
** Push changes in the local repository over into a remote repository.
136136
** See the "pull" command for additional information.
137137
*/
138138
void push_cmd(void){
139139
process_sync_args();
140
- client_sync(1,0,0);
140
+ client_sync(1,0,0,0);
141141
}
142142
143143
144144
/*
145145
** COMMAND: sync
@@ -150,7 +150,7 @@
150150
** the equivalent of running both "push" and "pull" at the same time.
151151
** See the "pull" command for additional information.
152152
*/
153153
void sync_cmd(void){
154154
process_sync_args();
155
- client_sync(1,1,0);
155
+ client_sync(1,1,0,0);
156156
}
157157
--- src/sync.c
+++ src/sync.c
@@ -61,20 +61,20 @@
61 printf("Autosync: http://%s:%d%s\n", g.urlName, g.urlPort, g.urlPath);
62 }else{
63 printf("Autosync: http://%s%s\n", g.urlName, g.urlPath);
64 }
65 url_enable_proxy("via proxy: ");
66 client_sync((flags & AUTOSYNC_PUSH)!=0, 1, 0);
67 }
68
69 /*
70 ** This routine processes the command-line argument for push, pull,
71 ** and sync. If a command-line argument is given, that is the URL
72 ** of a server to sync against. If no argument is given, use the
73 ** most recently synced URL. Remember the current URL for next time.
74 */
75 static void process_sync_args(void){
76 const char *zUrl = 0;
77 url_proxy_options();
78 db_find_and_open_repository(1);
79 if( g.argc==2 ){
80 zUrl = db_get("last-sync-url", 0);
@@ -122,11 +122,11 @@
122 ** specifies the TCP port of the server. The default port is
123 ** 80.
124 */
125 void pull_cmd(void){
126 process_sync_args();
127 client_sync(0,1,0);
128 }
129
130 /*
131 ** COMMAND: push
132 **
@@ -135,11 +135,11 @@
135 ** Push changes in the local repository over into a remote repository.
136 ** See the "pull" command for additional information.
137 */
138 void push_cmd(void){
139 process_sync_args();
140 client_sync(1,0,0);
141 }
142
143
144 /*
145 ** COMMAND: sync
@@ -150,7 +150,7 @@
150 ** the equivalent of running both "push" and "pull" at the same time.
151 ** See the "pull" command for additional information.
152 */
153 void sync_cmd(void){
154 process_sync_args();
155 client_sync(1,1,0);
156 }
157
--- src/sync.c
+++ src/sync.c
@@ -61,20 +61,20 @@
61 printf("Autosync: http://%s:%d%s\n", g.urlName, g.urlPort, g.urlPath);
62 }else{
63 printf("Autosync: http://%s%s\n", g.urlName, g.urlPath);
64 }
65 url_enable_proxy("via proxy: ");
66 client_sync((flags & AUTOSYNC_PUSH)!=0, 1, 0, 0);
67 }
68
69 /*
70 ** This routine processes the command-line argument for push, pull,
71 ** and sync. If a command-line argument is given, that is the URL
72 ** of a server to sync against. If no argument is given, use the
73 ** most recently synced URL. Remember the current URL for next time.
74 */
75 void process_sync_args(void){
76 const char *zUrl = 0;
77 url_proxy_options();
78 db_find_and_open_repository(1);
79 if( g.argc==2 ){
80 zUrl = db_get("last-sync-url", 0);
@@ -122,11 +122,11 @@
122 ** specifies the TCP port of the server. The default port is
123 ** 80.
124 */
125 void pull_cmd(void){
126 process_sync_args();
127 client_sync(0,1,0,0);
128 }
129
130 /*
131 ** COMMAND: push
132 **
@@ -135,11 +135,11 @@
135 ** Push changes in the local repository over into a remote repository.
136 ** See the "pull" command for additional information.
137 */
138 void push_cmd(void){
139 process_sync_args();
140 client_sync(1,0,0,0);
141 }
142
143
144 /*
145 ** COMMAND: sync
@@ -150,7 +150,7 @@
150 ** the equivalent of running both "push" and "pull" at the same time.
151 ** See the "pull" command for additional information.
152 */
153 void sync_cmd(void){
154 process_sync_args();
155 client_sync(1,1,0,0);
156 }
157
+36 -45
--- src/xfer.c
+++ src/xfer.c
@@ -24,39 +24,10 @@
2424
** This file contains code to implement the file transfer protocol.
2525
*/
2626
#include "config.h"
2727
#include "xfer.h"
2828
29
-#if INTERFACE
30
-/*
31
-** Configuration transfers occur in groups. These are the allowed
32
-** groupings:
33
-*/
34
-#define CONFIGSET_SKIN 0x000001 /* WWW interface appearance */
35
-#define CONFIGSET_TKT 0x000002 /* Ticket configuration */
36
-#define CONFIGSET_PROJ 0x000004 /* Project name */
37
-
38
-#endif /* INTERFACE */
39
-
40
-/*
41
-** The following is a list of settings that we are willing to
42
-** transfer.
43
-*/
44
-static struct {
45
- const char *zName; /* Name of the configuration parameter */
46
- int groupMask; /* Which config groups is it part of */
47
-} aSafeConfig[] = {
48
- { "css", CONFIGSET_SKIN },
49
- { "header", CONFIGSET_SKIN },
50
- { "footer", CONFIGSET_SKIN },
51
- { "project-name", CONFIGSET_PROJ },
52
- { "project-description", CONFIGSET_PROJ },
53
- { "index-page", CONFIGSET_SKIN },
54
- { "timeline-block-markup", CONFIGSET_SKIN },
55
- { "timeline-max-comment", CONFIGSET_SKIN },
56
-};
57
-
5829
/*
5930
** This structure holds information about the current state of either
6031
** a client or a server that is participating in xfer.
6132
*/
6233
typedef struct Xfer Xfer;
@@ -680,20 +651,16 @@
680651
if( blob_eq(&xfer.aToken[0], "reqconfig")
681652
&& xfer.nToken==2
682653
){
683654
if( g.okRead ){
684655
char *zName = blob_str(&xfer.aToken[1]);
685
- int i;
686
- for(i=0; i<count(aSafeConfig); i++){
687
- if( strcmp(aSafeConfig[i].zName, zName)==0 ){
688
- char *zValue = db_get(zName, 0);
689
- if( zValue ){
690
- blob_appendf(xfer.pOut, "config %s %d\n%s\n", zName,
691
- strlen(zValue), zValue);
692
- free(zValue);
693
- }
694
- break;
656
+ if( configure_is_exportable(zName) ){
657
+ char *zValue = db_get(zName, 0);
658
+ if( zValue ){
659
+ blob_appendf(xfer.pOut, "config %s %d\n%s\n", zName,
660
+ strlen(zValue), zValue);
661
+ free(zValue);
695662
}
696663
}
697664
}
698665
}else
699666
@@ -791,17 +758,19 @@
791758
**
792759
** Records are pushed to the server if pushFlag is true. Records
793760
** are pulled if pullFlag is true. A full sync occurs if both are
794761
** true.
795762
*/
796
-void client_sync(int pushFlag, int pullFlag, int cloneFlag){
763
+void client_sync(int pushFlag, int pullFlag, int cloneFlag, int configMask){
797764
int go = 1; /* Loop until zero */
798765
const char *zSCode = db_get("server-code", "x");
799766
const char *zPCode = db_get("project-code", 0);
800767
int nCard = 0; /* Number of cards sent or received */
801768
int nCycle = 0; /* Number of round trips to the server */
769
+ int size; /* Size of a config value */
802770
int nFileSend = 0;
771
+ int origConfigMask; /* Original value of configMask */
803772
int nFileRecv; /* Number of files received */
804773
int mxPhantomReq = 200; /* Max number of phantoms to request per comm */
805774
const char *zCookie; /* Server cookie */
806775
Blob send; /* Text we are sending to the server */
807776
Blob recv; /* Reply we got back from the server */
@@ -810,11 +779,11 @@
810779
memset(&xfer, 0, sizeof(xfer));
811780
xfer.pIn = &recv;
812781
xfer.pOut = &send;
813782
xfer.mxSend = db_get_int("max-upload", 250000);
814783
815
- assert( pushFlag || pullFlag || cloneFlag );
784
+ assert( pushFlag || pullFlag || cloneFlag || configMask );
816785
assert( !g.urlIsFile ); /* This only works for networking */
817786
818787
db_begin_transaction();
819788
db_multi_exec(
820789
"CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);"
@@ -822,10 +791,11 @@
822791
blobarray_zero(xfer.aToken, count(xfer.aToken));
823792
blob_zero(&send);
824793
blob_zero(&recv);
825794
blob_zero(&xfer.err);
826795
blob_zero(&xfer.line);
796
+ origConfigMask = configMask;
827797
828798
/*
829799
** Always begin with a clone, pull, or push message
830800
*/
831801
if( cloneFlag ){
@@ -863,10 +833,21 @@
863833
}
864834
if( pushFlag ){
865835
send_unsent(&xfer);
866836
nCard += send_unclustered(&xfer);
867837
}
838
+
839
+ /* Send configuration parameter requests */
840
+ if( configMask ){
841
+ const char *zName;
842
+ zName = configure_first_name(configMask);
843
+ while( zName ){
844
+ blob_appendf(&send, "reqconfig %s\n", zName);
845
+ zName = configure_next_name(configMask);
846
+ }
847
+ configMask = 0;
848
+ }
868849
869850
/* Exchange messages with the server */
870851
nFileSend = xfer.nFileSent + xfer.nDeltaSent;
871852
printf(zValueFormat, "Send:",
872853
blob_size(&send), nCard+xfer.nGimmeSent+xfer.nIGotSent,
@@ -976,14 +957,24 @@
976957
977958
/* config NAME SIZE \n CONTENT
978959
**
979960
** Receive a configuration value from the server.
980961
*/
981
- if( blob_eq(&xfer.aToken[0],"config") ){
982
- /* TBD: Extract name and content */
983
- /* Check to see if configuration name is authorized */
984
- /* Store content in the config table */
962
+ if( blob_eq(&xfer.aToken[0],"config") && xfer.nToken==3
963
+ && blob_is_int(&xfer.aToken[2], &size) ){
964
+ const char *zName = blob_str(&xfer.aToken[1]);
965
+ Blob content;
966
+ blob_zero(&content);
967
+ blob_extract(xfer.pIn, size, &content);
968
+ if( configure_is_exportable(zName) & origConfigMask ){
969
+ db_multi_exec(
970
+ "REPLACE INTO config(name,value) VALUES(%Q,%Q)",
971
+ zName, blob_str(&content)
972
+ );
973
+ }
974
+ blob_reset(&content);
975
+ blob_seek(xfer.pIn, 1, BLOB_SEEK_CUR);
985976
}else
986977
987978
988979
/* cookie TEXT
989980
**
990981
--- src/xfer.c
+++ src/xfer.c
@@ -24,39 +24,10 @@
24 ** This file contains code to implement the file transfer protocol.
25 */
26 #include "config.h"
27 #include "xfer.h"
28
29 #if INTERFACE
30 /*
31 ** Configuration transfers occur in groups. These are the allowed
32 ** groupings:
33 */
34 #define CONFIGSET_SKIN 0x000001 /* WWW interface appearance */
35 #define CONFIGSET_TKT 0x000002 /* Ticket configuration */
36 #define CONFIGSET_PROJ 0x000004 /* Project name */
37
38 #endif /* INTERFACE */
39
40 /*
41 ** The following is a list of settings that we are willing to
42 ** transfer.
43 */
44 static struct {
45 const char *zName; /* Name of the configuration parameter */
46 int groupMask; /* Which config groups is it part of */
47 } aSafeConfig[] = {
48 { "css", CONFIGSET_SKIN },
49 { "header", CONFIGSET_SKIN },
50 { "footer", CONFIGSET_SKIN },
51 { "project-name", CONFIGSET_PROJ },
52 { "project-description", CONFIGSET_PROJ },
53 { "index-page", CONFIGSET_SKIN },
54 { "timeline-block-markup", CONFIGSET_SKIN },
55 { "timeline-max-comment", CONFIGSET_SKIN },
56 };
57
58 /*
59 ** This structure holds information about the current state of either
60 ** a client or a server that is participating in xfer.
61 */
62 typedef struct Xfer Xfer;
@@ -680,20 +651,16 @@
680 if( blob_eq(&xfer.aToken[0], "reqconfig")
681 && xfer.nToken==2
682 ){
683 if( g.okRead ){
684 char *zName = blob_str(&xfer.aToken[1]);
685 int i;
686 for(i=0; i<count(aSafeConfig); i++){
687 if( strcmp(aSafeConfig[i].zName, zName)==0 ){
688 char *zValue = db_get(zName, 0);
689 if( zValue ){
690 blob_appendf(xfer.pOut, "config %s %d\n%s\n", zName,
691 strlen(zValue), zValue);
692 free(zValue);
693 }
694 break;
695 }
696 }
697 }
698 }else
699
@@ -791,17 +758,19 @@
791 **
792 ** Records are pushed to the server if pushFlag is true. Records
793 ** are pulled if pullFlag is true. A full sync occurs if both are
794 ** true.
795 */
796 void client_sync(int pushFlag, int pullFlag, int cloneFlag){
797 int go = 1; /* Loop until zero */
798 const char *zSCode = db_get("server-code", "x");
799 const char *zPCode = db_get("project-code", 0);
800 int nCard = 0; /* Number of cards sent or received */
801 int nCycle = 0; /* Number of round trips to the server */
 
802 int nFileSend = 0;
 
803 int nFileRecv; /* Number of files received */
804 int mxPhantomReq = 200; /* Max number of phantoms to request per comm */
805 const char *zCookie; /* Server cookie */
806 Blob send; /* Text we are sending to the server */
807 Blob recv; /* Reply we got back from the server */
@@ -810,11 +779,11 @@
810 memset(&xfer, 0, sizeof(xfer));
811 xfer.pIn = &recv;
812 xfer.pOut = &send;
813 xfer.mxSend = db_get_int("max-upload", 250000);
814
815 assert( pushFlag || pullFlag || cloneFlag );
816 assert( !g.urlIsFile ); /* This only works for networking */
817
818 db_begin_transaction();
819 db_multi_exec(
820 "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);"
@@ -822,10 +791,11 @@
822 blobarray_zero(xfer.aToken, count(xfer.aToken));
823 blob_zero(&send);
824 blob_zero(&recv);
825 blob_zero(&xfer.err);
826 blob_zero(&xfer.line);
 
827
828 /*
829 ** Always begin with a clone, pull, or push message
830 */
831 if( cloneFlag ){
@@ -863,10 +833,21 @@
863 }
864 if( pushFlag ){
865 send_unsent(&xfer);
866 nCard += send_unclustered(&xfer);
867 }
 
 
 
 
 
 
 
 
 
 
 
868
869 /* Exchange messages with the server */
870 nFileSend = xfer.nFileSent + xfer.nDeltaSent;
871 printf(zValueFormat, "Send:",
872 blob_size(&send), nCard+xfer.nGimmeSent+xfer.nIGotSent,
@@ -976,14 +957,24 @@
976
977 /* config NAME SIZE \n CONTENT
978 **
979 ** Receive a configuration value from the server.
980 */
981 if( blob_eq(&xfer.aToken[0],"config") ){
982 /* TBD: Extract name and content */
983 /* Check to see if configuration name is authorized */
984 /* Store content in the config table */
 
 
 
 
 
 
 
 
 
 
985 }else
986
987
988 /* cookie TEXT
989 **
990
--- src/xfer.c
+++ src/xfer.c
@@ -24,39 +24,10 @@
24 ** This file contains code to implement the file transfer protocol.
25 */
26 #include "config.h"
27 #include "xfer.h"
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29 /*
30 ** This structure holds information about the current state of either
31 ** a client or a server that is participating in xfer.
32 */
33 typedef struct Xfer Xfer;
@@ -680,20 +651,16 @@
651 if( blob_eq(&xfer.aToken[0], "reqconfig")
652 && xfer.nToken==2
653 ){
654 if( g.okRead ){
655 char *zName = blob_str(&xfer.aToken[1]);
656 if( configure_is_exportable(zName) ){
657 char *zValue = db_get(zName, 0);
658 if( zValue ){
659 blob_appendf(xfer.pOut, "config %s %d\n%s\n", zName,
660 strlen(zValue), zValue);
661 free(zValue);
 
 
 
 
662 }
663 }
664 }
665 }else
666
@@ -791,17 +758,19 @@
758 **
759 ** Records are pushed to the server if pushFlag is true. Records
760 ** are pulled if pullFlag is true. A full sync occurs if both are
761 ** true.
762 */
763 void client_sync(int pushFlag, int pullFlag, int cloneFlag, int configMask){
764 int go = 1; /* Loop until zero */
765 const char *zSCode = db_get("server-code", "x");
766 const char *zPCode = db_get("project-code", 0);
767 int nCard = 0; /* Number of cards sent or received */
768 int nCycle = 0; /* Number of round trips to the server */
769 int size; /* Size of a config value */
770 int nFileSend = 0;
771 int origConfigMask; /* Original value of configMask */
772 int nFileRecv; /* Number of files received */
773 int mxPhantomReq = 200; /* Max number of phantoms to request per comm */
774 const char *zCookie; /* Server cookie */
775 Blob send; /* Text we are sending to the server */
776 Blob recv; /* Reply we got back from the server */
@@ -810,11 +779,11 @@
779 memset(&xfer, 0, sizeof(xfer));
780 xfer.pIn = &recv;
781 xfer.pOut = &send;
782 xfer.mxSend = db_get_int("max-upload", 250000);
783
784 assert( pushFlag || pullFlag || cloneFlag || configMask );
785 assert( !g.urlIsFile ); /* This only works for networking */
786
787 db_begin_transaction();
788 db_multi_exec(
789 "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);"
@@ -822,10 +791,11 @@
791 blobarray_zero(xfer.aToken, count(xfer.aToken));
792 blob_zero(&send);
793 blob_zero(&recv);
794 blob_zero(&xfer.err);
795 blob_zero(&xfer.line);
796 origConfigMask = configMask;
797
798 /*
799 ** Always begin with a clone, pull, or push message
800 */
801 if( cloneFlag ){
@@ -863,10 +833,21 @@
833 }
834 if( pushFlag ){
835 send_unsent(&xfer);
836 nCard += send_unclustered(&xfer);
837 }
838
839 /* Send configuration parameter requests */
840 if( configMask ){
841 const char *zName;
842 zName = configure_first_name(configMask);
843 while( zName ){
844 blob_appendf(&send, "reqconfig %s\n", zName);
845 zName = configure_next_name(configMask);
846 }
847 configMask = 0;
848 }
849
850 /* Exchange messages with the server */
851 nFileSend = xfer.nFileSent + xfer.nDeltaSent;
852 printf(zValueFormat, "Send:",
853 blob_size(&send), nCard+xfer.nGimmeSent+xfer.nIGotSent,
@@ -976,14 +957,24 @@
957
958 /* config NAME SIZE \n CONTENT
959 **
960 ** Receive a configuration value from the server.
961 */
962 if( blob_eq(&xfer.aToken[0],"config") && xfer.nToken==3
963 && blob_is_int(&xfer.aToken[2], &size) ){
964 const char *zName = blob_str(&xfer.aToken[1]);
965 Blob content;
966 blob_zero(&content);
967 blob_extract(xfer.pIn, size, &content);
968 if( configure_is_exportable(zName) & origConfigMask ){
969 db_multi_exec(
970 "REPLACE INTO config(name,value) VALUES(%Q,%Q)",
971 zName, blob_str(&content)
972 );
973 }
974 blob_reset(&content);
975 blob_seek(xfer.pIn, 1, BLOB_SEEK_CUR);
976 }else
977
978
979 /* cookie TEXT
980 **
981

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button