LCOV - code coverage report
Current view: top level - common - helpfile.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 99 0.0 %
Date: 2016-09-12 13:01:59 Functions: 0 3 0.0 %

          Line data    Source code
       1             : /* helpfile.c - GnuPG's helpfile feature
       2             :  *      Copyright (C) 2007 Free Software Foundation, Inc.
       3             :  *
       4             :  * This file is part of GnuPG.
       5             :  *
       6             :  * This file is free software; you can redistribute it and/or modify
       7             :  * it under the terms of either
       8             :  *
       9             :  *   - the GNU Lesser General Public License as published by the Free
      10             :  *     Software Foundation; either version 3 of the License, or (at
      11             :  *     your option) any later version.
      12             :  *
      13             :  * or
      14             :  *
      15             :  *   - the GNU General Public License as published by the Free
      16             :  *     Software Foundation; either version 2 of the License, or (at
      17             :  *     your option) any later version.
      18             :  *
      19             :  * or both in parallel, as here.
      20             :  *
      21             :  * This file is distributed in the hope that it will be useful,
      22             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      23             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      24             :  * GNU General Public License for more details.
      25             :  *
      26             :  * You should have received a copy of the GNU General Public License
      27             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      28             :  */
      29             : 
      30             : #include <config.h>
      31             : #include <stdlib.h>
      32             : 
      33             : 
      34             : #include "util.h"
      35             : #include "i18n.h"
      36             : #include "membuf.h"
      37             : 
      38             : 
      39             : /* Try to find KEY in the file FNAME.  */
      40             : static char *
      41           0 : findkey_fname (const char *key, const char *fname)
      42             : {
      43           0 :   gpg_error_t err = 0;
      44             :   FILE *fp;
      45           0 :   int lnr = 0;
      46             :   int c;
      47             :   char *p, line[256];
      48           0 :   int in_item = 0;
      49           0 :   membuf_t mb = MEMBUF_ZERO;
      50             : 
      51           0 :   fp = fopen (fname, "r");
      52           0 :   if (!fp)
      53             :     {
      54           0 :       if (errno != ENOENT)
      55             :         {
      56           0 :           err = gpg_error_from_syserror ();
      57           0 :           log_error (_("can't open '%s': %s\n"), fname, gpg_strerror (err));
      58             :         }
      59           0 :       return NULL;
      60             :     }
      61             : 
      62           0 :   while (fgets (line, DIM(line)-1, fp))
      63             :     {
      64           0 :       lnr++;
      65             : 
      66           0 :       if (!*line || line[strlen(line)-1] != '\n')
      67             :         {
      68             :           /* Eat until end of line. */
      69           0 :           while ( (c=getc (fp)) != EOF && c != '\n')
      70             :             ;
      71           0 :           err = gpg_error (*line? GPG_ERR_LINE_TOO_LONG
      72             :                            : GPG_ERR_INCOMPLETE_LINE);
      73           0 :           log_error (_("file '%s', line %d: %s\n"),
      74             :                      fname, lnr, gpg_strerror (err));
      75             :         }
      76             :       else
      77           0 :         line[strlen(line)-1] = 0; /* Chop the LF. */
      78             : 
      79             :     again:
      80           0 :       if (!in_item)
      81             :         {
      82             :           /* Allow for empty lines and spaces while not in an item. */
      83           0 :           for (p=line; spacep (p); p++)
      84             :             ;
      85           0 :           if (!*p || *p == '#')
      86           0 :             continue;
      87           0 :           if (*line != '.' || spacep(line+1))
      88             :             {
      89           0 :               log_info (_("file '%s', line %d: %s\n"),
      90             :                         fname, lnr, _("ignoring garbage line"));
      91           0 :               continue;
      92             :             }
      93           0 :           trim_trailing_spaces (line);
      94           0 :           in_item = 1;
      95           0 :           if (!strcmp (line+1, key))
      96             :             {
      97             :               /* Found.  Start collecting.  */
      98           0 :               init_membuf (&mb, 1024);
      99             :             }
     100           0 :           continue;
     101             :         }
     102             : 
     103             :       /* If in an item only allow for comments in the first column
     104             :          and provide ". " as an escape sequence to allow for
     105             :          leading dots and hash marks in the actual text.  */
     106           0 :       if (*line == '#')
     107           0 :         continue;
     108           0 :       if (*line == '.')
     109             :         {
     110           0 :           if (spacep(line+1))
     111           0 :             p = line + 2;
     112             :           else
     113             :             {
     114           0 :               trim_trailing_spaces (line);
     115           0 :               in_item = 0;
     116           0 :               if (is_membuf_ready (&mb))
     117             :                 break;        /* Yep, found and collected the item.  */
     118           0 :               if (!line[1])
     119           0 :                 continue;     /* Just an end of text dot. */
     120           0 :               goto again;     /* A new key line.  */
     121             :             }
     122             :         }
     123             :       else
     124           0 :         p = line;
     125             : 
     126           0 :       if (is_membuf_ready (&mb))
     127             :         {
     128           0 :           put_membuf_str (&mb, p);
     129           0 :           put_membuf (&mb, "\n", 1);
     130             :         }
     131             : 
     132             :     }
     133           0 :   if ( !err && ferror (fp) )
     134             :     {
     135           0 :       err = gpg_error_from_syserror ();
     136           0 :       log_error (_("error reading '%s', line %d: %s\n"),
     137             :                  fname, lnr, gpg_strerror (err));
     138             :     }
     139             : 
     140           0 :   fclose (fp);
     141           0 :   if (is_membuf_ready (&mb))
     142             :     {
     143             :       /* We have collected something.  */
     144           0 :       if (err)
     145             :         {
     146           0 :           xfree (get_membuf (&mb, NULL));
     147           0 :           return NULL;
     148             :         }
     149             :       else
     150             :         {
     151           0 :           put_membuf (&mb, "", 1);  /* Terminate string.  */
     152           0 :           return get_membuf (&mb, NULL);
     153             :         }
     154             :     }
     155             :   else
     156           0 :     return NULL;
     157             : }
     158             : 
     159             : 
     160             : /* Try the help files depending on the locale.  */
     161             : static char *
     162           0 : findkey_locale (const char *key, const char *locname,
     163             :                 int only_current_locale, const char *dirname)
     164             : {
     165             :   const char *s;
     166             :   char *fname, *ext, *p;
     167             :   char *result;
     168             : 
     169           0 :   fname = xtrymalloc (strlen (dirname) + 6 + strlen (locname) + 4 + 1);
     170           0 :   if (!fname)
     171           0 :     return NULL;
     172           0 :   ext = stpcpy (stpcpy (fname, dirname), "/help.");
     173             :   /* Search with locale name and territory.  ("help.LL_TT.txt") */
     174           0 :   if (strchr (locname, '_'))
     175             :     {
     176           0 :       strcpy (stpcpy (ext, locname), ".txt");
     177           0 :       result = findkey_fname (key, fname);
     178             :     }
     179             :   else
     180           0 :     result = NULL;  /* No territory.  */
     181             : 
     182           0 :   if (!result)
     183             :     {
     184             :       /* Search with just the locale name - if any. ("help.LL.txt") */
     185           0 :       if (*locname)
     186             :         {
     187           0 :           for (p=ext, s=locname; *s && *s != '_';)
     188           0 :             *p++ = *s++;
     189           0 :           strcpy (p, ".txt");
     190           0 :           result = findkey_fname (key, fname);
     191             :         }
     192             :       else
     193           0 :         result = NULL;
     194             :     }
     195             : 
     196           0 :   if (!result && (!only_current_locale || !*locname) )
     197             :     {
     198             :       /* Last try: Search in file without any locale info.  ("help.txt") */
     199           0 :       strcpy (ext, "txt");
     200           0 :       result = findkey_fname (key, fname);
     201             :     }
     202             : 
     203           0 :   xfree (fname);
     204           0 :   return result;
     205             : }
     206             : 
     207             : 
     208             : /* Return a malloced help text as identified by KEY.  The system takes
     209             :    the string from an UTF-8 encoded file to be created by an
     210             :    administrator or as distributed with GnuPG.  On a GNU or Unix
     211             :    system the entry is searched in these files:
     212             : 
     213             :      /etc/gnupg/help.LL.txt
     214             :      /etc/gnupg/help.txt
     215             :      /usr/share/gnupg/help.LL.txt
     216             :      /usr/share/gnupg/help.txt
     217             : 
     218             :    Here LL denotes the two digit language code of the current locale.
     219             :    If ONLY_CURRENT_LOCALE is set, the function won't fallback to the
     220             :    english valiant ("help.txt") unless that locale has been requested.
     221             : 
     222             :    The help file needs to be encoded in UTF-8, lines with a '#' in the
     223             :    first column are comment lines and entirely ignored.  Help keys are
     224             :    identified by a key consisting of a single word with a single dot
     225             :    as the first character.  All key lines listed without any
     226             :    intervening lines (except for comment lines) lead to the same help
     227             :    text.  Lines following the key lines make up the actual hep texts.
     228             : 
     229             : */
     230             : 
     231             : char *
     232           0 : gnupg_get_help_string (const char *key, int only_current_locale)
     233             : {
     234             :   static const char *locname;
     235             :   char *result;
     236             : 
     237           0 :   if (!locname)
     238             :     {
     239             :       char *buffer, *p;
     240           0 :       int count = 0;
     241           0 :       const char *s = gnupg_messages_locale_name ();
     242           0 :       buffer = xtrystrdup (s);
     243           0 :       if (!buffer)
     244           0 :         locname = "";
     245             :       else
     246             :         {
     247           0 :           for (p = buffer; *p; p++)
     248           0 :             if (*p == '.' || *p == '@' || *p == '/' /*(safeguard)*/)
     249           0 :               *p = 0;
     250           0 :             else if (*p == '_')
     251             :               {
     252           0 :                 if (count++)
     253           0 :                   *p = 0;  /* Also cut at a underscore in the territory.  */
     254             :               }
     255           0 :           locname = buffer;
     256             :         }
     257             :     }
     258             : 
     259           0 :   if (!key || !*key)
     260           0 :     return NULL;
     261             : 
     262           0 :   result = findkey_locale (key, locname, only_current_locale,
     263             :                            gnupg_sysconfdir ());
     264           0 :   if (!result)
     265           0 :     result = findkey_locale (key, locname, only_current_locale,
     266             :                              gnupg_datadir ());
     267             : 
     268           0 :   if (result)
     269           0 :     trim_trailing_spaces (result);
     270             : 
     271           0 :   return result;
     272             : }

Generated by: LCOV version 1.11