// rdlog.cpp // // Abstract a Rivendell Log. // // (C) Copyright 2002-2003,2016-2018 Fred Gleason // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as // published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public // License along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // #include #include "rdapplication.h" #include "rddb.h" #include "rdconf.h" #include "rdescape_string.h" #include "rdlog.h" #include "rdlog_line.h" #include "rdsvc.h" #include "rdweb.h" RDLog::RDLog(const QString &name) { log_name=name; // // Normalize case // QString sql=QString("select NAME from LOGS where ")+ "NAME=\""+RDEscapeString(name)+"\""; RDSqlQuery *q=new RDSqlQuery(sql); if(q->first()) { log_name=q->value(0).toString(); } delete q; } QString RDLog::name() const { return log_name; } bool RDLog::exists() const { QString sql=QString("select NAME from LOGS where ")+ "NAME=\""+RDEscapeString(log_name)+"\""; RDSqlQuery *q=new RDSqlQuery(sql); if(q->first()) { delete q; return true; } delete q; return false; } bool RDLog::logExists() const { return RDBool(GetStringValue("LOG_EXISTS")); } void RDLog::setLogExists(bool state) const { SetRow("LOG_EXISTS",RDYesNo(state)); } RDLog::Type RDLog::type() const { return(RDLog::Type)GetIntValue("TYPE"); } void RDLog::setType(RDLog::Type type) const { SetRow("TYPE",(int)type); } QString RDLog::description() const { return GetStringValue("DESCRIPTION"); } void RDLog::setDescription(const QString &desc) const { SetRow("DESCRIPTION",desc); } QString RDLog::service() const { return GetStringValue("SERVICE"); } void RDLog::setService(const QString &svc) const { SetRow("SERVICE",svc); } QDate RDLog::startDate() const { return GetDateValue("START_DATE"); } void RDLog::setStartDate(const QDate &date) const { SetRow("START_DATE",date); } QDate RDLog::endDate() const { return GetDateValue("END_DATE"); } void RDLog::setEndDate(const QDate &date) const { SetRow("END_DATE",date); } QDate RDLog::purgeDate() const { return GetDateValue("PURGE_DATE"); } void RDLog::setPurgeDate(const QDate &date) const { SetRow("PURGE_DATE",date); } QString RDLog::originUser() const { return GetStringValue("ORIGIN_USER"); } void RDLog::setOriginUser(const QString &user) const { SetRow("ORIGIN_USER",user); } QDateTime RDLog::originDatetime() const { return GetDatetimeValue("ORIGIN_DATETIME"); } void RDLog::setOriginDatetime(const QDateTime &datetime) const { SetRow("ORIGIN_DATETIME",datetime); } QDateTime RDLog::linkDatetime() const { return GetDatetimeValue("LINK_DATETIME"); } void RDLog::setLinkDatetime(const QDateTime &datetime) const { SetRow("LINK_DATETIME",datetime); } QDateTime RDLog::modifiedDatetime() const { return GetDatetimeValue("MODIFIED_DATETIME"); } void RDLog::setModifiedDatetime(const QDateTime &datetime) const { SetRow("MODIFIED_DATETIME",datetime); } bool RDLog::autoRefresh() const { return RDBool(GetStringValue("AUTO_REFRESH")); } void RDLog::setAutoRefresh(bool state) const { SetRow("AUTO_REFRESH",RDYesNo(state)); } unsigned RDLog::scheduledTracks() const { return GetUnsignedValue("SCHEDULED_TRACKS"); } void RDLog::setScheduledTracks(unsigned tracks) const { SetRow("SCHEDULED_TRACKS",tracks); } unsigned RDLog::completedTracks() const { return GetUnsignedValue("COMPLETED_TRACKS"); } void RDLog::setCompletedTracks(unsigned tracks) const { SetRow("COMPLETED_TRACKS",tracks); } bool RDLog::includeImportMarkers() const { return RDBool(GetStringValue("INCLUDE_IMPORT_MARKERS")); } void RDLog::setIncludeImportMarkers(bool state) { SetRow("INCLUDE_IMPORT_MARKERS",RDYesNo(state)); } int RDLog::linkQuantity(RDLog::Source src) const { switch(src) { case RDLog::SourceMusic: return GetIntValue("MUSIC_LINKS"); case RDLog::SourceTraffic: return GetIntValue("TRAFFIC_LINKS"); } return 0; } void RDLog::setLinkQuantity(RDLog::Source src,int quan) const { switch(src) { case RDLog::SourceMusic: SetRow("MUSIC_LINKS",quan); break; case RDLog::SourceTraffic: SetRow("TRAFFIC_LINKS",quan); break; } } void RDLog::updateLinkQuantity(RDLog::Source src) const { QString sql; RDSqlQuery *q; switch(src) { case RDLog::SourceMusic: sql=QString("select LINE_ID from LOG_LINES where ")+ "LOG_NAME=\""+RDEscapeString(log_name)+"\" && "+ QString().sprintf("TYPE=%d",RDLogLine::MusicLink); q=new RDSqlQuery(sql); sql=QString("update LOGS set ")+ QString().sprintf("MUSIC_LINKS=%d ",q->size())+ "where NAME=\""+RDEscapeString(log_name)+"\""; break; case RDLog::SourceTraffic: sql=QString("select LINE_ID from LOG_LINES where ")+ "LOG_NAME=\""+RDEscapeString(log_name)+"\" && "+ QString().sprintf("TYPE=%d",RDLogLine::TrafficLink); q=new RDSqlQuery(sql); sql=QString("update LOGS set ")+ QString().sprintf("TRAFFIC_LINKS=%d ",q->size())+ "where NAME=\""+RDEscapeString(log_name)+"\""; break; default: return; } delete q; q=new RDSqlQuery(sql); delete q; } RDLog::LinkState RDLog::linkState(RDLog::Source src) const { if(linkQuantity(src)==0) { return RDLog::LinkNotPresent; } switch(src) { case RDLog::SourceMusic: return (RDLog::LinkState)RDBool(GetStringValue("MUSIC_LINKED")); case RDLog::SourceTraffic: return (RDLog::LinkState)RDBool(GetStringValue("TRAFFIC_LINKED")); } return RDLog::LinkNotPresent; } void RDLog::setLinkState(RDLog::Source src,bool state) const { switch(src) { case RDLog::SourceMusic: SetRow("MUSIC_LINKED",RDYesNo(state)); break; case RDLog::SourceTraffic: SetRow("TRAFFIC_LINKED",RDYesNo(state)); break; } } int RDLog::nextId() const { return GetIntValue("NEXT_ID"); } void RDLog::setNextId(int id) const { SetRow("NEXT_ID",id); } bool RDLog::isReady() const { QString sql; RDSqlQuery *q; bool ret=false; sql=QString("select ")+ "MUSIC_LINKS,"+ // 00 "MUSIC_LINKED,"+ // 01 "TRAFFIC_LINKS,"+ // 02 "TRAFFIC_LINKED,"+ // 03 "SCHEDULED_TRACKS,"+ // 04 "COMPLETED_TRACKS "+ // 05 "from LOGS where "+ "NAME=\""+RDEscapeString(log_name)+"\""; q=new RDSqlQuery(sql); if(q->first()) { ret=((q->value(0).toInt()==0)||(q->value(1).toString()=="Y"))&& ((q->value(2).toInt()==0)||(q->value(3).toString()=="Y"))&& ((q->value(4).toInt()==0)||(q->value(4).toInt()==q->value(5).toInt())); } delete q; return ret; } bool RDLog::remove(RDStation *station,RDUser *user,RDConfig *config) const { QString sql; RDSqlQuery *q; if(removeTracks(station,user,config)<0) { return false; } sql=QString("delete from LOG_LINES where ")+ "LOG_NAME=\""+RDEscapeString(log_name)+"\""; RDSqlQuery::apply(sql); sql=QString("delete from LOGS where ")+ "NAME=\""+RDEscapeString(log_name)+"\" && "+ "TYPE=0"; q=new RDSqlQuery(sql); delete q; return true; } void RDLog::updateTracks() { QString sql; RDSqlQuery *q; unsigned scheduled=0; unsigned completed=0; sql=QString("select LOG_LINES.LINE_ID from ")+ "LOG_LINES left join CART "+ "on LOG_LINES.CART_NUMBER=CART.NUMBER where "+ "LOG_NAME=\""+RDEscapeString(log_name)+"\" && "+ "CART.OWNER is not null"; q=new RDSqlQuery(sql); completed=q->size(); delete q; sql=QString("select LINE_ID from LOG_LINES where ")+ "LOG_NAME=\""+RDEscapeString(log_name)+"\" && "+ QString().sprintf("TYPE=%d",RDLogLine::Track); q=new RDSqlQuery(sql); scheduled=q->size()+completed; delete q; sql=QString("update LOGS set ")+ QString().sprintf("SCHEDULED_TRACKS=%d,",scheduled)+ QString().sprintf("COMPLETED_TRACKS=%u where ",completed)+ "NAME=\""+RDEscapeString(log_name)+"\""; q=new RDSqlQuery(sql); delete q; } int RDLog::removeTracks(RDStation *station,RDUser *user,RDConfig *config) const { QString sql; RDSqlQuery *q; int count=0; RDCart *cart; QString owner=log_name; owner.replace(" ","_"); sql=QString("select NUMBER from CART where ")+ "OWNER=\""+RDEscapeString(owner)+"\""; q=new RDSqlQuery(sql); while(q->next()) { cart=new RDCart(q->value(0).toUInt()); if(!cart->remove(station,user,config)) { delete cart; return -1; } delete cart; count++; } delete q; return count; } RDLogEvent *RDLog::createLogEvent() const { return new RDLogEvent(name()); } QString RDLog::xml() const { QString sql; RDSqlQuery *q; QString ret; sql=QString("select ")+ "NAME,"+ // 00 "SERVICE,"+ // 01 "DESCRIPTION,"+ // 02 "ORIGIN_USER,"+ // 03 "ORIGIN_DATETIME,"+ // 04 "LINK_DATETIME,"+ // 05 "MODIFIED_DATETIME,"+ // 06 "PURGE_DATE,"+ // 07 "AUTO_REFRESH,"+ // 08 "START_DATE,"+ // 09 "END_DATE,"+ // 10 "SCHEDULED_TRACKS,"+ // 11 "COMPLETED_TRACKS,"+ // 12 "MUSIC_LINKS,"+ // 13 "MUSIC_LINKED,"+ // 14 "TRAFFIC_LINKS,"+ // 15 "TRAFFIC_LINKED,"+ // 16 "NEXT_ID "+ // 17 "from LOGS where NAME=\""+RDEscapeString(log_name)+"\""; q=new RDSqlQuery(sql); if(q->first()) { ret+=" \n"; ret+=" "+RDXmlField("name",log_name); ret+=" "+RDXmlField("serviceName",q->value(1).toString()); ret+=" "+RDXmlField("description",q->value(2).toString()); ret+=" "+RDXmlField("originUserName",q->value(3).toString()); ret+=" "+RDXmlField("originDatetime",q->value(4).toDateTime()); ret+=" "+RDXmlField("linkDatetime",q->value(5).toDateTime()); ret+=" "+RDXmlField("modifiedDatetime",q->value(6).toDateTime()); ret+=" "+RDXmlField("purgeDate",q->value(7).toDate()); ret+=" "+RDXmlField("autoRefresh",RDBool(q->value(8).toString())); ret+=" "+RDXmlField("startDate",q->value(9).toDate()); ret+=" "+RDXmlField("endDate",q->value(10).toDate()); ret+=" "+RDXmlField("scheduledTracks",q->value(11).toInt()); ret+=" "+RDXmlField("completedTracks",q->value(12).toInt()); ret+=" "+RDXmlField("musicLinks",q->value(13).toInt()); ret+=" "+RDXmlField("musicLinked",RDBool(q->value(14).toString())); ret+=" "+RDXmlField("trafficLinks",q->value(15).toInt()); ret+=" "+RDXmlField("trafficLinked",RDBool(q->value(16).toString())); ret+=" \n"; } delete q; return ret; } bool RDLog::create(const QString &name,const QString &svc_name, const QDate &air_date,const QString &user_name, QString *err_msg,RDConfig *config) { QString sql; RDSqlQuery *q; int shelflife=-1; RDSvc::ShelflifeOrigin shelforigin; QString desc_tmpl; sql=QString("select ")+ "DEFAULT_LOG_SHELFLIFE,"+ // 00 "LOG_SHELFLIFE_ORIGIN,"+ // 01 "DESCRIPTION_TEMPLATE "+ // 02 "from SERVICES where "+ "NAME=\""+RDEscapeString(svc_name)+"\""; q=new RDSqlQuery(sql); if(q->first()) { shelflife=q->value(0).toInt(); shelforigin=(RDSvc::ShelflifeOrigin)q->value(1).toInt(); desc_tmpl=q->value(2).toString(); } else { *err_msg=QObject::tr("No such service!"); delete q; return false; } delete q; sql=QString("insert into LOGS set ")+ "NAME=\""+RDEscapeString(name)+"\","+ "TYPE=0,"+ "DESCRIPTION=\""+RDEscapeString(name)+" log \","+ "ORIGIN_USER=\""+RDEscapeString(user_name)+"\","+ "ORIGIN_DATETIME=now(),"+ "MODIFIED_DATETIME=now(),"+ "LINK_DATETIME=now(),"+ "SERVICE=\""+RDEscapeString(svc_name)+"\""; if(shelflife>=0) { switch(shelforigin) { case RDSvc::OriginCreationDate: sql+=",PURGE_DATE=\""+ QDate::currentDate().addDays(shelflife).toString("yyyy-MM-dd")+"\""; break; case RDSvc::OriginAirDate: if(air_date.isValid()) { sql+=",PURGE_DATE=\""+ air_date.addDays(shelflife).toString("yyyy-MM-dd")+"\""; } break; } } q=new RDSqlQuery(sql); if(!q->isActive()) { *err_msg=QObject::tr("Log already exists!"); delete q; return false; } delete q; *err_msg=QObject::tr("OK"); return true; } bool RDLog::exists(const QString &name) { QString sql; RDSqlQuery *q; bool ret=false; sql=QString("select NAME from LOGS where NAME=\"")+ RDEscapeString(name)+"\""; q=new RDSqlQuery(sql); ret=q->first(); delete q; return ret; } bool RDLog::remove(const QString &name,RDStation *station,RDUser *user, RDConfig *config) { RDLog *log=new RDLog(name); bool ret=false; ret=log->remove(station,user,config); delete log; return ret; } int RDLog::GetIntValue(const QString &field) const { QString sql; RDSqlQuery *q; int accum; sql=QString("select ")+field+" from LOGS where "+ "NAME=\""+RDEscapeString(log_name)+"\""; q=new RDSqlQuery(sql); if(q->first()) { accum=q->value(0).toInt(); delete q; return accum; } delete q; return 0; } unsigned RDLog::GetUnsignedValue(const QString &field) const { QString sql; RDSqlQuery *q; unsigned accum; sql=QString("select ")+ field+" from LOGS where "+ "NAME=\""+RDEscapeString(log_name)+"\""; q=new RDSqlQuery(sql); if(q->first()) { accum=q->value(0).toUInt(); delete q; return accum; } delete q; return 0; } QString RDLog::GetStringValue(const QString &field) const { QString sql; RDSqlQuery *q; QString accum; sql=QString("select ")+ field+" from LOGS where "+ "NAME=\""+RDEscapeString(log_name)+"\""; q=new RDSqlQuery(sql); if(q->first()) { accum=q->value(0).toString(); } delete q; return accum; } QDate RDLog::GetDateValue(const QString &field) const { QString sql; RDSqlQuery *q; QDate accum; sql=QString("select ")+ field+" from LOGS where "+ "NAME=\""+RDEscapeString(log_name)+"\""; q=new RDSqlQuery(sql); if(q->first()) { accum=q->value(0).toDate(); delete q; return accum; } delete q; return QDate(); } QDateTime RDLog::GetDatetimeValue(const QString &field) const { QString sql; RDSqlQuery *q; QDateTime accum; sql=QString("select ")+ field+" from LOGS where "+ "NAME=\""+RDEscapeString(log_name)+"\""; q=new RDSqlQuery(sql); if(q->first()) { accum=q->value(0).toDateTime(); delete q; return accum; } delete q; return QDateTime(); } void RDLog::SetRow(const QString ¶m,int value) const { RDSqlQuery *q; QString sql; sql=QString("update LOGS set ")+ param+QString().sprintf("=%d where ",value)+ "NAME=\""+RDEscapeString(log_name)+"\""; q=new RDSqlQuery(sql); delete q; } void RDLog::SetRow(const QString ¶m,unsigned value) const { RDSqlQuery *q; QString sql; sql=QString("update LOGS set ")+ param+QString().sprintf("=%u where ",value)+ "NAME=\""+RDEscapeString(log_name)+"\""; q=new RDSqlQuery(sql); delete q; } void RDLog::SetRow(const QString ¶m,const QString &value) const { RDSqlQuery *q; QString sql; sql=QString("update LOGS set ")+ param+"=\""+RDEscapeString(value)+"\" where "+ "NAME=\""+RDEscapeString(log_name)+"\""; q=new RDSqlQuery(sql); delete q; } void RDLog::SetRow(const QString ¶m,const QDate &value) const { RDSqlQuery *q; QString sql; sql=QString("update LOGS set ")+ param+"="+RDCheckDateTime(value,"yyyy/MM/dd")+" where "+ "NAME=\""+RDEscapeString(log_name)+"\""; q=new RDSqlQuery(sql); delete q; } void RDLog::SetRow(const QString ¶m,const QDateTime &value) const { RDSqlQuery *q; QString sql; sql=QString("update LOGS set ")+ param+"="+RDCheckDateTime(value,"yyyy-MM-dd hh:mm:ss")+" where "+ "NAME=\""+RDEscapeString(log_name)+"\""; q=new RDSqlQuery(sql); delete q; }