~ubuntu-branches/ubuntu/trusty/snowdrop/trusty-proposed

« back to all changes in this revision

Viewing changes to .pc/use-tls.patch/lang-eng.c

  • Committer: Bazaar Package Importer
  • Author(s): Arno Töll
  • Date: 2011-06-30 18:29:59 UTC
  • Revision ID: james.westby@ubuntu.com-20110630182959-92sg471gooknusnl
Tags: 0.02b-9
* QA upload.
* Push debhelper compatibility to v8
* Convert package to 3.0 (quilt) format
* Move man page to debian/ (thus, leave upstream source directory untouched)
* Track changes to upstream source in a quilt patch (use-tls.patch)
* Link as needed (-Wl,--as-needed, in link-as-needed.patch)
* Push Standards to the most recent version 3.9.2
* Fix "Very minor typo in manpage" fix several typos (Closes: #608868)
* Switch debian/copyright to DEP-5
* Use `pkg-config' in Makefile instead of `libgnutls-config'. The latter was
  obsolete since GnuTLS 2.7.12.1
* Provide future uploaders a hint in `debian/README.Debian-source' to learn
  about changes in the upstream tarball, as the original file is not ver-
  sioned

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 
 
3
   snowdrop - text watermarking and watermark recovery
 
4
   ---------------------------------------------------
 
5
 
 
6
   Copyright (C) 2002 by Michal Zalewski <lcamtuf@coredump.cx>
 
7
 
 
8
   This program is free software; you can redistribute it and/or modify
 
9
   it under the terms of the GNU General Public License as published by
 
10
   the Free Software Foundation; either version 2 of the License, or
 
11
   (at your option) any later version.
 
12
 
 
13
   As a special exception, this program may be linked with the
 
14
   OpenSSL library, despite that library's more restrictive license.
 
15
 
 
16
   English language backend.
 
17
 
 
18
*/
 
19
 
 
20
#include <stdio.h>
 
21
#include <stdlib.h>
 
22
#include <unistd.h>
 
23
#include <ctype.h>
 
24
#include <assert.h>
 
25
#include <string.h>
 
26
 
 
27
#ifdef USE_OPENSSL
 
28
#include <openssl/md5.h>
 
29
#else
 
30
#include <md5global.h>
 
31
#include <md5.h>
 
32
#define MD5_Init   MD5Init
 
33
#define MD5_Final  MD5Final
 
34
#define MD5_Update MD5Update
 
35
#endif /* USE_OPENSSL */
 
36
 
 
37
#include "language.h"
 
38
 
 
39
// Max synonym cache entries
 
40
#define MAXCACHE        4096
 
41
#define MAXSYN          16
 
42
 
 
43
// How often do you want typos (number of atoms)?
 
44
 
 
45
#ifndef ENG_FINE 
 
46
#define TYPORATIO       150
 
47
#else
 
48
#define TYPORATIO       500
 
49
#endif
 
50
 
 
51
static int   word_cnt;          // Original term counter
 
52
static char* use_quot;          // Close quotes using this string
 
53
static int   indent_val=-1;     // Indentation, if any
 
54
static char  prev_punct;        // Previous atom was a punctuation mark
 
55
static int   cur_size;          // Current input atom storage capacity
 
56
static int   cur_mod;           // Current input atom modification
 
57
static int   just_testing;      // Just teestiiing!
 
58
 
 
59
#define MOD_NONE        0       // No modification
 
60
#define MOD_SYNONYM     1       // Put a synonym
 
61
#define MOD_TYPO        2       // Make a typo
 
62
#define MOD_QUOTE       4       // Change quotes
 
63
#define MOD_PSPACE      5       // Add spaces
 
64
#define MOD_CAPS        7       // Capitalization
 
65
#define MOD_PERIOD      8       // ; -> .
 
66
#define MOD_DASH        9       // - -> 0xad
 
67
 
 
68
#define MAXWORD 1024
 
69
 
 
70
 
 
71
struct syncache {
 
72
  char* from;
 
73
  char* to[MAXSYN+1];
 
74
  char tcnt;
 
75
};
 
76
 
 
77
struct syncache scache[MAXCACHE+1];
 
78
int sctop;
 
79
 
 
80
struct sd_syns { char *from, *to, bid; };
 
81
static struct sd_syns syn[MAXWORD+1];
 
82
 
 
83
 
 
84
// Load synonym database, of course...
 
85
static void load_synonyms(void) {
 
86
  int line=0,added=0,z,m;
 
87
  char buf[MAXBUF+1];
 
88
  FILE* f;
 
89
 
 
90
  if (syn[0].from) return;
 
91
 
 
92
  if (getenv("SD_SYNONYMS")) {
 
93
    strcpy(buf,getenv("SD_SYNONYMS"));
 
94
    f=fopen(buf,"r");
 
95
  } else {
 
96
    sprintf(buf,"%s/.snowdrop/synonyms",getenv("HOME"));
 
97
    f=fopen(buf,"r");
 
98
    if (!f) f=fopen("/usr/share/snowdrop/synonyms","r");
 
99
    if (!f) f=fopen("synonyms","r");
 
100
  }
 
101
  if (!f) fatal("cannot find synonym dictionary (%s)",buf);
 
102
 
 
103
  while (fgets(buf,MAXBUF,f)) {
 
104
    char* bcop;
 
105
    char w1[MAXBUF], w2[MAXBUF],c;
 
106
    int i;
 
107
    line++;
 
108
    if (buf[strlen(buf)-1]=='\n') buf[strlen(buf)-1]=0;
 
109
    if (strchr(buf,'#')) *strchr(buf,'#')=0;
 
110
    bcop=buf;
 
111
    while (isspace(*bcop)) bcop++;
 
112
    if (!(*bcop)) continue;
 
113
    if (sscanf(buf,"%s %c %s",w1,&c,w2)!=3)
 
114
      fatal("malformed dictionary line %d [1]",line);
 
115
 
 
116
    if (!strcasecmp(w1,w2)) fatal("NOOP dictionary entry at line %d",line);
 
117
 
 
118
    i=0;
 
119
    while (syn[i].from) {
 
120
 
 
121
      if (!strcasecmp(syn[i].from,w1))
 
122
        if (!strcasecmp(syn[i].to,w2))
 
123
          fatal("duplicate dictionary entry for %s - %s at line %d",w1,w2,line);
 
124
 
 
125
      if (!strcasecmp(syn[i].from,w2))
 
126
        if (!strcasecmp(syn[i].to,w1))
 
127
          fatal("duplicate dictionary entry for %s - %s (reverse) at line %d",w1,w2,line);
 
128
 
 
129
      i++;
 
130
 
 
131
    }
 
132
 
 
133
    for (z=0;z<strlen(w1);z++) if (isupper(w1[z])) fatal("line %d: uppercase entry (%s)",line,w1);
 
134
    for (z=0;z<strlen(w2);z++) if (isupper(w2[z])) fatal("line %d: uppercase entry (%s)",line,w2);
 
135
 
 
136
    syn[i].from=strdup(w1);
 
137
    if (!syn[i].from) fatal("not enough memory");
 
138
    syn[i].to=strdup(w2);
 
139
    if (!syn[i].to) fatal("not enough memory");
 
140
 
 
141
    if (c=='>') syn[i].bid=0; else
 
142
    if (c=='|') syn[i].bid=1; else
 
143
      fatal("malformed dictionary line %d [2]",line);
 
144
    added++;
 
145
 
 
146
    // Add a synonym for w1 -> w2
 
147
 
 
148
    for (m=0;m<sctop;m++) if (!strcmp(scache[i].from,w1)) break;
 
149
    if (m==sctop) sctop++;
 
150
    if (sctop>=MAXCACHE) fatal("MAXCACHE exceeded");
 
151
 
 
152
    scache[m].from=syn[i].from;
 
153
    scache[m].to[(int)scache[m].tcnt]=syn[i].to;
 
154
    scache[m].tcnt++;
 
155
    if (scache[m].tcnt>=MAXSYN) fatal("MAXSYN for %s exceeded",w1);
 
156
 
 
157
    // Add a synonym for w2 -> w1 if bid
 
158
 
 
159
    if (syn[i].bid) {
 
160
      for (m=0;m<sctop;m++) if (!strcmp(scache[i].from,w2)) break;
 
161
      if (m==sctop) sctop++;
 
162
      if (sctop>=MAXCACHE) fatal("MAXCACHE exceeded");
 
163
  
 
164
      scache[m].from=syn[i].to;
 
165
      scache[m].to[(int)scache[m].tcnt]=syn[i].from;
 
166
      scache[m].tcnt++;
 
167
      if (scache[m].tcnt>=MAXSYN) fatal("MAXSYN for %s exceeded",w2);
 
168
      }
 
169
 
 
170
  }
 
171
 
 
172
  fclose(f);
 
173
  debug("[+] Loaded %d synonyms (%d lines parsed).\n",added,line);
 
174
 
 
175
}
 
176
 
 
177
static unsigned int got_md5;
 
178
 
 
179
unsigned int md5_importantstuff(void) {
 
180
  int i=0;
 
181
  unsigned int result[4];
 
182
  MD5_CTX kuku;
 
183
  load_synonyms();
 
184
  if (got_md5) return got_md5;
 
185
  MD5_Init(&kuku);
 
186
  while (syn[i].from) {
 
187
    MD5_Update(&kuku,&i,sizeof(int));
 
188
    MD5_Update(&kuku,syn[i].from,strlen(syn[i].from)+1);
 
189
    MD5_Update(&kuku,&syn[i].bid,1);
 
190
    MD5_Update(&kuku,syn[i].to,strlen(syn[i].to)+1);
 
191
    MD5_Update(&kuku,"-|-",3);
 
192
    i++;
 
193
  }
 
194
  MD5_Final((char*)result,&kuku);
 
195
  
 
196
  return got_md5=(result[0] ^ result[1] ^ result[2] ^ result[3]);
 
197
}
 
198
 
 
199
 
 
200
 
 
201
// Get the number of synonyms matching the term.
 
202
static int lookup_syn_cnt(const char* term) {
 
203
  int q=0;
 
204
  while (q<sctop) {
 
205
    if (!strcasecmp(scache[q].from,term)) return scache[q].tcnt;
 
206
    q++;
 
207
  }
 
208
  return 0;
 
209
}
 
210
 
 
211
 
 
212
static char caps[MAXBUF+1];
 
213
 
 
214
 
 
215
// Try to copy the capitalization scheme from original term...
 
216
// Assume that first letter is uppercase or all letters are uppercase.
 
217
// This if for compatibility with MOD_CAPS.
 
218
static char* handle_caps(const char* orig,const char* nterm) {
 
219
  int q=0;
 
220
 
 
221
  if (!nterm[0]) fatal("handle_caps with empty nterm");
 
222
 
 
223
  strcpy(caps,nterm);
 
224
 
 
225
  if (isupper(orig[0])) caps[0]=toupper(caps[0]);
 
226
 
 
227
  if (isupper(orig[1]) && orig[2])
 
228
    while (caps[q]) { caps[q]=toupper(caps[q]); q++; }
 
229
 
 
230
  return caps;
 
231
}
 
232
 
 
233
 
 
234
// Ok, give me the actual num-th synonym for 'term'.
 
235
static char* lookup_syn_no(const char* term,const int num) {
 
236
  int q=0;
 
237
  while (q<sctop) {
 
238
    if (!strcasecmp(scache[q].from,term)) return handle_caps(term,scache[q].to[num]);
 
239
    q++;
 
240
  }
 
241
  return 0;
 
242
}
 
243
 
 
244
 
 
245
static const char* input_data;
 
246
static int input_off;
 
247
static const char* water_data;
 
248
static int water_off;
 
249
 
 
250
static int cur_punct;
 
251
static int linesofar;  // How many things in this line?
 
252
static int atomsofar; // How many atoms in this line?
 
253
char resetinnext;
 
254
 
 
255
void  set_original(const char* buf) {
 
256
  if (!buf) fatal("set_original(NULL)");
 
257
  input_data=buf;
 
258
  input_off=0;
 
259
  water_off=0;
 
260
  load_synonyms();
 
261
 
 
262
  linesofar=0;
 
263
  atomsofar=0;
 
264
  resetinnext=0;
 
265
  just_testing=0;
 
266
  word_cnt=0;
 
267
  cur_punct=0;
 
268
  use_quot=0;
 
269
  indent_val=-1;
 
270
  prev_punct=0;
 
271
  cur_size=0;
 
272
  cur_mod=0;
 
273
}
 
274
 
 
275
 
 
276
void  set_watermarked(const char* buf) {
 
277
  if (!buf) fatal("set_watermarked(NULL)");
 
278
  if (!input_data) fatal("set_watermarked before set_original");
 
279
  water_data=buf;
 
280
  water_off=0;
 
281
}
 
282
 
 
283
 
 
284
char FOOBAR[]=".f00.b4r.";
 
285
 
 
286
static char orig_buf[MAXBUF+1];
 
287
 
 
288
 
 
289
char* get_orig_atom(void) {
 
290
  char* now=(char*)input_data+input_off, sth[2];
 
291
  unsigned char or;
 
292
  char* nospaced;
 
293
  if (!input_data) fatal("get_orig_atom before set_original");
 
294
 
 
295
  if (!*now) return 0;
 
296
 
 
297
  word_cnt++;
 
298
 
 
299
  prev_punct=cur_punct;
 
300
 
 
301
  if (resetinnext) { linesofar=0; atomsofar=0; resetinnext=0; }
 
302
 
 
303
  orig_buf[0]=0;
 
304
  // Duplicate spaces
 
305
  while (*now == ' ' || *now == '\t') {
 
306
#ifdef ENG_FINE
 
307
    strcat(orig_buf,*now==' '?" ":"\t");
 
308
#else
 
309
    strcat(orig_buf,*now==' '?" ":"        ");
 
310
#endif
 
311
    now++; 
 
312
  }
 
313
  nospaced=orig_buf+strlen(orig_buf);
 
314
  // Append next one character unconditionally.
 
315
  or=sth[0]=*now;
 
316
  sth[1]=0;
 
317
  strcat(orig_buf,sth);
 
318
  now++;
 
319
  // Certain chars should be kept together...
 
320
  if (!(or=='\'' || or=='`' || or==',')) or=0xff;
 
321
  if (or==0xff && !isalnum(sth[0])) or=0xfe;
 
322
 
 
323
contorig:
 
324
 
 
325
  // Copy the rest. Stop on something that does not belong.
 
326
  while ((or==0xff && isalnum(*now)) || (*now==or)) { 
 
327
    sth[0]=*now; 
 
328
    strcat(orig_buf,sth); 
 
329
    now++; 
 
330
  }
 
331
 
 
332
  // If we stopped because of ' surrounded by chars, continue.
 
333
  if (isalnum(*(now-1)) && *now=='\'' && isalnum(*(now+1))) {
 
334
    sth[0]=*now; 
 
335
    strcat(orig_buf,sth); 
 
336
    now++; 
 
337
    goto contorig;
 
338
  }   
 
339
 
 
340
  input_off=now-input_data;
 
341
  if (!*now) { if (!strlen(orig_buf)) return 0; }
 
342
 
 
343
  if (use_quot==FOOBAR) use_quot=0;
 
344
  if (use_quot && (*nospaced=='\'' || *nospaced=='"')) {
 
345
    int q=strlen(nospaced);
 
346
    strcpy(nospaced,use_quot);
 
347
    linesofar-=strlen(nospaced)-q;
 
348
    use_quot=FOOBAR;
 
349
  }
 
350
 
 
351
  if (indent_val!=-1) {
 
352
    if (orig_buf[0]==' ' && !linesofar) {
 
353
      char tmp[MAXBUF+1];
 
354
      int i;
 
355
      tmp[0]=0;
 
356
      for (i=0;i<indent_val;i++) strcat(tmp," ");
 
357
      strcat(tmp,nospaced);
 
358
      strcpy(orig_buf,tmp);
 
359
      linesofar-=indent_val;
 
360
    }
 
361
  }
 
362
 
 
363
  cur_punct=!isalnum(*nospaced);
 
364
  if (*nospaced=='\n') cur_punct=0;
 
365
 
 
366
  if (strchr(orig_buf,'\n')) resetinnext=1;
 
367
  else {
 
368
    linesofar+=strlen(orig_buf); 
 
369
    atomsofar++;
 
370
  }
 
371
 
 
372
  // Too late. Paragraph ended. You die.
 
373
  if (!linesofar && strchr(orig_buf,'\n')) {
 
374
    indent_val=-1; use_quot=0;
 
375
  }
 
376
 
 
377
  return orig_buf;
 
378
}
 
379
 
 
380
 
 
381
static char water_buf[MAXBUF+1];
 
382
 
 
383
char* get_water_atom(void) {
 
384
  char* now=(char*)water_data+water_off, sth[2];
 
385
  unsigned char or;
 
386
  char* nospaced;
 
387
  if (!water_data) fatal("get_water_atom before set_watermarked");
 
388
  if (!*now) return 0;
 
389
 
 
390
  water_buf[0]=0;
 
391
  // Duplicate spaces
 
392
  while (*now == ' ' || *now == '\t') {
 
393
    strcat(water_buf,*now==' '?" ":"\t");
 
394
    now++; 
 
395
  }
 
396
 
 
397
  nospaced=water_buf+strlen(water_buf);
 
398
  // Append next one character unconditionally.
 
399
  or=sth[0]=*now;
 
400
  sth[1]=0;
 
401
  strcat(water_buf,sth);
 
402
  now++;
 
403
  // Certain chars should be kept together...
 
404
  if (!(or=='\'' || or=='`' || or==',')) or=0xff;
 
405
  if (or==0xff && !isalnum(sth[0])) or=0xfe;
 
406
 
 
407
contwater:
 
408
 
 
409
  // Copy the rest. Stop on something that does not belong.
 
410
  while ((or==0xff && isalnum(*now)) || (*now==or)) { 
 
411
    sth[0]=*now; 
 
412
    strcat(water_buf,sth); 
 
413
    now++; 
 
414
  }
 
415
 
 
416
  // If we stopped because of ' surrounded by chars, continue.
 
417
  if (isalnum(*(now-1)) && *now=='\'' && isalnum(*(now+1))) {
 
418
    sth[0]=*now; 
 
419
    strcat(water_buf,sth); 
 
420
    now++; 
 
421
    goto contwater;
 
422
  }   
 
423
 
 
424
  water_off=now-water_data;
 
425
  if (!*now) { if (!strlen(water_buf)) return 0; }
 
426
 
 
427
  return water_buf;
 
428
}
 
429
 
 
430
 
 
431
 
 
432
#define CHECK_STOR(siz,id) if ((siz) >= top_storage) { \
 
433
                             mod_type=(id); top_storage=(siz); }
 
434
 
 
435
 
 
436
static inline int storcap(int max) {
 
437
  int bits=0,pw=1;
 
438
  while (max >= pw) {
 
439
    pw<<=1;
 
440
    bits++;
 
441
  }
 
442
  return bits-1;
 
443
}
 
444
 
 
445
 
 
446
static int mod_type;
 
447
 
 
448
int   get_storage(const char* orig, const int domain) {
 
449
  const char* text=orig;
 
450
  int tsp=0;
 
451
  int top_storage=0;
 
452
 
 
453
  if (!orig) fatal("get_storage(NULL...)");
 
454
  while (*text == ' ') {tsp++; text++; }
 
455
 
 
456
  switch (domain) {
 
457
    case DOMAIN_WHITE:
 
458
 
 
459
#ifndef ENG_FINE
 
460
      if (prev_punct && orig[0]==' ') { 
 
461
        CHECK_STOR(1,MOD_PSPACE);
 
462
      }
 
463
#endif
 
464
 
 
465
      if (strchr(orig,'\n')) {
 
466
#ifdef ENG_FINE
 
467
        if (linesofar>81) { CHECK_STOR(1,MOD_PSPACE); } else
 
468
        if (linesofar<76) CHECK_STOR(1,MOD_PSPACE);
 
469
#else
 
470
        if (linesofar>81) { CHECK_STOR(4,MOD_PSPACE); } else
 
471
        if (linesofar<79) CHECK_STOR(storcap(79-linesofar),MOD_PSPACE);
 
472
#endif
 
473
      }
 
474
 
 
475
      break;
 
476
 
 
477
    case DOMAIN_GRAMMAR:
 
478
 
 
479
      // FIXME: make typos a bit less predictable?
 
480
      if (!(word_cnt % TYPORATIO) && isalnum(*text)) {
 
481
#ifdef ENG_FINE
 
482
        CHECK_STOR(4,MOD_TYPO);
 
483
#else
 
484
        CHECK_STOR(5,MOD_TYPO);
 
485
#endif
 
486
      }
 
487
 
 
488
      break;
 
489
 
 
490
    case DOMAIN_FORMAT:
 
491
 
 
492
      // If the word has at least two uppercase letters,
 
493
      // either make it first-only or all uppercase. This gives us
 
494
      // one bit and would not break synonym capitalization.
 
495
      { int i,gu=0;
 
496
        for (i=0;i<strlen(text);i++) {
 
497
          if (isupper(text[i])) gu++;
 
498
        }
 
499
        if (gu > 1) CHECK_STOR(1,MOD_CAPS);
 
500
      }
 
501
 
 
502
#ifndef ENG_FINE
 
503
      // We can ruin some ;s ;-)
 
504
      if (*text==';') CHECK_STOR(1,MOD_PERIOD);
 
505
#endif
 
506
 
 
507
      // We can ruin some -s ;-)
 
508
      if (*text=='-' || *(unsigned char*)text==0xad) CHECK_STOR(1,MOD_DASH);
 
509
 
 
510
      // We can also mess with quotes. This is good.
 
511
      if (!use_quot)   
 
512
        if (!strcmp(text,"''") || !strcmp(text,"`") || !strcmp(text,"'") ||
 
513
            !strcmp(text,"``") || !strcmp(text,"\"") || !strcmp(text,",,")) CHECK_STOR(3,MOD_QUOTE);
 
514
 
 
515
      break;
 
516
 
 
517
    case DOMAIN_SYNONYMS:
 
518
      // Determine how many synonyms can be substituted for a word.
 
519
      // If any, add 1 to the number (as we can left the word unchanged,
 
520
      // as well). Now, determine largest power of two less or equal to
 
521
      // the number we got. This is our storage capacity.
 
522
 
 
523
      { int i;
 
524
        i=lookup_syn_cnt(text);
 
525
        if (i>0) {
 
526
          CHECK_STOR(storcap(i+1),MOD_SYNONYM);
 
527
        }
 
528
      }
 
529
      break;
 
530
 
 
531
    default: fatal("bogus domain in get_storage");
 
532
 
 
533
  }
 
534
 
 
535
  return top_storage;
 
536
 
 
537
}
 
538
 
 
539
static char setv[MAXBUF+1];
 
540
 
 
541
static char typovals[]="abcdefghijklmnopqrstuvwxyz0123456789";
 
542
 
 
543
 
 
544
char* set_value(const char* orig,int value, const int domain) {
 
545
  int cap,i;
 
546
  const char* text=orig;
 
547
  char* foo;
 
548
  cap=get_storage(orig,domain);
 
549
  if (cap <= 0) fatal("set_value with fixed atom");
 
550
  if (cap > 16) fatal("set_value with atom of excessive storage capacity");
 
551
  if (value >= (1<<cap)) fatal("set_value: new value exceeds storage capacity");
 
552
  if (value < 0) fatal("set_value: new value less than zero");
 
553
 
 
554
  setv[0]=0;
 
555
  while (*text == ' ') text++;
 
556
 
 
557
  switch (mod_type) {
 
558
 
 
559
    case MOD_PSPACE:
 
560
 
 
561
      // "Bite my shiny metal ass!"
 
562
      for (i=0;i<value+1;i++) strcat(setv," "); 
 
563
      strcat(setv,text);
 
564
      return setv;
 
565
 
 
566
    case MOD_TYPO:
 
567
 
 
568
        // There is a rare potential glitch here when capitalization
 
569
        // changes are ruined by digits. Should happen rarely, fix it
 
570
        // some day.
 
571
        strcpy(setv,orig);
 
572
        i=word_cnt % strlen(text);
 
573
        if (isupper(setv[text-orig+i]))
 
574
        setv[text-orig+i]=toupper(typovals[value]);
 
575
        else
 
576
        setv[text-orig+i]=typovals[value];
 
577
 
 
578
      return setv;
 
579
 
 
580
    case MOD_CAPS:
 
581
      strcpy(setv,orig);
 
582
      for (i=0;i<strlen(setv);i++) setv[i]=value?tolower(setv[i]):toupper(setv[i]);
 
583
      setv[text-orig]=toupper(setv[text-orig]);
 
584
      return setv;
 
585
 
 
586
    case MOD_PERIOD:
 
587
      strcpy(setv,orig);
 
588
      *strchr(setv,';')=value?';':'.';
 
589
      return setv;
 
590
 
 
591
    case MOD_DASH:
 
592
      strcpy(setv,orig);
 
593
      foo=strchr(setv,'-');
 
594
      if (!foo) foo=strchr(setv,0xad);
 
595
      *foo=value?'-':0xad;
 
596
      return setv;
 
597
 
 
598
    case MOD_QUOTE:
 
599
      i=0;
 
600
      while (orig[i]==' ') { strcat(setv," "); i++; }
 
601
      switch (value) {
 
602
         case 0: strcat(setv,"``"); if (!just_testing) use_quot="''"; break;
 
603
         case 1: strcat(setv,"''"); if (!just_testing) use_quot="''"; break;
 
604
         case 2: strcat(setv,"'");  if (!just_testing) use_quot="'"; break;
 
605
         case 3: strcat(setv,"`");  if (!just_testing) use_quot="'"; break;
 
606
         case 4: strcat(setv,"\""); if (!just_testing) use_quot="\""; break;
 
607
         case 5: strcat(setv,",,"); if (!just_testing) use_quot="''"; break;
 
608
         case 6: strcat(setv,"\xb4"); if (!just_testing) use_quot="\xb4"; break;
 
609
         case 7: strcat(setv,"\xbd"); if (!just_testing) use_quot="\xbd"; break;
 
610
         default: fatal("gremlins in the keyboard");
 
611
      }
 
612
      return setv;
 
613
 
 
614
    case MOD_SYNONYM:
 
615
 
 
616
      i=0;
 
617
      while (orig[i]==' ') { strcat(setv," "); i++; }
 
618
      if (!value) { strcat(setv,text); return setv; }
 
619
      strcat(setv,lookup_syn_no(text,value-1));
 
620
      return setv;
 
621
 
 
622
    default: fatal("bogus mod_type in set_value");
 
623
 
 
624
  }
 
625
 
 
626
  return setv;
 
627
 
 
628
}
 
629
 
 
630
 
 
631
char setval_copy[MAXBUF+1];
 
632
 
 
633
 
 
634
// Mooom! This is worse than terrible!
 
635
int strspcmp(const char* a,const char* b) {
 
636
  while (isspace(*a)) a++;
 
637
  while (isspace(*b)) b++;
 
638
  if (!*a || !*b) return 31337; // Bleh.
 
639
  return strcmp(a,b);
 
640
}
 
641
 
 
642
 
 
643
int strspcasecmp(const char* a,const char* b) {
 
644
  while (isspace(*a)) a++;
 
645
  while (isspace(*b)) b++;
 
646
  if (!*a || !*b) return 31337; // Bleh.
 
647
  return strcasecmp(a,b);
 
648
}
 
649
 
 
650
 
 
651
static int warned;
 
652
 
 
653
int get_value(const char* orig,const char* water,int* scr,int* va,char test) {
 
654
  int i3,i2,i1,i0;
 
655
  int sc[4];
 
656
  int cnt=0;
 
657
 
 
658
  if (!orig) fatal("get_value with orig==NULL");
 
659
  if (!water) fatal("get_value with water==NULL");
 
660
  if (!scr) fatal("get_value with sc==NULL");
 
661
  if (!va) fatal("get_value with va==NULL");
 
662
 
 
663
redome:
 
664
 
 
665
  // Enter dummy mode, save buffer.
 
666
  just_testing=1;
 
667
 
 
668
  sc[3]=get_storage(orig,3);
 
669
  sc[2]=get_storage(orig,2);
 
670
  sc[1]=get_storage(orig,1);
 
671
  sc[0]=get_storage(orig,0);
 
672
 
 
673
  for (i3=0;i3<(1<<sc[3]);i3++) {
 
674
    char b3[MAXBUF+1];    
 
675
    
 
676
    if (!sc[3]) strcpy(b3,orig); else strcpy(b3,set_value(orig,i3,3));
 
677
 
 
678
    for (i2=0;i2<(1<<sc[2]);i2++) {
 
679
      char b2[MAXBUF+1];    
 
680
      if (!sc[2]) strcpy(b2,b3); else strcpy(b2,set_value(b3,i2,2));
 
681
 
 
682
      for (i1=0;i1<(1<<sc[1]);i1++) {
 
683
        char b1[MAXBUF+1];    
 
684
        if (!sc[1]) strcpy(b1,b2); else strcpy(b1,set_value(b2,i1,1));
 
685
 
 
686
        for (i0=0;i0<(1<<sc[0]);i0++) {
 
687
          char b0[MAXBUF+1];    
 
688
          if (!sc[0]) strcpy(b0,b1); else strcpy(b0,set_value(b1,i0,0));
 
689
          // If final result matches...
 
690
          // First loop: just compare
 
691
          // Second loop: without spaces; compare with strnspcmp
 
692
          // Third loop: without spaces and grammar; compare with strnspcmp
 
693
          // Fourth loop: without spaces, grammar and notation; strnspcase...
 
694
          // Note that strnspcmp and strnspcasecmp return 0 if no non-space
 
695
          // characters are found to avoid stupid problems.
 
696
 
 
697
          if ((cnt==0 && !strcmp(water,b0)) ||
 
698
              (cnt==1 && !strspcmp(water,b1)) ||
 
699
              (cnt==2 && !strspcmp(water,b2)) ||
 
700
              (cnt==3 && !strspcasecmp(water,b3))) {
 
701
 
 
702
            just_testing=0;
 
703
 
 
704
            if (!test) {
 
705
              strcpy(setval_copy,setv);
 
706
              // Commit.
 
707
              if (sc[3]) set_value(orig,i3,3);
 
708
              if (sc[2]) set_value(orig,i2,2);
 
709
              if (sc[1]) set_value(orig,i1,1);
 
710
              if (sc[0]) set_value(orig,i0,0);
 
711
              strcpy(setv,setval_copy);
 
712
            }
 
713
            // Restore buffer...
 
714
            // Write capacities and values back...
 
715
            *(scr++)=sc[0]; *(va++)=i0;
 
716
            *(scr++)=sc[1]; *(va++)=i1;
 
717
            *(scr++)=sc[2]; *(va++)=i2;
 
718
            *(scr++)=sc[3]; *(va++)=i3;
 
719
            if (cnt && !warned) {
 
720
//              debug("[!] Data missing in certain channels (spell-checked or reformatted file?).\n");
 
721
              warned=1;
 
722
            }
 
723
            return 1;
 
724
          }
 
725
        }
 
726
      }
 
727
    }
 
728
  }
 
729
 
 
730
  cnt++;
 
731
  if (cnt<=3) goto redome;
 
732
 
 
733
  strcpy(setval_copy,setv);
 
734
 
 
735
  { 
 
736
    char wbuf[MAXBUF+1];
 
737
    strcpy(wbuf,orig);
 
738
    if (sc[3] && !test) {
 
739
      just_testing=0;
 
740
      strcpy(wbuf,set_value(wbuf,0,3));
 
741
      just_testing=1;
 
742
    }
 
743
 
 
744
    if (sc[2] && !test) {
 
745
      just_testing=0;
 
746
      strcpy(wbuf,set_value(wbuf,0,2));
 
747
      just_testing=1;
 
748
    }
 
749
 
 
750
    if (sc[1] && !test) {
 
751
      just_testing=0;
 
752
      strcpy(wbuf,set_value(wbuf,0,1));
 
753
      just_testing=1;
 
754
    }
 
755
 
 
756
    if (sc[0] && !test) {
 
757
      just_testing=0;
 
758
      strcpy(wbuf,set_value(wbuf,0,0));
 
759
      just_testing=1;
 
760
    }
 
761
  }
 
762
 
 
763
  strcpy(setv,setval_copy);
 
764
 
 
765
  just_testing=0;
 
766
 
 
767
  *(scr++)=sc[0];
 
768
  *(scr++)=sc[1];
 
769
  *(scr++)=sc[2];
 
770
  *(scr++)=sc[3];
 
771
 
 
772
  return 0;
 
773
}
 
774
 
 
775
 
 
776
int   get_water_pos(void) { return water_off; }
 
777
void  set_water_pos(int x) { water_off=x; }
 
778
 
 
779
 
 
780
 
 
781
char* get_langdesc(void) {
 
782
#ifdef ENG_FINE
 
783
  return "fine quality technical text";
 
784
#else
 
785
  return "draft / e-mail quality technical text";
 
786
#endif
 
787
}
 
788
 
 
789
 
 
790
void module_help(void) {
 
791
  debug("This module supports SD_SYNONYMS environment variable that should\n"
 
792
        "point to an alternative 'synonyms' file, if necessary. Make sure\n"
 
793
        "to keep the copy of used alternative file for further reference.\n");
 
794
}
 
795
 
 
796
 
 
797
void md5_wrong(void) {
 
798
  debug("You have used more than one synonyms file to generate your watermarks.\n"
 
799
        "Make sure you've passed the right one using SD_SYNONYMS environment\n"
 
800
        "variable.\n");
 
801
}