@@ -597,6 +597,33 @@ static int date_string(unsigned long date, int offset, char *buf, int len)
597597 return snprintf (buf , len , "%lu %c%02d%02d" , date , sign , offset / 60 , offset % 60 );
598598}
599599
600+ /*
601+ * Parse a string like "0 +0000" as ancient timestamp near epoch, but
602+ * only when it appears not as part of any other string.
603+ */
604+ static int match_object_header_date (const char * date , unsigned long * timestamp , int * offset )
605+ {
606+ char * end ;
607+ unsigned long stamp ;
608+ int ofs ;
609+
610+ if (* date < '0' || '9' <= * date )
611+ return -1 ;
612+ stamp = strtoul (date , & end , 10 );
613+ if (* end != ' ' || stamp == ULONG_MAX || (end [1 ] != '+' && end [1 ] != '-' ))
614+ return -1 ;
615+ date = end + 2 ;
616+ ofs = strtol (date , & end , 10 );
617+ if ((* end != '\0' && (* end != '\n' )) || end != date + 4 )
618+ return -1 ;
619+ ofs = (ofs / 100 ) * 60 + (ofs % 100 );
620+ if (date [-1 ] == '-' )
621+ ofs = - ofs ;
622+ * timestamp = stamp ;
623+ * offset = ofs ;
624+ return 0 ;
625+ }
626+
600627/* Gr. strptime is crap for this; it doesn't have a way to require RFC2822
601628 (i.e. English) day/month names, and it doesn't work correctly with %z. */
602629int parse_date_basic (const char * date , unsigned long * timestamp , int * offset )
@@ -622,6 +649,9 @@ int parse_date_basic(const char *date, unsigned long *timestamp, int *offset)
622649 * offset = -1 ;
623650 tm_gmt = 0 ;
624651
652+ if (* date == '@' &&
653+ !match_object_header_date (date + 1 , timestamp , offset ))
654+ return 0 ; /* success */
625655 for (;;) {
626656 int match = 0 ;
627657 unsigned char c = * date ;
0 commit comments