mirror of
https://github.com/ElvishArtisan/rivendell.git
synced 2025-05-22 23:51:41 +02:00
2017-03-29 Fred Gleason <fredg@paravelsystems.com>
* Added a 'CUTS.SHA1_HASH' field to the database. * Incremented the database version to 261. * Added a 'Sha1' column to the Cut List in 'rdlibrary/audio_cart.cpp'. * Added 'RDCut::sha1Hash()' and 'RDCut::setSha1Hash()' methods in 'lib/rdcut.cpp' and 'lib/rdcut.h'. * Added a '--rehash=' directive to rddbcheck(8). * Added a 'Rehash' Web API call. * Added an 'RDRehash' class in 'lib/rdrehash.cpp' and 'lib/rdrehash.h'.
This commit is contained in:
parent
bc2c441680
commit
5dc6fa92a9
1
.gitignore
vendored
1
.gitignore
vendored
@ -79,6 +79,7 @@ tests/reserve_carts_test
|
||||
tests/sas_switch_torture
|
||||
tests/sas_torture
|
||||
tests/stringcode_test
|
||||
tests/test_hash
|
||||
tests/test_pam
|
||||
tests/timer_test
|
||||
tests/upload_test
|
||||
|
@ -15664,3 +15664,12 @@
|
||||
* Added a 'WebAPI Timeout' control to the Edit User dialog in
|
||||
'rdadmin/edit_user.cpp' and 'rdadmin/edit_user.h'.
|
||||
* Implemented a 'CreateTicket' Web API call.
|
||||
2017-03-29 Fred Gleason <fredg@paravelsystems.com>
|
||||
* Added a 'CUTS.SHA1_HASH' field to the database.
|
||||
* Incremented the database version to 261.
|
||||
* Added a 'Sha1' column to the Cut List in 'rdlibrary/audio_cart.cpp'.
|
||||
* Added 'RDCut::sha1Hash()' and 'RDCut::setSha1Hash()' methods in
|
||||
'lib/rdcut.cpp' and 'lib/rdcut.h'.
|
||||
* Added a '--rehash=' directive to rddbcheck(8).
|
||||
* Added a 'Rehash' Web API call.
|
||||
* Added an 'RDRehash' class in 'lib/rdrehash.cpp' and 'lib/rdrehash.h'.
|
||||
|
@ -2585,6 +2585,73 @@
|
||||
</table>
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<title>Rehash</title>
|
||||
<subtitle>Generate a SHA-1 hash for a cut and write it to the database</subtitle>
|
||||
<para>
|
||||
Command Code: <code>RDXPORT_COMMAND_REHASH</code>
|
||||
</para>
|
||||
<para>
|
||||
Required User Permissions: None
|
||||
</para>
|
||||
<table xml:id="ex.rehash" frame="all">
|
||||
<title>Rehash Call Fields</title>
|
||||
<tgroup cols="3" align="left" colsep="1" rowsep="1">
|
||||
<colspec colname="FIELD NAME" />
|
||||
<colspec colname="MEANING" />
|
||||
<colspec colname="REMARKS" />
|
||||
<thead>
|
||||
<row>
|
||||
<entry>
|
||||
FIELD NAME
|
||||
</entry>
|
||||
<entry>
|
||||
MEANING
|
||||
</entry>
|
||||
<entry>
|
||||
REMARKS
|
||||
</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>
|
||||
COMMAND
|
||||
</entry>
|
||||
<entry>
|
||||
32
|
||||
</entry>
|
||||
<entry>
|
||||
Mandatory
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
CART_NUMBER
|
||||
</entry>
|
||||
<entry>
|
||||
Number of cart
|
||||
</entry>
|
||||
<entry>
|
||||
Mandatory
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
CUT_NUMBER
|
||||
</entry>
|
||||
<entry>
|
||||
Number of cut
|
||||
</entry>
|
||||
<entry>
|
||||
Mandatory
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<title>RemoveCart</title>
|
||||
<subtitle>Remove a cart from the Library</subtitle>
|
||||
|
@ -14,6 +14,7 @@ DESCRIPTION char(64) Indexed
|
||||
OUTCUE char(64) Indexed
|
||||
ISRC char(12) International Standard Recording Code
|
||||
ISCI char(32) ISCI Code
|
||||
SHA1_HASH char(40)
|
||||
LENGTH int(10) unsigned Overall length in ms.
|
||||
ORIGIN_DATETIME datetime Date/Time when recorded
|
||||
START_DATETIME datetime
|
||||
|
@ -142,6 +142,7 @@ dist_librd_la_SOURCES = dbversion.h\
|
||||
rdgrid.cpp rdgrid.h\
|
||||
rdgroup.cpp rdgroup.h\
|
||||
rdgroup_list.cpp rdgroup_list.h\
|
||||
rdhash.cpp rdhas.h\
|
||||
rdhotkeys.cpp rdhotkeys.h\
|
||||
rdhotkeylist.cpp rdhotkeylist.h\
|
||||
rdidvalidator.cpp rdidvalidator.h\
|
||||
@ -192,6 +193,7 @@ dist_librd_la_SOURCES = dbversion.h\
|
||||
rdprofilesection.cpp rdprofilesection.h\
|
||||
rdpushbutton.cpp rdpushbutton.h\
|
||||
rdrecording.cpp rdrecording.h\
|
||||
rdrehash.cpp rdrehash.h\
|
||||
rdreplicator.cpp rdreplicator.h\
|
||||
rdreport.cpp rdreport.h\
|
||||
rdringbuffer.cpp rdringbuffer.h\
|
||||
@ -307,6 +309,7 @@ nodist_librd_la_SOURCES = moc_rdadd_cart.cpp\
|
||||
moc_rdschedcodes_dialog.cpp\
|
||||
moc_rdsegmeter.cpp\
|
||||
moc_rdsimpleplayer.cpp\
|
||||
moc_rdrehash.cpp\
|
||||
moc_rdslider.cpp\
|
||||
moc_rdsocket.cpp\
|
||||
moc_rdsound_panel.cpp\
|
||||
|
@ -24,7 +24,7 @@
|
||||
/*
|
||||
* Current Database Version
|
||||
*/
|
||||
#define RD_VERSION_DATABASE 260
|
||||
#define RD_VERSION_DATABASE 261
|
||||
|
||||
|
||||
#endif // DBVERSION_H
|
||||
|
@ -149,6 +149,7 @@ x11 {
|
||||
SOURCES += rdgpioselector.cpp
|
||||
SOURCES += rdgrid.cpp
|
||||
SOURCES += rdgroup.cpp
|
||||
SOURCES += rdhash.cpp
|
||||
SOURCES += rdimport_audio.cpp
|
||||
SOURCES += rdlist_groups.cpp
|
||||
SOURCES += rdlist_logs.cpp
|
||||
@ -160,6 +161,7 @@ x11 {
|
||||
SOURCES += rdpasswd.cpp
|
||||
SOURCES += rdplay_deck.cpp
|
||||
SOURCES += rdrecording.cpp
|
||||
SOURCES += rdrehash.cpp
|
||||
SOURCES += rdsimpleplayer.cpp
|
||||
SOURCES += rdsound_panel.cpp
|
||||
SOURCES += rdstatus.cpp
|
||||
@ -282,6 +284,7 @@ x11 {
|
||||
HEADERS += rdgrid.h
|
||||
HEADERS += rdgpio.h
|
||||
HEADERS += rdgroup.h
|
||||
HEADERS += rdhash.h
|
||||
HEADERS += rdimport_audio.h
|
||||
HEADERS += rdlist_groups.h
|
||||
HEADERS += rdlist_logs.h
|
||||
@ -294,6 +297,7 @@ x11 {
|
||||
HEADERS += rdpasswd.h
|
||||
HEADERS += rdplay_deck.h
|
||||
HEADERS += rdrecording.h
|
||||
HEADERS += rdrehash.h
|
||||
HEADERS += rdsimpleplayer.h
|
||||
HEADERS += rdsound_panel.h
|
||||
HEADERS += rdstatus.h
|
||||
|
@ -2113,6 +2113,33 @@ Zkuste to, prosím, znovu!</translation>
|
||||
<translation type="obsolete">Unbekanntes Audioformat</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>RDRehash</name>
|
||||
<message>
|
||||
<source>OK</source>
|
||||
<translation type="unfinished">OK</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Internal Error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Invalid URL</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>RDXport service returned an error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Invalid user or password</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Audio does not exist</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>RDReport</name>
|
||||
<message>
|
||||
|
@ -2104,6 +2104,33 @@ bitte erneut versuchen!</translation>
|
||||
<translation type="obsolete">Unbekanntes Audioformat</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>RDRehash</name>
|
||||
<message>
|
||||
<source>OK</source>
|
||||
<translation type="unfinished">OK</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Internal Error</source>
|
||||
<translation type="unfinished">Interner Fehler</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Invalid URL</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>RDXport service returned an error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Invalid user or password</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Audio does not exist</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>RDReport</name>
|
||||
<message>
|
||||
|
@ -2106,6 +2106,33 @@ please try again!</source>
|
||||
<translation type="obsolete">Formado desconocido</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>RDRehash</name>
|
||||
<message>
|
||||
<source>OK</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Internal Error</source>
|
||||
<translation type="unfinished">Error interno</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Invalid URL</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>RDXport service returned an error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Invalid user or password</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Audio does not exist</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>RDReport</name>
|
||||
<message>
|
||||
|
@ -1765,6 +1765,33 @@ please try again!</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>RDRehash</name>
|
||||
<message>
|
||||
<source>OK</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Internal Error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Invalid URL</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>RDXport service returned an error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Invalid user or password</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Audio does not exist</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>RDSoundPanel</name>
|
||||
<message>
|
||||
|
@ -2054,6 +2054,33 @@ prøv ein gong til!</translation>
|
||||
<translation type="obsolete">Last opp</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>RDRehash</name>
|
||||
<message>
|
||||
<source>OK</source>
|
||||
<translation type="unfinished">OK</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Internal Error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Invalid URL</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>RDXport service returned an error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Invalid user or password</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Audio does not exist</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>RDReport</name>
|
||||
<message>
|
||||
|
@ -2054,6 +2054,33 @@ prøv ein gong til!</translation>
|
||||
<translation type="obsolete">Last opp</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>RDRehash</name>
|
||||
<message>
|
||||
<source>OK</source>
|
||||
<translation type="unfinished">OK</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Internal Error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Invalid URL</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>RDXport service returned an error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Invalid user or password</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Audio does not exist</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>RDReport</name>
|
||||
<message>
|
||||
|
@ -2053,6 +2053,33 @@ por favor, tente novamente!</translation>
|
||||
<translation type="obsolete">Upload</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>RDRehash</name>
|
||||
<message>
|
||||
<source>OK</source>
|
||||
<translation type="unfinished">OK</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Internal Error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Invalid URL</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>RDXport service returned an error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Invalid user or password</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Audio does not exist</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>RDReport</name>
|
||||
<message>
|
||||
|
@ -256,6 +256,19 @@ void RDCut::setIsci(const QString &isci) const
|
||||
}
|
||||
|
||||
|
||||
QString RDCut::sha1Hash() const
|
||||
{
|
||||
return RDGetSqlValue("CUTS","CUT_NAME",cut_name,"SHA1_HASH",cut_db).
|
||||
toString();
|
||||
}
|
||||
|
||||
|
||||
void RDCut::setSha1Hash(const QString &str)
|
||||
{
|
||||
SetRow("SHA1_HASH",str);
|
||||
}
|
||||
|
||||
|
||||
unsigned RDCut::length() const
|
||||
{
|
||||
return RDGetSqlValue("CUTS","CUT_NAME",cut_name,"LENGTH",cut_db).
|
||||
@ -1169,6 +1182,7 @@ bool RDCut::checkInRecording(const QString &stationname,RDSettings *settings,
|
||||
QString sql;
|
||||
RDSqlQuery *q;
|
||||
int format;
|
||||
QString hash;
|
||||
|
||||
switch(settings->format()) {
|
||||
case RDSettings::MpegL2:
|
||||
|
@ -59,6 +59,8 @@ class RDCut
|
||||
void setIsrc(const QString &isrc) const;
|
||||
QString isci() const;
|
||||
void setIsci(const QString &isci) const;
|
||||
QString sha1Hash() const;
|
||||
void setSha1Hash(const QString &str);
|
||||
unsigned length() const;
|
||||
void setLength(int length) const;
|
||||
QDateTime originDatetime(bool *valid) const;
|
||||
|
59
lib/rdhash.cpp
Normal file
59
lib/rdhash.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
// rdhash.cpp
|
||||
//
|
||||
// Functions for generating hashes.
|
||||
//
|
||||
// (C) Copyright 2017 Fred Gleason <fredg@paravelsystems.com>
|
||||
//
|
||||
// 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 <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include "rdhash.h"
|
||||
|
||||
QString RDSha1Hash(const QString &filename,bool throttle)
|
||||
{
|
||||
QString ret;
|
||||
SHA_CTX ctx;
|
||||
int fd=-1;
|
||||
int n;
|
||||
char data[1024];
|
||||
unsigned char md[SHA_DIGEST_LENGTH];
|
||||
|
||||
if((fd=open(filename,O_RDONLY))<0) {
|
||||
return ret;
|
||||
}
|
||||
SHA1_Init(&ctx);
|
||||
while((n=read(fd,data,1024))>0) {
|
||||
SHA1_Update(&ctx,data,n);
|
||||
if(throttle) {
|
||||
usleep(1);
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
SHA1_Final(md,&ctx);
|
||||
ret="";
|
||||
for(int i=0;i<SHA_DIGEST_LENGTH;i++) {
|
||||
ret+=QString().sprintf("%02x",0xff&md[i]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
29
lib/rdhash.h
Normal file
29
lib/rdhash.h
Normal file
@ -0,0 +1,29 @@
|
||||
// rdhash.h
|
||||
//
|
||||
// Functions for generating hashes.
|
||||
//
|
||||
// (C) Copyright 2017 Fred Gleason <fredg@paravelsystems.com>
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef RDHASH_H
|
||||
#define RDHASH_H
|
||||
|
||||
#include <qstring.h>
|
||||
|
||||
QString RDSha1Hash(const QString &filename,bool throttle=false);
|
||||
|
||||
|
||||
#endif // RD_H
|
190
lib/rdrehash.cpp
Normal file
190
lib/rdrehash.cpp
Normal file
@ -0,0 +1,190 @@
|
||||
// rdrehash.cpp
|
||||
//
|
||||
// Generate a SHA-1 hash of an audio file and write it to the database.
|
||||
//
|
||||
// (C) Copyright 2017 Fred Gleason <fredg@paravelsystems.com>
|
||||
//
|
||||
// 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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include <qstringlist.h>
|
||||
|
||||
#include <rd.h>
|
||||
#include <rdxport_interface.h>
|
||||
#include <rdformpost.h>
|
||||
#include <rdrehash.h>
|
||||
|
||||
size_t __RDRehashCallback(void *ptr,size_t size,size_t nmemb,void *userdata)
|
||||
{
|
||||
return size*nmemb;
|
||||
}
|
||||
|
||||
|
||||
RDRehash::RDRehash(RDStation *station,RDConfig *config,QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
conv_station=station;
|
||||
conv_config=config;
|
||||
conv_cart_number=0;
|
||||
conv_cut_number=0;
|
||||
}
|
||||
|
||||
|
||||
void RDRehash::setCartNumber(unsigned cartnum)
|
||||
{
|
||||
conv_cart_number=cartnum;
|
||||
}
|
||||
|
||||
|
||||
void RDRehash::setCutNumber(unsigned cutnum)
|
||||
{
|
||||
conv_cut_number=cutnum;
|
||||
}
|
||||
|
||||
|
||||
RDRehash::ErrorCode RDRehash::runRehash(const QString &username,
|
||||
const QString &password)
|
||||
{
|
||||
long response_code;
|
||||
CURL *curl=NULL;
|
||||
char url[1024];
|
||||
CURLcode curl_err;
|
||||
|
||||
//
|
||||
// Generate POST Data
|
||||
//
|
||||
QString post=QString().sprintf("COMMAND=%d&LOGIN_NAME=%s&PASSWORD=%s&CART_NUMBER=%u&CUT_NUMBER=%u",
|
||||
RDXPORT_COMMAND_REHASH,
|
||||
(const char *)RDFormPost::urlEncode(username),
|
||||
(const char *)RDFormPost::urlEncode(password),
|
||||
conv_cart_number,
|
||||
conv_cut_number);
|
||||
if((curl=curl_easy_init())==NULL) {
|
||||
return RDRehash::ErrorInternal;
|
||||
}
|
||||
|
||||
//
|
||||
// Write out URL as a C string before passing to curl_easy_setopt(),
|
||||
// otherwise some versions of LibCurl will throw a 'bad/illegal format'
|
||||
// error.
|
||||
//
|
||||
strncpy(url,conv_station->webServiceUrl(conv_config),1024);
|
||||
curl_easy_setopt(curl,CURLOPT_URL,url);
|
||||
curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,__RDRehashCallback);
|
||||
curl_easy_setopt(curl,CURLOPT_POST,1);
|
||||
curl_easy_setopt(curl,CURLOPT_POSTFIELDS,(const char *)post);
|
||||
curl_easy_setopt(curl,CURLOPT_TIMEOUT,RD_CURL_TIMEOUT);
|
||||
|
||||
switch(curl_err=curl_easy_perform(curl)) {
|
||||
case CURLE_OK:
|
||||
break;
|
||||
|
||||
case CURLE_UNSUPPORTED_PROTOCOL:
|
||||
case CURLE_FAILED_INIT:
|
||||
case CURLE_COULDNT_RESOLVE_PROXY:
|
||||
case CURLE_PARTIAL_FILE:
|
||||
case CURLE_HTTP_RETURNED_ERROR:
|
||||
case CURLE_WRITE_ERROR:
|
||||
case CURLE_OUT_OF_MEMORY:
|
||||
case CURLE_OPERATION_TIMEDOUT:
|
||||
case CURLE_HTTP_POST_ERROR:
|
||||
curl_easy_cleanup(curl);
|
||||
fprintf(stderr,"curl error: %d\n",curl_err);
|
||||
return RDRehash::ErrorInternal;
|
||||
|
||||
case CURLE_URL_MALFORMAT:
|
||||
case CURLE_COULDNT_RESOLVE_HOST:
|
||||
case CURLE_COULDNT_CONNECT:
|
||||
case 9: // CURLE_REMOTE_ACCESS_DENIED
|
||||
curl_easy_cleanup(curl);
|
||||
return RDRehash::ErrorUrlInvalid;
|
||||
|
||||
default:
|
||||
curl_easy_cleanup(curl);
|
||||
return RDRehash::ErrorService;
|
||||
}
|
||||
curl_easy_getinfo(curl,CURLINFO_RESPONSE_CODE,&response_code);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
switch(response_code) {
|
||||
case 200:
|
||||
break;
|
||||
|
||||
case 404:
|
||||
return RDRehash::ErrorNoAudio;
|
||||
|
||||
default:
|
||||
return RDRehash::ErrorService;
|
||||
}
|
||||
return RDRehash::ErrorOk;
|
||||
}
|
||||
|
||||
|
||||
QString RDRehash::errorText(RDRehash::ErrorCode err)
|
||||
{
|
||||
QString ret=QString().sprintf("Unknown Error [%u]",err);
|
||||
|
||||
switch(err) {
|
||||
case RDRehash::ErrorOk:
|
||||
ret=tr("OK");
|
||||
break;
|
||||
|
||||
case RDRehash::ErrorInternal:
|
||||
ret=tr("Internal Error");
|
||||
break;
|
||||
|
||||
case RDRehash::ErrorUrlInvalid:
|
||||
ret=tr("Invalid URL");
|
||||
break;
|
||||
|
||||
case RDRehash::ErrorService:
|
||||
ret=tr("RDXport service returned an error");
|
||||
break;
|
||||
|
||||
case RDRehash::ErrorInvalidUser:
|
||||
ret=tr("Invalid user or password");
|
||||
break;
|
||||
|
||||
case RDRehash::ErrorNoAudio:
|
||||
ret=tr("Audio does not exist");
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
RDRehash::ErrorCode RDRehash::rehash(RDStation *station,RDUser *user,
|
||||
RDConfig *config,
|
||||
unsigned cartnum,int cutnum)
|
||||
{
|
||||
RDRehash::ErrorCode err;
|
||||
RDRehash *rehash=new RDRehash(station,config);
|
||||
|
||||
rehash->setCartNumber(cartnum);
|
||||
rehash->setCutNumber(cutnum);
|
||||
err=rehash->runRehash(user->name(),user->password());
|
||||
|
||||
delete rehash;
|
||||
return err;
|
||||
}
|
54
lib/rdrehash.h
Normal file
54
lib/rdrehash.h
Normal file
@ -0,0 +1,54 @@
|
||||
// rdrehash.h
|
||||
//
|
||||
// Generate a SHA-1 hash of an audio file and write it to the database.
|
||||
//
|
||||
// (C) Copyright 2017 Fred Gleason <fredg@paravelsystems.com>
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef RDREHASH_H
|
||||
#define RDREHASH_H
|
||||
|
||||
#include <qobject.h>
|
||||
|
||||
#include <rdconfig.h>
|
||||
#include <rdstation.h>
|
||||
#include <rduser.h>
|
||||
|
||||
class RDRehash : public QObject
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
enum ErrorCode {ErrorOk=0,ErrorInternal=5,ErrorUrlInvalid=7,
|
||||
ErrorService=8,ErrorInvalidUser=9,ErrorNoAudio=10};
|
||||
RDRehash(RDStation *station,RDConfig *config,QObject *parent=0);
|
||||
void setCartNumber(unsigned cartnum);
|
||||
void setCutNumber(unsigned cutnum);
|
||||
RDRehash::ErrorCode runRehash(const QString &username,
|
||||
const QString &password);
|
||||
static QString errorText(RDRehash::ErrorCode err);
|
||||
static RDRehash::ErrorCode rehash(RDStation *station,RDUser *user,
|
||||
RDConfig *config,
|
||||
unsigned cartnum,int cutnum);
|
||||
|
||||
private:
|
||||
RDStation *conv_station;
|
||||
RDConfig *conv_config;
|
||||
unsigned conv_cart_number;
|
||||
unsigned conv_cut_number;
|
||||
};
|
||||
|
||||
|
||||
#endif // RDREHASH_H
|
@ -52,6 +52,7 @@
|
||||
#define RDXPORT_COMMAND_ADDLOG 29
|
||||
#define RDXPORT_COMMAND_DELETELOG 30
|
||||
#define RDXPORT_COMMAND_CREATETICKET 31
|
||||
#define RDXPORT_COMMAND_REHASH 32
|
||||
|
||||
|
||||
#endif // RDXPORT_INTERFACE_H
|
||||
|
@ -763,6 +763,7 @@ bool CreateDb(QString name,QString pwd)
|
||||
ISRC char(12),\
|
||||
ISCI char(32),\
|
||||
LENGTH INT UNSIGNED,\
|
||||
SHA1_HASH char(40),\
|
||||
ORIGIN_DATETIME DATETIME,\
|
||||
START_DATETIME DATETIME,\
|
||||
END_DATETIME DATETIME,\
|
||||
@ -8346,6 +8347,20 @@ int UpdateDb(int ver)
|
||||
}
|
||||
}
|
||||
|
||||
if(ver<261) {
|
||||
sql=QString("alter table CUTS add column ")+
|
||||
"SHA1_HASH char(40) after LENGTH";
|
||||
if(!RunQuery(sql)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sql="create index SHA1_HASH_IDX on CUTS(SHA1_HASH)";
|
||||
if(!RunQuery(sql)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Update Version Field
|
||||
|
@ -43,6 +43,7 @@
|
||||
|
||||
#include <rddb.h>
|
||||
#include <rdconf.h>
|
||||
#include <rdhash.h>
|
||||
#include <rdurl.h>
|
||||
#include <rdwavefile.h>
|
||||
#include <rdcut.h>
|
||||
@ -2394,6 +2395,7 @@ void MainObject::CheckInRecording(QString cutname,CatchEvent *evt,
|
||||
s->setBitRate(evt->bitrate());
|
||||
s->setChannels(evt->channels());
|
||||
cut->checkInRecording(catch_config->stationName(),s,msecs);
|
||||
cut->setSha1Hash(RDSha1Hash(RDCut::pathName(cut->cutName())));
|
||||
delete s;
|
||||
cut->autoTrim(RDCut::AudioBoth,-threshold);
|
||||
RDCart *cart=new RDCart(cut->cartNumber());
|
||||
|
@ -174,6 +174,9 @@ AudioCart::AudioCart(AudioControls *controls,RDCart *cart,QString *path,
|
||||
rdcart_cut_list->addColumn(tr("NAME"));
|
||||
rdcart_cut_list->setColumnAlignment(11,Qt::AlignLeft);
|
||||
|
||||
rdcart_cut_list->addColumn(tr("SHA1"));
|
||||
rdcart_cut_list->setColumnAlignment(12,Qt::AlignLeft);
|
||||
|
||||
RefreshList();
|
||||
|
||||
//
|
||||
@ -810,6 +813,12 @@ void AudioCart::RefreshList()
|
||||
l->setText(10,tr("None"));
|
||||
}
|
||||
l->setText(11,q->value(9).toString());
|
||||
if(q->value(23).toString().isEmpty()) {
|
||||
l->setText(12,"["+tr("not available")+"]");
|
||||
}
|
||||
else {
|
||||
l->setText(12,q->value(23).toString());
|
||||
}
|
||||
total_length+=q->value(3).toUInt();
|
||||
pass++;
|
||||
}
|
||||
@ -908,6 +917,12 @@ void AudioCart::RefreshLine(RDListViewItem *item)
|
||||
item->setText(10,tr("None"));
|
||||
}
|
||||
item->setText(11,q->value(9).toString());
|
||||
if(q->value(23).toString().isEmpty()) {
|
||||
item->setText(12,"["+tr("not available")+"]");
|
||||
}
|
||||
else {
|
||||
item->setText(12,q->value(23).toString());
|
||||
}
|
||||
total_length+=q->value(3).toUInt();
|
||||
}
|
||||
if(q->size()>0) {
|
||||
|
@ -224,6 +224,14 @@ Do you still want to delete?</source>
|
||||
<source>ORD</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>SHA1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>not available</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>CdRipper</name>
|
||||
|
@ -224,6 +224,14 @@ Do you still want to delete?</source>
|
||||
<source>ORD</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>SHA1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>not available</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>CdRipper</name>
|
||||
|
@ -224,6 +224,14 @@ Do you still want to delete?</source>
|
||||
<source>ORD</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>SHA1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>not available</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>CdRipper</name>
|
||||
|
@ -202,6 +202,14 @@ Do you still want to delete?</source>
|
||||
<source>ORD</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>SHA1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>not available</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>CdRipper</name>
|
||||
|
@ -219,6 +219,14 @@ Do you still want to delete?</source>
|
||||
<source>ORD</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>SHA1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>not available</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>CdRipper</name>
|
||||
|
@ -219,6 +219,14 @@ Do you still want to delete?</source>
|
||||
<source>ORD</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>SHA1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>not available</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>CdRipper</name>
|
||||
|
@ -220,6 +220,14 @@ Do you still want to delete?</source>
|
||||
<source>ORD</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>SHA1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>not available</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>CdRipper</name>
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <rd.h>
|
||||
#include <rdconf.h>
|
||||
#include <rdmixer.h>
|
||||
#include <rdrehash.h>
|
||||
|
||||
#include <record_cut.h>
|
||||
#include <globals.h>
|
||||
@ -865,6 +866,8 @@ void RecordCut::recordUnloadedData(int card,int stream,unsigned len)
|
||||
s->setChannels(rec_channels);
|
||||
s->setFormat((RDSettings::Format)rec_format);
|
||||
rec_cut->checkInRecording(rdstation_conf->name(),s,len);
|
||||
RDRehash::rehash(rdstation_conf,lib_user,lib_config,rec_cut->cartNumber(),
|
||||
rec_cut->cutNumber());
|
||||
if(rec_trim_box->currentItem()==0) {
|
||||
rec_cut->autoTrim(RDCut::AudioBoth,rdlibrary_conf->trimThreshold());
|
||||
}
|
||||
|
@ -31,24 +31,25 @@ QString ValidateCutFields()
|
||||
"DESCRIPTION,"+ // 02
|
||||
"LENGTH,"+ // 03
|
||||
"LAST_PLAY_DATETIME,"+ // 04
|
||||
"PLAY_COUNTER,"+ // 03
|
||||
"ORIGIN_DATETIME,"+ // 04
|
||||
"ORIGIN_NAME,"+ // 05
|
||||
"OUTCUE,"+ // 06
|
||||
"CUT_NAME,"+ // 07
|
||||
"LENGTH,"+ // 08
|
||||
"EVERGREEN,"+ // 09
|
||||
"START_DATETIME,"+ // 10
|
||||
"END_DATETIME,"+ // 11
|
||||
"START_DAYPART,"+ // 12
|
||||
"END_DAYPART,"+ // 13
|
||||
"MON,"+ // 14
|
||||
"TUE,"+ // 15
|
||||
"WED,"+ // 16
|
||||
"THU,"+ // 17
|
||||
"FRI,"+ // 18
|
||||
"SAT,"+ // 19
|
||||
"SUN "+ // 20
|
||||
"PLAY_COUNTER,"+ // 05
|
||||
"ORIGIN_DATETIME,"+ // 06
|
||||
"ORIGIN_NAME,"+ // 07
|
||||
"OUTCUE,"+ // 08
|
||||
"CUT_NAME,"+ // 09
|
||||
"LENGTH,"+ // 10
|
||||
"EVERGREEN,"+ // 11
|
||||
"START_DATETIME,"+ // 12
|
||||
"END_DATETIME,"+ // 13
|
||||
"START_DAYPART,"+ // 14
|
||||
"END_DAYPART,"+ // 15
|
||||
"MON,"+ // 16
|
||||
"TUE,"+ // 17
|
||||
"WED,"+ // 18
|
||||
"THU,"+ // 19
|
||||
"FRI,"+ // 20
|
||||
"SAT,"+ // 21
|
||||
"SUN,"+ // 22
|
||||
"SHA1_HASH "+ // 23
|
||||
"from CUTS";
|
||||
|
||||
return sql;
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <rdlibrary_conf.h>
|
||||
#include <rdedit_audio.h>
|
||||
#include <rdimport_audio.h>
|
||||
#include <rdrehash.h>
|
||||
#include <rdwavedata.h>
|
||||
|
||||
#include <globals.h>
|
||||
@ -1873,6 +1874,9 @@ void VoiceTracker::recordUnloadedData(int card,int stream,unsigned msecs)
|
||||
if(!track_aborting) {
|
||||
edit_track_cuts[1]->
|
||||
checkInRecording(rdstation_conf->name(),edit_settings,msecs);
|
||||
RDRehash::rehash(rdstation_conf,rduser,log_config,
|
||||
edit_track_cuts[1]->cartNumber(),
|
||||
edit_track_cuts[1]->cutNumber());
|
||||
edit_track_cuts[1]->setSampleRate(rdsystem->sampleRate());
|
||||
edit_track_cart->updateLength();
|
||||
edit_track_cart->resetRotation();
|
||||
|
@ -38,6 +38,7 @@ noinst_PROGRAMS = audio_convert_test\
|
||||
sas_switch_torture\
|
||||
sas_torture\
|
||||
stringcode_test\
|
||||
test_hash\
|
||||
test_pam\
|
||||
timer_test\
|
||||
upload_test\
|
||||
@ -75,6 +76,9 @@ sas_torture_LDADD = @LIB_RDLIBS@ @LIBVORBIS@
|
||||
dist_stringcode_test_SOURCES = stringcode_test.cpp stringcode_test.h
|
||||
stringcode_test_LDADD = @LIB_RDLIBS@ @LIBVORBIS@
|
||||
|
||||
dist_test_hash_SOURCES = test_hash.cpp test_hash.h
|
||||
test_hash_LDADD = @LIB_RDLIBS@ @LIBVORBIS@
|
||||
|
||||
dist_test_pam_SOURCES = test_pam.cpp test_pam.h
|
||||
test_pam_LDADD = @LIB_RDLIBS@ @LIBVORBIS@
|
||||
|
||||
|
69
tests/test_hash.cpp
Normal file
69
tests/test_hash.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
// test_hash.cpp
|
||||
//
|
||||
// Test SHA1 hash generation
|
||||
//
|
||||
// (C) Copyright 2017 Fred Gleason <fredg@paravelsystems.com>
|
||||
//
|
||||
// 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 <qapplication.h>
|
||||
|
||||
#include <rdcmd_switch.h>
|
||||
#include <rdconfig.h>
|
||||
#include <rdcut.h>
|
||||
#include <rddb.h>
|
||||
#include <rdhash.h>
|
||||
|
||||
#include "test_hash.h"
|
||||
|
||||
MainObject::MainObject(QObject *parent)
|
||||
:QObject(parent)
|
||||
{
|
||||
QString filename="";
|
||||
|
||||
//
|
||||
// Read Command Options
|
||||
//
|
||||
RDCmdSwitch *cmd=
|
||||
new RDCmdSwitch(qApp->argc(),qApp->argv(),"test_hash",TEST_HASH_USAGE);
|
||||
for(unsigned i=0;i<cmd->keys();i++) {
|
||||
if(cmd->key(i)=="--filename") {
|
||||
filename=cmd->value(i);
|
||||
cmd->setProcessed(i,true);
|
||||
}
|
||||
}
|
||||
if(filename.isEmpty()) {
|
||||
fprintf(stderr,"test_hash: missing --filename\n");
|
||||
exit(256);
|
||||
}
|
||||
|
||||
QString hash=RDSha1Hash(filename);
|
||||
if(hash.isEmpty()) {
|
||||
fprintf(stderr,"test_hash: unable to open \"%s\"\n",
|
||||
(const char *)filename);
|
||||
exit(256);
|
||||
}
|
||||
printf("%s\n",(const char *)hash);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
QApplication a(argc,argv,false);
|
||||
new MainObject();
|
||||
return a.exec();
|
||||
}
|
36
tests/test_hash.h
Normal file
36
tests/test_hash.h
Normal file
@ -0,0 +1,36 @@
|
||||
// test_hash.h
|
||||
//
|
||||
// Test SHA1 hash generation
|
||||
//
|
||||
// (C) Copyright 2017 Fred Gleason <fredg@paravelsystems.com>
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef TEST_HASH_H
|
||||
#define TEST_HASH_H
|
||||
|
||||
#include <rdcmd_switch.cpp>
|
||||
#include <rdhash.h>
|
||||
|
||||
#define TEST_HASH_USAGE "[options]\n\nTest SHA1 has generation\n\n--filename=<file-name>\n The name of the file for which to generate a hash.\n\n"
|
||||
|
||||
class MainObject : public QObject
|
||||
{
|
||||
public:
|
||||
MainObject(QObject *parent=0);
|
||||
};
|
||||
|
||||
|
||||
#endif // TEST_HASH_H
|
@ -34,6 +34,7 @@
|
||||
#include <rd.h>
|
||||
#include <rddbcheck.h>
|
||||
#include <rdcart.h>
|
||||
#include <rdhash.h>
|
||||
#include <rdlog.h>
|
||||
#include <rdclock.h>
|
||||
#include <rdcreate_log.h>
|
||||
@ -81,6 +82,9 @@ MainObject::MainObject(QObject *parent)
|
||||
if(cmd->key(i)=="--dump-cuts-dir") {
|
||||
dump_cuts_dir=cmd->value(i);
|
||||
}
|
||||
if(cmd->key(i)=="--rehash") {
|
||||
rehash=cmd->value(i);
|
||||
}
|
||||
}
|
||||
if(check_yes&&check_no) {
|
||||
fprintf(stderr,"rddbcheck: '--yes' and '--no' are mutually exclusive\n");
|
||||
@ -171,6 +175,14 @@ MainObject::MainObject(QObject *parent)
|
||||
delete q;
|
||||
}
|
||||
|
||||
//
|
||||
// Rehash
|
||||
//
|
||||
if(!rehash.isEmpty()) {
|
||||
Rehash(rehash);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
//
|
||||
// Check for Orphaned Voice Tracks
|
||||
//
|
||||
@ -685,6 +697,95 @@ void MainObject::ValidateAudioLengths()
|
||||
}
|
||||
|
||||
|
||||
void MainObject::Rehash(const QString &arg)
|
||||
{
|
||||
QString sql;
|
||||
QSqlQuery *q;
|
||||
unsigned cartnum;
|
||||
bool ok=false;
|
||||
|
||||
if(arg.lower()=="all") {
|
||||
sql=QString("select NUMBER from CART where ")+
|
||||
QString().sprintf("TYPE=%d ",RDCart::Audio)+
|
||||
"order by NUMBER";
|
||||
q=new QSqlQuery(sql);
|
||||
while(q->next()) {
|
||||
RehashCart(q->value(0).toUInt());
|
||||
}
|
||||
delete q;
|
||||
return;
|
||||
}
|
||||
cartnum=arg.toUInt(&ok);
|
||||
if(ok&&(cartnum>0)&&(cartnum<=RD_MAX_CART_NUMBER)) {
|
||||
RehashCart(cartnum);
|
||||
return;
|
||||
}
|
||||
RDCut *cut=new RDCut(arg);
|
||||
if(cut->exists()) {
|
||||
RehashCut(arg);
|
||||
}
|
||||
delete cut;
|
||||
}
|
||||
|
||||
|
||||
void MainObject::RehashCart(unsigned cartnum)
|
||||
{
|
||||
RDCart *cart=new RDCart(cartnum);
|
||||
if(cart->exists()) {
|
||||
if(cart->type()==RDCart::Audio) {
|
||||
QString sql=QString("select CUT_NAME from CUTS where ")+
|
||||
QString().sprintf("CART_NUMBER=%u ",cartnum)+
|
||||
"order by CUT_NAME";
|
||||
QSqlQuery *q=new QSqlQuery(sql);
|
||||
while(q->next()) {
|
||||
RehashCut(q->value(0).toString());
|
||||
}
|
||||
delete q;
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf(" Cart %06u does not exist.\n",cartnum);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainObject::RehashCut(const QString &cutnum)
|
||||
{
|
||||
QString hash=RDSha1Hash(RDCut::pathName(cutnum),true);
|
||||
if(hash.isEmpty()) {
|
||||
printf(" Unable to generate hash for \"%s\"\n",
|
||||
(const char *)RDCut::pathName(cutnum));
|
||||
}
|
||||
else {
|
||||
RDCut *cut=new RDCut(cutnum);
|
||||
if(cut->exists()) {
|
||||
if(cut->sha1Hash().isEmpty()) {
|
||||
cut->setSha1Hash(hash);
|
||||
}
|
||||
else {
|
||||
if(cut->sha1Hash()!=hash) {
|
||||
RDCart *cart=new RDCart(RDCut::cartNumber(cutnum));
|
||||
printf(" Cut %d [%s] in cart %06u [%s] has inconsistent SHA1 hash. Correct? (y/N) ",
|
||||
cut->cutNumber(),
|
||||
(const char *)cut->description(),
|
||||
cart->number(),
|
||||
(const char *)cart->title());
|
||||
fflush(NULL);
|
||||
if(UserResponse()) {
|
||||
cut->setSha1Hash(hash);
|
||||
}
|
||||
delete cart;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf(" Cut \"%s\" does not exist.\n",(const char *)cutnum);
|
||||
}
|
||||
delete cut;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainObject::SetCutLength(const QString &cutname,int len)
|
||||
{
|
||||
QString sql;
|
||||
|
@ -31,7 +31,7 @@
|
||||
#include <rdcmd_switch.cpp>
|
||||
#include <rdstation.h>
|
||||
|
||||
#define RDDBCHECK_USAGE "[options]\n\nCheck the Rivendell database and audio store for consistency\nand correctness.\n\n--yes\n Answer all questions with 'yes'\n\n--no\n Answer all questions with 'no'\n\n--user=<username>\n Connect using the Rivendell user <username> (default is \"user\").\n\n--orphan-group=<group-name>\n Move carts with missing/invalid GROUP information to the <group-name>\n group.\n\n--dump-cuts-dir=<dir-name>\n Move orphaned cut audio to the <dir-name> directory.\n"
|
||||
#define RDDBCHECK_USAGE "[options]\n\nCheck the Rivendell database and audio store for consistency\nand correctness.\n\n--yes\n Answer all questions with 'yes'\n\n--no\n Answer all questions with 'no'\n\n--user=<username>\n Connect using the Rivendell user <username> (default is \"user\").\n\n--orphan-group=<group-name>\n Move carts with missing/invalid GROUP information to the <group-name>\n group.\n\n--dump-cuts-dir=<dir-name>\n Move orphaned cut audio to the <dir-name> directory.\n\n--rehash=<cartnum>/ALL"
|
||||
|
||||
//
|
||||
// Global Variables
|
||||
@ -54,6 +54,9 @@ class MainObject : public QObject
|
||||
void CheckOrphanedCuts();
|
||||
void CheckOrphanedAudio();
|
||||
void ValidateAudioLengths();
|
||||
void Rehash(const QString &arg);
|
||||
void RehashCart(unsigned cartnum);
|
||||
void RehashCut(const QString &cutnum);
|
||||
void SetCutLength(const QString &cutname,int len);
|
||||
void CleanTables(const QString &ext,QSqlQuery *table_q,QSqlQuery *name_q);
|
||||
void CleanTables(const QString &ext,QSqlQuery *table_q);
|
||||
@ -63,6 +66,7 @@ class MainObject : public QObject
|
||||
bool check_no;
|
||||
QString orphan_group_name;
|
||||
QString dump_cuts_dir;
|
||||
QString rehash;
|
||||
RDStation *check_station;
|
||||
RDUser *check_user;
|
||||
};
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
#include <rd.h>
|
||||
#include <rdconf.h>
|
||||
#include <rdrehash.h>
|
||||
#include <rdmaint.h>
|
||||
#include <rdlibrary_conf.h>
|
||||
#include <rdescape_string.h>
|
||||
@ -127,14 +128,16 @@ void MainObject::RunSystemMaintenance()
|
||||
QString sql;
|
||||
RDSqlQuery *q;
|
||||
|
||||
sql="update VERSION set LAST_MAINT_DATETIME=now()";
|
||||
q=new RDSqlQuery(sql);
|
||||
delete q;
|
||||
|
||||
PurgeCuts();
|
||||
PurgeLogs();
|
||||
PurgeElr();
|
||||
PurgeGpioEvents();
|
||||
PurgeWebapiAuths();
|
||||
sql="update VERSION set LAST_MAINT_DATETIME=now()";
|
||||
q=new RDSqlQuery(sql);
|
||||
delete q;
|
||||
RehashCuts();
|
||||
}
|
||||
|
||||
|
||||
@ -293,6 +296,36 @@ void MainObject::PurgeWebapiAuths()
|
||||
}
|
||||
|
||||
|
||||
void MainObject::RehashCuts()
|
||||
{
|
||||
QString sql;
|
||||
RDSqlQuery *q;
|
||||
RDRehash::ErrorCode err;
|
||||
|
||||
sql="select CUT_NAME from CUTS where SHA1_HASH is null limit 100";
|
||||
q=new RDSqlQuery(sql);
|
||||
while(q->next()) {
|
||||
printf("CUT: %s\n",(const char *)q->value(0).toString());
|
||||
if((err=RDRehash::rehash(maint_station,maint_user,maint_config,
|
||||
RDCut::cartNumber(q->value(0).toString()),
|
||||
RDCut::cutNumber(q->value(0).toString())))!=RDRehash::ErrorOk) {
|
||||
maint_config->
|
||||
log("rdmaint",
|
||||
RDConfig::LogErr,QString().sprintf("failed to rehash cut %s [%s]",
|
||||
(const char *)q->value(0).toString(),
|
||||
(const char *)RDRehash::errorText(err)));
|
||||
|
||||
}
|
||||
if(maint_verbose) {
|
||||
fprintf(stderr,"rehashed cut \"%s\"\n",
|
||||
(const char *)q->value(0).toString());
|
||||
}
|
||||
sleep(1);
|
||||
}
|
||||
delete q;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
QApplication a(argc,argv,false);
|
||||
|
@ -45,6 +45,7 @@ class MainObject : public QObject
|
||||
void PurgeDropboxes();
|
||||
void PurgeGpioEvents();
|
||||
void PurgeWebapiAuths();
|
||||
void RehashCuts();
|
||||
RDConfig *maint_config;
|
||||
bool maint_verbose;
|
||||
bool maint_system;
|
||||
|
@ -198,6 +198,10 @@ void MainObject::Revert(int schema) const
|
||||
case 260:
|
||||
Revert260();
|
||||
break;
|
||||
|
||||
case 261:
|
||||
Revert261();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -550,6 +554,19 @@ void MainObject::Revert260() const
|
||||
}
|
||||
|
||||
|
||||
void MainObject::Revert261() const
|
||||
{
|
||||
QString sql;
|
||||
QSqlQuery *q;
|
||||
|
||||
sql=QString("alter table CUTS drop column SHA1_HASH");
|
||||
q=new QSqlQuery(sql);
|
||||
delete q;
|
||||
|
||||
SetVersion(260);
|
||||
}
|
||||
|
||||
|
||||
int MainObject::GetVersion() const
|
||||
{
|
||||
QString sql;
|
||||
@ -592,7 +609,7 @@ int MainObject::MapSchema(const QString &ver)
|
||||
version_map["2.13"]=255;
|
||||
version_map["2.14"]=258;
|
||||
version_map["2.15"]=259;
|
||||
version_map["2.16"]=260;
|
||||
version_map["2.16"]=261;
|
||||
|
||||
//
|
||||
// Normalize String
|
||||
|
@ -56,6 +56,7 @@ class MainObject : public QObject
|
||||
void Revert258() const;
|
||||
void Revert259() const;
|
||||
void Revert260() const;
|
||||
void Revert261() const;
|
||||
int GetVersion() const;
|
||||
void SetVersion(int schema) const;
|
||||
int MapSchema(const QString &ver);
|
||||
|
@ -39,6 +39,7 @@ dist_rdxport_cgi_SOURCES = audioinfo.cpp\
|
||||
import.cpp\
|
||||
logs.cpp\
|
||||
rdxport.cpp rdxport.h\
|
||||
rehash.cpp\
|
||||
schedcodes.cpp\
|
||||
services.cpp\
|
||||
trimaudio.cpp
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <rdsettings.h>
|
||||
#include <rdconf.h>
|
||||
#include <rdgroup.h>
|
||||
#include <rdhash.h>
|
||||
#include <rdlibrary_conf.h>
|
||||
|
||||
#include <rdxport.h>
|
||||
@ -214,12 +215,15 @@ void Xport::Import()
|
||||
resp_code=400;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
delete conv;
|
||||
delete settings;
|
||||
delete conf;
|
||||
delete cut;
|
||||
delete cart;
|
||||
*/
|
||||
if(resp_code==200) {
|
||||
cut->setSha1Hash(RDSha1Hash(RDCut::pathName(cut->cutName())));
|
||||
printf("Content-type: application/xml\n");
|
||||
printf("Status: %d\n",resp_code);
|
||||
printf("\n");
|
||||
|
@ -264,6 +264,10 @@ Xport::Xport(QObject *parent)
|
||||
ListServices();
|
||||
break;
|
||||
|
||||
case RDXPORT_COMMAND_REHASH:
|
||||
Rehash();
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Content-type: text/html\n\n");
|
||||
printf("rdxport: missing/invalid command\n");
|
||||
|
@ -64,6 +64,7 @@ class Xport : public QObject
|
||||
void DeleteLog();
|
||||
void ListLogs();
|
||||
void ListLog();
|
||||
void Rehash();
|
||||
void SaveLog();
|
||||
void ListSchedCodes();
|
||||
void AssignSchedCode();
|
||||
|
65
web/rdxport/rehash.cpp
Normal file
65
web/rdxport/rehash.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
// rehash.cpp
|
||||
//
|
||||
// Rivendell web service portal -- Rehash service
|
||||
//
|
||||
// (C) Copyright 2017 Fred Gleason <fredg@paravelsystems.com>
|
||||
//
|
||||
// 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 <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <rdformpost.h>
|
||||
#include <rdlog_line.h>
|
||||
#include <rdweb.h>
|
||||
#include <rduser.h>
|
||||
#include <rdgroup.h>
|
||||
#include <rdconf.h>
|
||||
#include <rdescape_string.h>
|
||||
#include <rdcart_search_text.h>
|
||||
#include <rdhash.h>
|
||||
|
||||
#include <rdxport.h>
|
||||
|
||||
void Xport::Rehash()
|
||||
{
|
||||
int cart_number;
|
||||
int cut_number;
|
||||
|
||||
//
|
||||
// Verify Post
|
||||
//
|
||||
if(!xport_post->getValue("CART_NUMBER",&cart_number)) {
|
||||
XmlExit("Missing CART_NUMBER",400);
|
||||
}
|
||||
if(!xport_post->getValue("CUT_NUMBER",&cut_number)) {
|
||||
XmlExit("Missing CUT_NUMBER",400);
|
||||
}
|
||||
|
||||
//
|
||||
// Process Request
|
||||
//
|
||||
RDCut *cut=new RDCut(cart_number,cut_number);
|
||||
if(!cut->exists()) {
|
||||
delete cut;
|
||||
XmlExit("No such cut",404);
|
||||
}
|
||||
cut->setSha1Hash(RDSha1Hash(RDCut::pathName(cart_number,cut_number)));
|
||||
delete cut;
|
||||
XmlExit("OK",200);
|
||||
}
|
@ -50,6 +50,7 @@ install-exec-am:
|
||||
cp listlogs.html $(DESTDIR)@libexecdir@
|
||||
cp listschedcodes.html $(DESTDIR)@libexecdir@
|
||||
cp listservices.html $(DESTDIR)@libexecdir@
|
||||
cp rehash.html $(DESTDIR)@libexecdir@
|
||||
cp removecart.html $(DESTDIR)@libexecdir@
|
||||
cp removecut.html $(DESTDIR)@libexecdir@
|
||||
cp savelog.html $(DESTDIR)@libexecdir@
|
||||
@ -86,6 +87,7 @@ uninstall-local:
|
||||
rm -f $(DESTDIR)@libexecdir@/listlogs.html
|
||||
rm -f $(DESTDIR)@libexecdir@/listschedcodes.html
|
||||
rm -f $(DESTDIR)@libexecdir@/listservices.html
|
||||
rm -f $(DESTDIR)@libexecdir@/rehash.html
|
||||
rm -f $(DESTDIR)@libexecdir@/removecart.html
|
||||
rm -f $(DESTDIR)@libexecdir@/removecut.html
|
||||
rm -f $(DESTDIR)@libexecdir@/savelog.html
|
||||
@ -121,6 +123,7 @@ EXTRA_DIST = addcart.html\
|
||||
listlogs.html\
|
||||
listschedcodes.html\
|
||||
listservices.html\
|
||||
rehash.html\
|
||||
removecart.html\
|
||||
removecut.html\
|
||||
savelog.html\
|
||||
|
37
web/tests/rehash.html
Normal file
37
web/tests/rehash.html
Normal file
@ -0,0 +1,37 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Rivendell REHASH Service Test Harness</title>
|
||||
<body>
|
||||
<form action="/rd-bin/rdxport.cgi" method="post" enctype="multipart/form-data">
|
||||
<input type="hidden" name="COMMAND" value="32">
|
||||
<table cellpadding="0" cellspacing="2" border="0">
|
||||
<tr>
|
||||
<td align="right">LOGIN NAME:</td>
|
||||
<td><input type="text" name="LOGIN_NAME" size="20" maxlength="255"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">PASSWORD:</td>
|
||||
<td><input type="password" name="PASSWORD" size="20" maxlength="32"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">TICKET:</td>
|
||||
<td><input type="text" name="TICKET" size="40" maxlength="40"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">CART NUMBER:</td>
|
||||
<td><input type="text" name="CART_NUMBER" size="20" maxlength="6"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">CUT NUMBER:</td>
|
||||
<td><input type="text" name="CUT_NUMBER" size="20" maxlength="3"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" align="right"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" align="right"><input type="submit" value="OK"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
Loading…
x
Reference in New Issue
Block a user