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

File mythtv-5319-add_query_timezone_to_protocol-20080729.patch, 11.5 KB (added by sphery <mtdean@…>, 12 years ago)

Updated patch for recent changes to trunk

  • libs/libmyth/util.h

    old new  
    2424
    2525MPUBLIC QDateTime mythCurrentDateTime();
    2626MPUBLIC int calc_utc_offset(void);
     27MPUBLIC QString format_utc_offset(void);
     28MPUBLIC QString getTimeZoneID(void);
    2729
    2830// This is necessary for GCC 3.3, which has llabs(long long)
    2931// but not abs(long long) or std::llabs(long long)
  • libs/libmyth/util.cpp

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

    old new  
    137137    void HandleQueryLoad(PlaybackSock *pbs);
    138138    void HandleQueryUptime(PlaybackSock *pbs);
    139139    void HandleQueryMemStats(PlaybackSock *pbs);
     140    void HandleQueryTimeZone(PlaybackSock *pbs);
    140141    void HandleBlockShutdown(bool blockShutdown, PlaybackSock *pbs);
    141142   
    142143    void SendResponse(MythSocket *pbs, QStringList &commands);
  • programs/mythbackend/mainserver.cpp

    old new  
    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);
     
    23512355
    23522356/**
    23532357 * \addtogroup myth_network_protocol
     2358 * \par        QUERY_TIME_ZONE
     2359 * Returns time zone ID, current offset, current time
     2360 */
     2361void MainServer::HandleQueryTimeZone(PlaybackSock *pbs)
     2362{
     2363    MythSocket *pbssock = pbs->getSocket();
     2364    QStringList strlist;
     2365    strlist << getTimeZoneID() << format_utc_offset()
     2366            << mythCurrentDateTime().toString(Qt::ISODate);
     2367
     2368    SendResponse(pbssock, strlist);
     2369}
     2370
     2371/**
     2372 * \addtogroup myth_network_protocol
    23542373 * \par        QUERY_CHECKFILE \e checkslaves \e programinfo
    23552374 */
    23562375void MainServer::HandleQueryCheckFile(QStringList &slist, PlaybackSock *pbs)