LCOV - code coverage report
Current view: top level - src/base - pdf-time-string.c (source / functions) Hit Total Coverage
Test: libgnupdf.info Lines: 270 306 88.2 %
Date: 2011-12-09 Functions: 10 10 100.0 %
Branches: 242 276 87.7 %

           Branch data     Line data    Source code
       1                 :            : /* -*- mode: C -*-
       2                 :            :  *
       3                 :            :  *       File:         pdf-time-string.c
       4                 :            :  *       Date:         Sun May 18 13:08:37 2008
       5                 :            :  *
       6                 :            :  *       GNU PDF Library - Time Module String utilities
       7                 :            :  *
       8                 :            :  */
       9                 :            : 
      10                 :            : /* Copyright (C) 2008 Free Software Foundation, Inc. */
      11                 :            : 
      12                 :            : /* This program is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU General Public License as published by
      14                 :            :  * the Free Software Foundation, either version 3 of the License, or
      15                 :            :  * (at your option) any later version.
      16                 :            :  *
      17                 :            :  * This program is distributed in the hope that it will be useful,
      18                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      19                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      20                 :            :  * GNU General Public License for more details.
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU General Public License
      23                 :            :  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
      24                 :            :  */
      25                 :            : 
      26                 :            : #include <config.h>
      27                 :            : 
      28                 :            : #include <stdio.h>
      29                 :            : #include <string.h>
      30                 :            : #include <stdlib.h>
      31                 :            : 
      32                 :            : #include <pdf-alloc.h>
      33                 :            : #include <pdf-time-string.h>
      34                 :            : 
      35                 :            : /* In order to use this macro, make sure that every byte represents a digit */
      36                 :            : #define __GET_FIELD2(str,start,dest)                            \
      37                 :            :   (dest += ((str[start] - 48) * 10 + (str[start + 1] - 48)));
      38                 :            : 
      39                 :            : 
      40                 :            : /* Macro to check if given bytes are digits or not */
      41                 :            : #define __CHECK_MASK(mask, masklength, str, i)                          \
      42                 :            :   while (i < masklength) {                                              \
      43                 :            :     if (mask & (1 << i)) {                                              \
      44                 :            :       if((str[i] < '0') ||                                              \
      45                 :            :          (str[i] > '9')) {                                              \
      46                 :            :         PDF_DEBUG_BASE("Expected digit and found '%c' in '%s'", str[i], str); \
      47                 :            :         return PDF_EBADDATA;                                            \
      48                 :            :       }                                                                 \
      49                 :            :     }                                                                   \
      50                 :            :     i++;                                                                \
      51                 :            :   }
      52                 :            : 
      53                 :            : /* Maximum length of strings, including trailing NUL */
      54                 :            : #define PDF_MAX_ISO8601_STR_LENGTH  30
      55                 :            : #define PDF_MAX_UTCASN1_STR_LENGTH  19
      56                 :            : #define PDF_MAX_GENASN1_STR_LENGTH  21
      57                 :            : #define PDF_MAX_PDFDATE_STR_LENGTH  24
      58                 :            : 
      59                 :            : static pdf_bool_t
      60                 :      15718 : pdf_time_check_string_pdf (const pdf_char_t  *time_str,
      61                 :            :                            const pdf_size_t   time_str_length,
      62                 :            :                            pdf_bool_t         require_trailing_apostrophe,
      63                 :            :                            pdf_error_t      **error)
      64                 :            : {
      65                 :            :   pdf_i32_t i;
      66                 :            : 
      67                 :            :   /* Check minimum length      D:YYYY */
      68         [ -  + ]:      15718 :   if (time_str_length < 6)
      69                 :            :     {
      70                 :          0 :       pdf_set_error (error,
      71                 :            :                      PDF_EDOMAIN_BASE_TIME,
      72                 :            :                      PDF_EBADDATA,
      73                 :            :                      "invalid PDF time string, too short (%u): '%s'",
      74                 :            :                      time_str_length,
      75                 :            :                      time_str);
      76                 :          0 :       return PDF_FALSE;
      77                 :            :     }
      78                 :            : 
      79                 :            :   /* Check prefix */
      80         [ -  + ]:      15718 :   if (strncmp (time_str, "D:", 2) != 0)
      81                 :            :     {
      82                 :          0 :       pdf_set_error (error,
      83                 :            :                      PDF_EDOMAIN_BASE_TIME,
      84                 :            :                      PDF_EBADDATA,
      85                 :            :                      "invalid PDF time string, no prefix: '%s",
      86                 :            :                      time_str);
      87                 :          0 :       return PDF_FALSE;
      88                 :            :     }
      89                 :            : 
      90                 :            :   /* We need to check the input characters are digits when we expect digits and
      91                 :            :    *  the opposite as well. */
      92                 :            : 
      93                 :            : #define PDF_STRING_DIGIT_MASK  0x36FFFC /* 0011 0110 1111 1111 1111 1100 */
      94                 :            : 
      95                 :            :   /* Don't really need to check again two first bytes, as already done before */
      96                 :      15718 :   i = 2;
      97 [ +  + ][ -  + ]:     337464 :   __CHECK_MASK (PDF_STRING_DIGIT_MASK, time_str_length, time_str, i);
                 [ +  + ]
      98                 :            : 
      99                 :            :   /* Check time zone definer */
     100 [ +  - ][ +  + ]:      15718 :   if ((time_str_length >=16) &&
         [ +  + ][ -  + ]
     101                 :      15718 :       (time_str[16] != 'Z') &&
     102                 :      15632 :       (time_str[16] != '+') &&
     103                 :       8256 :       (time_str[16] != '-'))
     104                 :            :     {
     105                 :          0 :       pdf_set_error (error,
     106                 :            :                      PDF_EDOMAIN_BASE_TIME,
     107                 :            :                      PDF_EBADDATA,
     108                 :            :                      "invalid PDF time string, "
     109                 :            :                      "invalid time zone identifier ('%c'): '%s",
     110                 :          0 :                      time_str[16],
     111                 :            :                      time_str);
     112                 :          0 :       return PDF_FALSE;
     113                 :            :     }
     114                 :            : 
     115                 :            :   /* Check additional ' characters. Remember that the last ' character is
     116                 :            :    * mandatory depending on the require_trailing_apostrophe parameter */
     117 [ +  + ][ -  + ]:      15718 :   if ((time_str_length >= 20) &&
     118                 :      15632 :       (time_str[19] != '\''))
     119                 :            :     {
     120                 :          0 :       pdf_set_error (error,
     121                 :            :                      PDF_EDOMAIN_BASE_TIME,
     122                 :            :                      PDF_EBADDATA,
     123                 :            :                      "invalid PDF time string, "
     124                 :            :                      "invalid separator ('%c'): '%s",
     125                 :          0 :                      time_str[19],
     126                 :            :                      time_str);
     127                 :          0 :       return PDF_FALSE;
     128                 :            :     }
     129                 :            : 
     130         [ +  + ]:      15718 :   if (require_trailing_apostrophe)
     131                 :            :     {
     132 [ +  + ][ -  + ]:       7816 :       if ((time_str_length < 23) ||
     133                 :       3908 :           ((time_str[22] != '\'')))
     134                 :            :         {
     135         [ +  - ]:       3908 :           pdf_set_error (error,
     136                 :            :                          PDF_EDOMAIN_BASE_TIME,
     137                 :            :                          PDF_EBADDATA,
     138                 :            :                          "invalid PDF time string, "
     139                 :            :                          "invalid separator ('%c'): '%s",
     140                 :       3908 :                          (time_str_length >= 21) ? time_str[22] : ' ',
     141                 :            :                          time_str);
     142                 :       3908 :           return PDF_FALSE;
     143                 :            :         }
     144                 :            :     }
     145                 :            :   else
     146                 :            :     {
     147         [ +  + ]:       7902 :       if (time_str_length >= 23)
     148                 :            :         {
     149                 :       3908 :           pdf_set_error (error,
     150                 :            :                          PDF_EDOMAIN_BASE_TIME,
     151                 :            :                          PDF_EBADDATA,
     152                 :            :                          "invalid PDF time string, invalid separator ('%c'): '%s",
     153                 :       3908 :                          time_str[19],
     154                 :            :                          time_str);
     155                 :       3908 :           return PDF_FALSE;
     156                 :            :         }
     157                 :            :     }
     158                 :            : 
     159                 :      15718 :   return PDF_TRUE;
     160                 :            : }
     161                 :            : 
     162                 :            : pdf_bool_t
     163                 :      15718 : pdf_time_from_string_pdf (pdf_time_t        *time_var,
     164                 :            :                           const pdf_char_t  *time_str,
     165                 :            :                           pdf_bool_t         require_trailing_apostrophe,
     166                 :            :                           pdf_error_t      **error)
     167                 :            : {
     168                 :            :   /*
     169                 :            :    * From PDF Reference 1.7: ( D:YYYYMMDDHHmmSSOHH'mm' )
     170                 :            :    * From ISO 32000:         ( D:YYYYMMDDHHmmSSOHH'mm  )
     171                 :            :    *
     172                 :            :    * Notes: Year is mandatory, all the other fields may appear if the preceding
     173                 :            :    *        also appear.
     174                 :            :    *
     175                 :            :    *  D:   = string "D:"
     176                 :            :    *  YYYY = four-digit year
     177                 :            :    *  MM   = two-digit month (01=January, etc.)
     178                 :            :    *  DD   = two-digit day of month (01 through 31)
     179                 :            :    *  HH   = two digits of hour (00 through 23)
     180                 :            :    *  mm   = two digits of minute (00 through 59)
     181                 :            :    *  SS   = two digits of second (00 through 59)
     182                 :            :    *  O    = either '+', '-' or 'Z'
     183                 :            :    *  HH   = two digits of hour (00 through 23) for the GMT offset
     184                 :            :    *  '    = string "'"
     185                 :            :    *  MM   = two digits of minute (00 through 59) for the GMT offset
     186                 :            :    *  '    = string "'"  (NOTE: Mandatory in 1.7, non-valid in ISO32000)
     187                 :            :    */
     188                 :            : 
     189                 :      15718 :   struct pdf_time_cal_s calendar = { 0 };
     190                 :            :   pdf_size_t time_str_length;
     191                 :            : 
     192                 :      15718 :   time_str_length = strlen (time_str);
     193                 :            : 
     194         [ +  + ]:      15718 :   if (!pdf_time_check_string_pdf (time_str,
     195                 :            :                                   time_str_length,
     196                 :            :                                   require_trailing_apostrophe,
     197                 :            :                                   error))
     198                 :            :     {
     199                 :       7816 :       pdf_prefix_error (error,
     200                 :            :                         "couldn't get time from PDF date string: ");
     201                 :       7816 :       return PDF_FALSE;
     202                 :            :     }
     203                 :            : 
     204                 :            :   while (PDF_TRUE)
     205                 :            :     {
     206                 :            :       /* Get century */
     207                 :       7902 :       __GET_FIELD2 (time_str, 2, calendar.year);
     208                 :       7902 :       calendar.year *= 100;
     209                 :            :       /* Get year in century */
     210                 :       7902 :       __GET_FIELD2 (time_str, 4, calendar.year);
     211                 :            :       /* more than year ? */
     212         [ -  + ]:       7902 :       if (time_str_length == 6)
     213                 :            :         {
     214                 :          0 :           calendar.month = 1;
     215                 :          0 :           calendar.day = 1;
     216                 :          0 :           break;
     217                 :            :         }
     218                 :            : 
     219                 :            :       /* Get month */
     220                 :       7902 :       __GET_FIELD2 (time_str, 6, calendar.month);
     221                 :            :       /* more than month ? */
     222         [ -  + ]:       7902 :       if (time_str_length == 8)
     223                 :            :         {
     224                 :          0 :           calendar.day = 1;
     225                 :          0 :           break;
     226                 :            :         }
     227                 :            : 
     228                 :            :       /* Get day */
     229                 :       7902 :       __GET_FIELD2 (time_str, 8, calendar.day);
     230                 :            :       /* more than day ? */
     231         [ +  - ]:       7902 :       if (time_str_length == 10)
     232                 :            :         break;
     233                 :            : 
     234                 :            :       /* Get hour */
     235                 :       7902 :       __GET_FIELD2 (time_str, 10, calendar.hour);
     236                 :            :       /* more than hour ? */
     237         [ +  - ]:       7902 :       if (time_str_length == 12)
     238                 :            :         break;
     239                 :            : 
     240                 :            :       /* Get minute */
     241                 :       7902 :       __GET_FIELD2 (time_str, 12, calendar.minute);
     242                 :            :       /* more than minute ? */
     243         [ +  - ]:       7902 :       if (time_str_length == 14)
     244                 :            :         break;
     245                 :            : 
     246                 :            :       /* Get second */
     247                 :       7902 :       __GET_FIELD2 (time_str, 14, calendar.second);
     248                 :            :       /* more than second ? */
     249         [ +  + ]:       7902 :       if (time_str_length <= 17) /* Considering timezone offset separator */
     250                 :            :         break;
     251                 :            : 
     252                 :            :       /* Get timezone offset hours */
     253                 :       7816 :       __GET_FIELD2 (time_str, 17, calendar.gmt_offset);
     254                 :            :       /* And convert it in minutes */
     255                 :       7816 :       calendar.gmt_offset *= 60;
     256                 :            : 
     257                 :            :       /* Get timezone offset minutes */
     258         [ +  - ]:       7816 :       if (time_str_length > 19)
     259                 :       7816 :         __GET_FIELD2 (time_str, 20, calendar.gmt_offset);
     260                 :            : 
     261                 :            :       /* Convert from minutes to seconds */
     262                 :       7816 :       calendar.gmt_offset *= 60;
     263                 :            : 
     264                 :            :       /* Set proper sign */
     265         [ +  + ]:       7816 :       if (time_str[16] == '-')
     266                 :       4128 :         calendar.gmt_offset *= (-1);
     267                 :            : 
     268                 :            :       /* Stop loop :-) */
     269                 :            :       break;
     270                 :            :     }
     271                 :            : 
     272                 :            :   /* Get time value from break-down UTC calendar !*/
     273                 :       7902 :   pdf_time_set_from_cal (time_var, &calendar);
     274                 :            : 
     275                 :      15718 :   return PDF_TRUE;
     276                 :            : }
     277                 :            : 
     278                 :            : static pdf_bool_t
     279                 :       7988 : pdf_time_check_string_utc_asn1 (const pdf_char_t  *time_str,
     280                 :            :                                 const pdf_size_t   time_str_length,
     281                 :            :                                 pdf_error_t      **error)
     282                 :            : {
     283                 :            :   pdf_i32_t i;
     284                 :            :   pdf_i32_t base_mask;
     285                 :            :   pdf_i32_t mask_length;
     286                 :            :   pdf_bool_t with_gmt_offset;
     287                 :            : 
     288                 :            : #define UTCASN1_STRING_DIGIT_MASK1  0x03FF /* 0000 0011 1111 1111 */
     289                 :            : #define UTCASN1_STRING_DIGIT_MASK2  0x0FFF /* 0000 1111 1111 1111 */
     290                 :            : 
     291                 :            :   /* Check length */
     292         [ +  + ]:       7988 :   if ((time_str_length == 11) ||
     293                 :       7988 :       (time_str_length == 15))
     294                 :            :     {
     295                 :       3994 :       base_mask = UTCASN1_STRING_DIGIT_MASK1;
     296                 :       3994 :       mask_length = 10;
     297                 :            :     }
     298         [ +  - ]:       3994 :   else if ((time_str_length == 13) ||
     299                 :       3994 :            (time_str_length == 17))
     300                 :            :     {
     301                 :       3994 :       base_mask = UTCASN1_STRING_DIGIT_MASK2;
     302                 :       3994 :       mask_length = 12;
     303                 :            :     }
     304                 :            :   else
     305                 :            :     {
     306                 :          0 :       pdf_set_error (error,
     307                 :            :                      PDF_EDOMAIN_BASE_TIME,
     308                 :            :                      PDF_EBADDATA,
     309                 :            :                      "invalid UTC-ASN1 time string, invalid length (%u): '%s'",
     310                 :            :                      time_str_length,
     311                 :            :                      time_str);
     312                 :          0 :       return PDF_FALSE;
     313                 :            :     }
     314                 :            : 
     315                 :            :   /* Check if GMT offset is expected */
     316                 :       7988 :   with_gmt_offset = (time_str_length >= 15) ? PDF_TRUE : PDF_FALSE;
     317                 :            : 
     318                 :            :   /* Check extra non-digit characters */
     319 [ +  + ][ -  + ]:       7988 :   if ((!with_gmt_offset) &&
     320                 :        172 :       (time_str[time_str_length - 1] != 'Z'))
     321                 :            :     {
     322                 :          0 :       pdf_set_error (error,
     323                 :            :                      PDF_EDOMAIN_BASE_TIME,
     324                 :            :                      PDF_EBADDATA,
     325                 :            :                      "invalid UTC-ASN1 time string, expected UTC string "
     326                 :            :                      "but no Zulu timezone identifier found: '%s'",
     327                 :            :                      time_str);
     328                 :          0 :       return PDF_FALSE;
     329                 :            :     }
     330                 :            : 
     331 [ +  + ][ -  + ]:       7988 :   if ((with_gmt_offset) &&
     332                 :       7816 :       ((time_str[time_str_length - 5] != '+') &&
     333                 :            :        (time_str[time_str_length - 5] != '-')))
     334                 :            :     {
     335                 :          0 :       pdf_set_error (error,
     336                 :            :                      PDF_EDOMAIN_BASE_TIME,
     337                 :            :                      PDF_EBADDATA,
     338                 :            :                      "invalid UTC-ASN1 time string, expected non-UTC string "
     339                 :            :                      "but no GMT offset found: '%s'",
     340                 :            :                      time_str);
     341                 :          0 :       return PDF_FALSE;
     342                 :            :     }
     343                 :            : 
     344                 :            :   /* Check mask if base string */
     345                 :       7988 :   i = 0;
     346 [ +  - ][ -  + ]:      95856 :   __CHECK_MASK (base_mask, mask_length, time_str, i);
                 [ +  + ]
     347                 :            :   /* Check mask of offset string if available */
     348         [ +  + ]:       7988 :   if (with_gmt_offset)
     349                 :            :     {
     350                 :       7816 :       i = time_str_length - 4;
     351 [ #  # ][ #  # ]:       7816 :       __CHECK_MASK (0x000F, 4, time_str, i);
                 [ -  + ]
     352                 :            :     }
     353                 :            : 
     354                 :       7988 :   return PDF_TRUE;
     355                 :            : }
     356                 :            : 
     357                 :            : static pdf_i32_t
     358                 :            : pdf_time_get_century_in_sliding_window (pdf_i32_t year_in_century)
     359                 :            : {
     360                 :       7988 :   pdf_i32_t full_year = -1;
     361                 :            :   pdf_time_t current;
     362                 :            :   pdf_i32_t century;
     363                 :            :   struct pdf_time_cal_s current_cal;
     364                 :            : 
     365                 :       7988 :   pdf_time_init (&current);
     366                 :            : 
     367                 :       7988 :   pdf_time_set_to_current_utc_time (&current);
     368                 :       7988 :   pdf_time_get_utc_cal (&current, &current_cal);
     369                 :            : 
     370                 :            :   /* Get century from full current year */
     371                 :       7988 :   century = 100 * (current_cal.year / 100);
     372                 :            : 
     373                 :            :   /* Appy current century */
     374                 :       7988 :   full_year = century + year_in_century;
     375                 :            : 
     376                 :            :   /* Check if the century must be changed */
     377   [ +  +  +  - ]:       7988 :   if ((full_year > current_cal.year) &&
     378                 :       4988 :       ((full_year - current_cal.year) > 50))
     379                 :            :     {
     380                 :       4988 :       full_year -= 100;
     381                 :            :     }
     382 [ +  - ][ -  + ]:       3000 :   else if ((full_year < current_cal.year) &&
     383                 :       3000 :            ((current_cal.year - full_year) > 50))
     384                 :            :     {
     385                 :          0 :       full_year += 100;
     386                 :            :     }
     387                 :            : 
     388                 :       7988 :   pdf_time_deinit (&current);
     389                 :            : 
     390                 :       7988 :   return full_year;
     391                 :            : }
     392                 :            : 
     393                 :            : pdf_bool_t
     394                 :       7988 : pdf_time_from_string_utc_asn1 (pdf_time_t       *time_var,
     395                 :            :                                const pdf_char_t *time_str,
     396                 :            :                                pdf_error_t      **error)
     397                 :            : {
     398                 :            :   /*
     399                 :            :    * yymmddhhmmZ
     400                 :            :    * yymmddhhmmssZ
     401                 :            :    * yymmddhhmm+hhmm
     402                 :            :    * yymmddhhmm-hhmm
     403                 :            :    * yymmddhhmmss+hhmm
     404                 :            :    * yymmddhhmmss-hhmm
     405                 :            :    *
     406                 :            :    * Note: As year is only stored in 2 digits, a sliding window of [-50,+50]
     407                 :            :    *       years will be used to get the century.
     408                 :            :    */
     409                 :       7988 :   struct pdf_time_cal_s calendar = { 0 };
     410                 :            :   pdf_size_t time_str_length;
     411                 :            : 
     412                 :       7988 :   time_str_length = strlen (time_str);
     413                 :            : 
     414         [ -  + ]:       7988 :   if (!pdf_time_check_string_utc_asn1 (time_str,
     415                 :            :                                        time_str_length,
     416                 :            :                                        error))
     417                 :            :     {
     418                 :          0 :       pdf_prefix_error (error,
     419                 :            :                         "couldn't get time from UTC ASN1 string: ");
     420                 :          0 :       return PDF_FALSE;
     421                 :            :     }
     422                 :            : 
     423                 :            :   while (PDF_TRUE)
     424                 :            :     {
     425                 :       7988 :       pdf_bool_t has_seconds = PDF_FALSE;
     426                 :            : 
     427                 :            :       /* Get year in century */
     428                 :       7988 :       __GET_FIELD2 (time_str, 0, calendar.year);
     429                 :            :       /* Get 4-digit year from 2-digit year */
     430                 :      15976 :       calendar.year = pdf_time_get_century_in_sliding_window (calendar.year);
     431                 :            : 
     432                 :            :       /* Get month */
     433                 :       7988 :       __GET_FIELD2 (time_str, 2, calendar.month);
     434                 :            : 
     435                 :            :       /* Get day */
     436                 :       7988 :       __GET_FIELD2 (time_str, 4, calendar.day);
     437                 :            : 
     438                 :            :       /* Get hour */
     439                 :       7988 :       __GET_FIELD2 (time_str, 6, calendar.hour);
     440                 :            : 
     441                 :            :       /* Get minute */
     442                 :       7988 :       __GET_FIELD2 (time_str, 8, calendar.minute);
     443                 :            : 
     444                 :            :       /* Get second if available */
     445         [ +  + ]:       7988 :       if ((time_str[10] >= '0') &&
     446                 :            :           (time_str[10] <= '9'))
     447                 :            :         {
     448                 :       3994 :           has_seconds = PDF_TRUE;
     449                 :       3994 :           __GET_FIELD2 (time_str, 10, calendar.second);
     450                 :            :         }
     451                 :            : 
     452                 :            :       /* Check if we have GMT offset */
     453         [ +  + ]:       7988 :       if (time_str[time_str_length - 1] == 'Z')
     454                 :            :         break;
     455                 :            : 
     456                 :            :       /* Get timezone offset hours */
     457 [ +  + ][ +  + ]:       7816 :       __GET_FIELD2 (time_str, (has_seconds ? 13 : 11), calendar.gmt_offset);
     458                 :            :       /* And convert it in minutes */
     459                 :       7816 :       calendar.gmt_offset *= 60;
     460                 :            :       /* Get timezone offset minutes */
     461 [ +  + ][ +  + ]:       7816 :       __GET_FIELD2 (time_str, (has_seconds ? 15 : 13), calendar.gmt_offset);
     462                 :            :       /* Convert from minutes to seconds */
     463                 :       7816 :       calendar.gmt_offset *= 60;
     464                 :            : 
     465                 :            :       /* Set proper sign */
     466 [ +  + ][ +  + ]:       7816 :       if (time_str[(has_seconds ? 12 : 10)] == '-')
     467                 :       4128 :         calendar.gmt_offset *= (-1);
     468                 :            : 
     469                 :            :       /* Stop loop :-) */
     470                 :            :       break;
     471                 :            :     }
     472                 :            : 
     473                 :            :   /* Get time value from break-down UTC calendar !*/
     474                 :       7988 :   pdf_time_set_from_cal (time_var, &calendar);
     475                 :            : 
     476                 :       7988 :   return PDF_TRUE;
     477                 :            : }
     478                 :            : 
     479                 :            : pdf_bool_t
     480                 :       8162 : pdf_time_from_string_generalized_asn1 (pdf_time_t        *time_var,
     481                 :            :                                        const pdf_char_t  *time_str,
     482                 :            :                                        pdf_error_t      **error)
     483                 :            : {
     484                 :            :   /*
     485                 :            :    *  Year:
     486                 :            :    *    YYYY (eg 1997)
     487                 :            :    *  Year and month:
     488                 :            :    *    YYYYMM (eg 199707)
     489                 :            :    *  Complete date:
     490                 :            :    *    YYYYMMDD (eg 19970716)
     491                 :            :    *  Complete date plus hours and minutes:
     492                 :            :    *    YYYYMMDDhhmmTZD (eg 199707161920+01:00)
     493                 :            :    *  Complete date plus hours, minutes and seconds:
     494                 :            :    *    YYYYMMDDhhmmssTZD (eg 19970716192030+01:00)
     495                 :            :    *  Complete date plus hours, minutes, seconds and a decimal fraction of a
     496                 :            :    *  second
     497                 :            :    *    YYYYMMDDThhmmss.sTZD (eg 1997071619:20:30.45+01:00)
     498                 :            :    *
     499                 :            :    *  where:
     500                 :            :    *
     501                 :            :    *  YYYY = four-digit year
     502                 :            :    *  MM   = two-digit month (01=January, etc.)
     503                 :            :    *  DD   = two-digit day of month (01 through 31)
     504                 :            :    *  hh   = two digits of hour (00 through 23) (am/pm NOT allowed)
     505                 :            :    *  mm   = two digits of minute (00 through 59)
     506                 :            :    *  ss   = two digits of second (00 through 59)
     507                 :            :    *  s    = one or more digits representing a decimal fraction of a second
     508                 :            :    *  TZD  = time zone designator (Z or +hh:mm or -hh:mm)
     509                 :            :    *
     510                 :            :    */
     511                 :       8162 :   struct pdf_time_cal_s calendar = { 0 };
     512                 :            :   pdf_size_t time_str_length;
     513                 :            : 
     514                 :       8162 :   time_str_length = strlen (time_str);
     515                 :            : 
     516                 :            :   /* Check minimum length */
     517         [ -  + ]:       8162 :   if (time_str_length < 4)
     518                 :            :     {
     519                 :          0 :       pdf_set_error (error,
     520                 :            :                      PDF_EDOMAIN_BASE_TIME,
     521                 :            :                      PDF_EBADDATA,
     522                 :            :                      "couldn't get time from Generalized ASN1 date string: "
     523                 :            :                      "invalid date string, too short (%u): '%s'",
     524                 :            :                      time_str_length,
     525                 :            :                      time_str);
     526                 :          0 :       return PDF_FALSE;
     527                 :            :     }
     528                 :            : 
     529                 :            :   while (PDF_TRUE)
     530                 :            :     {
     531                 :            :       /* Get century */
     532                 :       8162 :       __GET_FIELD2 (time_str, 0, calendar.year);
     533                 :       8162 :       calendar.year *= 100;
     534                 :            :       /* Get year in century */
     535                 :       8162 :       __GET_FIELD2 (time_str, 2, calendar.year);
     536                 :            :       /* more than year ? */
     537         [ +  + ]:       8162 :       if (time_str_length == 4)
     538                 :            :         {
     539                 :         40 :           calendar.month = 1;
     540                 :         40 :           calendar.day = 1;
     541                 :         40 :           break;
     542                 :            :         }
     543                 :            : 
     544                 :            :       /* Get month */
     545                 :       8122 :       __GET_FIELD2 (time_str, 4, calendar.month);
     546                 :            :       /* more than month ? */
     547         [ +  + ]:       8122 :       if (time_str_length == 6)
     548                 :            :         {
     549                 :         48 :           calendar.day = 1;
     550                 :         48 :           break;
     551                 :            :         }
     552                 :            : 
     553                 :            :       /* Get day */
     554                 :       8074 :       __GET_FIELD2 (time_str, 6, calendar.day);
     555                 :            :       /* more than day ? */
     556         [ +  + ]:       8074 :       if (time_str_length == 8)
     557                 :            :         break;
     558                 :            : 
     559                 :            :       /* Get hour and minutes */
     560                 :       7988 :       __GET_FIELD2 (time_str, 8, calendar.hour);
     561                 :       7988 :       __GET_FIELD2 (time_str, 10, calendar.minute);
     562                 :            : 
     563                 :            :       /* Get second if available */
     564         [ +  + ]:       7988 :       if ((time_str[17] >= '0') &&
     565                 :            :           (time_str[17] <= '9'))
     566                 :            :         {
     567                 :       3994 :           __GET_FIELD2 (time_str, 12, calendar.second);
     568                 :            :         }
     569                 :            : 
     570                 :            :       /* Note: Fractional part of seconds not considered */
     571         [ +  + ]:       7988 :       if (time_str[time_str_length - 1] == 'Z')
     572                 :            :         break;
     573                 :            : 
     574                 :            :       /* Get timezone offset hours */
     575                 :       7816 :       __GET_FIELD2 (time_str, (time_str_length - 4), calendar.gmt_offset);
     576                 :            :       /* And convert it in minutes */
     577                 :       7816 :       calendar.gmt_offset *= 60;
     578                 :            :       /* Get timezone offset minutes */
     579                 :       7816 :       __GET_FIELD2 (time_str, (time_str_length - 2), calendar.gmt_offset);
     580                 :            :       /* Convert from minutes to seconds */
     581                 :       7816 :       calendar.gmt_offset *= 60;
     582                 :            : 
     583                 :            :       /* Set proper sign */
     584         [ +  + ]:       7816 :       if (time_str[(time_str_length - 5)] == '-')
     585                 :       4128 :         calendar.gmt_offset *= (-1);
     586                 :            : 
     587                 :            :       /* Stop loop :-) */
     588                 :            :       break;
     589                 :            :     }
     590                 :            : 
     591                 :            :   /* Get time value from break-down calendar !*/
     592                 :       8162 :   pdf_time_set_from_cal (time_var, &calendar);
     593                 :            : 
     594                 :       8162 :   return PDF_TRUE;
     595                 :            : }
     596                 :            : 
     597                 :            : pdf_bool_t
     598                 :       8208 : pdf_time_from_string_iso8601 (pdf_time_t        *time_var,
     599                 :            :                               const pdf_char_t  *time_str,
     600                 :            :                               pdf_error_t      **error)
     601                 :            : {
     602                 :            :   /*
     603                 :            :    *  Year:
     604                 :            :    *    YYYY (eg 1997)
     605                 :            :    *  Year and month:
     606                 :            :    *    YYYY-MM (eg 1997-07)
     607                 :            :    *  Complete date:
     608                 :            :    *    YYYY-MM-DD (eg 1997-07-16)
     609                 :            :    *  Complete date plus hours and minutes:
     610                 :            :    *    YYYY-MM-DDThh:mmTZD (eg 1997-07-16T19:20+01:00)
     611                 :            :    *  Complete date plus hours, minutes and seconds:
     612                 :            :    *    YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00)
     613                 :            :    *  Complete date plus hours, minutes, seconds and a decimal fraction of a
     614                 :            :    *  second
     615                 :            :    *    YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00)
     616                 :            :    *
     617                 :            :    *  where:
     618                 :            :    *
     619                 :            :    *  YYYY = four-digit year
     620                 :            :    *  MM   = two-digit month (01=January, etc.)
     621                 :            :    *  DD   = two-digit day of month (01 through 31)
     622                 :            :    *  hh   = two digits of hour (00 through 23) (am/pm NOT allowed)
     623                 :            :    *  mm   = two digits of minute (00 through 59)
     624                 :            :    *  ss   = two digits of second (00 through 59)
     625                 :            :    *  s    = one or more digits representing a decimal fraction of a second
     626                 :            :    *  TZD  = time zone designator (Z or +hh:mm or -hh:mm)
     627                 :            :    *
     628                 :            :    */
     629                 :       8208 :   struct pdf_time_cal_s calendar = { 0 };
     630                 :            :   pdf_size_t time_str_length;
     631                 :            : 
     632                 :       8208 :   time_str_length = strlen (time_str);
     633                 :            : 
     634                 :            :   /* Check minimum length */
     635         [ -  + ]:       8208 :   if (time_str_length < 4)
     636                 :            :     {
     637                 :          0 :       pdf_set_error (error,
     638                 :            :                      PDF_EDOMAIN_BASE_TIME,
     639                 :            :                      PDF_EBADDATA,
     640                 :            :                      "couldn't get time from ISO-8601 date string: "
     641                 :            :                      "invalid date string, too short (%u): '%s'",
     642                 :            :                      time_str_length,
     643                 :            :                      time_str);
     644                 :          0 :       return PDF_FALSE;
     645                 :            :     }
     646                 :            : 
     647                 :            :   while (PDF_TRUE)
     648                 :            :     {
     649                 :            :       /* Get century */
     650                 :       8208 :       __GET_FIELD2 (time_str, 0, calendar.year);
     651                 :       8208 :       calendar.year *= 100;
     652                 :            :       /* Get year in century */
     653                 :       8208 :       __GET_FIELD2 (time_str, 2, calendar.year);
     654                 :            :       /* more than year ? */
     655         [ +  + ]:       8208 :       if (time_str_length == 4)
     656                 :            :         {
     657                 :         86 :           calendar.month = 1;
     658                 :         86 :           calendar.day = 1;
     659                 :         86 :           break;
     660                 :            :         }
     661                 :            : 
     662                 :            :       /* Get month */
     663                 :       8122 :       __GET_FIELD2 (time_str, 5, calendar.month);
     664                 :            :       /* more than month ? */
     665         [ +  + ]:       8122 :       if (time_str_length == 7)
     666                 :            :         {
     667                 :         48 :           calendar.day = 1;
     668                 :         48 :           break;
     669                 :            :         }
     670                 :            : 
     671                 :            :       /* Get day */
     672                 :       8074 :       __GET_FIELD2 (time_str, 8, calendar.day);
     673                 :            :       /* more than day ? */
     674         [ +  + ]:       8074 :       if (time_str_length == 10)
     675                 :            :         break;
     676                 :            : 
     677                 :            :       /* Get hour and minutes */
     678                 :       7988 :       __GET_FIELD2 (time_str, 11, calendar.hour);
     679                 :       7988 :       __GET_FIELD2 (time_str, 14, calendar.minute);
     680                 :            : 
     681                 :            :       /* Get second if available */
     682 [ +  + ][ +  + ]:       7988 :       if ((time_str[17] >= '0') &&
     683                 :       7988 :           (time_str[17] <= '9') &&
     684                 :       7902 :           (time_str[16] == ':'))
     685                 :            :         {
     686                 :       3994 :           __GET_FIELD2 (time_str, 17, calendar.second);
     687                 :            :         }
     688                 :            : 
     689                 :            :       /* Note: Fractional part of seconds not considered */
     690         [ +  + ]:       7988 :       if (time_str[time_str_length - 1] == 'Z')
     691                 :            :         break;
     692                 :            : 
     693                 :            :       /* Get timezone offset hours */
     694                 :       7816 :       __GET_FIELD2 (time_str, (time_str_length - 5), calendar.gmt_offset);
     695                 :            :       /* And convert it in minutes */
     696                 :       7816 :       calendar.gmt_offset *= 60;
     697                 :            :       /* Get timezone offset minutes */
     698                 :       7816 :       __GET_FIELD2 (time_str, (time_str_length - 2), calendar.gmt_offset);
     699                 :            :       /* Convert from minutes to seconds */
     700                 :       7816 :       calendar.gmt_offset *= 60;
     701                 :            : 
     702                 :            :       /* Set proper sign */
     703         [ +  + ]:       7816 :       if (time_str[(time_str_length - 6)] == '-')
     704                 :       4128 :         calendar.gmt_offset *= (-1);
     705                 :            : 
     706                 :            :       /* Stop loop :-) */
     707                 :            :       break;
     708                 :            :     }
     709                 :            : 
     710                 :            :   /* Get time value from break-down calendar !*/
     711                 :       8208 :   pdf_time_set_from_cal (time_var, &calendar);
     712                 :            : 
     713                 :       8208 :   return PDF_TRUE;
     714                 :            : }
     715                 :            : 
     716                 :            : /* Get Date as a string in PDF format */
     717                 :            : pdf_char_t *
     718                 :       6860 : pdf_time_to_string_pdf (const pdf_time_t  *time_var,
     719                 :            :                         pdf_bool_t         include_trailing_apostrophe,
     720                 :            :                         pdf_error_t      **error)
     721                 :            : {
     722                 :            :   pdf_char_t *str;
     723                 :       6860 :   struct pdf_time_cal_s calendar = { 0 };
     724                 :            : 
     725                 :       6860 :   str = (pdf_char_t *) pdf_alloc (PDF_MAX_PDFDATE_STR_LENGTH);
     726         [ -  + ]:       6860 :   if (!str)
     727                 :            :     {
     728                 :          0 :       pdf_set_error (error,
     729                 :            :                      PDF_EDOMAIN_BASE_TIME,
     730                 :            :                      PDF_ENOMEM,
     731                 :            :                      "cannot create string with PDF time: "
     732                 :            :                      "couldn't allocate %lu bytes",
     733                 :            :                      PDF_MAX_PDFDATE_STR_LENGTH);
     734                 :          0 :       return NULL;
     735                 :            :     }
     736                 :            : 
     737                 :            :   /* D:YYYYMMDDHHmmSSOHH'mm' */
     738                 :       6860 :   pdf_time_get_local_cal (time_var, &calendar);
     739                 :            : 
     740         [ +  + ]:       6860 :   if (calendar.gmt_offset != 0)
     741                 :            :     {
     742                 :            :       pdf_i32_t offset_hours;
     743                 :            :       pdf_i32_t offset_minutes;
     744                 :            : 
     745         [ +  + ]:       6720 :       offset_hours = (((calendar.gmt_offset < 0) ? (-1) : (1)) * calendar.gmt_offset) / 3600;
     746         [ +  + ]:       6720 :       offset_minutes = (((calendar.gmt_offset < 0) ? (-1) : (1)) * calendar.gmt_offset) % 3600;
     747                 :       6720 :       offset_minutes /= 60; /* Get only full minutes */
     748 [ +  + ][ +  + ]:       6720 :       sprintf (str, "D:%4d%s%d%s%d%s%d%s%d%s%d%c%s%d'%s%d",
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
     749                 :       6720 :                calendar.year,
     750                 :      13440 :                (calendar.month < 10 ? "0" : ""), calendar.month,
     751                 :      13440 :                (calendar.day < 10 ? "0" : ""), calendar.day,
     752                 :      13440 :                (calendar.hour < 10 ? "0" : ""), calendar.hour,
     753                 :      13440 :                (calendar.minute < 10 ? "0" : ""), calendar.minute,
     754                 :      13440 :                (calendar.second < 10 ? "0" : ""), calendar.second,
     755                 :       6720 :                ((calendar.gmt_offset < 0) ? '-' : '+'),
     756                 :            :                (offset_hours < 10 ? "0" : ""), offset_hours,
     757                 :            :                (offset_minutes < 10 ? "0" : ""), offset_minutes);
     758                 :            : 
     759         [ +  + ]:       6720 :       if (include_trailing_apostrophe)
     760                 :            :         {
     761                 :       3360 :           str[PDF_MAX_PDFDATE_STR_LENGTH - 2] = '\'';
     762                 :       3360 :           str[PDF_MAX_PDFDATE_STR_LENGTH - 1] = '\0';
     763                 :            :         }
     764                 :            :     }
     765                 :            :   else
     766                 :            :     {
     767 [ +  + ][ +  + ]:        140 :       sprintf (str, "D:%4d%s%d%s%d%s%d%s%d%s%dZ",
         [ +  + ][ +  + ]
                 [ +  + ]
     768                 :        140 :                calendar.year,
     769                 :        280 :                (calendar.month < 10 ? "0" : ""), calendar.month,
     770                 :        280 :                (calendar.day < 10 ? "0" : ""), calendar.day,
     771                 :        280 :                (calendar.hour < 10 ? "0" : ""), calendar.hour,
     772                 :        280 :                (calendar.minute < 10 ? "0" : ""), calendar.minute,
     773                 :        280 :                (calendar.second < 10 ? "0" : ""), calendar.second);
     774                 :            :     }
     775                 :            : 
     776                 :       6860 :   return str;
     777                 :            : }
     778                 :            : 
     779                 :            : /* Get Date as a string in UTC-ASN1 format */
     780                 :            : pdf_char_t *
     781                 :       3430 : pdf_time_to_string_utc_asn1(const pdf_time_t  *time_var,
     782                 :            :                             pdf_error_t      **error)
     783                 :            : {
     784                 :            :   pdf_char_t *str;
     785                 :            :   struct pdf_time_cal_s calendar;
     786                 :            :   pdf_i32_t smallyear;
     787                 :            : 
     788                 :       3430 :   str = (pdf_char_t *) pdf_alloc (PDF_MAX_UTCASN1_STR_LENGTH);
     789         [ -  + ]:       3430 :   if (!str)
     790                 :            :     {
     791                 :          0 :       pdf_set_error (error,
     792                 :            :                      PDF_EDOMAIN_BASE_TIME,
     793                 :            :                      PDF_ENOMEM,
     794                 :            :                      "cannot create string with UTC ASN1 time: "
     795                 :            :                      "couldn't allocate %lu bytes",
     796                 :            :                      PDF_MAX_UTCASN1_STR_LENGTH);
     797                 :          0 :       return NULL;
     798                 :            :     }
     799                 :            : 
     800                 :       3430 :   pdf_time_get_local_cal (time_var, &calendar);
     801                 :            : 
     802                 :            :   /* Convert 4-digit year to 2-digit year */
     803                 :       3430 :   smallyear = calendar.year -1900;
     804         [ +  + ]:       4900 :   while (smallyear > 99)
     805                 :       1470 :     smallyear -= 100;
     806                 :            : 
     807         [ +  + ]:       3430 :   if (calendar.gmt_offset != 0)
     808                 :            :     {
     809                 :            :       pdf_i32_t offset_hours;
     810                 :            :       pdf_i32_t offset_minutes;
     811                 :            : 
     812         [ +  + ]:       3360 :       offset_hours = (((calendar.gmt_offset < 0) ? (-1) : (1)) * calendar.gmt_offset) / 3600;
     813         [ +  + ]:       3360 :       offset_minutes = (((calendar.gmt_offset < 0) ? (-1) : (1)) * calendar.gmt_offset) % 3600;
     814                 :       3360 :       offset_minutes /= 60;
     815                 :            :       /* yymmddhhmmss+hhmm
     816                 :            :        * yymmddhhmmss-hhmm
     817                 :            :        */
     818 [ +  + ][ +  + ]:       3360 :       sprintf (str, "%s%d%s%d%s%d%s%d%s%d%s%d%c%s%d%s%d",
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
                 [ +  + ]
     819                 :            :                (smallyear < 10 ? "0" : ""), smallyear,
     820                 :       6720 :                (calendar.month < 10 ? "0" : ""), calendar.month,
     821                 :       6720 :                (calendar.day < 10 ? "0" : ""), calendar.day,
     822                 :       6720 :                (calendar.hour < 10 ? "0" : ""), calendar.hour,
     823                 :       6720 :                (calendar.minute < 10 ? "0" : ""), calendar.minute,
     824                 :       6720 :                (calendar.second < 10 ? "0" : ""), calendar.second,
     825                 :       3360 :                ((calendar.gmt_offset < 0) ? '-' : '+'),
     826                 :            :                (offset_hours < 10 ? "0" : ""), offset_hours,
     827                 :            :                (offset_minutes < 10 ? "0" : ""), offset_minutes);
     828                 :            :     }
     829                 :            :   else
     830                 :            :     {
     831                 :            :       /*
     832                 :            :        * yymmddhhmmssZ
     833                 :            :        */
     834 [ +  + ][ +  + ]:         70 :       sprintf (str, "%s%d%s%d%s%d%s%d%s%d%s%dZ",
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
     835                 :            :                (smallyear < 10 ? "0" : ""), smallyear,
     836                 :        140 :                (calendar.month < 10 ? "0" : ""), calendar.month,
     837                 :        140 :                (calendar.day < 10 ? "0" : ""), calendar.day,
     838                 :        140 :                (calendar.hour < 10 ? "0" : ""), calendar.hour,
     839                 :        140 :                (calendar.minute < 10 ? "0" : ""), calendar.minute,
     840                 :        140 :                (calendar.second < 10 ? "0" : ""), calendar.second);
     841                 :            :     }
     842                 :            : 
     843                 :       3430 :   return str;
     844                 :            : }
     845                 :            : 
     846                 :            : /* Get Date as a string in Generalized ASN1 format */
     847                 :            : pdf_char_t *
     848                 :       3430 : pdf_time_to_string_generalized_asn1(const pdf_time_t  *time_var,
     849                 :            :                                     pdf_error_t      **error)
     850                 :            : {
     851                 :            :   pdf_char_t *str;
     852                 :            :   struct pdf_time_cal_s calendar;
     853                 :            : 
     854                 :       3430 :   str = (pdf_char_t *) pdf_alloc (PDF_MAX_GENASN1_STR_LENGTH);
     855         [ -  + ]:       3430 :   if (!str)
     856                 :            :     {
     857                 :          0 :       pdf_set_error (error,
     858                 :            :                      PDF_EDOMAIN_BASE_TIME,
     859                 :            :                      PDF_ENOMEM,
     860                 :            :                      "cannot create string with Generalized ASN1 time: "
     861                 :            :                      "couldn't allocate %lu bytes",
     862                 :            :                      PDF_MAX_GENASN1_STR_LENGTH);
     863                 :          0 :       return NULL;
     864                 :            :     }
     865                 :            : 
     866                 :            :   /* YYYYMMDDhhmmssTZD (eg 19970716192030+01:00) */
     867                 :       3430 :   pdf_time_get_local_cal (time_var, &calendar);
     868                 :            : 
     869         [ +  + ]:       3430 :   if (calendar.gmt_offset != 0)
     870                 :            :     {
     871                 :            :       pdf_i32_t offset_hours;
     872                 :            :       pdf_i32_t offset_minutes;
     873                 :            : 
     874         [ +  + ]:       3360 :       offset_hours = (((calendar.gmt_offset < 0) ? (-1) : (1)) * calendar.gmt_offset) / 3600;
     875         [ +  + ]:       3360 :       offset_minutes = (((calendar.gmt_offset < 0) ? (-1) : (1)) * calendar.gmt_offset) % 3600;
     876                 :       3360 :       offset_minutes /= 60;
     877 [ +  + ][ +  + ]:       3360 :       sprintf (str, "%4d%s%d%s%d%s%d%s%d%s%d%c%s%d%s%d",
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
     878                 :       3360 :                calendar.year,
     879                 :       6720 :                (calendar.month < 10 ? "0" : ""), calendar.month,
     880                 :       6720 :                (calendar.day < 10 ? "0" : ""), calendar.day,
     881                 :       6720 :                (calendar.hour < 10 ? "0" : ""), calendar.hour,
     882                 :       6720 :                (calendar.minute < 10 ? "0" : ""), calendar.minute,
     883                 :       6720 :                (calendar.second < 10 ? "0" : ""), calendar.second,
     884                 :       3360 :                ((calendar.gmt_offset < 0) ? '-' : '+'),
     885                 :            :                (offset_hours < 10 ? "0" : ""), offset_hours,
     886                 :            :                (offset_minutes < 10 ? "0" : ""), offset_minutes);
     887                 :            :     }
     888                 :            :   else
     889                 :            :     {
     890 [ +  + ][ +  + ]:         70 :       sprintf (str, "%4d%s%d%s%d%s%d%s%d%s%dZ",
         [ +  + ][ +  + ]
                 [ +  + ]
     891                 :         70 :                calendar.year,
     892                 :        140 :                (calendar.month < 10 ? "0" : ""), calendar.month,
     893                 :        140 :                (calendar.day < 10 ? "0" : ""), calendar.day,
     894                 :        140 :                (calendar.hour < 10 ? "0" : ""), calendar.hour,
     895                 :        140 :                (calendar.minute < 10 ? "0" : ""), calendar.minute,
     896                 :        140 :                (calendar.second < 10 ? "0" : ""), calendar.second);
     897                 :            :     }
     898                 :            : 
     899                 :       3430 :   return str;
     900                 :            : }
     901                 :            : 
     902                 :            : /* Get Date as a string in ISO8601 format */
     903                 :            : pdf_char_t *
     904                 :       3431 : pdf_time_to_string_iso8601(const pdf_time_t  *time_var,
     905                 :            :                            pdf_error_t      **error)
     906                 :            : {
     907                 :            :   pdf_char_t *str;
     908                 :            :   struct pdf_time_cal_s calendar;
     909                 :            : 
     910                 :       3431 :   str = (pdf_char_t *) pdf_alloc (PDF_MAX_ISO8601_STR_LENGTH);
     911         [ -  + ]:       3431 :   if (!str)
     912                 :            :     {
     913                 :          0 :       pdf_set_error (error,
     914                 :            :                      PDF_EDOMAIN_BASE_TIME,
     915                 :            :                      PDF_ENOMEM,
     916                 :            :                      "cannot create string with ISO8601 time: "
     917                 :            :                      "couldn't allocate %lu bytes",
     918                 :            :                      PDF_MAX_ISO8601_STR_LENGTH);
     919                 :          0 :       return NULL;
     920                 :            :     }
     921                 :            : 
     922                 :            :   /* YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00) */
     923                 :       3431 :   pdf_time_get_local_cal (time_var, &calendar);
     924         [ +  + ]:       3431 :   if (calendar.gmt_offset != 0)
     925                 :            :     {
     926                 :            :       pdf_i32_t offset_hours;
     927                 :            :       pdf_i32_t offset_minutes;
     928                 :            : 
     929         [ +  + ]:       3360 :       offset_hours = (((calendar.gmt_offset < 0) ? (-1) : (1)) * calendar.gmt_offset) / 3600;
     930         [ +  + ]:       3360 :       offset_minutes = (((calendar.gmt_offset < 0) ? (-1) : (1)) * calendar.gmt_offset) % 3600;
     931                 :       3360 :       offset_minutes /= 60; /* Get only full minutes */
     932 [ +  + ][ +  + ]:       3360 :       sprintf (str, "%4d-%s%d-%s%dT%s%d:%s%d:%s%d%c%s%d:%s%d",
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
     933                 :       3360 :                calendar.year,
     934                 :       6720 :                (calendar.month < 10 ? "0" : ""), calendar.month,
     935                 :       6720 :                (calendar.day < 10 ? "0" : ""), calendar.day,
     936                 :       6720 :                (calendar.hour < 10 ? "0" : ""), calendar.hour,
     937                 :       6720 :                (calendar.minute < 10 ? "0" : ""), calendar.minute,
     938                 :       6720 :                (calendar.second < 10 ? "0" : ""), calendar.second,
     939                 :       3360 :                ((calendar.gmt_offset < 0) ? '-' : '+'),
     940                 :            :                (offset_hours < 10 ? "0" : ""), offset_hours,
     941                 :            :                (offset_minutes < 10 ? "0" : ""), offset_minutes);
     942                 :            :     }
     943                 :            :   else
     944                 :            :     {
     945 [ +  + ][ +  + ]:         71 :       sprintf (str, "%4d-%s%d-%s%dT%s%d:%s%d:%s%dZ",
         [ +  + ][ +  + ]
                 [ +  + ]
     946                 :         71 :                calendar.year,
     947                 :        142 :                (calendar.month < 10 ? "0" : ""), calendar.month,
     948                 :        142 :                (calendar.day < 10 ? "0" : ""), calendar.day,
     949                 :        142 :                (calendar.hour < 10 ? "0" : ""), calendar.hour,
     950                 :        142 :                (calendar.minute < 10 ? "0" : ""), calendar.minute,
     951                 :        142 :                (calendar.second < 10 ? "0" : ""), calendar.second);
     952                 :            :     }
     953                 :            : 
     954                 :       3431 :   return str;
     955                 :            : }
     956                 :            : 
     957                 :            : /* End of pdf-time-string.c */

Generated by: LCOV version 1.8