diff options
author | Patrick Ohly <patrick.ohly@intel.com> | 2011-07-22 09:04:01 +0200 |
---|---|---|
committer | Patrick Ohly <patrick.ohly@intel.com> | 2011-07-22 09:04:01 +0200 |
commit | e3fdd5ca811f24b2f80e598f9d00d2e134aa85e1 (patch) | |
tree | b6afade0cb627e206d297ddc5ac739d5f3ccc7c4 | |
parent | b69d0aecf612d0f009903179619a983706f3b8f7 (diff) |
scripting: added READ() method
The READ(filename) method returns the content of the file identified
with "filename". Relative paths are interpreted relative to the current
directory. On failures, an error messages is logged and UNASSIGNED
is returned.
This method is useful for inlining the photo data referenced with
local file:// URIs shortly before sending to a remote peer. SyncEvolution
uses the method in its outgoing vcard script as follows:
Field list:
<!-- Photo -->
<field name="PHOTO" type="blob" compare="never" merge="fillempty"/>
<field name="PHOTO_TYPE" type="string" compare="never" merge="fillempty"/>
<field name="PHOTO_VALUE" type="string" compare="never" merge="fillempty"/>
Profile:
<property name="PHOTO" filter="no">
<value field="PHOTO" conversion="BLOB_B64"/>
<parameter name="TYPE" default="no" show="yes">
<value field="PHOTO_TYPE"/>
</parameter>
<parameter name="VALUE" default="no" show="yes">
<value field="PHOTO_VALUE"/>
</parameter>
</property>
Script:
if (PHOTO_VALUE == "uri" &&
SUBSTR(PHOTO, 0, 7) == "file://") {
// inline the photo data
string data;
data = READ(SUBSTR(PHOTO, 7));
if (data != UNASSIGNED) {
PHOTO = data;
PHOTO_VALUE = "binary";
}
}
Test cases for inlining, not inlining because of non-file URI and
failed inling (file not found) were added to SyncEvolution.
-rwxr-xr-x | src/sysync/scriptcontext.cpp | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/src/sysync/scriptcontext.cpp b/src/sysync/scriptcontext.cpp index f21641e..e6124c9 100755 --- a/src/sysync/scriptcontext.cpp +++ b/src/sysync/scriptcontext.cpp @@ -27,6 +27,7 @@ #include "pcre.h" // for RegEx functions #endif +#include <stdio.h> // script debug messages #ifdef SYDEBUG @@ -869,6 +870,55 @@ public: aTermP->setAsInteger(exitcode); }; // func_Shellexecute + // string READ(string file) + // reads the file and returns its content or UNASSIGNED in case of failure; + // errors are logged + static void func_Read(TItemField *&aTermP, TScriptContext *aFuncContextP) + { + // get params + string file; + aFuncContextP->getLocalVar(0)->getAsString(file); + + // execute now + string content; + FILE *in; + in = fopen(file.c_str(), "rb"); + if (in) { + long size = fseek(in, 0, SEEK_END); + if (size >= 0) { + // managed to obtain size, use it to pre-allocate result + content.reserve(size); + fseek(in, 0, SEEK_SET); + } else { + // ignore seek error, might not be a plain file + clearerr(in); + } + + if (!ferror(in)) { + char buf[8192]; + size_t read; + while ((read = fread(buf, 1, sizeof(buf), in)) > 0) { + content.append(buf, read); + } + } + } + + if (in && !ferror(in)) { + // return content as string + aTermP->setAsString(content); + } else { + PLOGDEBUGPRINTFX(aFuncContextP->getDbgLogger(), + DBG_ERROR,( + "IO error in READ(\"%s\"): %s ", + file.c_str(), + strerror(errno))); + } + + if (in) { + fclose(in); + } + } // func_Read + // string REMOTERULENAME() // returns name of the LAST matched remote rule (or subrule), empty if none @@ -2220,6 +2270,7 @@ const TBuiltInFuncDef BuiltInFuncDefs[] = { { "REQUESTMAXTIME", TBuiltinStdFuncs::func_RequestMaxTime, fty_none, 1, param_oneInteger }, { "REQUESTMINTIME", TBuiltinStdFuncs::func_RequestMinTime, fty_none, 1, param_oneInteger }, { "SHELLEXECUTE", TBuiltinStdFuncs::func_Shellexecute, fty_integer, 3, param_Shellexecute }, + { "READ", TBuiltinStdFuncs::func_Read, fty_string, 1, param_oneString }, { "SESSIONVAR", TBuiltinStdFuncs::func_SessionVar, fty_none, 1, param_oneString }, { "SETSESSIONVAR", TBuiltinStdFuncs::func_SetSessionVar, fty_none, 2, param_SetSessionVar }, { "ABORTSESSION", TBuiltinStdFuncs::func_AbortSession, fty_none, 1, param_oneInteger }, |