Unify Copyright header indentation
[gpgol.git] / src / common_indep.c
1 /* common_indep.c - Common, platform indepentent routines used by GpgOL
2  * Copyright (C) 2005, 2007, 2008 g10 Code GmbH
3  * Copyright (C) 2016 by Bundesamt für Sicherheit in der Informationstechnik
4  * Software engineering by Intevation GmbH
5  *
6  * This file is part of GpgOL.
7  *
8  * GpgOL is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1
11  * of the License, or (at your option) any later version.
12  *
13  * GpgOL is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include "common_indep.h"
23 #ifdef HAVE_W32_SYSTEM
24 #include <windows.h>
25 #endif
26
27 #include <stdlib.h>
28 #include <ctype.h>
29
30 /* The base-64 list used for base64 encoding. */
31 static unsigned char bintoasc[64+1] = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
32                                        "abcdefghijklmnopqrstuvwxyz"
33                                        "0123456789+/");
34
35 /* The reverse base-64 list used for base-64 decoding. */
36 static unsigned char const asctobin[256] = {
37   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
38   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
39   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
40   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
41   0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
42   0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
43   0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
44   0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
45   0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
46   0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
47   0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
48   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
49   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
50   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
51   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
52   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
53   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
54   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
55   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
56   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
57   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
58   0xff, 0xff, 0xff, 0xff
59 };
60
61 void
62 out_of_core (void)
63 {
64 #ifdef HAVE_W32_SYSTEM
65   MessageBox (NULL, "Out of core!", "Fatal Error", MB_OK);
66 #endif
67   abort ();
68 }
69
70 void*
71 xmalloc (size_t n)
72 {
73   void *p = malloc (n);
74   if (!p)
75     out_of_core ();
76   return p;
77 }
78
79 void*
80 xcalloc (size_t m, size_t n)
81 {
82   void *p = calloc (m, n);
83   if (!p)
84     out_of_core ();
85   return p;
86 }
87
88 void *
89 xrealloc (void *a, size_t n)
90 {
91   void *p = realloc (a, n);
92   if (!p)
93     out_of_core ();
94   return p;
95 }
96
97 char*
98 xstrdup (const char *s)
99 {
100   char *p = xmalloc (strlen (s)+1);
101   strcpy (p, s);
102   return p;
103 }
104
105 void
106 xfree (void *p)
107 {
108   if (p)
109     free (p);
110 }
111
112 /* Strip off leading and trailing white spaces from STRING.  Returns
113    STRING. */
114 char *
115 trim_spaces (char *arg_string)
116 {
117   char *string = arg_string;
118   char *p, *mark;
119
120   /* Find first non space character. */
121   for (p = string; *p && isascii (*p) && isspace (*p) ; p++ )
122     ;
123   /* Move characters. */
124   for (mark = NULL; (*string = *p); string++, p++ )
125     {
126       if (isascii (*p) && isspace (*p))
127         {
128           if (!mark)
129             mark = string;
130         }
131       else
132         mark = NULL ;
133     }
134   if (mark)
135     *mark = 0;
136
137   return arg_string;
138 }
139 /* Assume STRING is a Latin-1 encoded and convert it to utf-8.
140    Returns a newly malloced UTF-8 string. */
141 char *
142 latin1_to_utf8 (const char *string)
143 {
144   const char *s;
145   char *buffer, *p;
146   size_t n;
147
148   for (s=string, n=0; *s; s++)
149     {
150       n++;
151       if (*s & 0x80)
152         n++;
153     }
154   buffer = xmalloc (n + 1);
155   for (s=string, p=buffer; *s; s++)
156     {
157       if (*s & 0x80)
158         {
159           *p++ = 0xc0 | ((*s >> 6) & 3);
160           *p++ = 0x80 | (*s & 0x3f);
161         }
162       else
163         *p++ = *s;
164     }
165   *p = 0;
166   return buffer;
167 }
168
169
170 /* This function is similar to strncpy().  However it won't copy more
171    than N - 1 characters and makes sure that a Nul is appended. With N
172    given as 0, nothing will happen.  With DEST given as NULL, memory
173    will be allocated using xmalloc (i.e. if it runs out of core the
174    function terminates).  Returns DEST or a pointer to the allocated
175    memory.  */
176 char *
177 mem2str (char *dest, const void *src, size_t n)
178 {
179   char *d;
180   const char *s;
181
182   if (n)
183     {
184       if (!dest)
185         dest = xmalloc (n);
186       d = dest;
187       s = src ;
188       for (n--; n && *s; n--)
189         *d++ = *s++;
190       *d = 0;
191     }
192   else if (!dest)
193     {
194       dest = xmalloc (1);
195       *dest = 0;
196     }
197
198   return dest;
199 }
200
201
202 /* Strip off trailing white spaces from STRING.  Returns STRING. */
203 char *
204 trim_trailing_spaces (char *string)
205 {
206   char *p, *mark;
207
208   for (mark=NULL, p=string; *p; p++)
209     {
210       if (strchr (" \t\r\n", *p ))
211         {
212           if (!mark)
213             mark = p;
214         }
215       else
216         mark = NULL;
217     }
218
219   if (mark)
220     *mark = 0;
221   return string;
222 }
223
224 /* Do in-place decoding of quoted-printable data of LENGTH in BUFFER.
225    Returns the new length of the buffer and stores true at R_SLBRK if
226    the line ended with a soft line break; false is stored if not.
227    This fucntion asssumes that a complete line is passed in
228    buffer.  */
229 size_t
230 qp_decode (char *buffer, size_t length, int *r_slbrk)
231 {
232   char *d, *s;
233
234   if (r_slbrk)
235     *r_slbrk = 0;
236
237   /* Fixme:  We should remove trailing white space first.  */
238   for (s=d=buffer; length; length--)
239     if (*s == '=')
240       {
241         if (length > 2 && hexdigitp (s+1) && hexdigitp (s+2))
242           {
243             s++;
244             *(unsigned char*)d++ = xtoi_2 (s);
245             s += 2;
246             length -= 2;
247           }
248         else if (length > 2 && s[1] == '\r' && s[2] == '\n')
249           {
250             /* Soft line break.  */
251             s += 3;
252             length -= 2;
253             if (r_slbrk && length == 1)
254               *r_slbrk = 1;
255           }
256         else if (length > 1 && s[1] == '\n')
257           {
258             /* Soft line break with only a Unix line terminator. */
259             s += 2;
260             length -= 1;
261             if (r_slbrk && length == 1)
262               *r_slbrk = 1;
263           }
264         else if (length == 1)
265           {
266             /* Soft line break at the end of the line. */
267             s += 1;
268             if (r_slbrk)
269               *r_slbrk = 1;
270           }
271         else
272           *d++ = *s++;
273       }
274     else
275       *d++ = *s++;
276
277   return d - buffer;
278 }
279
280 /* Return the a quoted printable encoded version of the
281    input string. If outlen is not null the size of the
282    quoted printable string is returned. String will be
283    malloced and zero terminated. Aborts if the output
284    is more then three times the size of the input.
285    This is only basic and does not handle mutliline data. */
286 char *
287 qp_encode (const char *input, size_t inlen, size_t *r_outlen)
288 {
289   size_t max_len = inlen * 3 +1;
290   char *outbuf = xmalloc (max_len);
291   size_t outlen = 0;
292   const unsigned char *p;
293
294   memset (outbuf, 0, max_len);
295
296   for (p = input; inlen; p++, inlen--)
297     {
298       if (*p >= '!' && *p <= '~' && *p != '=')
299         {
300           outbuf[outlen++] = *p;
301         }
302       else if (*p == ' ')
303         {
304           /* Outlook does it this way */
305           outbuf[outlen++] = '_';
306         }
307       else
308         {
309           outbuf[outlen++] = '=';
310           outbuf[outlen++] = tohex ((*p>>4)&15);
311           outbuf[outlen++] = tohex (*p&15);
312         }
313       if (outlen == max_len -1)
314         {
315           log_error ("Quoted printable too long. Bug.");
316           r_outlen = NULL;
317           xfree (outbuf);
318           return NULL;
319         }
320     }
321   if (r_outlen)
322     *r_outlen = outlen;
323   return outbuf;
324 }
325
326
327 /* Initialize the Base 64 decoder state.  */
328 void b64_init (b64_state_t *state)
329 {
330   state->idx = 0;
331   state->val = 0;
332   state->stop_seen = 0;
333   state->invalid_encoding = 0;
334 }
335
336
337 /* Do in-place decoding of base-64 data of LENGTH in BUFFER.  Returns
338    the new length of the buffer. STATE is required to return errors and
339    to maintain the state of the decoder.  */
340 size_t
341 b64_decode (b64_state_t *state, char *buffer, size_t length)
342 {
343   int idx = state->idx;
344   unsigned char val = state->val;
345   int c;
346   char *d, *s;
347
348   if (state->stop_seen)
349     return 0;
350
351   for (s=d=buffer; length; length--, s++)
352     {
353       if (*s == '\n' || *s == ' ' || *s == '\r' || *s == '\t')
354         continue;
355       if (*s == '=')
356         {
357           /* Pad character: stop */
358           if (idx == 1)
359             *d++ = val;
360           state->stop_seen = 1;
361           break;
362         }
363
364       if ((c = asctobin[*(unsigned char *)s]) == 255)
365         {
366           if (!state->invalid_encoding)
367             log_debug ("%s: invalid base64 character %02X at pos %d skipped\n",
368                        __func__, *(unsigned char*)s, (int)(s-buffer));
369           state->invalid_encoding = 1;
370           continue;
371         }
372
373       switch (idx)
374         {
375         case 0:
376           val = c << 2;
377           break;
378         case 1:
379           val |= (c>>4)&3;
380           *d++ = val;
381           val = (c<<4)&0xf0;
382           break;
383         case 2:
384           val |= (c>>2)&15;
385           *d++ = val;
386           val = (c<<6)&0xc0;
387           break;
388         case 3:
389           val |= c&0x3f;
390           *d++ = val;
391           break;
392         }
393       idx = (idx+1) % 4;
394     }
395
396
397   state->idx = idx;
398   state->val = val;
399   return d - buffer;
400 }
401
402
403 /* Base 64 encode the input. If input is null returns NULL otherwise
404    a pointer to the malloced encoded string. */
405 char *
406 b64_encode (const char *input, size_t length)
407 {
408   size_t out_len = 4 * ((length + 2) / 3);
409   char *ret;
410   int i, j;
411
412   if (!length || !input)
413     {
414       return NULL;
415     }
416   ret = xmalloc (out_len);
417   memset (ret, 0, out_len);
418
419   for (i = 0, j = 0; i < length;)
420     {
421       unsigned int a = i < length ? (unsigned char)input[i++] : 0;
422       unsigned int b = i < length ? (unsigned char)input[i++] : 0;
423       unsigned int c = i < length ? (unsigned char)input[i++] : 0;
424
425       unsigned int triple = (a << 0x10) + (b << 0x08) + c;
426
427       ret[j++] = bintoasc[(triple >> 3 * 6) & 0x3F];
428       ret[j++] = bintoasc[(triple >> 2 * 6) & 0x3F];
429       ret[j++] = bintoasc[(triple >> 1 * 6) & 0x3F];
430       ret[j++] = bintoasc[(triple >> 0 * 6) & 0x3F];
431     }
432
433   if (length % 3)
434     {
435       ret [j - 1] = '=';
436     }
437   if (length % 3 == 1)
438     {
439       ret [j - 2] = '=';
440     }
441
442   return ret;
443 }
444
445 /* Create a boundary.  Note that mimemaker.c knows about the structure
446    of the boundary (i.e. that it starts with "=-=") so that it can
447    protect against accidently used boundaries within the content.  */
448 char *
449 generate_boundary (char *buffer)
450 {
451   char *p = buffer;
452   int i;
453
454 #if RAND_MAX < (64*2*BOUNDARYSIZE)
455 #error RAND_MAX is way too small
456 #endif
457
458   *p++ = '=';
459   *p++ = '-';
460   *p++ = '=';
461   for (i=0; i < BOUNDARYSIZE-6; i++)
462     *p++ = bintoasc[rand () % 64];
463   *p++ = '=';
464   *p++ = '-';
465   *p++ = '=';
466   *p = 0;
467
468   return buffer;
469 }
470
471 /* The malloced name of the logfile and the logging stream.  If
472    LOGFILE is NULL, no logging is done. */
473 static char *logfile;
474 static FILE *logfp;
475
476 #ifdef HAVE_W32_SYSTEM
477
478 /* Acquire the mutex for logging.  Returns 0 on success. */
479 static int
480 lock_log (void)
481 {
482   int code = WaitForSingleObject (log_mutex, INFINITE);
483   return code != WAIT_OBJECT_0;
484 }
485
486 /* Release the mutex for logging. No error return is done because this
487    is a fatal error anyway and we have no means for proper
488    notification. */
489 static void
490 unlock_log (void)
491 {
492   ReleaseMutex (log_mutex);
493 }
494 #endif
495
496 const char *
497 get_log_file (void)
498 {
499   return logfile? logfile : "";
500 }
501
502 void
503 set_log_file (const char *name)
504 {
505 #ifdef HAVE_W32_SYSTEM
506   if (!lock_log ())
507     {
508 #endif
509       if (logfp)
510         {
511           fclose (logfp);
512           logfp = NULL;
513         }
514       xfree (logfile);
515       if (!name || *name == '\"' || !*name)
516         logfile = NULL;
517       else
518         logfile = xstrdup (name);
519 #ifdef HAVE_W32_SYSTEM
520       unlock_log ();
521     }
522 #endif
523 }
524
525 static void
526 do_log (const char *fmt, va_list a, int w32err, int err,
527         const void *buf, size_t buflen)
528 {
529   if (!logfile)
530     return;
531
532 #ifdef HAVE_W32_SYSTEM
533   if (lock_log ())
534     return;
535 #endif
536
537   if (!strcmp (logfile, "stdout"))
538     {
539       logfp = stdout;
540     }
541   else if (!strcmp (logfile, "stderr"))
542     {
543       logfp = stderr;
544     }
545   if (!logfp)
546     logfp = fopen (logfile, "a+");
547 #ifdef HAVE_W32_SYSTEM
548   if (!logfp)
549     {
550       unlock_log ();
551       return;
552     }
553
554   char time_str[9];
555   SYSTEMTIME utc_time;
556   GetSystemTime (&utc_time);
557   if (GetTimeFormatA (LOCALE_INVARIANT,
558                       TIME_FORCE24HOURFORMAT | LOCALE_USE_CP_ACP,
559                       &utc_time,
560                       "HH:mm:ss",
561                       time_str,
562                       9))
563     {
564       fprintf (logfp, "%s/%lu/",
565                time_str,
566                (unsigned long)GetCurrentThreadId ());
567     }
568   else
569     {
570       fprintf (logfp, "unknown/%lu/",
571                (unsigned long)GetCurrentThreadId ());
572     }
573 #endif
574
575   if (err == 1)
576     fputs ("ERROR/", logfp);
577   vfprintf (logfp, fmt, a);
578 #ifdef HAVE_W32_SYSTEM
579   if (w32err)
580     {
581       char tmpbuf[256];
582
583       FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, w32err,
584                      MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
585                      tmpbuf, sizeof (tmpbuf)-1, NULL);
586       fputs (": ", logfp);
587       if (*tmpbuf && tmpbuf[strlen (tmpbuf)-1] == '\n')
588         tmpbuf[strlen (tmpbuf)-1] = 0;
589       if (*tmpbuf && tmpbuf[strlen (tmpbuf)-1] == '\r')
590         tmpbuf[strlen (tmpbuf)-1] = 0;
591       fprintf (logfp, "%s (%d)", tmpbuf, w32err);
592     }
593 #endif
594   if (buf)
595     {
596       const unsigned char *p = (const unsigned char*)buf;
597
598       for ( ; buflen; buflen--, p++)
599         fprintf (logfp, "%02X", *p);
600       putc ('\n', logfp);
601     }
602   else if ( *fmt && fmt[strlen (fmt) - 1] != '\n')
603     putc ('\n', logfp);
604
605   fflush (logfp);
606 #ifdef HAVE_W32_SYSTEM
607   unlock_log ();
608 #endif
609 }
610
611 const char *
612 log_srcname (const char *file)
613 {
614   const char *s = strrchr (file, '/');
615   return s? s+1:file;
616 }
617
618 void
619 log_debug (const char *fmt, ...)
620 {
621   va_list a;
622
623   va_start (a, fmt);
624   do_log (fmt, a, 0, 0, NULL, 0);
625   va_end (a);
626 }
627
628 void
629 log_error (const char *fmt, ...)
630 {
631   va_list a;
632
633   va_start (a, fmt);
634   do_log (fmt, a, 0, 1, NULL, 0);
635   va_end (a);
636 }
637
638 void
639 log_vdebug (const char *fmt, va_list a)
640 {
641   do_log (fmt, a, 0, 0, NULL, 0);
642 }
643
644 void
645 log_hexdump (const void *buf, size_t buflen, const char *fmt, ...)
646 {
647   va_list a;
648
649   va_start (a, fmt);
650   do_log (fmt, a, 0, 2, buf, buflen);
651   va_end (a);
652 }
653
654 #ifdef HAVE_W32_SYSTEM
655 void
656 log_debug_w32 (int w32err, const char *fmt, ...)
657 {
658   va_list a;
659
660   if (w32err == -1)
661     w32err = GetLastError ();
662
663   va_start (a, fmt);
664   do_log (fmt, a, w32err, 0, NULL, 0);
665   va_end (a);
666 }
667
668 void
669 log_error_w32 (int w32err, const char *fmt, ...)
670 {
671   va_list a;
672
673   if (w32err == -1)
674     w32err = GetLastError ();
675
676   va_start (a, fmt);
677   do_log (fmt, a, w32err, 1, NULL, 0);
678   va_end (a);
679 }
680
681 static void
682 do_log_window_info (HWND window, int level)
683 {
684   char buf[1024+1];
685   char name[200];
686   int nname;
687   char *pname;
688   DWORD pid;
689
690   if (!window)
691     return;
692
693   GetWindowThreadProcessId (window, &pid);
694   if (pid != GetCurrentProcessId ())
695     return;
696
697   memset (buf, 0, sizeof (buf));
698   GetWindowText (window, buf, sizeof (buf)-1);
699   nname = GetClassName (window, name, sizeof (name)-1);
700   if (nname)
701     pname = name;
702   else
703     pname = NULL;
704
705   if (level == -1)
706     log_debug ("  parent=%p/%lu (%s) `%s'", window, (unsigned long)pid,
707                pname? pname:"", buf);
708   else
709     log_debug ("    %*shwnd=%p/%lu (%s) `%s'", level*2, "", window,
710                (unsigned long)pid, pname? pname:"", buf);
711 }
712
713
714 /* Helper to log_window_hierarchy.  */
715 static HWND
716 do_log_window_hierarchy (HWND parent, int level)
717 {
718   HWND child;
719
720   child = GetWindow (parent, GW_CHILD);
721   while (child)
722     {
723       do_log_window_info (child, level);
724       do_log_window_hierarchy (child, level+1);
725       child = GetNextWindow (child, GW_HWNDNEXT);
726     }
727
728   return NULL;
729 }
730
731
732 /* Print a debug message using the format string FMT followed by the
733    window hierarchy of WINDOW.  */
734 void
735 log_window_hierarchy (HWND window, const char *fmt, ...)
736 {
737   va_list a;
738
739   va_start (a, fmt);
740   do_log (fmt, a, 0, 0, NULL, 0);
741   va_end (a);
742   if (window)
743     {
744       do_log_window_info (window, -1);
745       do_log_window_hierarchy (window, 0);
746     }
747 }
748
749 void
750 set_default_key (const char *name)
751 {
752   if (!lock_log ())
753     {
754       if (!name || *name == '\"' || !*name)
755         {
756           xfree (opt.default_key);
757           opt.default_key = NULL;
758         }
759       else
760         {
761           xfree (opt.default_key);
762           opt.default_key = xstrdup (name);;
763         }
764       unlock_log ();
765     }
766 }
767 #endif