diff --git a/libfreerdp-core/CMakeLists.txt b/libfreerdp-core/CMakeLists.txt index 939a9cf52..b01d5f967 100644 --- a/libfreerdp-core/CMakeLists.txt +++ b/libfreerdp-core/CMakeLists.txt @@ -63,6 +63,8 @@ set(LIBFREERDP_CORE_SRCS connection.h redirection.c redirection.h + timezone.c + timezone.h rdp.c rdp.h per.c diff --git a/libfreerdp-core/info.c b/libfreerdp-core/info.c index 6390ca79c..648e06de8 100644 --- a/libfreerdp-core/info.c +++ b/libfreerdp-core/info.c @@ -17,6 +17,8 @@ * limitations under the License. */ +#include "timezone.h" + #include "info.h" #define INFO_TYPE_LOGON 0x00000000 @@ -34,195 +36,6 @@ static const char* const INFO_TYPE_LOGON_STRINGS[] = }; */ -/** - * Read SYSTEM_TIME structure (TS_SYSTEMTIME).\n - * @msdn{cc240478} - * @param s stream - * @param system_time system time structure - */ - -void rdp_read_system_time(STREAM* s, SYSTEM_TIME* system_time) -{ - stream_read_uint16(s, system_time->wYear); /* wYear, must be set to 0 */ - stream_read_uint16(s, system_time->wMonth); /* wMonth */ - stream_read_uint16(s, system_time->wDayOfWeek); /* wDayOfWeek */ - stream_read_uint16(s, system_time->wDay); /* wDay */ - stream_read_uint16(s, system_time->wHour); /* wHour */ - stream_read_uint16(s, system_time->wMinute); /* wMinute */ - stream_read_uint16(s, system_time->wSecond); /* wSecond */ - stream_read_uint16(s, system_time->wMilliseconds); /* wMilliseconds */ -} - -/** - * Write SYSTEM_TIME structure (TS_SYSTEMTIME).\n - * @msdn{cc240478} - * @param s stream - * @param system_time system time structure - */ - -void rdp_write_system_time(STREAM* s, SYSTEM_TIME* system_time) -{ - stream_write_uint16(s, system_time->wYear); /* wYear, must be set to 0 */ - stream_write_uint16(s, system_time->wMonth); /* wMonth */ - stream_write_uint16(s, system_time->wDayOfWeek); /* wDayOfWeek */ - stream_write_uint16(s, system_time->wDay); /* wDay */ - stream_write_uint16(s, system_time->wHour); /* wHour */ - stream_write_uint16(s, system_time->wMinute); /* wMinute */ - stream_write_uint16(s, system_time->wSecond); /* wSecond */ - stream_write_uint16(s, system_time->wMilliseconds); /* wMilliseconds */ -} - -/** - * Get client time zone information.\n - * @param s stream - * @param settings settings - */ - -void rdp_get_client_time_zone(STREAM* s, rdpSettings* settings) -{ - time_t t; - struct tm* local_time; - TIME_ZONE_INFO* clientTimeZone; - - time(&t); - local_time = localtime(&t); - clientTimeZone = settings->client_time_zone; - -#ifdef HAVE_TM_GMTOFF - if (local_time->tm_gmtoff >= 0) - clientTimeZone->bias = (uint32) (local_time->tm_gmtoff / 60); - else - clientTimeZone->bias = (uint32) ((-1 * local_time->tm_gmtoff) / 60 + 720); -#elif sun - if (local_time->tm_isdst > 0) - clientTimeZone->bias = (uint32) (altzone / 3600); - else - clientTimeZone->bias = (uint32) (timezone / 3600); -#else - clientTimeZone->bias = 0; -#endif - - if (local_time->tm_isdst > 0) - { - clientTimeZone->standardBias = clientTimeZone->bias - 60; - clientTimeZone->daylightBias = clientTimeZone->bias; - } - else - { - clientTimeZone->standardBias = clientTimeZone->bias; - clientTimeZone->daylightBias = clientTimeZone->bias + 60; - } - - strftime(clientTimeZone->standardName, 32, "%Z, Standard Time", local_time); - clientTimeZone->standardName[31] = 0; - strftime(clientTimeZone->daylightName, 32, "%Z, Summer Time", local_time); - clientTimeZone->daylightName[31] = 0; -} - -/** - * Read client time zone information (TS_TIME_ZONE_INFORMATION).\n - * @msdn{cc240477} - * @param s stream - * @param settings settings - */ - -boolean rdp_read_client_time_zone(STREAM* s, rdpSettings* settings) -{ - char* str; - TIME_ZONE_INFO* clientTimeZone; - - if (stream_get_left(s) < 172) - return false; - - clientTimeZone = settings->client_time_zone; - - stream_read_uint32(s, clientTimeZone->bias); /* Bias */ - - /* standardName (64 bytes) */ - str = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), 64); - stream_seek(s, 64); - strncpy(clientTimeZone->standardName, str, sizeof(clientTimeZone->standardName)); - xfree(str); - - rdp_read_system_time(s, &clientTimeZone->standardDate); /* StandardDate */ - stream_read_uint32(s, clientTimeZone->standardBias); /* StandardBias */ - - /* daylightName (64 bytes) */ - str = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), 64); - stream_seek(s, 64); - strncpy(clientTimeZone->daylightName, str, sizeof(clientTimeZone->daylightName)); - xfree(str); - - rdp_read_system_time(s, &clientTimeZone->daylightDate); /* DaylightDate */ - stream_read_uint32(s, clientTimeZone->daylightBias); /* DaylightBias */ - - return true; -} - -/** - * Write client time zone information (TS_TIME_ZONE_INFORMATION).\n - * @msdn{cc240477} - * @param s stream - * @param settings settings - */ - -void rdp_write_client_time_zone(STREAM* s, rdpSettings* settings) -{ - size_t length; - uint8* standardName; - uint8* daylightName; - size_t standardNameLength; - size_t daylightNameLength; - TIME_ZONE_INFO* clientTimeZone; - - rdp_get_client_time_zone(s, settings); - clientTimeZone = settings->client_time_zone; - - /* - * temporary fix: to be valid the time zone names need to match - * the data that can be found at the following registry location: - * HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones - * - * We should extract the data out of the registry and hardcode it - * within FreeRDP. We should then be able to figure out the proper - * names to use from the standardBias and daylightBias numerical - * values which we detect. - */ - sprintf(clientTimeZone->standardName, "%s", "GMT Standard Time"); - sprintf(clientTimeZone->daylightName, "%s", "GMT Daylight Time"); - - standardName = (uint8*) freerdp_uniconv_out(settings->uniconv, clientTimeZone->standardName, &length); - standardNameLength = length; - - daylightName = (uint8*) freerdp_uniconv_out(settings->uniconv, clientTimeZone->daylightName, &length); - daylightNameLength = length; - - if (standardNameLength > 62) - standardNameLength = 62; - - if (daylightNameLength > 62) - daylightNameLength = 62; - - stream_write_uint32(s, clientTimeZone->bias); /* Bias */ - - /* standardName (64 bytes) */ - stream_write(s, standardName, standardNameLength); - stream_write_zero(s, 64 - standardNameLength); - - rdp_write_system_time(s, &clientTimeZone->standardDate); /* StandardDate */ - stream_write_uint32(s, clientTimeZone->standardBias); /* StandardBias */ - - /* daylightName (64 bytes) */ - stream_write(s, daylightName, daylightNameLength); - stream_write_zero(s, 64 - daylightNameLength); - - rdp_write_system_time(s, &clientTimeZone->daylightDate); /* DaylightDate */ - stream_write_uint32(s, clientTimeZone->daylightBias); /* DaylightBias */ - - xfree(standardName); - xfree(daylightName); -} - /** * Read Server Auto Reconnect Cookie (ARC_SC_PRIVATE_PACKET).\n * @msdn{cc240540} diff --git a/libfreerdp-core/timezone.c b/libfreerdp-core/timezone.c new file mode 100644 index 000000000..cc4ef9615 --- /dev/null +++ b/libfreerdp-core/timezone.c @@ -0,0 +1,209 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * Time Zone Redirection + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "timezone.h" + +/** + * Read SYSTEM_TIME structure (TS_SYSTEMTIME).\n + * @msdn{cc240478} + * @param s stream + * @param system_time system time structure + */ + +void rdp_read_system_time(STREAM* s, SYSTEM_TIME* system_time) +{ + stream_read_uint16(s, system_time->wYear); /* wYear, must be set to 0 */ + stream_read_uint16(s, system_time->wMonth); /* wMonth */ + stream_read_uint16(s, system_time->wDayOfWeek); /* wDayOfWeek */ + stream_read_uint16(s, system_time->wDay); /* wDay */ + stream_read_uint16(s, system_time->wHour); /* wHour */ + stream_read_uint16(s, system_time->wMinute); /* wMinute */ + stream_read_uint16(s, system_time->wSecond); /* wSecond */ + stream_read_uint16(s, system_time->wMilliseconds); /* wMilliseconds */ +} + +/** + * Write SYSTEM_TIME structure (TS_SYSTEMTIME).\n + * @msdn{cc240478} + * @param s stream + * @param system_time system time structure + */ + +void rdp_write_system_time(STREAM* s, SYSTEM_TIME* system_time) +{ + stream_write_uint16(s, system_time->wYear); /* wYear, must be set to 0 */ + stream_write_uint16(s, system_time->wMonth); /* wMonth */ + stream_write_uint16(s, system_time->wDayOfWeek); /* wDayOfWeek */ + stream_write_uint16(s, system_time->wDay); /* wDay */ + stream_write_uint16(s, system_time->wHour); /* wHour */ + stream_write_uint16(s, system_time->wMinute); /* wMinute */ + stream_write_uint16(s, system_time->wSecond); /* wSecond */ + stream_write_uint16(s, system_time->wMilliseconds); /* wMilliseconds */ +} + +/** + * Get client time zone information.\n + * @param s stream + * @param settings settings + */ + +void rdp_get_client_time_zone(STREAM* s, rdpSettings* settings) +{ + time_t t; + struct tm* local_time; + TIME_ZONE_INFO* clientTimeZone; + + time(&t); + local_time = localtime(&t); + clientTimeZone = settings->client_time_zone; + +#ifdef HAVE_TM_GMTOFF + if (local_time->tm_gmtoff >= 0) + clientTimeZone->bias = (uint32) (local_time->tm_gmtoff / 60); + else + clientTimeZone->bias = (uint32) ((-1 * local_time->tm_gmtoff) / 60 + 720); +#elif sun + if (local_time->tm_isdst > 0) + clientTimeZone->bias = (uint32) (altzone / 3600); + else + clientTimeZone->bias = (uint32) (timezone / 3600); +#else + clientTimeZone->bias = 0; +#endif + + if (local_time->tm_isdst > 0) + { + clientTimeZone->standardBias = clientTimeZone->bias - 60; + clientTimeZone->daylightBias = clientTimeZone->bias; + } + else + { + clientTimeZone->standardBias = clientTimeZone->bias; + clientTimeZone->daylightBias = clientTimeZone->bias + 60; + } + + strftime(clientTimeZone->standardName, 32, "%Z, Standard Time", local_time); + clientTimeZone->standardName[31] = 0; + strftime(clientTimeZone->daylightName, 32, "%Z, Summer Time", local_time); + clientTimeZone->daylightName[31] = 0; +} + +/** + * Read client time zone information (TS_TIME_ZONE_INFORMATION).\n + * @msdn{cc240477} + * @param s stream + * @param settings settings + */ + +boolean rdp_read_client_time_zone(STREAM* s, rdpSettings* settings) +{ + char* str; + TIME_ZONE_INFO* clientTimeZone; + + if (stream_get_left(s) < 172) + return false; + + clientTimeZone = settings->client_time_zone; + + stream_read_uint32(s, clientTimeZone->bias); /* Bias */ + + /* standardName (64 bytes) */ + str = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), 64); + stream_seek(s, 64); + strncpy(clientTimeZone->standardName, str, sizeof(clientTimeZone->standardName)); + xfree(str); + + rdp_read_system_time(s, &clientTimeZone->standardDate); /* StandardDate */ + stream_read_uint32(s, clientTimeZone->standardBias); /* StandardBias */ + + /* daylightName (64 bytes) */ + str = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), 64); + stream_seek(s, 64); + strncpy(clientTimeZone->daylightName, str, sizeof(clientTimeZone->daylightName)); + xfree(str); + + rdp_read_system_time(s, &clientTimeZone->daylightDate); /* DaylightDate */ + stream_read_uint32(s, clientTimeZone->daylightBias); /* DaylightBias */ + + return true; +} + +/** + * Write client time zone information (TS_TIME_ZONE_INFORMATION).\n + * @msdn{cc240477} + * @param s stream + * @param settings settings + */ + +void rdp_write_client_time_zone(STREAM* s, rdpSettings* settings) +{ + size_t length; + uint8* standardName; + uint8* daylightName; + size_t standardNameLength; + size_t daylightNameLength; + TIME_ZONE_INFO* clientTimeZone; + + rdp_get_client_time_zone(s, settings); + clientTimeZone = settings->client_time_zone; + + /* + * temporary fix: to be valid the time zone names need to match + * the data that can be found at the following registry location: + * HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones + * + * We should extract the data out of the registry and hardcode it + * within FreeRDP. We should then be able to figure out the proper + * names to use from the standardBias and daylightBias numerical + * values which we detect. + */ + sprintf(clientTimeZone->standardName, "%s", "GMT Standard Time"); + sprintf(clientTimeZone->daylightName, "%s", "GMT Daylight Time"); + + standardName = (uint8*) freerdp_uniconv_out(settings->uniconv, clientTimeZone->standardName, &length); + standardNameLength = length; + + daylightName = (uint8*) freerdp_uniconv_out(settings->uniconv, clientTimeZone->daylightName, &length); + daylightNameLength = length; + + if (standardNameLength > 62) + standardNameLength = 62; + + if (daylightNameLength > 62) + daylightNameLength = 62; + + stream_write_uint32(s, clientTimeZone->bias); /* Bias */ + + /* standardName (64 bytes) */ + stream_write(s, standardName, standardNameLength); + stream_write_zero(s, 64 - standardNameLength); + + rdp_write_system_time(s, &clientTimeZone->standardDate); /* StandardDate */ + stream_write_uint32(s, clientTimeZone->standardBias); /* StandardBias */ + + /* daylightName (64 bytes) */ + stream_write(s, daylightName, daylightNameLength); + stream_write_zero(s, 64 - daylightNameLength); + + rdp_write_system_time(s, &clientTimeZone->daylightDate); /* DaylightDate */ + stream_write_uint32(s, clientTimeZone->daylightBias); /* DaylightBias */ + + xfree(standardName); + xfree(daylightName); +} diff --git a/libfreerdp-core/timezone.h b/libfreerdp-core/timezone.h new file mode 100644 index 000000000..facd11809 --- /dev/null +++ b/libfreerdp-core/timezone.h @@ -0,0 +1,34 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * Time Zone Redirection + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIMEZONE_H +#define __TIMEZONE_H + +#include "rdp.h" + +#include +#include + +void rdp_read_system_time(STREAM* s, SYSTEM_TIME* system_time); +void rdp_write_system_time(STREAM* s, SYSTEM_TIME* system_time); +void rdp_get_client_time_zone(STREAM* s, rdpSettings* settings); +boolean rdp_read_client_time_zone(STREAM* s, rdpSettings* settings); +void rdp_write_client_time_zone(STREAM* s, rdpSettings* settings); + +#endif /* __TIMEZONE_H */