[OpenSRF-GIT] OpenSRF branch master updated. f3ac7f14ec675e99784b9a5037be66f8c90c22f2

Evergreen Git git at git.evergreen-ils.org
Fri Aug 12 13:32:01 EDT 2016


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "OpenSRF".

The branch, master has been updated
       via  f3ac7f14ec675e99784b9a5037be66f8c90c22f2 (commit)
       via  91a8f051220ba1b29e76068a58cbb400ae521834 (commit)
      from  e7fe347408b52295f2f820f9527ccf00952b71e8 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit f3ac7f14ec675e99784b9a5037be66f8c90c22f2
Author: Mike Rylander <mrylander at gmail.com>
Date:   Tue Feb 23 11:22:34 2016 -0500

    LP#1485371: Release notes for TZ handling in OpenSRF
    
    Signed-off-by: Mike Rylander <mrylander at gmail.com>
    Signed-off-by: Galen Charlton <gmc at esilibrary.com>

diff --git a/doc/TZ-handling.txt b/doc/TZ-handling.txt
new file mode 100644
index 0000000..6a583dd
--- /dev/null
+++ b/doc/TZ-handling.txt
@@ -0,0 +1,44 @@
+Propagating client time zone in OpenSRF
+=======================================
+
+OpenSRF has long inspected the envelope of incoming requests for information
+about the client's locale and made this information available to business
+logic.  This is used, among other things, to drive transparent translation of
+in-database strings within Evergreen.  In addition to locale, OpenSRF will
+now respect client-supplied adjustment to the effective time zone in which it
+operates, and provide that information to the business logic layer of
+applications built on the framework.
+
+Client
+------
+
+As most clients that have time zones which differ from that of the server on
+which the OpenSRF processes run are, in fact, web browsers, it is necessary
+to include time zone detection directly within the browser.  This will be
+stored in a cookie to be sent with all subsequent HTTP requests, and used in
+all OpenSRF-over-HTTP calls made using the JavaScript bindings for OpenSRF,
+including those for WebSockets communication.
+
+For non-browser clients, such as support scripts written in Perl or other
+scripting languages, the local system's mechanisms for detecting time zone
+is relied upon.  For instance, Perl scripts can directly read the TZ
+environment variable.
+
+Additionally, the srfsh client now reads its local time zone from the
+environment and passes that to the server. 
+
+Server
+------
+
+Within OpenSRF services implemented in Perl, this information is now passed up
+to the business logic layer via the TZ environment variable, and is reverted
+to the server's value at the end of each request.  This allows automatic,
+transparent use of the client's time zone in almost all cases, and provides a
+system-normal access mechanism when direct access is required.
+
+For OpenSRF services implemented in C, the time zone information is provided
+as part of the request context object that is passed to implementation
+functions.  In particular, this allows services that interact with a database
+to set the time zone in which the database interprets timestamps to that of
+the client.
+

commit 91a8f051220ba1b29e76068a58cbb400ae521834
Author: Mike Rylander <mrylander at gmail.com>
Date:   Mon Aug 3 13:27:56 2015 -0400

    LP#1485371: Use client-supplied TZ
    
    Currently, there is no protocol-level mechanism for passing the client's
    desired timezone to the server. In much the same way we pass the locale,
    we can let the server know what timezone it should use when interpreting
    time stamps.
    
    To do this we:
    
     * Teach perl server code to live in the client TZ, if supplied
     * Teach perl client code to send the current $ENV{TZ}
     * Teach javascript library to include client TZ in
       gateway/translator/websocket communication
     * Teach C code to pull the incoming TZ and apply it to outgoing messages
     * Teach srfsh to pull TZ from the environment and pass it with requests
    
    Signed-off-by: Mike Rylander <mrylander at gmail.com>
    Signed-off-by: Galen Charlton <gmc at esilibrary.com>

diff --git a/include/opensrf/osrf_app_session.h b/include/opensrf/osrf_app_session.h
index f0e2586..57d9092 100644
--- a/include/opensrf/osrf_app_session.h
+++ b/include/opensrf/osrf_app_session.h
@@ -74,6 +74,9 @@ struct osrf_app_session_struct {
 	/** the current locale for this session. **/
 	char* session_locale;
 
+	/** the current TZ for this session. **/
+	char* session_tz;
+
 	/** let the user use the session to store their own session data. */
 	void* userData;
 
@@ -105,6 +108,8 @@ osrfAppSession* osrf_app_server_session_init(
 
 char* osrf_app_session_set_locale( osrfAppSession*, const char* );
 
+char* osrf_app_session_set_tz( osrfAppSession*, const char* );
+
 /* ingress used by all sessions until replaced */
 char* osrfAppSessionSetIngress( const char* );
 
diff --git a/include/opensrf/osrf_message.h b/include/opensrf/osrf_message.h
index 76091d0..14b601b 100644
--- a/include/opensrf/osrf_message.h
+++ b/include/opensrf/osrf_message.h
@@ -95,17 +95,24 @@ struct osrf_message_struct {
 
 	/** Magical ingress hint. */
 	char* sender_ingress;
+
+	/** Magical TZ hint. */
+	char* sender_tz;
 };
 typedef struct osrf_message_struct osrfMessage;
 
 const char* osrf_message_set_locale( osrfMessage* msg, const char* locale );
 
+const char* osrf_message_set_tz( osrfMessage* msg, const char* tz );
+
 const char* osrfMessageSetIngress( osrfMessage* msg, const char* ingress );
 
 const char* osrf_message_set_default_locale( const char* locale );
 
 const char* osrf_message_get_last_locale(void);
 
+const char* osrf_message_get_last_tz(void);
+
 osrfMessage* osrf_message_init( enum M_TYPE type, int thread_trace, int protocol );
 
 void osrf_message_set_status_info( osrfMessage*,
diff --git a/src/javascript/opensrf.js b/src/javascript/opensrf.js
index d67fbfd..414233f 100644
--- a/src/javascript/opensrf.js
+++ b/src/javascript/opensrf.js
@@ -13,6 +13,16 @@
  * GNU General Public License for more details.
  * ----------------------------------------------------------------------- */
 
+/* -----------------------------------------------------------------------
+ * Portions of this file are Copyright (c) Jon Nylander
+ *
+ * jsTimezoneDetect is released under the MIT License
+ *  - http://www.opensource.org/licenses/mit-license.php
+ *
+ * For usage and examples, visit: http://pellepim.bitbucket.org/jstz/
+ * ----------------------------------------------------------------------- */
+(function(e){var t=function(){"use strict";var e="s",n=function(e){var t=-e.getTimezoneOffset();return t!==null?t:0},r=function(e,t,n){var r=new Date;return e!==undefined&&r.setFullYear(e),r.setDate(n),r.setMonth(t),r},i=function(e){return n(r(e,0,2))},s=function(e){return n(r(e,5,2))},o=function(e){var t=e.getMonth()>7?s(e.getFullYear()):i(e.getFullYear()),r=n(e);return t-r!==0},u=function(){var t=i(),n=s(),r=i()-s();return r<0?t+",1":r>0?n+",1,"+e:t+",0"},a=function(){var e=u();return new t.TimeZone(t.olson.timezones[e])},f=function(e){var t=new Date(2010,6,15,1,0,0,0),n={"America/Denver":new Date(2011,2,13,3,0,0,0),"America/Mazatlan":new Date(2011,3,3,3,0,0,0),"America/Chicago":new Date(2011,2,13,3,0,0,0),"America/Mexico_City":new Date(2011,3,3,3,0,0,0),"America/Asuncion":new Date(2012,9,7,3,0,0,0),"America/Santiago":new Date(2012,9,3,3,0,0,0),"America/Campo_Grande":new Date(2012,9,21,5,0,0,0),"America/Montevideo":new Date(2011,9,2,3,0,0,0),"America/Sao_Paulo":new Date(20
 11,9,16,5,0,0,0),"America/Los_Angeles":new Date(2011,2,13,8,0,0,0),"America/Santa_Isabel":new Date(2011,3,5,8,0,0,0),"America/Havana":new Date(2012,2,10,2,0,0,0),"America/New_York":new Date(2012,2,10,7,0,0,0),"Asia/Beirut":new Date(2011,2,27,1,0,0,0),"Europe/Helsinki":new Date(2011,2,27,4,0,0,0),"Europe/Istanbul":new Date(2011,2,28,5,0,0,0),"Asia/Damascus":new Date(2011,3,1,2,0,0,0),"Asia/Jerusalem":new Date(2011,3,1,6,0,0,0),"Asia/Gaza":new Date(2009,2,28,0,30,0,0),"Africa/Cairo":new Date(2009,3,25,0,30,0,0),"Pacific/Auckland":new Date(2011,8,26,7,0,0,0),"Pacific/Fiji":new Date(2010,11,29,23,0,0,0),"America/Halifax":new Date(2011,2,13,6,0,0,0),"America/Goose_Bay":new Date(2011,2,13,2,1,0,0),"America/Miquelon":new Date(2011,2,13,5,0,0,0),"America/Godthab":new Date(2011,2,27,1,0,0,0),"Europe/Moscow":t,"Asia/Yekaterinburg":t,"Asia/Omsk":t,"Asia/Krasnoyarsk":t,"Asia/Irkutsk":t,"Asia/Yakutsk":t,"Asia/Vladivostok":t,"Asia/Kamchatka":t,"Europe/Minsk":t,"Australia/Perth":new Date(2
 008,10,1,1,0,0,0)};return n[e]};return{determine:a,date_is_dst:o,dst_start_for:f}}();t.TimeZone=function(e){"use strict";var n={"America/Denver":["America/Denver","America/Mazatlan"],"America/Chicago":["America/Chicago","America/Mexico_City"],"America/Santiago":["America/Santiago","America/Asuncion","America/Campo_Grande"],"America/Montevideo":["America/Montevideo","America/Sao_Paulo"],"Asia/Beirut":["Asia/Beirut","Europe/Helsinki","Europe/Istanbul","Asia/Damascus","Asia/Jerusalem","Asia/Gaza"],"Pacific/Auckland":["Pacific/Auckland","Pacific/Fiji"],"America/Los_Angeles":["America/Los_Angeles","America/Santa_Isabel"],"America/New_York":["America/Havana","America/New_York"],"America/Halifax":["America/Goose_Bay","America/Halifax"],"America/Godthab":["America/Miquelon","America/Godthab"],"Asia/Dubai":["Europe/Moscow"],"Asia/Dhaka":["Asia/Yekaterinburg"],"Asia/Jakarta":["Asia/Omsk"],"Asia/Shanghai":["Asia/Krasnoyarsk","Australia/Perth"],"Asia/Tokyo":["Asia/Irkutsk"],"Australia/B
 risbane":["Asia/Yakutsk"],"Pacific/Noumea":["Asia/Vladivostok"],"Pacific/Tarawa":["Asia/Kamchatka"],"Africa/Johannesburg":["Asia/Gaza","Africa/Cairo"],"Asia/Baghdad":["Europe/Minsk"]},r=e,i=function(){var e=n[r],i=e.length,s=0,o=e[0];for(;s<i;s+=1){o=e[s];if(t.date_is_dst(t.dst_start_for(o))){r=o;return}}},s=function(){return typeof n[r]!="undefined"};return s()&&i(),{name:function(){return r}}},t.olson={},t.olson.timezones={"-720,0":"Etc/GMT+12","-660,0":"Pacific/Pago_Pago","-600,1":"America/Adak","-600,0":"Pacific/Honolulu","-570,0":"Pacific/Marquesas","-540,0":"Pacific/Gambier","-540,1":"America/Anchorage","-480,1":"America/Los_Angeles","-480,0":"Pacific/Pitcairn","-420,0":"America/Phoenix","-420,1":"America/Denver","-360,0":"America/Guatemala","-360,1":"America/Chicago","-360,1,s":"Pacific/Easter","-300,0":"America/Bogota","-300,1":"America/New_York","-270,0":"America/Caracas","-240,1":"America/Halifax","-240,0":"America/Santo_Domingo","-240,1,s":"America/Santiago","-210
 ,1":"America/St_Johns","-180,1":"America/Godthab","-180,0":"America/Argentina/Buenos_Aires","-180,1,s":"America/Montevideo","-120,0":"Etc/GMT+2","-120,1":"Etc/GMT+2","-60,1":"Atlantic/Azores","-60,0":"Atlantic/Cape_Verde","0,0":"Etc/UTC","0,1":"Europe/London","60,1":"Europe/Berlin","60,0":"Africa/Lagos","60,1,s":"Africa/Windhoek","120,1":"Asia/Beirut","120,0":"Africa/Johannesburg","180,0":"Asia/Baghdad","180,1":"Europe/Moscow","210,1":"Asia/Tehran","240,0":"Asia/Dubai","240,1":"Asia/Baku","270,0":"Asia/Kabul","300,1":"Asia/Yekaterinburg","300,0":"Asia/Karachi","330,0":"Asia/Kolkata","345,0":"Asia/Kathmandu","360,0":"Asia/Dhaka","360,1":"Asia/Omsk","390,0":"Asia/Rangoon","420,1":"Asia/Krasnoyarsk","420,0":"Asia/Jakarta","480,0":"Asia/Shanghai","480,1":"Asia/Irkutsk","525,0":"Australia/Eucla","525,1,s":"Australia/Eucla","540,1":"Asia/Yakutsk","540,0":"Asia/Tokyo","570,0":"Australia/Darwin","570,1,s":"Australia/Adelaide","600,0":"Australia/Brisbane","600,1":"Asia/Vladivostok","
 600,1,s":"Australia/Sydney","630,1,s":"Australia/Lord_Howe","660,1":"Asia/Kamchatka","660,0":"Pacific/Noumea","690,0":"Pacific/Norfolk","720,1,s":"Pacific/Auckland","720,0":"Pacific/Tarawa","765,1,s":"Pacific/Chatham","780,0":"Pacific/Tongatapu","780,1,s":"Pacific/Apia","840,0":"Pacific/Kiritimati"},typeof exports!="undefined"?exports.jstz=t:e.jstz=t})(this);
+
 /* session states */
 var OSRF_APP_SESSION_CONNECTED = 0;
 var OSRF_APP_SESSION_CONNECTING = 1;
@@ -57,6 +67,8 @@ function osrfMessage(hash) {
     this.hash = hash;
     if(!this.hash.locale)
         this.hash.locale = OpenSRF.locale || 'en-US';
+    if(!this.hash.tz)
+        this.hash.tz = jstz.determine().name()
     this._encodehash = true;
 }
 osrfMessage.prototype.threadTrace = function(d) { 
@@ -79,6 +91,11 @@ osrfMessage.prototype.locale = function(d) {
         this.hash.locale = d; 
     return this.hash.locale; 
 };
+osrfMessage.prototype.tz = function(d) { 
+    if(arguments.length == 1) 
+        this.hash.tz = d; 
+    return this.hash.tz; 
+};
 osrfMessage.prototype.api_level = function(d) { 
     if(arguments.length == 1) 
         this.hash.api_level = d; 
@@ -92,6 +109,7 @@ osrfMessage.prototype.serialize = function() {
             'type' : this.hash.type,
             'payload' : (this.hash.payload) ? this.hash.payload.serialize() : 'null',
             'locale' : this.hash.locale,
+            'tz' : this.hash.tz,
             'api_level' : this.hash.api_level
         }
     };
@@ -198,6 +216,7 @@ osrfContinueStatus.prototype.statusCode = function(d) {
 };
 
 OpenSRF = {};
+OpenSRF.tz = jstz.determine().name();
 OpenSRF.locale = null;
 OpenSRF.api_level = 1;
 
@@ -384,6 +403,7 @@ OpenSRF.ClientSession = function(service) {
     this.service = service;
     this.remote_id = null;
     this.locale = OpenSRF.locale || 'en-US';
+    this.tz = OpenSRF.tz;
     this.last_id = 0;
     this.requests = [];
     this.onconnect = null;
@@ -519,6 +539,7 @@ OpenSRF.Request.prototype.send = function() {
         'type' : OSRF_MESSAGE_TYPE_REQUEST, 
         'payload' : method, 
         'locale' : this.session.locale,
+        'tz' : this.session.tz,
         'api_level' : this.api_level
     });
 
diff --git a/src/libopensrf/osrf_app_session.c b/src/libopensrf/osrf_app_session.c
index 3e00393..0b5c6d6 100644
--- a/src/libopensrf/osrf_app_session.c
+++ b/src/libopensrf/osrf_app_session.c
@@ -372,6 +372,31 @@ char* osrf_app_session_set_locale( osrfAppSession* session, const char* locale )
 }
 
 /**
+	@brief Install a copy of a TZ string in a specified session.
+	@param session Pointer to the osrfAppSession in which the TZ is to be installed.
+	@param TZ The TZ string to be copied and installed.
+	@return A pointer to the installed copy of the TZ string.
+*/
+char* osrf_app_session_set_tz( osrfAppSession* session, const char* tz ) {
+	if (!session || !tz)
+		return NULL;
+
+	if(session->session_tz) {
+		if( strlen(session->session_tz) >= strlen(tz) ) {
+			/* There's room available; just copy */
+			strcpy(session->session_tz, tz);
+		} else {
+			free(session->session_tz);
+			session->session_tz = strdup( tz );
+		}
+	} else {
+		session->session_tz = strdup( tz );
+	}
+
+	return session->session_tz;
+}
+
+/**
 	@brief Install a copy of a ingress string as the new default.
 	@param session Pointer to the new strdup'ed default_ingress
 	@param ingress The ingress string to be copied and installed.
@@ -499,6 +524,7 @@ osrfAppSession* osrfAppSessionClientInit( const char* remote_service ) {
 	session->orig_remote_id = strdup(session->remote_id);
 	session->remote_service = strdup(remote_service);
 	session->session_locale = NULL;
+	session->session_tz = NULL;
 	session->transport_error = 0;
 	session->panic = 0;
 	session->outbuf = NULL;   // Not used by client
@@ -603,6 +629,7 @@ osrfAppSession* osrf_app_server_session_init(
 	session->state = OSRF_SESSION_DISCONNECTED;
 	session->type = OSRF_SESSION_SERVER;
 	session->session_locale = NULL;
+	session->session_tz = NULL;
 
 	session->userData = NULL;
 	session->userDataFree = NULL;
@@ -711,6 +738,8 @@ static int osrfAppSessionMakeLocaleRequest(
 		osrf_message_set_locale(req_msg, session->session_locale);
 	}
 
+	osrf_message_set_tz(req_msg, session->session_tz);
+
 	if (!current_ingress)
 		osrfAppSessionSetIngress("opensrf");
 	osrfMessageSetIngress(req_msg, current_ingress);
@@ -1110,6 +1139,9 @@ void osrfAppSessionFree( osrfAppSession* session ){
 	if(session->session_locale)
 		free(session->session_locale);
 
+	if(session->session_tz)
+		free(session->session_tz);
+
 	free(session->remote_id);
 	free(session->orig_remote_id);
 	free(session->session_id);
diff --git a/src/libopensrf/osrf_message.c b/src/libopensrf/osrf_message.c
index 3681dfa..9de5e0f 100644
--- a/src/libopensrf/osrf_message.c
+++ b/src/libopensrf/osrf_message.c
@@ -42,6 +42,7 @@ osrfMessage* osrf_message_init( enum M_TYPE type, int thread_trace, int protocol
 	msg->_result_content        = NULL;
 	msg->method_name            = NULL;
 	msg->sender_locale          = NULL;
+	msg->sender_tz              = NULL;
 	msg->sender_ingress         = NULL;
 
 	return msg;
@@ -84,6 +85,25 @@ const char* osrf_message_set_locale( osrfMessage* msg, const char* locale ) {
 }
 
 /**
+	@brief Set the TZ for a specified osrfMessage.
+	@param msg Pointer to the osrfMessage.
+	@param TZ Pointer to the TZ string to be installed in the osrfMessage.
+	@return Pointer to the new TZ string for the osrfMessage, or NULL if either
+		parameter is NULL.
+
+	If no TZ is specified for an osrfMessage, we use the system TZ.
+
+	Used for a REQUEST message.
+*/
+const char* osrf_message_set_tz( osrfMessage* msg, const char* tz ) {
+	if( msg == NULL || tz == NULL )
+		return NULL;
+	if( msg->sender_tz )
+		free( msg->sender_tz );
+	return msg->sender_tz = strdup( tz );
+}
+
+/**
 	@brief Set the ingress for a specified osrfMessage.
 	@param msg Pointer to the osrfMessage.
 	@param ingress Pointer to the ingress string to be installed in the osrfMessage.
@@ -307,6 +327,9 @@ void osrfMessageFree( osrfMessage* msg ) {
 	if( msg->sender_locale != NULL )
 		free(msg->sender_locale);
 
+	if( msg->sender_tz != NULL )
+		free(msg->sender_tz);
+
 	if( msg->sender_ingress != NULL )
 		free(msg->sender_ingress);
 
@@ -384,6 +407,7 @@ char* osrf_message_serialize(const osrfMessage* msg) {
 	The resulting jsonObject is a JSON_HASH with a classname of "osrfMessage", and the following keys:
 	- "threadTrace"
 	- "locale"
+	- "tz"
 	- "ingress"
 	- "type"
 	- "payload" (only for STATUS, REQUEST, and RESULT messages)
@@ -422,6 +446,10 @@ jsonObject* osrfMessageToJSON( const osrfMessage* msg ) {
 		jsonObjectSetKey(json, "locale", jsonNewObject(default_locale));
 	}
 
+	if (msg->sender_tz != NULL) {
+		jsonObjectSetKey(json, "tz", jsonNewObject(msg->sender_tz));
+	}
+
 	if (msg->sender_ingress != NULL) 
 		jsonObjectSetKey(json, "ingress", jsonNewObject(msg->sender_ingress));
 
@@ -657,6 +685,11 @@ static osrfMessage* deserialize_one_message( const jsonObject* obj ) {
 		osrfMessageSetIngress(msg, jsonObjectGetString(tmp));
 	}
 
+	tmp = jsonObjectGetKeyConst(obj, "tz");
+	if (tmp) {
+		osrf_message_set_tz(msg, jsonObjectGetString(tmp));
+	}
+
 	tmp = jsonObjectGetKeyConst( obj, "payload" );
 	if(tmp) {
 		// Get method name and parameters for a REQUEST
diff --git a/src/libopensrf/osrf_stack.c b/src/libopensrf/osrf_stack.c
index 73793f8..e176b9e 100644
--- a/src/libopensrf/osrf_stack.c
+++ b/src/libopensrf/osrf_stack.c
@@ -274,6 +274,11 @@ static void _do_server( osrfAppSession* session, osrfMessage* msg ) {
 
 	osrfLogDebug( OSRF_LOG_MARK, "Server received message of type %d", msg->m_type );
 
+        osrf_app_session_set_tz(session, msg->sender_tz);
+        osrf_app_session_set_locale(session, msg->sender_locale);
+
+	osrfLogDebug( OSRF_LOG_MARK, "Message has locale %s and tz %s", session->session_locale, session->session_tz );
+
 	switch( msg->m_type ) {
 
 		case STATUS:
diff --git a/src/perl/lib/OpenSRF/DomainObject/oilsMessage.pm b/src/perl/lib/OpenSRF/DomainObject/oilsMessage.pm
index 54c5963..33675a8 100644
--- a/src/perl/lib/OpenSRF/DomainObject/oilsMessage.pm
+++ b/src/perl/lib/OpenSRF/DomainObject/oilsMessage.pm
@@ -5,6 +5,7 @@ use OpenSRF::DomainObject::oilsResponse qw/:status/;
 use OpenSRF::Utils::Logger qw/:level/;
 use warnings; use strict;
 use OpenSRF::EX qw/:try/;
+use POSIX qw/tzset/;
 
 OpenSRF::Utils::JSON->register_class_hint(hint => 'osrfMessage', name => 'OpenSRF::DomainObject::oilsMessage', type => 'hash');
 
@@ -17,6 +18,7 @@ sub new {
 	my $self = shift;
 	my $class = ref($self) || $self;
 	my %args = @_;
+	$args{tz} = $ENV{TZ};
 	return bless \%args => $class;
 }
 
@@ -102,6 +104,24 @@ sub sender_locale {
 	return $self->{locale};
 }
 
+=head2 OpenSRF::DomainObject::oilsMessage->sender_tz( [$tz] );
+
+=over 4
+
+Sets or gets the current message tz.  Useful for telling the
+server how you see the world.
+
+=back
+
+=cut
+
+sub sender_tz {
+	my $self = shift;
+	my $val = shift;
+	$self->{tz} = $val if (defined $val);
+	return $self->{tz};
+}
+
 =head2 OpenSRF::DomainObject::oilsMessage->sender_ingress( [$ingress] );
 
 =over 4
@@ -197,12 +217,13 @@ sub handler {
 	my $session = shift;
 
 	my $mtype = $self->type;
+	my $tz = $self->sender_tz || '';
 	my $locale = $self->sender_locale || '';
 	my $ingress = $self->sender_ingress || '';
 	my $api_level = $self->api_level || 1;
 	my $tT = $self->threadTrace;
 
-    $log->debug("Message locale is $locale; ingress = $ingress", DEBUG);
+    $log->debug("Message locale is $locale; ingress = $ingress; tz = $tz", DEBUG);
 
 	$session->last_message_type($mtype);
 	$session->last_message_api_level($api_level);
@@ -217,10 +238,13 @@ sub handler {
 		$val = $self->do_server( $session, $mtype, $api_level, $tT );
 
 	} elsif ($session->endpoint == $session->CLIENT()) {
+		$tz = undef; # Client should not adopt the TZ of the server
 		$val = $self->do_client( $session, $mtype, $api_level, $tT );
 	}
 
 	if( $val ) {
+		local $ENV{TZ} = $tz || $ENV{TZ}; # automatic revert at the end of this scope
+		tzset();
 		return OpenSRF::Application->handler($session, $self->payload);
 	} else {
 		$log->debug("Request was handled internally", DEBUG);
diff --git a/src/srfsh/srfsh.c b/src/srfsh/srfsh.c
index d8132d1..e3705a9 100644
--- a/src/srfsh/srfsh.c
+++ b/src/srfsh/srfsh.c
@@ -37,6 +37,7 @@ static void get_misc( ArgParser* parser );
 #define SRFSH_PORT 5222
 #define COMMAND_BUFSIZE 4096
 
+static char* tz = NULL;
 
 /* shell prompt */
 static const char* prompt = "srfsh# ";
@@ -104,6 +105,7 @@ int main( int argc, char* argv[] ) {
 	/* --------------------------------------------- */
 	/* see if they have a .srfsh.xml in their home directory */
 	char* home = getenv("HOME");
+	tz = getenv("TZ");
 	int l = strlen(home) + 36;
 	char fbuf[l];
 	snprintf(fbuf, sizeof(fbuf), "%s/.srfsh.xml", home);
@@ -798,6 +800,8 @@ int send_request( const char* server,
 		session_is_temporary = 1;                     // just for this request
 	}
 
+	if (tz) osrf_app_session_set_tz(session,tz);
+
 	double start = get_timestamp_millis();
 
 	int req_id = osrfAppSessionSendRequest( session, params, method, 1 );

-----------------------------------------------------------------------

Summary of changes:
 doc/TZ-handling.txt                              |   44 ++++++++++++++++++++++
 include/opensrf/osrf_app_session.h               |    5 ++
 include/opensrf/osrf_message.h                   |    7 +++
 src/javascript/opensrf.js                        |   21 ++++++++++
 src/libopensrf/osrf_app_session.c                |   32 ++++++++++++++++
 src/libopensrf/osrf_message.c                    |   33 ++++++++++++++++
 src/libopensrf/osrf_stack.c                      |    5 ++
 src/perl/lib/OpenSRF/DomainObject/oilsMessage.pm |   26 ++++++++++++-
 src/srfsh/srfsh.c                                |    4 ++
 9 files changed, 176 insertions(+), 1 deletions(-)
 create mode 100644 doc/TZ-handling.txt


hooks/post-receive
-- 
OpenSRF


More information about the opensrf-commits mailing list