[ruby-oci8-commit] [308] trunk/ruby-oci8: * ext/oci8/encoding.c: (ruby 1.9) add OCI8. encoding and

nobody at rubyforge.org nobody at rubyforge.org
Sun Jan 11 10:11:10 EST 2009


Revision: 308
Author:   kubo
Date:     2009-01-11 10:11:09 -0500 (Sun, 11 Jan 2009)

Log Message:
-----------
* ext/oci8/encoding.c: (ruby 1.9) add OCI8.encoding and
    OCI8.encoding= to get and set the encoding of the Oracle
    library.
* ext/oci8/oci8.h: (ruby 1.9) add macros OCI8StringValue
    and OCI8SafeStringValue which convert the string encoding
    to Oracle librarie's encoding.
* ext/oci8/oci8.c: OCI8.new raise a SecurityError when specified
    connect string is tainted and $SAFE >= 1.
* ext/oci8/stmt.c: OCI8#parse raise a SecurityError when specified
    SQL statemenet is tainted and $SAFE >= 1.
* ext/oci8/metadata.c: OCI8#describe_* raise a SecurityError
    when the object name to be described is tainted and $SAFE >= 1.
* ext/oci8/lob.c: OCI8::BFILE.new, OCI8::BFILE#dir_alias= and
    OCI8::BFILE#filename= raise a SecurityError when specified
    dir_alias or filename is tainted and $SAFE >= 1.
* ext/oci8/attr.c, ext/oci8/bind.c, ext/oci8/error.c,
  ext/oci8/object.c, ext/oci8/oci8lib.c, ext/oci8/ocinumber.c:
    (ruby 1.9) converts encoding from/to OCI.encoding.

Modified Paths:
--------------
    trunk/ruby-oci8/ChangeLog
    trunk/ruby-oci8/ext/oci8/attr.c
    trunk/ruby-oci8/ext/oci8/bind.c
    trunk/ruby-oci8/ext/oci8/encoding.c
    trunk/ruby-oci8/ext/oci8/error.c
    trunk/ruby-oci8/ext/oci8/lob.c
    trunk/ruby-oci8/ext/oci8/metadata.c
    trunk/ruby-oci8/ext/oci8/object.c
    trunk/ruby-oci8/ext/oci8/oci8.c
    trunk/ruby-oci8/ext/oci8/oci8.h
    trunk/ruby-oci8/ext/oci8/oci8lib.c
    trunk/ruby-oci8/ext/oci8/ocinumber.c
    trunk/ruby-oci8/ext/oci8/stmt.c

Modified: trunk/ruby-oci8/ChangeLog
===================================================================
--- trunk/ruby-oci8/ChangeLog	2009-01-11 08:38:04 UTC (rev 307)
+++ trunk/ruby-oci8/ChangeLog	2009-01-11 15:11:09 UTC (rev 308)
@@ -1,4 +1,24 @@
 2009-01-11  KUBO Takehiro  <kubo at jiubao.org>
+	* ext/oci8/encoding.c: (ruby 1.9) add OCI8.encoding and
+	    OCI8.encoding= to get and set the encoding of the Oracle
+	    library.
+	* ext/oci8/oci8.h: (ruby 1.9) add macros OCI8StringValue
+	    and OCI8SafeStringValue which convert the string encoding
+	    to Oracle librarie's encoding.
+	* ext/oci8/oci8.c: OCI8.new raise a SecurityError when specified
+	    connect string is tainted and $SAFE >= 1.
+	* ext/oci8/stmt.c: OCI8#parse raise a SecurityError when specified
+	    SQL statemenet is tainted and $SAFE >= 1.
+	* ext/oci8/metadata.c: OCI8#describe_* raise a SecurityError
+	    when the object name to be described is tainted and $SAFE >= 1.
+	* ext/oci8/lob.c: OCI8::BFILE.new, OCI8::BFILE#dir_alias= and
+	    OCI8::BFILE#filename= raise a SecurityError when specified
+	    dir_alias or filename is tainted and $SAFE >= 1.
+	* ext/oci8/attr.c, ext/oci8/bind.c, ext/oci8/error.c,
+	  ext/oci8/object.c, ext/oci8/oci8lib.c, ext/oci8/ocinumber.c:
+	    (ruby 1.9) converts encoding from/to OCI.encoding.
+
+2009-01-11  KUBO Takehiro  <kubo at jiubao.org>
 	* ext/oci8/lob.c: concatenate read data at the end, instead of
 	    appending them for each pieces when reading LOB data.
 	* test/test_oranumber.rb: fix for ruby 1.9.

Modified: trunk/ruby-oci8/ext/oci8/attr.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/attr.c	2009-01-11 08:38:04 UTC (rev 307)
+++ trunk/ruby-oci8/ext/oci8/attr.c	2009-01-11 15:11:09 UTC (rev 308)
@@ -66,7 +66,7 @@
     rv = OCIAttrGet(base->hp.ptr, base->type, &val, &size, attrtype, oci8_errhp);
     if (rv != OCI_SUCCESS)
         oci8_raise(oci8_errhp, rv, NULL);
-    return rb_str_new(TO_CHARPTR(val), size);
+    return rb_external_str_new_with_enc(TO_CHARPTR(val), size, oci8_encoding);
 }
 
 #define MAX_ROWID_LEN 128
@@ -134,7 +134,7 @@
             return Qnil;
         }
     }
-    return rb_str_new(buf, buflen);
+    return rb_external_str_new_with_enc(buf, buflen, rb_usascii_encoding());
 }
 
 static VALUE rowid_ensure(rowid_arg_t *arg)

Modified: trunk/ruby-oci8/ext/oci8/bind.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/bind.c	2009-01-11 08:38:04 UTC (rev 307)
+++ trunk/ruby-oci8/ext/oci8/bind.c	2009-01-11 15:11:09 UTC (rev 308)
@@ -20,14 +20,14 @@
 static VALUE bind_string_get(oci8_bind_t *obind, void *data, void *null_struct)
 {
     oci8_vstr_t *vstr = (oci8_vstr_t *)data;
-    return rb_str_new(vstr->buf, vstr->size);
+    return rb_external_str_new_with_enc(vstr->buf, vstr->size, oci8_encoding);
 }
 
 static void bind_string_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
 {
     oci8_vstr_t *vstr = (oci8_vstr_t *)data;
 
-    StringValue(val);
+    OCI8StringValue(val);
     if (RSTRING_LEN(val) > obind->value_sz - sizeof(vstr->size)) {
         rb_raise(rb_eArgError, "too long String to set. (%ld for %d)", RSTRING_LEN(val), obind->value_sz - (sb4)sizeof(vstr->size));
     }
@@ -74,13 +74,19 @@
 /*
  * bind_raw
  */
+static VALUE bind_raw_get(oci8_bind_t *obind, void *data, void *null_struct)
+{
+    oci8_vstr_t *vstr = (oci8_vstr_t *)data;
+    return rb_str_new(vstr->buf, vstr->size);
+}
+
 static const oci8_bind_class_t bind_raw_class = {
     {
         NULL,
         oci8_bind_free,
         sizeof(oci8_bind_t)
     },
-    bind_string_get,
+    bind_raw_get,
     bind_string_set,
     bind_string_init,
     NULL,

Modified: trunk/ruby-oci8/ext/oci8/encoding.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/encoding.c	2009-01-11 08:38:04 UTC (rev 307)
+++ trunk/ruby-oci8/ext/oci8/encoding.c	2009-01-11 15:11:09 UTC (rev 308)
@@ -28,6 +28,9 @@
 static ID id_upcase;
 static VALUE csname2id;
 static VALUE oci8_charset_name2id(VALUE svc, VALUE name);
+#ifdef HAVE_TYPE_RB_ENCODING
+rb_encoding *oci8_encoding;
+#endif
 
 VALUE oci8_charset_id2name(VALUE svc, VALUE csid)
 {
@@ -129,7 +132,52 @@
     return csid;
 }
 
+#ifdef HAVE_TYPE_RB_ENCODING
 
+/*
+ * call-seq:
+ *   OCI8.encoding -> enc
+ *
+ * (new in ruby 1.9)
+ *
+ * Returns Oracle client encoding.
+ *
+ * String values passed to Oracle, such as SQL statements,
+ * bind values etc., are converted from their encoding to
+ * the Oracle client encoding.
+ *
+ * If <code>Encoding.default_internal</code> is nil,
+ * string values got from Oracle are tagged by
+ * <code>OCI8.encoding</code>. If not nil, they are
+ * converted from <code>OCI8.encoding</code> to
+ * <code>Encoding.default_internal</code> by default.
+ *
+ * If it is 'ASCII-8BIT', no encoding conversions are done.
+ */
+static VALUE oci8_get_encoding(VALUE klass)
+{
+    return rb_enc_from_encoding(oci8_encoding);
+}
+
+/*
+ * call-seq:
+ *   OCI8.encoding = enc or nil
+ *
+ * (new in ruby 1.9)
+ *
+ * Sets Oracle client encoding.
+ */
+static VALUE oci8_set_encoding(VALUE klass, VALUE encoding)
+{
+    if (NIL_P(encoding)) {
+        oci8_encoding = NULL;
+    } else {
+        oci8_encoding = rb_to_encoding(encoding);
+    }
+    return encoding;
+}
+#endif
+
 void Init_oci8_encoding(VALUE cOCI8)
 {
     csid2name = rb_hash_new();
@@ -141,4 +189,8 @@
 
     rb_define_method(cOCI8, "charset_name2id", oci8_charset_name2id, 1);
     rb_define_method(cOCI8, "charset_id2name", oci8_charset_id2name, 1);
+#ifdef HAVE_TYPE_RB_ENCODING
+    rb_define_singleton_method(cOCI8, "encoding", oci8_get_encoding, 0);
+    rb_define_singleton_method(cOCI8, "encoding=", oci8_set_encoding, 1);
+#endif
 }

Modified: trunk/ruby-oci8/ext/oci8/error.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/error.c	2009-01-11 08:38:04 UTC (rev 307)
+++ trunk/ruby-oci8/ext/oci8/error.c	2009-01-11 15:11:09 UTC (rev 308)
@@ -69,7 +69,7 @@
                 }
             }
             rb_ary_push(vcodes, INT2FIX(errcode));
-            rb_ary_push(vmessages, rb_str_new2(errmsg));
+            rb_ary_push(vmessages, rb_external_str_new_with_enc(errmsg, strlen(errmsg), oci8_encoding));
         }
         if (RARRAY_LEN(vmessages) > 0) {
             msg = RARRAY_PTR(vmessages)[0];
@@ -96,7 +96,7 @@
             ub4 size;
             rv = OCIAttrGet(stmthp, OCI_HTYPE_STMT, &sql, &size, OCI_ATTR_STATEMENT, errhp);
             if (rv == OCI_SUCCESS) {
-                vsql = rb_str_new(TO_CHARPTR(sql), size);
+                vsql = rb_external_str_new_with_enc(TO_CHARPTR(sql), size, oci8_encoding);
             }
         }
 #endif

Modified: trunk/ruby-oci8/ext/oci8/lob.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/lob.c	2009-01-11 08:38:04 UTC (rev 307)
+++ trunk/ruby-oci8/ext/oci8/lob.c	2009-01-11 15:11:09 UTC (rev 308)
@@ -154,7 +154,7 @@
     if (!NIL_P(val)) {
         if (have_OCILobCreateTemporary_nb) {
             oci8_svcctx_t *svcctx = oci8_get_svcctx(svc);
-            StringValue(val);
+            OCI8StringValue(val);
             oci_lc(OCILobCreateTemporary_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, 0, csfrm, lobtype, TRUE, OCI_DURATION_SESSION));
             oci8_lob_write(self, val);
         } else {
@@ -358,7 +358,10 @@
     if (RARRAY_LEN(v) == 0) {
         return Qnil;
     }
-    return rb_ary_join(v, Qnil);
+    v = rb_ary_join(v, Qnil);
+    OBJ_TAINT(v);
+    rb_enc_associate(v, oci8_encoding);
+    return rb_str_conv_enc(v, oci8_encoding, rb_default_internal_encoding());
 }
 
 static VALUE oci8_lob_write(VALUE self, VALUE data)
@@ -368,7 +371,7 @@
     ub4 amt;
 
     lob_open(lob);
-    StringValue(data);
+    OCI8StringValue(data);
     amt = RSTRING_LEN(data);
     oci_lc(OCILobWrite_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &amt, lob->pos + 1, RSTRING_PTR(data), amt, OCI_ONE_PIECE, NULL, NULL, 0, lob->csfrm));
     lob->pos += amt;
@@ -462,8 +465,8 @@
         VALUE filename;
 
         oci_lc(OCILobFileGetName(oci8_envhp, oci8_errhp, lob->base.hp.lob, TO_ORATEXT(d_buf), &d_length, TO_ORATEXT(f_buf), &f_length));
-        dir_alias = rb_str_new(d_buf, d_length);
-        filename = rb_str_new(f_buf, f_length);
+        dir_alias = rb_external_str_new_with_enc(d_buf, d_length, oci8_encoding);
+        filename = rb_external_str_new_with_enc(f_buf, f_length, oci8_encoding);
         rb_ivar_set(self, id_dir_alias, dir_alias);
         rb_ivar_set(self, id_filename, filename);
         if (dir_alias_p != NULL) {
@@ -502,8 +505,8 @@
     lob->csfrm = SQLCS_IMPLICIT;
     lob->state = S_BFILE_CLOSE;
     if (argc != 1) {
-        StringValue(dir_alias);
-        StringValue(filename);
+        OCI8SafeStringValue(dir_alias);
+        OCI8SafeStringValue(filename);
         oci8_bfile_set_name(self, dir_alias, filename);
     }
     oci8_link_to_parent((oci8_base_t*)lob, (oci8_base_t*)DATA_PTR(svc));
@@ -530,7 +533,7 @@
 {
     VALUE filename;
 
-    StringValue(dir_alias);
+    OCI8SafeStringValue(dir_alias);
     oci8_bfile_get_name(self, NULL, &filename);
     oci8_bfile_set_name(self, dir_alias, filename);
     rb_ivar_set(self, id_dir_alias, dir_alias);
@@ -541,7 +544,7 @@
 {
     VALUE dir_alias;
 
-    StringValue(filename);
+    OCI8SafeStringValue(filename);
     oci8_bfile_get_name(self, &dir_alias, NULL);
     oci8_bfile_set_name(self, dir_alias, filename);
     rb_ivar_set(self, id_filename, filename);

Modified: trunk/ruby-oci8/ext/oci8/metadata.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/metadata.c	2009-01-11 08:38:04 UTC (rev 307)
+++ trunk/ruby-oci8/ext/oci8/metadata.c	2009-01-11 15:11:09 UTC (rev 308)
@@ -174,7 +174,7 @@
 
     /* remote call sometimes? */
     oci_lc(OCIAttrGet_nb(svcctx, md->base.hp.ptr, md->base.type, &value, &size, FIX2INT(idx), oci8_errhp));
-    return rb_str_new(TO_CHARPTR(value), size);
+    return rb_external_str_new_with_enc(TO_CHARPTR(value), size, oci8_encoding);
 }
 
 static VALUE metadata_get_oradate(VALUE self, VALUE idx)
@@ -284,7 +284,7 @@
 
 static VALUE oci8_describe(VALUE self, VALUE name, VALUE klass, VALUE check_public)
 {
-    StringValue(name);
+    OCI8SafeStringValue(name);
     if (RSTRING_LEN(name) == 0) {
         rb_raise(rb_eArgError, "empty string is set.");
     }

Modified: trunk/ruby-oci8/ext/oci8/object.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/object.c	2009-01-11 08:38:04 UTC (rev 307)
+++ trunk/ruby-oci8/ext/oci8/object.c	2009-01-11 15:11:09 UTC (rev 308)
@@ -150,8 +150,9 @@
     Check_Type(datatype, T_FIXNUM);
     switch (FIX2INT(datatype)) {
     case ATTR_STRING:
-        return rb_str_new(TO_CHARPTR(OCIStringPtr(oci8_envhp, *(OCIString **)data)),
-                          OCIStringSize(oci8_envhp, *(OCIString **)data));
+        return rb_external_str_new_with_enc(TO_CHARPTR(OCIStringPtr(oci8_envhp, *(OCIString **)data)),
+                                            OCIStringSize(oci8_envhp, *(OCIString **)data),
+                                            oci8_encoding);
     case ATTR_RAW:
         return rb_str_new(TO_CHARPTR(OCIRawPtr(oci8_envhp, *(OCIRaw **)data)),
                           OCIRawSize(oci8_envhp, *(OCIRaw **)data));
@@ -417,7 +418,7 @@
     Check_Type(datatype, T_FIXNUM);
     switch (FIX2INT(datatype)) {
     case ATTR_STRING:
-        StringValue(val);
+        OCI8StringValue(val);
         oci_lc(OCIStringAssignText(oci8_envhp, oci8_errhp,
                                    RSTRING_ORATEXT(val), RSTRING_LEN(val),
                                    (OCIString **)data));

Modified: trunk/ruby-oci8/ext/oci8/oci8.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/oci8.c	2009-01-11 08:38:04 UTC (rev 307)
+++ trunk/ruby-oci8/ext/oci8/oci8.c	2009-01-11 15:11:09 UTC (rev 308)
@@ -77,7 +77,7 @@
         re = rb_eval_string(CONN_STR_REGEX);
         rb_global_variable(&re);
     }
-    StringValue(conn_str);
+    OCI8SafeStringValue(conn_str);
     if (RTEST(rb_reg_match(re, conn_str))) {
         *user = rb_reg_nth_match(1, rb_backref_get());
         *pass = rb_reg_nth_match(2, rb_backref_get());
@@ -90,7 +90,7 @@
         }
         if (!NIL_P(*mode)) {
             char *ptr;
-            StringValue(*mode);
+            SafeStringValue(*mode);
             ptr = RSTRING_PTR(*mode);
             if (strcasecmp(ptr, "SYSDBA") == 0) {
                 *mode = sym_SYSDBA;
@@ -175,11 +175,11 @@
         cred = OCI_CRED_EXT;
     } else {
         /* RDBMS credential */
-        StringValue(vusername); /* 1 */
-        StringValue(vpassword); /* 2 */
+        OCI8SafeStringValue(vusername); /* 1 */
+        OCI8SafeStringValue(vpassword); /* 2 */
     }
     if (!NIL_P(vdbname)) {
-        StringValue(vdbname); /* 3 */
+        OCI8SafeStringValue(vdbname); /* 3 */
     }
     if (!NIL_P(vmode)) { /* 4 */
         logon_type = T_EXPLICIT;

Modified: trunk/ruby-oci8/ext/oci8/oci8.h
===================================================================
--- trunk/ruby-oci8/ext/oci8/oci8.h	2009-01-11 08:38:04 UTC (rev 307)
+++ trunk/ruby-oci8/ext/oci8/oci8.h	2009-01-11 15:11:09 UTC (rev 308)
@@ -8,9 +8,6 @@
 #define _RUBY_OCI_H_ 1
 
 #include "ruby.h"
-#ifdef HAVE_INTERN_H
-#include "intern.h"
-#endif
 
 #ifndef rb_pid_t
 #ifdef WIN32
@@ -48,6 +45,9 @@
 #define ORAVER_11_1 ORAVERNUM(11, 1, 0, 0, 0)
 
 #include "extconf.h"
+#ifdef HAVE_TYPE_RB_ENCODING
+#include <ruby/encoding.h>
+#endif
 
 #if ACTUAL_ORACLE_CLIENT_VERSION < ORAVER_10_2
 typedef struct OCIAdmin OCIAdmin;
@@ -90,7 +90,10 @@
 #endif
 
 #ifndef HAVE_TYPE_RB_ENCODING
+#define rb_enc_associate(str, enc) do {} while(0)
 #define rb_external_str_new_with_enc(ptr, len, enc) rb_tainted_str_new((ptr), (len))
+#define rb_locale_str_new_cstr(ptr)  rb_str_new2(ptr)
+#define rb_str_conv_enc(str, from, to) (str)
 #define rb_usascii_str_new(ptr, len) rb_str_new((ptr), (len))
 #define rb_usascii_str_new_cstr(ptr) rb_str_new2(ptr)
 #endif
@@ -433,6 +436,22 @@
 void Init_oci8_encoding(VALUE cOCI8);
 VALUE oci8_charset_id2name(VALUE svc, VALUE charset_id);
 
+#ifdef HAVE_TYPE_RB_ENCODING
+extern rb_encoding *oci8_encoding;
+
+#define OCI8StringValue(v) do { \
+    StringValue(v); \
+    (v) = rb_str_export_to_enc(v, oci8_encoding); \
+} while (0)
+#define OCI8SafeStringValue(v) do { \
+    SafeStringValue(v); \
+    (v) = rb_str_export_to_enc(v, oci8_encoding); \
+} while (0)
+#else
+#define OCI8StringValue(v)     StringValue(v)
+#define OCI8SafeStringValue(v) SafeStringValue(v)
+#endif
+
 #include "apiwrap.h"
 
 #endif

Modified: trunk/ruby-oci8/ext/oci8/oci8lib.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/oci8lib.c	2009-01-11 08:38:04 UTC (rev 307)
+++ trunk/ruby-oci8/ext/oci8/oci8lib.c	2009-01-11 15:11:09 UTC (rev 308)
@@ -459,7 +459,7 @@
             if (handle != NULL) {
                 break;
             }
-            rb_ary_push(err, rb_str_new2(dlerror()));
+            rb_ary_push(err, rb_locale_str_new_cstr(dlerror()));
         }
         if (handle == NULL) {
             VALUE msg;

Modified: trunk/ruby-oci8/ext/oci8/ocinumber.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/ocinumber.c	2009-01-11 08:38:04 UTC (rev 307)
+++ trunk/ruby-oci8/ext/oci8/ocinumber.c	2009-01-11 15:11:09 UTC (rev 308)
@@ -854,7 +854,7 @@
         }
         oci8_raise(oci8_errhp, rv, NULL);
     }
-    return rb_str_new(buf, buf_size);
+    return rb_usascii_str_new(buf, buf_size);
 }
 
 /*

Modified: trunk/ruby-oci8/ext/oci8/stmt.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/stmt.c	2009-01-11 08:38:04 UTC (rev 307)
+++ trunk/ruby-oci8/ext/oci8/stmt.c	2009-01-11 15:11:09 UTC (rev 308)
@@ -69,7 +69,7 @@
 
     oci8_check_pid_consistency(oci8_get_svcctx(svc));
     if (argc > 1)
-        StringValue(sql);
+        OCI8SafeStringValue(sql);
 
     rv = OCIHandleAlloc(oci8_envhp, &stmt->base.hp.ptr, OCI_HTYPE_STMT, 0, NULL);
     if (rv != OCI_SUCCESS)
@@ -168,7 +168,7 @@
     } else if (FIXNUM_P(vplaceholder)) {
         position = NUM2INT(vplaceholder);
     } else {
-        StringValue(vplaceholder);
+        OCI8StringValue(vplaceholder);
         placeholder_ptr = RSTRING_PTR(vplaceholder);
         placeholder_len = RSTRING_LEN(vplaceholder);
     }




More information about the ruby-oci8-commit mailing list