CFLAGS:=${DEBUG} -I. -I${top_srcdir}/interface -I${stagedir}/include \
${GLOBUSINC}
+LDFLAGS:=-L${globus_prefix}/lib
+
offset=0
version_info:=-version-info ${shell \
perl -e '$$,=":"; @F=split "\\.","${version}"; print $$F[0]+$$F[1]+${offset},$$F[2],$$F[1]' }
TRIO_LIB:=libglite_jp_trio.la
TRIO_LOBJS:=${TRIO_OBJS:.o=.lo}
+TEST_LIBS:=-L${cppunit}/lib -lcppunit -ldl
+TEST_INC:=-I${cppunit}/include
+
+
default all: compile
-compile: ${commonlib} ${TRIO_LIB}
+compile: ${commonlib} ${TRIO_LIB}
${commonlib}: ${OBJS}
- ${LINK} -o $@ ${OBJS}
+ ${LINK} -o $@ ${OBJS} -lcrypto_${nothrflavour}
${TRIO_LIB}: ${TRIO_LOBJS}
${LINK} ${version_info} -o $@ ${TRIO_LOBJS} -lm
-check:
- -echo nothing yet
+check: base64_test type_test
+ ./base64_test base64_test.xml
+ ./type_test type_test.xml
+
+type_test base64_test: %: %.cpp compile
+ ${CXX} -c ${CFLAGS} ${TEST_INC} $<
+ ${LINKXX} -o $@ $@.o ${commonlib} ${TRIO_LIB} ${TEST_LIBS}
doc:
#ifndef __GLITE_JP_ATTR
#define __GLITE_JP_ATTR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void glite_jp_attrval_free(glite_jp_attrval_t *,int);
void glite_jp_attrval_copy(glite_jp_attrval_t *,const glite_jp_attrval_t *);
time_t glite_jp_attr2time(const char *);
char * glite_jp_time2attr(time_t);
+#ifdef __cplusplus
+};
+#endif
+
#endif
#ifndef __GLITE_JP_CONTEXT
#define __GLITE_JP_CONTEXT
+#ifdef __cplusplus
+extern "C" {
+#endif
+
int glite_jp_init_context(glite_jp_context_t *);
void glite_jp_free_context(glite_jp_context_t);
void glite_jp_free_query_rec(glite_jp_query_rec_t *);
int glite_jp_run_deferred(glite_jp_context_t);
+#ifdef __cplusplus
+};
+#endif
+
#endif
#ifndef _GLITE_STRMD5_H
#define _GLITE_STRMD5_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#ident "$Header$"
/* Compute MD5 sum of the first argument.
int base64_encode(const void *enc, int enc_size, char *out, int out_max_size);
int base64_decode(const char *enc,char *out,int out_size);
+#ifdef __cplusplus
+};
+#endif
+
#endif /* _GLITE_STRMD5_H */
return 0;
}
+/* XXX: depends on specific definition of glite_jp_attr_orig_t */
+static char orig_char[] = "ASUF";
+
+/* XXX: don't allocate memory, don't grow more than twice */
+static int escape_colon(const char *in, char *out)
+{
+ int i,o;
+
+ for (i=o=0; in[i]; i++) switch (in[i]) {
+ case ':': out[o++] = '\\'; out[o++] = ':'; break;
+ case '\\': out[o++] = '\\'; out[o++] = '\\'; break;
+ default: out[o++] = in[i]; break;
+ }
+ out[o] = 0;
+ return o;
+}
+
+/* XXX: read until unescaped colon is found
+ * allocates output */
+static char * unescape_colon(const char *in,int *rd)
+{
+ int i,o;
+ char *out;
+
+ for (i=o=0; in[i] && in[i] != ':'; i++,o++)
+ if (in[i] == '\\') i++;
+
+ out = malloc(o+1);
+
+ for (i=o=0; in[i] && in[i] != ':'; i++)
+ if (in[i] == '\\') out[o++] = in[++i];
+ else out[o++] = in[i];
+
+ out[o] = 0;
+ *rd = i;
+ return out;
+}
+
static char * fb_to_db_full(void *ctx,const glite_jp_attrval_t *attr)
{
- char *db;
- if (attr->binary) {
- int osize = attr->size * 4/3 + 6;
- db = malloc(osize);
- db[0] = 'B'; db[1] = ':';
- osize = base64_encode(attr->value,attr->size,db+2,osize-3);
- assert(osize >= 0);
- db[osize] = 0;
+
+ int vsize = attr->binary ? attr->size * 4/3 + 6 : strlen(attr->value)+1,
+ len;
+
+ /* 4x: + \0 + ASUF + BS + %12d */
+ char *db = malloc(19 + (attr->origin_detail ? 2*strlen(attr->origin_detail) : 0) + vsize);
+
+ if (attr->origin < 0 || attr->origin > GLITE_JP_ATTR_ORIG_FILE) {
+ free(db); return NULL;
}
- else {
- db = malloc(strlen(attr->value)+3);
- db[0] = 'S'; db[1] = ':';
- strcpy(db+2,attr->value);
+ len = sprintf(db,"%c:%d:%c:",attr->binary ? 'B' : 'S',
+ attr->timestamp,orig_char[attr->origin]);
+
+ if (attr->origin_detail) len += escape_colon(attr->origin_detail,db+len);
+ db[len++] = ':';
+
+ if (attr->binary) {
+ vsize = base64_encode(attr->value,attr->size,db+len,vsize-1);
+ if (vsize < 0) { free(db); return NULL; }
+ db[len+vsize] = 0;
}
+ else strcpy(db+len,attr->value);
+
return db;
}
static char * fb_to_db_index(void *ctx,const glite_jp_attrval_t *attr,int len)
{
- char *db = fb_to_db_full(ctx,attr);
- if (len < strlen(db)) db[len] = 0;
- return db;
+ char *s;
+
+/* XXX: binary values not really handled. Though the formal semantics is not broken */
+ if (attr->binary) return strdup("XXX");
+
+ s = strdup(attr->value);
+ if (len < strlen(s)) s[len] = 0;
+ return s;
}
-int fb_from_db(void *ctx,const char *str,glite_jp_attrval_t *attr)
-{
- int osize;
- switch (str[0]) {
- case 'B':
- attr->value = malloc(osize = strlen(str) * 3/4 + 4);
- attr->size = base64_decode(str,str+2,osize);
- assert(attr->size >= 0);
- attr->binary = 1;
- break;
- case 'S':
- attr->value = strdup(str + 2);
- attr->size = 0;
- attr->binary = 0;
- break;
- default: return EINVAL;
+static int fb_from_db(void *ctx,const char *str,glite_jp_attrval_t *attr)
+{
+ int p = 2;
+ char *colon,*cp;
+
+ if (str[0] != 'B' && str[0] != 'S') return EINVAL;
+ attr->binary = str[0] == 'B';
+ cp = attr->value = strdup(str);
+
+ colon = strchr(cp+p,':');
+ if (!colon) return EINVAL;
+
+ *colon++ = 0;
+ attr->timestamp = (time_t) atol(cp+p);
+ p = colon-cp;
+
+ for (attr->origin = GLITE_JP_ATTR_ORIG_ANY; orig_char[attr->origin] && orig_char[attr->origin] != cp[p]; attr->origin++);
+ if (!orig_char[attr->origin]) return EINVAL;
+
+ p += 2;
+ if (cp[p] == ':') attr->origin_detail = NULL;
+ else {
+ int r;
+ attr->origin_detail = unescape_colon(cp+p,&r);
+ p += r;
}
+ if (cp[p++] != ':') return EINVAL;
+
+ if (attr->binary) {
+ attr->size = base64_decode(str+p,attr->value,strlen(str));
+ if (attr->size < 0) return EINVAL;
+ }
+ else strcpy(attr->value,str+p);
+
return 0;
}
}
while (*enc && *enc != '=') {
- bits << 6;
+ bits <<= 6;
bits |= b64r[*enc++];
shift += 6;
}
}
- /* XXX: will it ever happen? */
- if (shift) {
- if (out_size >= max_out_size) return -1;
- bits <<= 8-shift;
- *out = bits & 0xff;
- out_size++;
- }
-
return out_size;
}
--- /dev/null
+#include <assert.h>
+#include <fstream>
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/CompilerOutputter.h>
+#include <cppunit/XmlOutputter.h>
+#include <cppunit/TestRunner.h>
+#include <cppunit/TestResult.h>
+#include <cppunit/TestResultCollector.h>
+
+#include "strmd5.h"
+
+class Base64Test: public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(Base64Test);
+ CPPUNIT_TEST(test);
+ CPPUNIT_TEST_SUITE_END();
+public:
+ void test();
+};
+
+void Base64Test::test()
+{
+ int i;
+ unsigned char in[2000], b[4000], out[2000];
+
+ srandom(0xDEAD);
+ in[0] = 'x';
+ for (i=1; i<2000; i++) {
+ char s[20];
+ int len;
+ sprintf(s,"%d",i);
+ in[i] = random() % 256;
+
+ std::cerr << '.';
+
+ base64_encode(in,i,(char *) b,sizeof b);
+ len = base64_decode((const char *) b,(char *) out,sizeof out);
+
+ CPPUNIT_ASSERT_MESSAGE(std::string("len"),i == len);
+ CPPUNIT_ASSERT_MESSAGE(std::string(s),!memcmp(in,out,i));
+ }
+ std::cerr << std::endl;
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Base64Test);
+
+
+int main (int argc,const char *argv[])
+{
+ CppUnit::Test *suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest();
+
+ assert(argc == 2);
+ std::ofstream xml(argv[1]);
+
+ CppUnit::TestResult controller;
+ CppUnit::TestResultCollector result;
+ controller.addListener( &result );
+
+ CppUnit::TestRunner runner;
+ runner.addTest(suite);
+ runner.run(controller);
+
+ CppUnit::XmlOutputter xout( &result, xml );
+ CppUnit::CompilerOutputter tout( &result, std::cout);
+ xout.write();
+ tout.write();
+
+ return result.wasSuccessful() ? 0 : 1 ;
+}
+
+
+
--- /dev/null
+#include <assert.h>
+#include <fstream>
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/CompilerOutputter.h>
+#include <cppunit/XmlOutputter.h>
+#include <cppunit/TestRunner.h>
+#include <cppunit/TestResult.h>
+#include <cppunit/TestResultCollector.h>
+
+#include "types.h"
+#include "attr.h"
+#include "context.h"
+
+
+class TypePluginTest: public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(TypePluginTest);
+ CPPUNIT_TEST(simple);
+ CPPUNIT_TEST(binary);
+ CPPUNIT_TEST(origin);
+ CPPUNIT_TEST(origin2);
+ CPPUNIT_TEST(index);
+ CPPUNIT_TEST_SUITE_END();
+public:
+ void simple();
+ void binary();
+ void origin();
+ void origin2();
+ void index();
+};
+
+void TypePluginTest::simple()
+{
+ glite_jp_context_t ctx;
+
+ glite_jp_attrval_t attr = {
+ "myattr",
+ "short string",
+ 0,0,
+ GLITE_JP_ATTR_ORIG_USER,
+ NULL,
+ 0
+ },attr2;
+
+ char *db;
+
+ glite_jp_init_context(&ctx);
+ attr.timestamp = time(NULL);
+
+ db = glite_jp_attrval_to_db_full(ctx,&attr);
+
+ CPPUNIT_ASSERT_MESSAGE(std::string("glite_jp_attrval_to_db_full()"),db);
+ std::cerr << db << std::endl;
+
+ glite_jp_attrval_from_db(ctx,db,&attr2);
+ CPPUNIT_ASSERT_MESSAGE(std::string("value"),!strcmp(attr.value,attr2.value));
+ CPPUNIT_ASSERT_MESSAGE(std::string("origin"),attr.origin == attr2.origin);
+ CPPUNIT_ASSERT_MESSAGE(std::string("timestamp"),attr.timestamp == attr2.timestamp);
+}
+
+void TypePluginTest::binary()
+{
+ glite_jp_context_t ctx;
+
+ glite_jp_attrval_t attr = {
+ "myattr",
+ NULL,
+ 1,1000,
+ GLITE_JP_ATTR_ORIG_USER,
+ NULL,
+ 0
+ },attr2;
+
+ char *db;
+
+ glite_jp_init_context(&ctx);
+ attr.timestamp = time(NULL);
+ attr.value = (char *) malloc(attr.size);
+
+ db = glite_jp_attrval_to_db_full(ctx,&attr);
+
+ CPPUNIT_ASSERT_MESSAGE(std::string("glite_jp_attrval_to_db_full()"),db);
+ std::cerr << db << std::endl;
+
+ glite_jp_attrval_from_db(ctx,db,&attr2);
+ CPPUNIT_ASSERT_MESSAGE(std::string("size"),attr.size == attr2.size);
+ CPPUNIT_ASSERT_MESSAGE(std::string("value"),!memcmp(attr.value,attr2.value,attr.size));
+}
+
+void TypePluginTest::origin()
+{
+ glite_jp_context_t ctx;
+
+ glite_jp_attrval_t attr = {
+ "myattr",
+ NULL,
+ 0,0,
+ GLITE_JP_ATTR_ORIG_USER,
+ NULL,
+ 0
+ },attr2;
+
+ char *db;
+
+ glite_jp_init_context(&ctx);
+ attr.timestamp = time(NULL);
+ attr.value = "origin test";
+ attr.origin_detail = "simple origin";
+
+ db = glite_jp_attrval_to_db_full(ctx,&attr);
+
+ CPPUNIT_ASSERT_MESSAGE(std::string("glite_jp_attrval_to_db_full()"),db);
+ std::cerr << db << std::endl;
+
+ glite_jp_attrval_from_db(ctx,db,&attr2);
+ CPPUNIT_ASSERT_MESSAGE(std::string("origin detail"),!strcmp(attr.origin_detail,attr2.origin_detail));
+}
+
+void TypePluginTest::origin2()
+{
+ glite_jp_context_t ctx;
+
+ glite_jp_attrval_t attr = {
+ "myattr",
+ NULL,
+ 0,0,
+ GLITE_JP_ATTR_ORIG_USER,
+ NULL,
+ 0
+ },attr2;
+
+ char *db;
+
+ glite_jp_init_context(&ctx);
+ attr.timestamp = time(NULL);
+ attr.value = "origin:test";
+ attr.origin_detail = "ftp://some.server:1234/ugly \\file";
+
+ db = glite_jp_attrval_to_db_full(ctx,&attr);
+
+ CPPUNIT_ASSERT_MESSAGE(std::string("glite_jp_attrval_to_db_full()"),db);
+ std::cerr << db << std::endl;
+
+ glite_jp_attrval_from_db(ctx,db,&attr2);
+ CPPUNIT_ASSERT_MESSAGE(std::string("origin detail"),!strcmp(attr.origin_detail,attr2.origin_detail));
+ CPPUNIT_ASSERT_MESSAGE(std::string("value"),!strcmp(attr.value,attr2.value));
+}
+
+void TypePluginTest::index()
+{
+ /* TODO: check monotonity */
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(TypePluginTest);
+
+
+int main (int argc,const char *argv[])
+{
+ CppUnit::Test *suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest();
+
+ assert(argc == 2);
+ std::ofstream xml(argv[1]);
+
+ CppUnit::TestResult controller;
+ CppUnit::TestResultCollector result;
+ controller.addListener( &result );
+
+ CppUnit::TestRunner runner;
+ runner.addTest(suite);
+ runner.run(controller);
+
+ CppUnit::XmlOutputter xout( &result, xml );
+ CppUnit::CompilerOutputter tout( &result, std::cout);
+ xout.write();
+ tout.write();
+
+ return result.wasSuccessful() ? 0 : 1 ;
+}
+
+
+