Ticket #5319: mythtv-5319-add_query_timezone_to_protocol-20080510.patch

File mythtv-5319-add_query_timezone_to_protocol-20080510.patch, 11.3 KB (added by sphery <mtdean@…>, 16 years ago)

Replaces mythtv-5319-add_query_timezone_to_protocol.patch

  • libs/libmyth/util.h

     
    4747
    4848MPUBLIC QDateTime mythCurrentDateTime();
    4949MPUBLIC int calc_utc_offset(void);
     50MPUBLIC QString format_utc_offset(void);
     51MPUBLIC QString getTimeZoneID(void);
    5052
    5153// This is necessary for GCC 3.3, which has llabs(long long)
    5254// but not abs(long long) or std::llabs(long long)
  • libs/libmyth/util.cpp

     
    1010#include <unistd.h>
    1111#include <stdlib.h>
    1212#include <fcntl.h>
     13#include <time.h>
    1314
    1415// System specific C headers
    1516#include "compat.h"
     
    4445#include <qfile.h>
    4546#include <Q3CString>
    4647#include <Q3DeepCopy>
     48#include <QDir>
     49#include <QFile>
     50#include <QFileInfo>
    4751
    4852// Myth headers
    4953#include "mythconfig.h"
     
    9599    return utc_offset;
    96100}
    97101
     102QString format_utc_offset(void)
     103{
     104    char offset[32];
     105    int offset_total_seconds, offset_hours, offset_minutes;
     106    QString offset_string("UNDEF");
     107
     108    offset_total_seconds = calc_utc_offset();
     109
     110    offset_hours = offset_total_seconds / 3600;
     111    offset_minutes = abs((offset_total_seconds % 3600) / 60);
     112
     113    if (sprintf(offset, "%.2i:%.2i", offset_hours, offset_minutes) > 0)
     114        offset_string = offset;
     115
     116    return offset_string;
     117}
     118
     119#ifndef USING_MINGW
     120/* Helper function for getSystemTimeZoneID() that compares the
     121   zoneinfo_file_path (regular) file with files in the zoneinfo_dir_path until
     122   it finds a match.  The matching file's name is used to determine the time
     123   zone ID. */
     124static QString findZoneinfoFile(QString zoneinfo_file_path,
     125                                QString zoneinfo_dir_path)
     126{
     127    QString zone_id("UNDEF");
     128    QDir zoneinfo_dir(zoneinfo_dir_path);
     129    QFileInfoList dirlist = zoneinfo_dir.entryInfoList();
     130    QFileInfo info;
     131    QString basename;
     132    QFile zoneinfo_file(zoneinfo_file_path);
     133    qint64 zoneinfo_file_size = zoneinfo_file.size();
     134
     135    for (QFileInfoList::const_iterator it = dirlist.begin();
     136         it != dirlist.end(); it++)
     137    {
     138        info = *it;
     139         // Skip '.' and '..' and other files starting with "." and
     140         // skip localtime (which is often a link to zoneinfo_file_path)
     141        basename = info.baseName();
     142        if (basename.isEmpty() || (basename == "localtime")) {
     143            continue;
     144        }
     145        if (info.isDir())
     146        {
     147            zone_id = findZoneinfoFile(zoneinfo_file_path,
     148                                       info.absoluteFilePath());
     149            if (zone_id != "UNDEF")
     150                return zone_id;
     151        }
     152        else if (info.isFile() && (info.size() == zoneinfo_file_size) &&
     153                 info.isReadable())
     154        {
     155            // sanity check - zoneinfo files should typically be less than
     156            // about 4kB, but leave room for growth
     157            if (zoneinfo_file_size > 200 * 1024)
     158                continue;
     159            QFile this_file(info.absoluteFilePath());
     160            QByteArray zoneinfo_file_data;
     161            zoneinfo_file_data.resize(zoneinfo_file_size);
     162            QByteArray this_file_data;
     163            this_file_data.resize(zoneinfo_file_size);
     164            if (zoneinfo_file.open(QIODevice::ReadOnly))
     165            {
     166                QDataStream in(&zoneinfo_file);
     167                if (in.readRawData(zoneinfo_file_data.data(),
     168                                   zoneinfo_file_size) != zoneinfo_file_size)
     169                {
     170                    zoneinfo_file.close();
     171                    return zone_id;
     172                }
     173                zoneinfo_file.close();
     174            }
     175            if (this_file.open(QIODevice::ReadOnly))
     176            {
     177                QDataStream in(&this_file);
     178                if (in.readRawData(this_file_data.data(),
     179                                   zoneinfo_file_size) != zoneinfo_file_size)
     180                {
     181                    this_file.close();
     182                    return zone_id;
     183                }
     184                this_file.close();
     185            }
     186            if (zoneinfo_file_data == this_file_data)
     187            {
     188                zone_id = info.absoluteFilePath();
     189                break;
     190            }
     191        }
     192    }
     193    return zone_id;
     194}
     195#endif
     196
     197/* Helper function for getTimeZoneID() that provides an unprocessed time zone
     198   id obtained using system-dependent means of identifying the system's time
     199   zone. */
     200static QString getSystemTimeZoneID(void)
     201{
     202    QString zone_id("UNDEF");
     203#ifndef USING_MINGW
     204    // Try to determine the time zone information by inspecting the system
     205    // configuration
     206    bool found = false;
     207    QString time_zone_file_path("/etc/timezone");
     208    QString clock_file_path("/etc/sysconfig/clock");
     209    QString zoneinfo_file_path("/etc/localtime");
     210    QString zoneinfo_dir_path("/usr/share/zoneinfo");
     211
     212    // First, check time_zone_file_path (used by Debian-based systems)
     213    QFile time_zone_file(time_zone_file_path);
     214    QFileInfo info(time_zone_file);
     215    if (info.exists() && info.isFile() && info.isReadable())
     216    {
     217        if (time_zone_file.open(QIODevice::ReadOnly | QIODevice::Text))
     218        {
     219            QString line;
     220            QTextStream in(&time_zone_file);
     221            while (!in.atEnd())
     222            {
     223                line = in.readLine();
     224                line = line.trimmed();
     225                if (!line.startsWith("#"))
     226                {
     227                    zone_id = line;
     228                    found = true;
     229                    break;
     230                }
     231            }
     232            time_zone_file.close();
     233            if (found)
     234                return zone_id;
     235        }
     236    }
     237
     238    // Next, look for the ZONE entry in clock_file_path (used by Red Hat-based
     239    // systems)
     240    QFile clock_file(clock_file_path);
     241    info.setFile(clock_file);
     242    if (info.exists() && info.isFile() && info.isReadable())
     243    {
     244        if (clock_file.open(QIODevice::ReadOnly | QIODevice::Text))
     245        {
     246            QString line;
     247            QTextStream in(&clock_file);
     248            // Handle whitespace and quotes
     249            QRegExp re("^ZONE\\s*=\\s*(?:'|\")?(.+)$");
     250            re.setPatternSyntax(QRegExp::RegExp2);
     251            while (!in.atEnd())
     252            {
     253                line = in.readLine();
     254                if (re.indexIn(line) != -1)
     255                {
     256                    zone_id = re.cap(1);
     257                    found = true;
     258                    break;
     259                }
     260            }
     261            clock_file.close();
     262            if (found)
     263                return zone_id;
     264        }
     265    }
     266
     267    // Next check zoneinfo_file_path
     268    QFile zoneinfo_file(zoneinfo_file_path);
     269    info.setFile(zoneinfo_file);
     270
     271    if (info.exists() && info.isFile())
     272    {
     273        QString tz;
     274        if (info.isSymLink())
     275        {
     276            // The symlink refers to a file whose name contains the zone ID
     277            tz = info.symLinkTarget();
     278        }
     279        else
     280        {
     281            // The zoneinfo_file is a copy of the file in the
     282            // zoneinfo_dir_path, so search for the same file in
     283            // zoneinfo_dir_path
     284            tz = findZoneinfoFile(zoneinfo_file_path, zoneinfo_dir_path);
     285        }
     286        if (tz != "UNDEF")
     287        {
     288            int pos = 0;
     289            // Get the zone ID from the filename
     290            // Look for the basename of zoneinfo_dir_path in case it's a
     291            // relative link
     292            QString zoneinfo_dirname = zoneinfo_dir_path.section('/', -1);
     293            if ((pos = tz.indexOf(zoneinfo_dirname)) != -1)
     294            {
     295                zone_id = tz.right(tz.size() - (pos + 1) -
     296                                   zoneinfo_dirname.size());
     297            }
     298        }
     299        else
     300        {
     301            // If we still haven't found a time zone, try localtime_r() to at
     302            // least get the zone name/abbreviation (as opposed to the
     303            // identifier for the set of rules governing the zone)
     304            char name[64];
     305            time_t t;
     306            struct tm *result = (struct tm *)malloc(sizeof(*result));
     307
     308            t = time(NULL);
     309            localtime_r(&t, result);
     310
     311            if (result != NULL)
     312            {
     313                if (strftime(name, sizeof(name), "%Z", result) > 0)
     314                    zone_id = name;
     315                free(result);
     316            }
     317        }
     318    }
     319
     320#endif
     321    return zone_id;
     322}
     323
     324/** \fn getTimeZoneID()
     325 *  \brief Returns the zoneinfo time zone ID or as much time zone information
     326 *         as possible
     327 */
     328QString getTimeZoneID(void)
     329{
     330    QString zone_id("UNDEF");
     331#ifndef USING_MINGW
     332    // First, try the TZ environment variable to check for environment-specific
     333    // overrides
     334    QString tz = getenv("TZ");
     335    if (tz.isEmpty())
     336    {
     337        // No TZ, so attempt to determine the system-configured time zone ID
     338        tz = getSystemTimeZoneID();
     339    }
     340
     341    if (!tz.isEmpty())
     342    {
     343        zone_id = tz;
     344        if (zone_id.startsWith("\"") || zone_id.startsWith("'"))
     345                zone_id.remove(0, 1);
     346        if (zone_id.endsWith("\"") || zone_id.endsWith("'"))
     347                zone_id.chop(1);
     348        if (zone_id.startsWith(":"))
     349            zone_id.remove(0, 1);
     350        // the "posix/" subdirectory typically contains the same files as the
     351        // "zoneinfo/" parent directory, but are not typically what are in use
     352        if (zone_id.startsWith("posix/"))
     353            zone_id.remove(0, 6);
     354    }
     355
     356#endif
     357    return zone_id;
     358}
     359
    98360/** \fn encodeLongLong(QStringList&,long long)
    99361 *  \brief Encodes a long for streaming in the MythTV protocol.
    100362 *
  • programs/mythbackend/mainserver.h

     
    135135    void HandleQueryLoad(PlaybackSock *pbs);
    136136    void HandleQueryUptime(PlaybackSock *pbs);
    137137    void HandleQueryMemStats(PlaybackSock *pbs);
     138    void HandleQueryTimeZone(PlaybackSock *pbs);
    138139    void HandleBlockShutdown(bool blockShutdown, PlaybackSock *pbs);
    139140   
    140141    void SendResponse(MythSocket *pbs, QStringList &commands);
  • programs/mythbackend/mainserver.cpp

     
    374374    {
    375375        HandleQueryMemStats(pbs);
    376376    }
     377    else if (command == "QUERY_TIME_ZONE")
     378    {
     379        HandleQueryTimeZone(pbs);
     380    }
    377381    else if (command == "QUERY_CHECKFILE")
    378382    {
    379383        HandleQueryCheckFile(listline, pbs);
     
    23102314
    23112315/**
    23122316 * \addtogroup myth_network_protocol
     2317 * \par        QUERY_TIME_ZONE
     2318 * Returns time zone ID, current offset, current time
     2319 */
     2320void MainServer::HandleQueryTimeZone(PlaybackSock *pbs)
     2321{
     2322    MythSocket *pbssock = pbs->getSocket();
     2323    QStringList strlist;
     2324    strlist << getTimeZoneID() << format_utc_offset()
     2325            << mythCurrentDateTime().toString(Qt::ISODate);
     2326
     2327    SendResponse(pbssock, strlist);
     2328}
     2329
     2330/**
     2331 * \addtogroup myth_network_protocol
    23132332 * \par        QUERY_CHECKFILE \e checkslaves \e programinfo
    23142333 */
    23152334void MainServer::HandleQueryCheckFile(QStringList &slist, PlaybackSock *pbs)