summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Ohly <patrick.ohly@intel.com>2011-07-22 09:04:01 +0200
committerPatrick Ohly <patrick.ohly@intel.com>2011-07-22 09:04:01 +0200
commite3fdd5ca811f24b2f80e598f9d00d2e134aa85e1 (patch)
treeb6afade0cb627e206d297ddc5ac739d5f3ccc7c4
parentb69d0aecf612d0f009903179619a983706f3b8f7 (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-xsrc/sysync/scriptcontext.cpp51
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 },