/*
OpenChange OCPF (OpenChange Property File) implementation.
Copyright (C) Julien Kerihuel 2008.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
%{
#include
#include
#include
void yyerror(char *);
union SPropValue_CTR lpProp;
struct ocpf_nprop nprop;
int typeset;
uint16_t type;
int folderset;
uint8_t recip_type;
%}
%union {
uint8_t i;
uint8_t b;
uint16_t s;
uint32_t l;
uint64_t d;
char *name;
char *nameW;
char *date;
char *var;
struct SLPSTRArray MVszA;
}
%token UINT8
%token BOOLEAN
%token SHORT
%token INTEGER
%token DOUBLE
%token IDENTIFIER
%token STRING
%token UNICODE
%token MVSTRING
%token SYSTIME
%token VAR
%token kw_TYPE
%token kw_FOLDER
%token kw_OLEGUID
%token kw_SET
%token kw_PROPERTY
%token kw_NPROPERTY
%token kw_RECIPIENT
%token kw_TO
%token kw_CC
%token kw_BCC
%token kw_OOM
%token kw_MNID_ID
%token kw_MNID_STRING
%token kw_PT_BOOLEAN
%token kw_PT_STRING8
%token kw_PT_UNICODE
%token kw_PT_SHORT
%token kw_PT_LONG
%token kw_PT_SYSTIME
%token kw_PT_MV_STRING8
%token kw_PT_BINARY
%token OBRACE
%token EBRACE
%token COMMA
%token SEMICOLON
%token COLON
%token LOWER
%token GREATER
%token EQUAL
%start keywords
%%
keywords : | keywords kvalues
{
memset(&lpProp, 0, sizeof (union SPropValue_CTR));
}
;
kvalues : Type
| Folder
| OLEGUID
| Set
| Property
| NProperty
| Recipient
;
Type :
kw_TYPE STRING
{
if (!typeset) {
ocpf_type_add($2);
typeset++;
} else {
error_message("%s", "duplicated TYPE\n");
return -1;
}
}
;
Folder :
kw_FOLDER STRING
{
if (folderset == false) {
ocpf_folder_add($2, 0, NULL);
folderset = true;
} else {
error_message("%s", "duplicated FOLDER\n");
}
}
| kw_FOLDER DOUBLE
{
if (folderset == false) {
ocpf_folder_add(NULL, $2, NULL);
folderset = true;
} else {
error_message("%s", "duplicated FOLDER\n");
}
}
| kw_FOLDER VAR
{
if (folderset == false) {
ocpf_folder_add(NULL, 0, $2);
folderset = true;
} else {
error_message("%s", "duplicated FOLDER\n");
}
}
;
OLEGUID :
kw_OLEGUID IDENTIFIER STRING
{
char *name;
char *guid;
name = talloc_strdup(ocpf->mem_ctx, $2);
guid = talloc_strdup(ocpf->mem_ctx, $3);
ocpf_oleguid_add(name, guid);
}
;
Set :
kw_SET VAR EQUAL propvalue
{
ocpf_variable_add($2, lpProp, type, true);
memset(&lpProp, 0, sizeof (union SPropValue_CTR));
}
;
Property :
kw_PROPERTY OBRACE pcontent EBRACE SEMICOLON
{
}
pcontent : | pcontent content
{
memset(&lpProp, 0, sizeof (union SPropValue_CTR));
}
;
content :
IDENTIFIER EQUAL propvalue
{
ocpf_propvalue_s($1, lpProp, type, true);
ocpf_propvalue_free(lpProp, type);
}
| INTEGER EQUAL propvalue
{
ocpf_propvalue($1, "UNNAMED", lpProp, type, true);
ocpf_propvalue_free(lpProp, type);
}
| IDENTIFIER EQUAL VAR
{
ocpf_propvalue_var($1, 0x0, $3, true);
}
| INTEGER EQUAL VAR
{
ocpf_propvalue_var(NULL, $1, $3, true);
}
;
propvalue : STRING
{
lpProp.lpszA = talloc_strdup(ocpf->mem_ctx, $1);
type = PT_STRING8;
}
| UNICODE
{
lpProp.lpszW = talloc_strdup(ocpf->mem_ctx, $1);
type = PT_UNICODE;
}
| SHORT { lpProp.i = $1; type = PT_SHORT; }
| INTEGER { lpProp.l = $1; type = PT_LONG; }
| BOOLEAN { lpProp.b = $1; type = PT_BOOLEAN; }
| DOUBLE { lpProp.d = $1; type = PT_DOUBLE; }
| SYSTIME
{
ocpf_add_filetime($1, &lpProp.ft);
type = PT_SYSTIME;
}
| OBRACE mvstring_contents STRING EBRACE
{
TALLOC_CTX *mem_ctx;
if (!lpProp.MVszA.cValues) {
lpProp.MVszA.cValues = 0;
lpProp.MVszA.strings = talloc_array(ocpf->mem_ctx, struct LPSTR *, 2);
} else {
lpProp.MVszA.strings = talloc_realloc(NULL, lpProp.MVszA.strings, struct LPSTR *,
lpProp.MVszA.cValues + 2);
}
mem_ctx = (TALLOC_CTX *) lpProp.MVszA.strings;
lpProp.MVszA.strings[lpProp.MVszA.cValues] = talloc_zero(mem_ctx, struct LPSTR);
mem_ctx = (TALLOC_CTX *) lpProp.MVszA.strings[lpProp.MVszA.cValues];
lpProp.MVszA.strings[lpProp.MVszA.cValues]->lppszA = talloc_strdup(mem_ctx, $3);
lpProp.MVszA.cValues += 1;
type = PT_MV_STRING8;
}
| OBRACE binary_contents EBRACE
{
type = PT_BINARY;
}
| LOWER STRING GREATER
{
int ret;
ret = ocpf_binary_add($2, &lpProp.bin);
type = (ret == OCPF_SUCCESS) ? PT_BINARY : PT_ERROR;
}
;
mvstring_contents: | mvstring_contents mvstring_content
mvstring_content : STRING COMMA
{
TALLOC_CTX *mem_ctx;
if (!lpProp.MVszA.cValues) {
lpProp.MVszA.cValues = 0;
lpProp.MVszA.strings = talloc_array(ocpf->mem_ctx, struct LPSTR *, 2);
} else {
lpProp.MVszA.strings = talloc_realloc(NULL, lpProp.MVszA.strings, struct LPSTR *,
lpProp.MVszA.cValues + 2);
}
mem_ctx = (TALLOC_CTX *) lpProp.MVszA.strings;
lpProp.MVszA.strings[lpProp.MVszA.cValues] = talloc_zero(mem_ctx, struct LPSTR);
mem_ctx = (TALLOC_CTX *) lpProp.MVszA.strings[lpProp.MVszA.cValues];
lpProp.MVszA.strings[lpProp.MVszA.cValues]->lppszA = talloc_strdup(mem_ctx, $1);
lpProp.MVszA.cValues += 1;
}
;
binary_contents: | binary_contents binary_content
binary_content : INTEGER
{
TALLOC_CTX *mem_ctx;
if ($1 > 0xFF) {
error_message("Invalid Binary constant: 0x%x > 0xFF\n", $1);
}
if (!lpProp.bin.cb) {
lpProp.bin.cb = 0;
lpProp.bin.lpb = talloc_array(ocpf->mem_ctx, uint8_t, 2);
} else {
lpProp.bin.lpb = talloc_realloc(NULL, lpProp.bin.lpb, uint8_t,
lpProp.bin.cb + 2);
}
mem_ctx = (TALLOC_CTX *) lpProp.bin.lpb;
lpProp.bin.lpb[lpProp.bin.cb] = $1;
lpProp.bin.cb += 1;
}
;
NProperty :
kw_NPROPERTY OBRACE npcontent EBRACE SEMICOLON
{
}
npcontent : | npcontent ncontent
{
memset(&lpProp, 0, sizeof (union SPropValue_CTR));
}
;
ncontent : kind EQUAL propvalue
{
ocpf_nproperty_add(&nprop, lpProp, NULL, type, true);
}
| known_kind EQUAL propvalue
{
ocpf_nproperty_add(&nprop, lpProp, NULL, type, true);
}
| kind EQUAL VAR
{
ocpf_nproperty_add(&nprop, lpProp, $3, type, true);
}
| known_kind EQUAL VAR
{
ocpf_nproperty_add(&nprop, lpProp, $3, type, true);
}
;
kind : kw_OOM COLON IDENTIFIER COLON IDENTIFIER
{
memset(&nprop, 0, sizeof (struct ocpf_nprop));
nprop.OOM = talloc_strdup(ocpf->mem_ctx, $3);
nprop.guid = $5;
}
| kw_MNID_ID COLON INTEGER COLON proptype COLON IDENTIFIER
{
nprop.registered = false;
nprop.mnid_id = $3;
nprop.guid = $7;
}
| kw_MNID_STRING COLON STRING COLON proptype COLON IDENTIFIER
{
nprop.registered = false;
nprop.mnid_string = talloc_strdup(ocpf->mem_ctx, $3);
nprop.guid = $7;
}
;
proptype : kw_PT_STRING8
{
memset(&nprop, 0, sizeof (struct ocpf_nprop));
nprop.propType = PT_STRING8;
}
| kw_PT_UNICODE
{
memset(&nprop, 0, sizeof (struct ocpf_nprop));
nprop.propType = PT_UNICODE;
}
| kw_PT_SHORT
{
memset(&nprop, 0, sizeof (struct ocpf_nprop));
nprop.propType = PT_SHORT;
}
| kw_PT_LONG
{
memset(&nprop, 0, sizeof (struct ocpf_nprop));
nprop.propType = PT_LONG;
}
| kw_PT_BOOLEAN
{
memset(&nprop, 0, sizeof (struct ocpf_nprop));
nprop.propType = PT_BOOLEAN;
}
| kw_PT_SYSTIME
{
memset(&nprop, 0, sizeof (struct ocpf_nprop));
nprop.propType = PT_SYSTIME;
}
| kw_PT_MV_STRING8
{
memset(&nprop, 0, sizeof (struct ocpf_nprop));
nprop.propType = PT_MV_STRING8;
}
| kw_PT_BINARY
{
memset(&nprop, 0, sizeof (struct ocpf_nprop));
nprop.propType = PT_BINARY;
}
;
known_kind : kw_MNID_ID COLON INTEGER COLON IDENTIFIER
{
memset(&nprop, 0, sizeof (struct ocpf_nprop));
nprop.registered = true;
nprop.mnid_id = $3;
nprop.guid = $5;
}
| kw_MNID_STRING COLON STRING COLON IDENTIFIER
{
memset(&nprop, 0, sizeof (struct ocpf_nprop));
nprop.registered = true;
nprop.mnid_string = talloc_strdup(ocpf->mem_ctx, $3);
nprop.guid = $5;
}
;
Recipient :
kw_RECIPIENT recipClass recipients STRING
{
char *recipient = NULL;
recipient = talloc_strdup(ocpf->mem_ctx, $4);
ocpf_recipient_add(recip_type, recipient);
talloc_free(recipient);
recip_type = 0;
}
;
recipClass : kw_TO
{
recip_type = MAPI_TO;
}
| kw_CC
{
recip_type = MAPI_CC;
}
| kw_BCC
{
recip_type = MAPI_BCC;
}
;
recipients : | recipients recipient
recipient : STRING SEMICOLON
{
char *recipient = NULL;
recipient = talloc_strdup(ocpf->mem_ctx, $1);
ocpf_recipient_add(recip_type, recipient);
talloc_free(recipient);
}
%%
void yyerror(char *s)
{
printf("%s: %d", s, lineno);
}