LTP GCOV extension - code coverage report
Current view: directory - src/base - pdf-time-string.c
Test: libgnupdf.info
Date: 2010-07-31 Instrumented lines: 229
Code covered: 84.7 % Executed lines: 194

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

Generated by: LTP GCOV extension version 1.6