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

version» Context lines:

pike.git/lib/modules/Sql.pmod/pgsql.pike:1:   /*    * This is the PostgreSQL direct network module for Pike. -  * -  * TODO: support SSL connections +     */      //! This is an interface to the PostgreSQL database   //! server. This module is independent of external libraries.   //! Note that you @b{do not@} need to have a   //! PostgreSQL server running on your host to use this module: you can   //! connect to the database over a TCP/IP socket.   //!   //! This module replaces the functionality of the older @[Sql.postgres]   //! and @[Postgres.postgres] modules.
pike.git/lib/modules/Sql.pmod/pgsql.pike:157:   //!   //! The host argument can have the syntax @expr{"hostname"@} or   //! @expr{"hostname:portname"@}. This allows to specify the TCP/IP   //! port to connect to. If it is @expr{0@} or @expr{""@}, it will try   //! to connect to localhost, default port.   //!   //! The database argument specifies the database to connect to. If   //! @expr{0@} or @expr{""@}, it will try to connect to the specified   //! database.   //! + //! The options argument currently supports two options: use_ssl and force_ssl + //!   //! @note   //! You need to have a database selected before using the sql-object,   //! otherwise you'll get exceptions when you try to query it. Also   //! notice that this function @b{can@} raise exceptions if the db   //! server doesn't respond, if the database doesn't exist or is not   //! accessible by you.   //!   //! @seealso   //! @[Postgres.postgres], @[Sql.Sql], @[postgres->select_db]   protected void create(void|string _host, void|string _database,    void|string _user, void|string _pass, void|mapping(string:mixed) _options) {    pass = _pass; _pass = "CENSORED";    user = _user; database = _database; host = _host || PGSQL_DEFAULT_HOST; -  options = _options; +  options = _options || ([]);    if(search(host,":")>=0 && sscanf(_host,"%s:%d",host,port)!=2)    ERROR("Error in parsing the hostname argument\n");    if(!port)    port = PGSQL_DEFAULT_PORT;    querymutex=Thread.Mutex();    stealmutex=Thread.Mutex();    reconnect();   }      //! @decl string error()
pike.git/lib/modules/Sql.pmod/pgsql.pike:218:   #define GETBYTE() conn.getbyte()   #define GETSTRING(x) conn.getstring(x)   #define GETINT16() conn.getint16()   #define GETINT32() conn.getint32()   #define FLUSHED conn.flushed      #ifdef USEPGsql   #define PEEK(x) conn.bpeek(x)   #else   #define PEEK(x) conn.peek(x) -  +    #endif      #define plugstring(x) (sprintf x)    - #define plugbyte(x) sprintf("%c",x) + #define plugbyte(x) String.int2char(x)      inline final private string plugint16(int x) {    return sprintf("%c%c",x>>8&255,x&255);   }      inline final private string plugint32(int x) {    return sprintf("%c%c%c%c",x>>24&255,x>>16&255,x>>8&255,x&255);   }      inline final private string plugint64(int x) {    return sprintf("%c%c%c%c%c%c%c%c",    x>>56&255,x>>48&255,x>>40&255,x>>32&255,x>>24&255,x>>16&255,x>>8&255,x&255);   }      class PGassist { - #ifdef UNBUFFEREDIO -  inherit Stdio.File:std; - #else -  inherit Stdio.FILE:std; - #endif +  +  int(-1..1) peek(int timeout) { +  } +  +  string read(int len,void|int(0..1) not_all) { +  } +  +  int write(string|array(string) data) { +  } +  +  int getchar() { +  } +  +  int close() { +  } +    #ifdef USEPGsql -  inherit _PGsql.PGsql:pg; +  inherit _PGsql.PGsql;   #else    int flushed;   #endif -  +     void create(object pgsqlsess) { -  std::create(); +    #ifdef USEPGsql -  pg::setpgsqlsess(pgsqlsess); +  ::create(pgsqlsess);   #else    flushed=-1;   #endif    } -  int connect(string host,int port) { -  int res=std::connect(host,port); - #ifdef USEPGsql -  if(res) -  pg::create(std::query_fd()); - #endif -  return res; -  } +       #ifndef USEPGsql -  +     inline final int getbyte() {    if(!FLUSHED && !PEEK(0))    sendflush(); - #ifdef UNBUFFEREDIO -  return read(1)[0]; - #else +     return getchar(); - #endif +     }       final string getstring(void|int len) {    if(!zero_type(len)) {    string acc="",res;    do {    if(!FLUSHED && !PEEK(0))    sendflush();    res=conn.read(len,!FLUSHED);    if(res) {
pike.git/lib/modules/Sql.pmod/pgsql.pike:336:    data=({data,FLUSH});    else    data+=({FLUSH});    PD("Flush\n");    FLUSHED=1;    }    else if(FLUSHED!=-1)    FLUSHED=0;    return write(data);    } +  +  final void sendterminate() { +  PD("Terminate\n"); +  SENDCMD(({"X",plugint32(4)})); +  close();    } -  + }    -  + class PGconn { +  +  inherit PGassist:pg; + #ifdef UNBUFFEREDIO +  inherit Stdio.File:std; +  +  inline int getchar() { +  return std::read(1)[0]; +  } + #else +  inherit Stdio.FILE:std; +  +  inline int getchar() { +  return std::getchar(); +  } + #endif +  +  inline int(-1..1) peek(int timeout) { +  return std::peek(timeout); +  } +  +  inline string read(int len,void|int(0..1) not_all) { +  return std::read(len,not_all); +  } +  +  inline int write(string|array(string) data) { +  return std::write(data); +  } +  +  int close() { +  return std::close(); +  } +  +  void create(Stdio.File stream,object pgsqlsess) { +  std::create(); +  std::assign(stream); +  pg::create(pgsqlsess); +  } + } +  + #if constant(SSL.sslfile) + class PGconnS { +  inherit SSL.sslfile:std; +  inherit PGassist:pg; +  +  Stdio.File rawstream; +  +  inline int(-1..1) peek(int timeout) { +  return rawstream.peek(timeout); +  } +  +  inline string read(int len,void|int(0..1) not_all) { +  return std::read(len,not_all); +  } +  +  inline int write(string|array(string) data) { +  return std::write(data); +  } +  +  void create(Stdio.File stream, SSL.context ctx,object pgsqlsess) { +  rawstream=stream; +  std::create(stream,ctx,1,1); +  pg::create(pgsqlsess); +  } + } + #endif +    final private object getsocket() { -  object lcon = PGassist(this); +  object lcon = Stdio.File();    if(!lcon.connect(host,port))    return UNDEFINED; -  +  +  object fcon;   #if constant(SSL.sslfile) - #if 0 +  if(options->use_ssl || options->force_ssl) { +  PD("SSLRequest\n"); +  lcon.write(({plugint32(8),plugint32(PG_PROTOCOL(1234,5679))})); +  switch(lcon.read(1)) { +  case "S":    SSL.context context = SSL.context(); - #if 1 -  context->preferred_suites = ({ -  SSL_rsa_with_idea_cbc_sha, -  SSL_rsa_with_rc4_128_sha, -  SSL_rsa_with_rc4_128_md5, -  SSL_rsa_with_3des_ede_cbc_sha, -  SSL_rsa_export_with_rc4_40_md5, -  SSL_rsa_export_with_rc2_cbc_40_md5, -  SSL_rsa_export_with_des40_cbc_sha, -  }); - #endif +     context->random = Crypto.Random.random_string; -  object read_callback=con->query_read_callback(); -  object write_callback=con->query_write_callback(); -  object close_callback=con->query_close_callback(); -  -  ssl = SSL.sslfile(con, context, 1,blocking); -  if(!blocking) { -  ssl->set_read_callback(read_callback); -  ssl->set_write_callback(write_callback); -  ssl->set_close_callback(close_callback); +  fcon=PGconnS(lcon, context, this); +  if(fcon) +  return fcon; +  default:lcon.close(); +  if(!lcon.connect(host,port)) +  return UNDEFINED; +  case "N": +  if(options->force_ssl) +  ERROR("Encryption not supported on connection to %s:%d\n", +  host,port);    } -  con=ssl; +  } + #else +  if(options->force_ssl) +  ERROR("Encryption library missing, cannot establish connection to %s:%d\n", +  host,port);   #endif - #endif -  return lcon; +  fcon=PGconn(lcon, this); +  return fcon;   }      //! Cancels the currently running query.   //!   //! This function is PostgreSQL-specific, and thus it is not available   //! through the generic SQL-interface.   void cancelquery() {    if(qstate==inquery) {    qstate=cancelpending;    object lcon;    PD("CancelRequest\n");    if(!(lcon=getsocket()))    ERROR("Cancel connect failed\n"); -  lcon.write(({plugint32(16),plugint32(PG_PROTOCOL(1234,4567)), +  lcon.write(({plugint32(16),plugint32(PG_PROTOCOL(1234,5678)),    plugint32(backendpid),cancelsecret}));    lcon.close();    }   }      //! Returns the old cachedepth, sets the new cachedepth for prepared   //! statements automatic caching.   //!   //! This function is PostgreSQL-specific, and thus it is not available   //! through the generic SQL-interface.
pike.git/lib/modules/Sql.pmod/pgsql.pike:838: Inside #if undefined(UNBUFFEREDIO)
     #ifndef UNBUFFEREDIO   private int read_cb(mixed foo, string d) {    conn.unread(d);    do _decodemsg();    while(PEEK(0)==1);    return 0;   }   #endif    - final private void sendterminate() { -  PD("Terminate\n"); -  SENDCMD(({"X",plugint32(4)})); -  conn.close(); - } -  +    void destroy() { -  sendterminate(); +  conn.sendterminate();   }      private void reconnect(void|int force) {    if(conn) {    reconnected++;   #ifdef DEBUG    ERROR("While debugging, reconnects are forbidden\n");    exit(1);   #endif    if(!force) -  sendterminate(); +  conn.sendterminate();    foreach(prepareds;;mapping tprepared)    m_delete(tprepared,"preparedname");    }    if(!(conn=getsocket()))    ERROR("Couldn't connect to database on %s:%d\n",host,port);    _closesent=0;    mstate=unauthenticated;    qstate=queryidle;    runtimeparameter=([]);    array(string) plugbuf=({"",plugint32(PG_PROTOCOL(3,0))});