pike.git / lib / modules / Sql.pmod / tds.pike

version» Context lines:

pike.git/lib/modules/Sql.pmod/tds.pike:1:   /* -  * $Id: tds.pike,v 1.6 2006/02/10 14:45:56 grubba Exp $ +  * $Id: tds.pike,v 1.7 2006/02/10 16:03:52 grubba Exp $    *    * A Pike implementation of the TDS protocol.    *    * Henrik Grubbström 2006-02-08.    */      #define TDS_DEBUG      #ifdef TDS_DEBUG   #define TDS_WERROR(X...) werror("TDS:" + X)
pike.git/lib/modules/Sql.pmod/tds.pike:168:    TDS_ROWFMT_RESULT = 4049,    TDS_COMPUTEFMT_RESULT = 4050,    TDS_DESCRIBE_RESULT = 4051,    TDS_DONE_RESULT = 4052,    TDS_DONEPROC_RESULT = 4053,    TDS_DONEINPROC_RESULT = 4054,    };       string server_data;    string last_error; -  array(mapping(string:mixed)) column_info; +        void tds_error(string msg, mixed ... args)    {    if (sizeof(args)) msg = sprintf(msg, @args);    predef::error(last_error = msg);    }       static object utf16enc = Locale.Charset.encoder("UTF16LE");    static string string_to_utf16(string s)    {
pike.git/lib/modules/Sql.pmod/tds.pike:221:    {    int inpos = 0;    string inbuf = "";    int done;       static void fill_buf()    {    if (done) {    TDS_WERROR("Filling buffer on finished packet!\n"    "%s\n", hex_dump(inbuf)); +  tds_error("Filling buffer on finished packet!\n");    }       string header = socket->read(8);    if (!header || sizeof(header) < 8) {    busy = !(done = 1);    tds_error("Failed to read packet header: %O, %s.\n",    header, strerror(socket->errno()));    }    TDS_WERROR("Read header:\n%s\n", hex_dump(header));    int packet_type;
pike.git/lib/modules/Sql.pmod/tds.pike:250:    if (!data || sizeof(data) < len) {    tds_error("Failed to read packet data (%d bytes), got %O (%d bytes), %s\n",    len, data, sizeof(data||""), strerror(socket->errno()));    }    TDS_WERROR("Read packet with %d bytes.\n%s\n",    sizeof(data), hex_dump(data));    inbuf = inbuf[inpos..] + data;    inpos = 0;    }    +  static void destroy() +  { +  // Return the connection to the idle state. +  while (!done) { +  inbuf = ""; +  inpos = 0; +  fill_buf(); +  } +  } +     string get_raw(int bytes)    {    while (inpos + bytes > sizeof(inbuf)) {    fill_buf();    }    string raw = inbuf[inpos..inpos + bytes - 1];    inpos += bytes;    return raw;    }   
pike.git/lib/modules/Sql.pmod/tds.pike:312:    {    string r = get_raw(sizeof(s));    if (r != s) {    tds_error("Expectation failed: Got %O, expected %O\n",    r, s);    }    }       static void create()    { -  if (!busy) { -  TDS_WERROR("Creating input packet on idle connection!\n"); +  if (busy) { +  tds_error("Creating InPacket on busy connection!\n");    } -  +  busy = 1;    }    }       //static InPacket login_answer;       class Packet    {    array(string|int) segments = ({});    array(string) strings = ({});    int flags;
pike.git/lib/modules/Sql.pmod/tds.pike:429:    }    }    string res = segments * "";    TDS_WERROR("Generated packet: %O (%d bytes)\n",    res, sizeof(res));    if (!flags) return res;    return sprintf("%-4c%s", sizeof(res)+4, res);    }    }    -  static void send_packet(Packet p, int flag, int|void last) +  InPacket send_packet(Packet p, int flag, int|void last)    { -  string raw = (string) p; -  +     if (busy) { -  TDS_WERROR("Sending packet on busy connection!\n"); +  tds_error("Sending packet on busy connection!\n");    } -  busy = last; +     -  // FIXME: Split large packets! -  +  string packet = (string) p; +  foreach(packet/512.0, string raw) {    // NOTE: Network byteorder!! -  raw = -  sprintf("%-1c%-1c%2c\0\0%-1c\0%s", +  raw = sprintf("%1c%1c%2c\0\0%1c\0%s",    flag, last,    sizeof(raw) + 8,    1, /* TDS 7 or 8. */ -  (string)raw); +  raw);    TDS_WERROR("Wrapped packet: %O\n%s\n", raw, hex_dump(raw));    if (socket->write(raw) != sizeof(raw)) { -  +  socket->close(); +  socket = 0;    tds_error("Failed to send packet.\n"    "raw: %O\n", raw);    } -  +  }    //Stdio.write_file("packet.bin", raw); -  +  if (last) return InPacket(); +  return 0;    }       static string crypt_pass(string password)    {    password = string_to_utf16(password);    password ^= "\x5a"*sizeof(password);    return (string)map((array)password,    lambda(int byte) {    return ((byte >> 4) | (byte << 4)) & 0xff;    });
pike.git/lib/modules/Sql.pmod/tds.pike:508:    p->put_string(database);    p->put_raw("\0"*6, 6); // MAC address    if (domain) {    p->put_domain_login(domain, hostname);    } else {    p->put_string("");    }    p->put_string("");       TDS_WERROR("Sending login packet.\n"); -  send_packet(p, 0x10, 1); -  return InPacket(); +  return send_packet(p, 0x10, 1);    }       string ecb_encrypt(string data, string key)    {   #if constant(Crypto.DES)    Crypto.DES des = Crypto.DES();    des->set_encrypt_key(des->fix_parity(key));   #else    Crypto.des des = Crypto.des();    des->set_encrypt_key(Crypto.des_parity(key));
pike.git/lib/modules/Sql.pmod/tds.pike:853:    if (is_blob_type(res->cardinal_type)) {    TDS_WERROR("is_blob\n");    res->table = inp->get_string(inp->get_smallint());    TDS_WERROR("Table name: %O\n", res->table);    }    res->name = inp->get_string(inp->get_byte());    TDS_WERROR("Column info: %O\n", res);    return res;    }    -  static void tds7_process_result(InPacket inp) +  static array(mapping(string:mixed)) tds7_process_result(InPacket inp)    {    int num_cols = inp->get_smallint();    if (num_cols == 0xffff) {    TDS_WERROR("No meta data.\n"); -  column_info = 0; -  return; +  return 0;    }    TDS_WERROR("%d columns in result.\n", num_cols); -  column_info = allocate(num_cols); -  //busy = 1; -  int offset = 0; +  array(mapping(string:mixed)) column_info = allocate(num_cols);    foreach(column_info; int col; ) {    column_info[col] = tds7_get_data_info(inp); -  column_info[col]->column_offset = offset; -  TDS_WERROR("Offset: 0x%04x\n", offset); -  if (is_numeric_type(column_info[col]->cardinal_type)) { -  offset += 35; // sizeof(TDS_NUMERIC) -  } else if (is_blob_type(column_info[col]->cardinal_type)) { -  offset += 32; // sizeof(TDSBLOB) -  } else { -  offset += column_info[col]->column_size; +     } -  offset += (~(offset - 1) & 0x3); // Align. -  TDS_WERROR("Next offset: 0x%04x\n", offset); +  return column_info;    }    -  } -  +     static void process_default_tokens(InPacket inp, int token_type)    {    if (token_type == TDS_DONE_TOKEN) return;    switch(token_type) {    case TDS_DONE_TOKEN:    return;    case TDS_ERROR_TOKEN:    case TDS_INFO_TOKEN:    case TDS_EED_TOKEN:    process_msg(inp, token_type);    return;    case TDS_ENVCHANGE_TOKEN:    process_env_chg(inp);    return;    case TDS7_RESULT_TOKEN: -  tds7_process_result(inp); +  tds_error("TDS7_RESULT_TOKEN in default handler!\n"); +  //tds7_process_result(inp);    break;    case TDS5_DYNAMIC_TOKEN:    case TDS_LOGINACK_TOKEN:    case TDS_ORDERBY_TOKEN:    case TDS_CONTROL_TOKEN:    case TDS_TABNAME_TOKEN:    TDS_WERROR("Skipping token: %d\n", token_type);    inp->get_raw(inp->get_smallint());    break;    default:    TDS_WERROR("FIXME: Got unknown token in process_default_tokens: %d\n",    token_type);    break;    }    }    -  int process_result_tokens(InPacket inp) +  array(mapping(string:mixed)) process_result_tokens(InPacket inp)    { -  if (!busy) { -  //return TDS_NO_MORE_RESULTS; -  } +  array(mapping(string:mixed)) column_info;    while (1) {    int token_type = inp->peek_byte();    TDS_WERROR("Got result token %d\n", token_type);    switch(token_type) {    case TDS7_RESULT_TOKEN:    TDS_WERROR("TDS7_RESULT_TOKEN\n");    inp->get_byte(); -  tds7_process_result(inp); +  column_info = tds7_process_result(inp);    if (inp->peek_byte() == TDS_TABNAME_TOKEN) {    TDS_WERROR("TDS_TABNAME_TOKEN\n");    process_default_tokens(inp, inp->get_byte());    if (inp->peek_byte() == TDS_COLINFO_TOKEN) {    TDS_WERROR("TDS_COLINFO_TOKEN\n");    inp->get_byte();    //process_colinfo(); // FIXME!    }    } -  TDS_WERROR("==> TDS_ROWFMT_RESULT\n"); -  return TDS_ROWFMT_RESULT; +  break;    case TDS_DONE_TOKEN: -  +  TDS_WERROR(" TDS_DONE_TOKEN pending\n"); +  return column_info;    case TDS_ROW_TOKEN: -  TDS_WERROR("==> TDS_ROW_RESULT\n"); -  return TDS_ROW_RESULT; +  TDS_WERROR(" TDS_ROW_TOKEN pending\n"); +  return column_info;    default:    TDS_WERROR("==> FIXME: process_result_tokens\n");    // FALL_THROUGH    case TDS_ORDERBY_TOKEN: -  +  /* Ignore. */    inp->get_byte();    process_default_tokens(inp, token_type); -  return 0; /***** FIXME:::::: *****/ +     break;    }    }    }       static string|int get_data(InPacket inp,    mapping(string:mixed) info, int col)    {    TDS_WERROR("get_data for column %d info:%O\n", col, info);    mapping blobinfo;
pike.git/lib/modules/Sql.pmod/tds.pike:1155:    year += (century + 15)*100 + l;    if (!l && !(year & 3) && ((year % 100) || !(year % 400)))    yday++;    return sprintf("%04d-%02d-%02dT%02d:%02d:%02d",    year, mon, mday, hour, min, sec);    }    }    return raw;    }    -  static array(string|int) process_row(InPacket inp) +  static array(string|int) process_row(InPacket inp, +  array(mapping(string:mixed)) col_info)    { -  if (!column_info) return 0; -  array(string|int) res = allocate(sizeof(column_info)); -  foreach(column_info; int i; mapping(string:mixed) info) { +  if (!col_info) return 0; +  array(string|int) res = allocate(sizeof(col_info)); +  foreach(col_info; int i; mapping(string:mixed) info) {    res[i] = convert(get_data(inp, info, i), info);    }    return res;    }       array(string|int) process_row_tokens(InPacket inp, -  +  array(mapping(string:mixed)) col_info,    int|void leave_end_token)    {    //if (!busy) return 0; // No more rows.    while (1) {    int token_type = inp->peek_byte();    TDS_WERROR("Process row tokens: Token type: %d\n", token_type);    switch(token_type) {    case TDS_RESULT_TOKEN:    case TDS_ROWFMT2_TOKEN:    case TDS7_RESULT_TOKEN:    // Some other result starts here.    //busy = 0;    return 0;    case TDS_ROW_TOKEN:    inp->get_byte(); -  return process_row(inp); +  return process_row(inp, col_info);    break;    case TDS_DONE_TOKEN:    case TDS_DONEPROC_TOKEN:    case TDS_DONEINPROC_TOKEN:    if (!leave_end_token) inp->get_byte();    //busy = 0;    return 0;    default:    inp->get_byte();    process_default_tokens(inp, token_type);
pike.git/lib/modules/Sql.pmod/tds.pike:1257:    if (!ok) tds_error("Login failed.\n");    TDS_WERROR("Login ok!\n");    }       InPacket submit_query(compile_query query, void|array(mixed) params)    {    Packet p = Packet();    if (!query->n_param || !params || !sizeof(params)) {    string raw = query->splitted_query*"?";    p->put_raw(raw, sizeof(raw)); -  send_packet(p, 0x01, 1); -  return InPacket(); +  return send_packet(p, 0x01, 1);    } else {    tds_error("parametrized queries not supported yet.\n");    }    }       static void disconnect()    {    socket->close();    destruct();    }
pike.git/lib/modules/Sql.pmod/tds.pike:1319:    con->disconnect();    con = 0;    }       void Connect(string server, int port, string database,    string uid, string password)    {    con = Connection(server, port, database, uid, password);    }    -  Connection.InPacket Execute(compile_query query) -  { -  query->parse_prepared_query(); -  if (busy) { -  tds_error("Connection not idle.\n"); -  } -  Connection.InPacket res; -  if (!query->params) { -  res = con->submit_query(query); -  } else { -  res = con->submit_execdirect(query, query->params); -  } -  int done = 0; -  int res_type; -  while (!done) { -  res_type = con->process_result_tokens(res); -  switch(res_type) { -  case TDS_COMPUTE_RESULT: -  case TDS_ROW_RESULT: -  done = 1; -  break; -  default: -  TDS_WERROR("res_type: %d\n", res_type); -  break; -  } -  } -  // populate_ird -  switch(res_type) { -  //case TDS_NO_MORE_RESULTS: -  } -  return res; -  } +    #if (__REAL_MAJOR__ > 7) || ((__REAL_MAJOR__ == 7) && (__REAL_MINOR__ >= 6))   };   #endif /* Pike 7.6 or later */      class compile_query   {    int n_param;    array(string) splitted_query;       array(mixed) params;
pike.git/lib/modules/Sql.pmod/tds.pike:1437:    n_param = sizeof(splitted_query)-1;    }   }      class big_query   {    static int row_no;    static int eot;       static Connection.InPacket result_packet; +  static array(mapping(string:mixed)) column_info;       int|array(string|int) fetch_row()    {    if (eot) return 0;    TDS_WERROR("fetch_row()::::::::::::::::::::::::::::::::::::::::::\n"); -  int|array(string|int) res = con->process_row_tokens(result_packet); +  int|array(string|int) res = con->process_row_tokens(result_packet, +  column_info);    eot = !res;    row_no++;    return res;    }       array(mapping(string:mixed)) fetch_fields()    {    TDS_WERROR("fetch_fields()::::::::::::::::::::::::::::::::::::::::::\n"); -  return copy_value(column_info || ({})); +  return copy_value(column_info);    }       static void create(string|compile_query query)    {    if (stringp(query)) {    query = compile_query(query);    } -  result_packet = Execute(query); +  +  query->parse_prepared_query(); +  if (busy) { +  tds_error("Connection not idle.\n");    } -  +  if (!query->params) { +  result_packet = con->submit_query(query); +  } else { +  result_packet = con->submit_execdirect(query, query->params);    } -  +  column_info = con->process_result_tokens(result_packet); +  if (!column_info) destruct(); +  } + }      string server_info()   {    return server_data;   }      string error()   {    return last_error;   }