/* BASIC2026 portable PDF metadata editor. */
typedef struct {
    char *value[8];
    char *xmp_value[8];
    int changed[8];
} B2026PdfMetadataValues;

static const char *b2026_pdf_metadata_pdf_keys[8]={"/Title","/Author","/Subject","/Keywords","/Creator","/Producer","/CreationDate","/ModDate"};
static const char *b2026_pdf_metadata_en_keys[8]={"title","author","subject","keywords","creator","producer","creationDate","modDate"};
static const char *b2026_pdf_metadata_jp_keys[8]={"題名","著者","件名","キーワード","作成ソフト","生成ソフト","作成日時","更新日時"};
static const char *b2026_pdf_metadata_xml_keys[8]={"dc:title","dc:creator","dc:description","pdf:Keywords","xmp:CreatorTool","pdf:Producer","xmp:CreateDate","xmp:ModifyDate"};

static void b2026_pdf_metadata_values_free(B2026PdfMetadataValues *m){int i;for(i=0;i<8;++i){free(m->value[i]);free(m->xmp_value[i]);}memset(m,0,sizeof(*m));}

static char *b2026_pdf_metadata_fullwidth(const char *source){
    B2026PdfTextBuffer out;const unsigned char *p=(const unsigned char*)(source!=NULL?source:"");memset(&out,0,sizeof(out));
    while(*p){
        if(p[0]==0xEFU&&p[1]==0xBCU&&p[2]>=0x90U&&p[2]<=0x99U){if(!b2026_pdf_text_append_char(&out,(char)('0'+p[2]-0x90U)))goto fail;p+=3;continue;}
        if(p[0]==0xEFU&&p[1]==0xBCU&&p[2]==0x9AU){if(!b2026_pdf_text_append_char(&out,':'))goto fail;p+=3;continue;}
        if(p[0]==0xEFU&&p[1]==0xBCU&&p[2]==0x8BU){if(!b2026_pdf_text_append_char(&out,'+'))goto fail;p+=3;continue;}
        if(p[0]==0xEFU&&p[1]==0xBCU&&p[2]==0x8DU){if(!b2026_pdf_text_append_char(&out,'-'))goto fail;p+=3;continue;}
        if(p[0]==0xE3U&&p[1]==0x80U&&p[2]==0x80U){if(!b2026_pdf_text_append_char(&out,' '))goto fail;p+=3;continue;}
        if(!b2026_pdf_text_append_char(&out,(char)*p++))goto fail;
    }
    return b2026_pdf_text_take(&out);
fail:free(out.data);return NULL;
}

static int b2026_pdf_metadata_leap(int y){return y%4==0&&(y%100!=0||y%400==0);}
static int b2026_pdf_metadata_valid_date(int y,int mo,int d,int h,int mi,int se,int precision){
    static const int days[12]={31,28,31,30,31,30,31,31,30,31,30,31};int maxd;
    if(y<1||y>9999||mo<1||mo>12)return 0;maxd=days[mo-1]+(mo==2&&b2026_pdf_metadata_leap(y));
    if(d<1||d>maxd)return 0;if(precision>=4&&(h<0||h>23))return 0;if(precision>=5&&(mi<0||mi>59))return 0;if(precision>=6&&(se<0||se>59))return 0;return 1;
}

static const char *b2026_pdf_metadata_skip_space(const char *s){while(*s&&isspace((unsigned char)*s))++s;return s;}

static int b2026_pdf_metadata_uint(const char **cursor,int min_digits,int max_digits,int *value){
    const char *p=*cursor;int digits=0,v=0;
    while(digits<max_digits&&p[digits]>='0'&&p[digits]<='9'){v=v*10+(p[digits]-'0');++digits;}
    if(digits<min_digits)return 0;*cursor=p+digits;*value=v;return 1;
}

static int b2026_pdf_metadata_token(const char **cursor,const char *token){
    size_t n=strlen(token);if(strncmp(*cursor,token,n)!=0)return 0;*cursor+=n;return 1;
}

static int b2026_pdf_metadata_timezone(const char *s,char *tz,size_t cap){
    int h,m;char sign;s=b2026_pdf_metadata_skip_space(s);if(*s=='\0'){tz[0]='\0';return 1;}
    if(b2026_strcasecmp(s,"JST")==0){snprintf(tz,cap,"+09:00");return 1;}
    if(strcmp(s,"Z")==0||b2026_strcasecmp(s,"UTC")==0){snprintf(tz,cap,"Z");return 1;}
    if(*s!='+'&&*s!='-')return 0;sign=*s++;
    if(!b2026_pdf_metadata_uint(&s,2,2,&h))return 0;
    if(*s==':')++s;
    if(!b2026_pdf_metadata_uint(&s,2,2,&m))return 0;
    s=b2026_pdf_metadata_skip_space(s);if(*s!='\0'||h>23||m>59)return 0;snprintf(tz,cap,"%c%02d:%02d",sign,h,m);return 1;
}

static int b2026_pdf_metadata_date(const char *input,char **pdf_out,char **xmp_out){
    char *s=b2026_pdf_metadata_fullwidth(input),tz[16]="",pdf[80],xmp[80];const char *p,*rest;int y=0,mo=1,d=1,h=0,mi=0,se=0,precision=3,pm=0;
    if(s==NULL)return 0;p=b2026_pdf_metadata_skip_space(s);
    if(strncmp(p,"D:",2U)==0){
        const char *q=p+2;size_t digits=0U;while(q[digits]>='0'&&q[digits]<='9')++digits;if(digits<8U||digits>14U||digits==9U||digits==11U||digits==13U){free(s);return 0;}
        rest=q;if(!b2026_pdf_metadata_uint(&rest,4,4,&y)||!b2026_pdf_metadata_uint(&rest,2,2,&mo)||!b2026_pdf_metadata_uint(&rest,2,2,&d)){free(s);return 0;}precision=3;
        if(digits>=10U){if(!b2026_pdf_metadata_uint(&rest,2,2,&h)){free(s);return 0;}precision=4;}
        if(digits>=12U){if(!b2026_pdf_metadata_uint(&rest,2,2,&mi)){free(s);return 0;}precision=5;}
        if(digits>=14U){if(!b2026_pdf_metadata_uint(&rest,2,2,&se)){free(s);return 0;}precision=6;}
        if(*rest=='Z'){snprintf(tz,sizeof(tz),"Z");++rest;}
        else if(*rest=='+'||*rest=='-'){char sign=*rest++,separator='\0';int oh,om;if(!b2026_pdf_metadata_uint(&rest,2,2,&oh)){free(s);return 0;}if(*rest=='\''||*rest==':')separator=*rest++;if(!b2026_pdf_metadata_uint(&rest,2,2,&om)){free(s);return 0;}if(separator=='\''&&!b2026_pdf_metadata_token(&rest,"'")){free(s);return 0;}if(oh>23||om>59){free(s);return 0;}snprintf(tz,sizeof(tz),"%c%02d:%02d",sign,oh,om);}
        rest=b2026_pdf_metadata_skip_space(rest);if(*rest!='\0'){free(s);return 0;}
    } else if(strstr(p,"年")!=NULL){
        rest=p;if(!b2026_pdf_metadata_uint(&rest,1,4,&y)||!b2026_pdf_metadata_token(&rest,"年")||!b2026_pdf_metadata_uint(&rest,1,2,&mo)||!b2026_pdf_metadata_token(&rest,"月")||!b2026_pdf_metadata_uint(&rest,1,2,&d)||!b2026_pdf_metadata_token(&rest,"日")){free(s);return 0;}rest=b2026_pdf_metadata_skip_space(rest);
        if(strncmp(rest,"午前",6U)==0){pm=1;rest=b2026_pdf_metadata_skip_space(rest+6);}
        else if(strncmp(rest,"午後",6U)==0){pm=2;rest=b2026_pdf_metadata_skip_space(rest+6);}
        if(*rest!='\0'){
            if(!b2026_pdf_metadata_uint(&rest,1,2,&h)){free(s);return 0;}
            if(b2026_pdf_metadata_token(&rest,"時")){precision=4;if(*rest>='0'&&*rest<='9'){if(!b2026_pdf_metadata_uint(&rest,1,2,&mi)||!b2026_pdf_metadata_token(&rest,"分")){free(s);return 0;}precision=5;if(*rest>='0'&&*rest<='9'){if(!b2026_pdf_metadata_uint(&rest,1,2,&se)||!b2026_pdf_metadata_token(&rest,"秒")){free(s);return 0;}precision=6;}}}
            else if(*rest==':'){++rest;if(!b2026_pdf_metadata_uint(&rest,1,2,&mi)){free(s);return 0;}precision=5;if(*rest==':'){++rest;if(!b2026_pdf_metadata_uint(&rest,1,2,&se)){free(s);return 0;}precision=6;}}
            else {free(s);return 0;}
            if(pm&&((h<1)||(h>12))){free(s);return 0;}if(pm==1&&h==12)h=0;else if(pm==2&&h<12)h+=12;
            if(!b2026_pdf_metadata_timezone(rest,tz,sizeof(tz))){free(s);return 0;}
        }else if(pm){free(s);return 0;}
    } else {
        rest=p;if(!b2026_pdf_metadata_uint(&rest,4,4,&y)||!b2026_pdf_metadata_token(&rest,"-")||!b2026_pdf_metadata_uint(&rest,1,2,&mo)||!b2026_pdf_metadata_token(&rest,"-")||!b2026_pdf_metadata_uint(&rest,1,2,&d)){free(s);return 0;}
        if(*rest=='T'||*rest==' '){++rest;if(!b2026_pdf_metadata_uint(&rest,1,2,&h)||!b2026_pdf_metadata_token(&rest,":")||!b2026_pdf_metadata_uint(&rest,1,2,&mi)){free(s);return 0;}precision=5;if(*rest==':'){++rest;if(!b2026_pdf_metadata_uint(&rest,1,2,&se)){free(s);return 0;}precision=6;}if(!b2026_pdf_metadata_timezone(rest,tz,sizeof(tz))){free(s);return 0;}}
        else if(!b2026_pdf_metadata_timezone(rest,tz,sizeof(tz))){free(s);return 0;}
    }
    if(!b2026_pdf_metadata_valid_date(y,mo,d,h,mi,se,precision)){free(s);return 0;}
    snprintf(pdf,sizeof(pdf),"D:%04d%02d%02d",y,mo,d);
    snprintf(xmp,sizeof(xmp),"%04d-%02d-%02d",y,mo,d);
    if(precision>=4){size_t a=strlen(pdf),b=strlen(xmp);snprintf(pdf+a,sizeof(pdf)-a,"%02d",h);snprintf(xmp+b,sizeof(xmp)-b,"T%02d",h);}
    if(precision>=5){size_t a=strlen(pdf),b=strlen(xmp);snprintf(pdf+a,sizeof(pdf)-a,"%02d",mi);snprintf(xmp+b,sizeof(xmp)-b,":%02d",mi);}
    if(precision>=6){size_t a=strlen(pdf),b=strlen(xmp);snprintf(pdf+a,sizeof(pdf)-a,"%02d",se);snprintf(xmp+b,sizeof(xmp)-b,":%02d",se);}
    if(tz[0]){size_t a=strlen(pdf),b=strlen(xmp);if(strcmp(tz,"Z")==0){snprintf(pdf+a,sizeof(pdf)-a,"Z");snprintf(xmp+b,sizeof(xmp)-b,"Z");}else{snprintf(pdf+a,sizeof(pdf)-a,"%c%c%c'%c%c'",tz[0],tz[1],tz[2],tz[4],tz[5]);snprintf(xmp+b,sizeof(xmp)-b,"%s",tz);}}
    *pdf_out=b2026_strdup_simple(pdf);*xmp_out=b2026_strdup_simple(xmp);free(s);if(*pdf_out==NULL||*xmp_out==NULL){free(*pdf_out);free(*xmp_out);*pdf_out=*xmp_out=NULL;return 0;}return 1;
}

static char *b2026_pdf_metadata_pdf_hex(const char *text){
    B2026PdfTextBuffer out;const unsigned char *p=(const unsigned char*)(text!=NULL?text:"");memset(&out,0,sizeof(out));if(!b2026_pdf_text_append_bytes(&out,"<FEFF",5U))goto fail;
    while(*p){int span=utf8_char_span(p);unsigned int cp=utf8_decode_codepoint(p,span);char h[16];p+=span;if(cp>0x10FFFFU)cp=0xFFFDU;if(cp<=0xFFFFU){snprintf(h,sizeof(h),"%04X",cp);if(!b2026_pdf_text_append_bytes(&out,h,4U))goto fail;}else{unsigned int v=cp-0x10000U,hi=0xD800U+(v>>10),lo=0xDC00U+(v&0x3FFU);snprintf(h,sizeof(h),"%04X%04X",hi,lo);if(!b2026_pdf_text_append_bytes(&out,h,8U))goto fail;}}
    if(!b2026_pdf_text_append_char(&out,'>'))goto fail;return b2026_pdf_text_take(&out);
fail:free(out.data);return NULL;
}

static char *b2026_pdf_metadata_xml_escape(const char *text){B2026PdfTextBuffer out;const char*p=text!=NULL?text:"";memset(&out,0,sizeof(out));while(*p){const char*r=NULL;if(*p=='&')r="&amp;";else if(*p=='<')r="&lt;";else if(*p=='>')r="&gt;";else if(*p=='\"')r="&quot;";else if(*p=='\'')r="&apos;";if(r!=NULL){if(!b2026_pdf_text_append_bytes(&out,r,strlen(r)))goto fail;}else if(!b2026_pdf_text_append_char(&out,*p))goto fail;++p;}return b2026_pdf_text_take(&out);fail:free(out.data);return NULL;}

static char *b2026_pdf_metadata_remove_element(char *xml,const char *tag){
    char open[64],close[64];char *start,*end;snprintf(open,sizeof(open),"<%s",tag);snprintf(close,sizeof(close),"</%s>",tag);
    while((start=strstr(xml,open))!=NULL){end=strstr(start,close);if(end==NULL)break;end+=strlen(close);memmove(start,end,strlen(end)+1U);}return xml;
}

static char *b2026_pdf_metadata_xmp(B2026PdfDocument *doc,B2026PdfMetadataValues *m){
    char *old=b2026_pdf_xmp_text(doc);B2026PdfTextBuffer properties,out;char *insert,*close;int i;memset(&properties,0,sizeof(properties));memset(&out,0,sizeof(out));
    if(old==NULL)old=b2026_strdup_simple("<?xpacket begin=\"\"?>\n<x:xmpmeta xmlns:x=\"adobe:ns:meta/\"><rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"></rdf:RDF></x:xmpmeta>\n<?xpacket end=\"w\"?>");if(old==NULL)return NULL;
    for(i=0;i<8;++i)b2026_pdf_metadata_remove_element(old,b2026_pdf_metadata_xml_keys[i]);
    for(i=0;i<8;++i)if(m->value[i]!=NULL){const char *xml_value=m->xmp_value[i]!=NULL?m->xmp_value[i]:m->value[i];char *escaped=b2026_pdf_metadata_xml_escape(xml_value);char line[256];if(escaped==NULL)goto fail;
        if(i==0)snprintf(line,sizeof(line),"<dc:title><rdf:Alt><rdf:li xml:lang=\"x-default\">");
        else if(i==1)snprintf(line,sizeof(line),"<dc:creator><rdf:Seq><rdf:li>");
        else if(i==2)snprintf(line,sizeof(line),"<dc:description><rdf:Alt><rdf:li xml:lang=\"x-default\">");
        else snprintf(line,sizeof(line),"<%s>",b2026_pdf_metadata_xml_keys[i]);
        if(!b2026_pdf_text_append_bytes(&properties,line,strlen(line))||!b2026_pdf_text_append_bytes(&properties,escaped,strlen(escaped))){free(escaped);goto fail;}free(escaped);
        if(i==0||i==2)snprintf(line,sizeof(line),"</rdf:li></rdf:Alt></%s>\n",b2026_pdf_metadata_xml_keys[i]);
        else if(i==1)snprintf(line,sizeof(line),"</rdf:li></rdf:Seq></dc:creator>\n");
        else snprintf(line,sizeof(line),"</%s>\n",b2026_pdf_metadata_xml_keys[i]);
        if(!b2026_pdf_text_append_bytes(&properties,line,strlen(line)))goto fail;
    }
    close=strstr(old,"</rdf:RDF>");if(close==NULL)goto fail;
    insert="<rdf:Description rdf:about=\"\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:pdf=\"http://ns.adobe.com/pdf/1.3/\" xmlns:xmp=\"http://ns.adobe.com/xap/1.0/\">\n";
    if(!b2026_pdf_text_append_bytes(&out,old,(size_t)(close-old))||!b2026_pdf_text_append_bytes(&out,insert,strlen(insert))||!b2026_pdf_text_append_bytes(&out,properties.data!=NULL?properties.data:"",properties.used)||!b2026_pdf_text_append_bytes(&out,"</rdf:Description>\n",strlen("</rdf:Description>\n"))||!b2026_pdf_text_append_bytes(&out,close,strlen(close)))goto fail;
    free(properties.data);free(old);return b2026_pdf_text_take(&out);
fail:free(properties.data);free(out.data);free(old);return NULL;
}

static int b2026_pdf_metadata_next_number(B2026PdfDocument *doc){int i,max=0;for(i=0;i<doc->object_count;++i)if(doc->objects[i].old_number>max)max=doc->objects[i].old_number;return max+1;}

static int b2026_pdf_metadata_scrub_object(B2026PdfDocument *doc,int index,const char *replacement){
    unsigned char *copy;size_t length;
    if(index<0||index>=doc->object_count)return 1;
    length=strlen(replacement);copy=(unsigned char*)malloc(length+1U);if(copy==NULL)return 0;
    memcpy(copy,replacement,length+1U);free(doc->objects[index].body);doc->objects[index].body=copy;doc->objects[index].body_length=length;return 1;
}

static int b2026_pdf_metadata_replace_objects(B2026PdfDocument *doc,B2026PdfMetadataValues *m){
    B2026PdfTextBuffer info,stream;char *xmp=NULL;int i,number,old_info=doc->info_object,old_metadata=doc->metadata_object;memset(&info,0,sizeof(info));memset(&stream,0,sizeof(stream));if(!b2026_pdf_text_append_bytes(&info,"<<",2U))goto fail;
    for(i=0;i<8;++i)if(m->value[i]!=NULL){char *hex=b2026_pdf_metadata_pdf_hex(m->value[i]);if(hex==NULL)goto fail;if(!b2026_pdf_text_append_char(&info,' ')||!b2026_pdf_text_append_bytes(&info,b2026_pdf_metadata_pdf_keys[i],strlen(b2026_pdf_metadata_pdf_keys[i]))||!b2026_pdf_text_append_char(&info,' ')||!b2026_pdf_text_append_bytes(&info,hex,strlen(hex))){free(hex);goto fail;}free(hex);}
    if(!b2026_pdf_text_append_bytes(&info," >>",3U))goto fail;number=b2026_pdf_metadata_next_number(doc);if(!b2026_pdf_add_object(doc,number,0,(unsigned char*)info.data,info.used))goto fail;doc->info_object=b2026_pdf_object_lookup(doc,number,0);free(info.data);info.data=NULL;
    xmp=b2026_pdf_metadata_xmp(doc,m);if(xmp==NULL)goto fail;
    if(!b2026_pdf_metadata_scrub_object(doc,old_info,"<< >>")||!b2026_pdf_metadata_scrub_object(doc,old_metadata,"<< /Length 0 >>\nstream\n\nendstream"))goto fail;
    {char head[128];snprintf(head,sizeof(head),"<< /Type /Metadata /Subtype /XML /Length %lu >>\nstream\n",(unsigned long)strlen(xmp));if(!b2026_pdf_text_append_bytes(&stream,head,strlen(head))||!b2026_pdf_text_append_bytes(&stream,xmp,strlen(xmp))||!b2026_pdf_text_append_bytes(&stream,"\nendstream",10U))goto fail;}
    free(xmp);xmp=NULL;number=b2026_pdf_metadata_next_number(doc);if(!b2026_pdf_add_object(doc,number,0,(unsigned char*)stream.data,stream.used))goto fail;doc->metadata_object=b2026_pdf_object_lookup(doc,number,0);free(stream.data);return 1;
fail:free(info.data);free(stream.data);free(xmp);return 0;
}

static int b2026_pdf_metadata_read_current(B2026PdfDocument *doc,B2026PdfMetadataValues *m){
    char *xmp=b2026_pdf_xmp_text(doc);int i;memset(m,0,sizeof(*m));
    for(i=0;i<8;++i){
        char *iv=NULL,*xv=NULL,*chosen=NULL;
        if(doc->info_object>=0)iv=b2026_pdf_dict_string(doc,doc->objects[doc->info_object].body,doc->objects[doc->info_object].body_length,b2026_pdf_metadata_pdf_keys[i]);
        if(xmp!=NULL)xv=b2026_pdf_xml_field(xmp,b2026_pdf_metadata_xml_keys[i]);
        chosen=(xv!=NULL&&*xv!='\0')?xv:iv;
        if(i>=6&&chosen!=NULL){
            char *pdfdate=NULL,*xmpdate=NULL;
            if(b2026_pdf_metadata_date(chosen,&pdfdate,&xmpdate)){m->value[i]=pdfdate;m->xmp_value[i]=xmpdate;}
            else m->value[i]=b2026_strdup_simple(chosen);
            free(iv);free(xv);
        }else{
            m->value[i]=chosen;
            if(chosen==xv)free(iv);else free(xv);
        }
    }
    free(xmp);return 1;
}

static int b2026_pdf_metadata_hash_value(HashVariable *h,int index,char **value,int *remove,int *present){
    HashEntry *en=find_hash_entry(h,b2026_pdf_metadata_en_keys[index]),*jp=find_hash_entry(h,b2026_pdf_metadata_jp_keys[index]);const char *a=NULL,*b=NULL;int an=0,bn=0;
    *present=0;*remove=0;*value=NULL;if(en==NULL&&jp==NULL)return 1;*present=1;
    if(en!=NULL){if(en->value.type==TYPE_NUMBER){if(!isnan(en->value.val.number))return 0;an=1;}else a=hash_value_as_text(&en->value);}
    if(jp!=NULL){if(jp->value.type==TYPE_NUMBER){if(!isnan(jp->value.val.number))return 0;bn=1;}else b=hash_value_as_text(&jp->value);}
    if(en!=NULL&&jp!=NULL){if(an!=bn)return -1;if(!an&&strcmp(a!=NULL?a:"",b!=NULL?b:"")!=0)return -1;}
    if(an||bn){*remove=1;return 1;}*value=b2026_strdup_simple(en!=NULL?(a!=NULL?a:""):(b!=NULL?b:""));return *value!=NULL;
}

static int b2026_pdf_metadata_known_key(const char *key){
    static const char *readonly[]={"ok","partial","version","headerVersion","metadataSource","pages","fileSize","encrypted","signed","hasForm","hasAttachments","hasJavaScript","hasBookmarks","hasPageLabels","tagged","hasXMP","hasObjectStreams","incrementalUpdates","xrefType","hasAnnotations","annotationCount","commentAnnotationCount","linkAnnotationCount","widgetAnnotationCount","fileAttachmentAnnotationCount","mediaAnnotationCount","otherAnnotationCount","取得","一部取得","版","ヘッダー版","メタデータ元","総ページ数","ファイルサイズ","暗号化","電子署名","フォーム","添付ファイル","JavaScript","しおり","ページラベル","タグ付き","XMP","オブジェクトストリーム","増分更新回数","相互参照形式","注釈","注釈数"};
    size_t i;int n;
    if(key==NULL)return 0;
    for(n=0;n<8;++n)if(strcmp(key,b2026_pdf_metadata_en_keys[n])==0||strcmp(key,b2026_pdf_metadata_jp_keys[n])==0)return 1;
    for(i=0U;i<sizeof(readonly)/sizeof(readonly[0]);++i)if(strcmp(key,readonly[i])==0)return 1;
    return 0;
}

static void b2026_pdf_metadata_warn_unknown_keys(HashVariable *hash){
    HashEntry *entry=hash!=NULL?hash->entries:NULL;int warned=0;
    while(entry!=NULL){if(!b2026_pdf_metadata_known_key(entry->key)){warned=1;break;}entry=entry->next;}
    if(warned)b2026_pdf_log_warning("未対応の文書情報キーを無視しました。 / Unsupported metadata keys were ignored.");
}

static const char *b2026_pdf_metadata_edit(const char *operation,int argc,const B2026PdfArg *args){
    int separate,source_index,i,rc,valid=0;const char *source;char *output=NULL;B2026PdfDocument doc;B2026PdfPageList pages;B2026PdfMetadataValues values;HashVariable *hash=NULL;memset(&doc,0,sizeof(doc));memset(&pages,0,sizeof(pages));memset(&values,0,sizeof(values));
    separate=strcmp(operation,"SETMETADATA")==0?(argc==3):(argc==2);source_index=separate?1:0;
    if((strcmp(operation,"SETMETADATA")==0&&(argc!=2&&argc!=3))||(strcmp(operation,"CLEARMETADATA")==0&&(argc!=1&&argc!=2))||args[0].kind!=1||(separate&&args[1].kind!=1))return b2026_pdf_fail(4160,"","invalid metadata edit arguments / 文書情報編集の引数が正しくありません");
    if(strcmp(operation,"SETMETADATA")==0){const B2026PdfArg *ha=&args[argc-1];if(ha->kind!=3||ha->hash_name==NULL)return b2026_pdf_fail(4161,"","SETMETADATA requires an associative array / 情報設定には連想配列が必要です");hash=find_local_hash(get_hash_frame(ha->hash_name),ha->hash_name);if(hash==NULL)return b2026_pdf_fail(4161,"","metadata associative array does not exist / 文書情報の連想配列がありません");b2026_pdf_metadata_warn_unknown_keys(hash);}
    source=args[source_index].text;output=b2026_pdf_output_path(args[0].text);if(source==NULL||output==NULL)goto fail;rc=b2026_pdf_load(&doc,source,1);if(rc<=0){b2026_pdf_fail(4162,source,b2026_pdf_load_error(rc));goto fail;}
    for(i=0;i<doc.page_count;++i)if(!b2026_pdf_pages_push(&pages,&doc,doc.page_objects[i],-1))goto memory_fail;
    if(strcmp(operation,"CLEARMETADATA")==0){if(!b2026_pdf_metadata_scrub_object(&doc,doc.info_object,"<< >>")||!b2026_pdf_metadata_scrub_object(&doc,doc.metadata_object,"<< /Length 0 >>\nstream\n\nendstream"))goto memory_fail;doc.info_object=-1;doc.metadata_object=-1;}
    else{
        b2026_pdf_metadata_read_current(&doc,&values);
        for(i=0;i<8;++i){char *v=NULL;int remove=0,present=0,status=b2026_pdf_metadata_hash_value(hash,i,&v,&remove,&present);if(status<0){free(v);b2026_pdf_fail(4163,source,"Japanese and English metadata keys conflict / 日本語キーと英語キーの値が競合しています");goto fail;}if(status==0){free(v);b2026_pdf_fail(4164,source,"metadata values must be strings or NULL / 文書情報は文字列またはNULLで指定してください");goto fail;}if(!present)continue;++valid;values.changed[i]=1;free(values.value[i]);values.value[i]=NULL;free(values.xmp_value[i]);values.xmp_value[i]=NULL;if(!remove){if(i>=6){char *pdfdate=NULL,*xmpdate=NULL;if(!b2026_pdf_metadata_date(v,&pdfdate,&xmpdate)){free(v);b2026_pdf_fail(4165,source,"invalid metadata date / 文書情報の日付が正しくありません");goto fail;}free(v);values.value[i]=pdfdate;values.xmp_value[i]=xmpdate;}else values.value[i]=v;}}
        if(valid==0){b2026_pdf_fail(4166,source,"no writable metadata keys were supplied / 更新可能な文書情報が指定されていません");goto fail;}
        if(!b2026_pdf_metadata_replace_objects(&doc,&values))goto memory_fail;
    }
    if(!b2026_pdf_write_output(output,&doc,1,&pages,0,0,0)){b2026_pdf_fail(4167,output,"metadata output could not be written atomically or exceeded 2 GiB / 文書情報を原子的に保存できないか2GiB上限を超えました");goto fail;}
    {const char *result=runtime_temp_string_copy(output);b2026_pdf_metadata_values_free(&values);b2026_pdf_document_free(&doc);free(pages.items);free(output);return result;}
memory_fail:b2026_pdf_fail(4199,output,"out of memory / メモリ不足です");
fail:b2026_pdf_metadata_values_free(&values);b2026_pdf_document_free(&doc);free(pages.items);free(output);return runtime_temp_string_copy("");
}
