(root)/
gettext-0.22.4/
gettext-tools/
src/
msgl-header.c
       1  /* Message list header manipulation.
       2     Copyright (C) 2007, 2016-2017 Free Software Foundation, Inc.
       3     Written by Bruno Haible <bruno@clisp.org>, 2007.
       4  
       5     This program is free software: you can redistribute it and/or modify
       6     it under the terms of the GNU General Public License as published by
       7     the Free Software Foundation; either version 3 of the License, or
       8     (at your option) any later version.
       9  
      10     This program is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13     GNU General Public License for more details.
      14  
      15     You should have received a copy of the GNU General Public License
      16     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      17  
      18  
      19  #ifdef HAVE_CONFIG_H
      20  # include "config.h"
      21  #endif
      22  
      23  /* Specification.  */
      24  #include "msgl-header.h"
      25  
      26  #include <string.h>
      27  
      28  #include "xalloc.h"
      29  
      30  #define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
      31  
      32  
      33  /* The known fields in their usual order.  */
      34  static const struct
      35  {
      36    const char *name;
      37    size_t len;
      38  }
      39  known_fields[] =
      40    {
      41      { "Project-Id-Version:", sizeof ("Project-Id-Version:") - 1 },
      42      { "Report-Msgid-Bugs-To:", sizeof ("Report-Msgid-Bugs-To:") - 1 },
      43      { "POT-Creation-Date:", sizeof ("POT-Creation-Date:") - 1 },
      44      { "PO-Revision-Date:", sizeof ("PO-Revision-Date:") - 1 },
      45      { "Last-Translator:", sizeof ("Last-Translator:") - 1 },
      46      { "Language-Team:", sizeof ("Language-Team:") - 1 },
      47      { "Language:", sizeof ("Language:") - 1 },
      48      { "MIME-Version:", sizeof ("MIME-Version:") - 1 },
      49      { "Content-Type:", sizeof ("Content-Type:") - 1 },
      50      { "Content-Transfer-Encoding:", sizeof ("Content-Transfer-Encoding:") - 1 }
      51    };
      52  
      53  
      54  void
      55  msgdomain_list_set_header_field (msgdomain_list_ty *mdlp,
      56                                   const char *field, const char *value)
      57  {
      58    size_t field_len;
      59    int field_index;
      60    size_t k, i;
      61  
      62    field_len = strlen (field);
      63  
      64    /* Search the field in known_fields[].  */
      65    field_index = -1;
      66    for (k = 0; k < SIZEOF (known_fields); k++)
      67      if (strcmp (known_fields[k].name, field) == 0)
      68        {
      69          field_index = k;
      70          break;
      71        }
      72  
      73    for (i = 0; i < mdlp->nitems; i++)
      74      {
      75        message_list_ty *mlp = mdlp->item[i]->messages;
      76        size_t j;
      77  
      78        /* Search the header entry.  */
      79        for (j = 0; j < mlp->nitems; j++)
      80          if (is_header (mlp->item[j]) && !mlp->item[j]->obsolete)
      81            {
      82              message_ty *mp = mlp->item[j];
      83  
      84              /* Modify the header entry.  */
      85              const char *header = mp->msgstr;
      86              char *new_header =
      87                XNMALLOC (strlen (header) + 1
      88                          + strlen (field) + 1 + strlen (value) + 1 + 1,
      89                          char);
      90  
      91              /* Test whether the field already occurs in the header entry.  */
      92              const char *h;
      93  
      94              for (h = header; *h != '\0'; )
      95                {
      96                  if (strncmp (h, field, field_len) == 0)
      97                    break;
      98                  h = strchr (h, '\n');
      99                  if (h == NULL)
     100                    break;
     101                  h++;
     102                }
     103              if (h != NULL && *h != '\0')
     104                {
     105                  /* Replace the field.  */
     106                  char *p = new_header;
     107                  memcpy (p, header, h - header);
     108                  p += h - header;
     109                  p = stpcpy (p, field);
     110                  p = stpcpy (stpcpy (stpcpy (p, " "), value), "\n");
     111                  h = strchr (h, '\n');
     112                  if (h != NULL)
     113                    {
     114                      h++;
     115                      stpcpy (p, h);
     116                    }
     117                }
     118              else if (field_index < 0)
     119                {
     120                  /* An unknown field.  Append it at the end.  */
     121                  char *p = new_header;
     122                  p = stpcpy (p, header);
     123                  if (p > new_header && p[-1] != '\n')
     124                    *p++ = '\n';
     125                  p = stpcpy (p, field);
     126                  stpcpy (stpcpy (stpcpy (p, " "), value), "\n");
     127                }
     128              else
     129                {
     130                  /* Find the appropriate position for inserting the field.  */
     131                  for (h = header; *h != '\0'; )
     132                    {
     133                      /* Test whether h starts with a field name whose index is
     134                         > field_index.  */
     135                      for (k = field_index + 1; k < SIZEOF (known_fields); k++)
     136                        if (strncmp (h, known_fields[k].name, known_fields[k].len)
     137                            == 0)
     138                          break;
     139                      if (k < SIZEOF (known_fields))
     140                        break;
     141                      h = strchr (h, '\n');
     142                      if (h == NULL)
     143                        break;
     144                      h++;
     145                    }
     146                  if (h != NULL && *h != '\0')
     147                    {
     148                      /* Insert the field at position h.  */
     149                      char *p = new_header;
     150                      memcpy (p, header, h - header);
     151                      p += h - header;
     152                      p = stpcpy (p, field);
     153                      p = stpcpy (stpcpy (stpcpy (p, " "), value), "\n");
     154                      stpcpy (p, h);
     155                    }
     156                  else
     157                    {
     158                      /* Append it at the end.  */
     159                      char *p = new_header;
     160                      p = stpcpy (p, header);
     161                      if (p > new_header && p[-1] != '\n')
     162                        *p++ = '\n';
     163                      p = stpcpy (p, field);
     164                      stpcpy (stpcpy (stpcpy (p, " "), value), "\n");
     165                    }
     166                }
     167  
     168              mp->msgstr = new_header;
     169              mp->msgstr_len = strlen (new_header) + 1;
     170            }
     171      }
     172  }
     173  
     174  
     175  void
     176  message_list_delete_header_field (message_list_ty *mlp,
     177                                    const char *field)
     178  {
     179    size_t field_len = strlen (field);
     180    size_t j;
     181  
     182    /* Search the header entry.  */
     183    for (j = 0; j < mlp->nitems; j++)
     184      if (is_header (mlp->item[j]) && !mlp->item[j]->obsolete)
     185        {
     186          message_ty *mp = mlp->item[j];
     187  
     188          /* Modify the header entry.  */
     189          const char *header = mp->msgstr;
     190  
     191          /* Test whether the field occurs in the header entry.  */
     192          const char *h;
     193  
     194          for (h = header; *h != '\0'; )
     195            {
     196              if (strncmp (h, field, field_len) == 0)
     197                break;
     198              h = strchr (h, '\n');
     199              if (h == NULL)
     200                break;
     201              h++;
     202            }
     203          if (h != NULL && *h != '\0')
     204            {
     205              /* Delete the field.  */
     206              char *new_header = XCALLOC (strlen (header) + 1, char);
     207  
     208              char *p = new_header;
     209              memcpy (p, header, h - header);
     210              p += h - header;
     211              h = strchr (h, '\n');
     212              if (h != NULL)
     213                {
     214                  h++;
     215                  strcpy (p, h);
     216                }
     217              else
     218                *p = '\0';
     219  
     220              mp->msgstr = new_header;
     221              mp->msgstr_len = strlen (new_header) + 1;
     222            }
     223        }
     224  }