mirror of
https://github.com/ElvishArtisan/rivendell.git
synced 2025-04-09 22:43:11 +02:00
2020-09-21 Fred Gleason <fredg@paravelsystems.com>
* Added a 'PODCASTS.SHA1_HASH' field to the database. * Incremented the database version to 335. * Added 'RDPodcast::sha1Hash()' and 'RDPodcast::setSha1Hash()' methods. * Implemented audio relinking for podcast media files. Signed-off-by: Fred Gleason <fredg@paravelsystems.com>
This commit is contained in:
parent
6516c20ff6
commit
6d3a60d174
@ -20285,3 +20285,9 @@
|
||||
* Added a 'SavePodcast' method to the Web API.
|
||||
* Added a 'GetPodcast' method to the Web API.
|
||||
* Added a 'DeletePodcast' method to the Web API.
|
||||
2020-09-21 Fred Gleason <fredg@paravelsystems.com>
|
||||
* Added a 'PODCASTS.SHA1_HASH' field to the database.
|
||||
* Incremented the database version to 335.
|
||||
* Added 'RDPodcast::sha1Hash()' and 'RDPodcast::setSha1Hash()'
|
||||
methods.
|
||||
* Implemented audio relinking for podcast media files.
|
||||
|
@ -20,6 +20,7 @@ ITEM_IMAGE_ID int(11) From FEED_IMAGES.ID
|
||||
AUDIO_FILENAME varchar(191)
|
||||
AUDIO_LENGTH int(10) unsigned
|
||||
AUDIO_TIME int(10) unsigned
|
||||
SHA1_HASH varchar(40)
|
||||
ORIGIN_LOGIN_NAME varchar(191) From USERS.LOGIN_NAME
|
||||
ORIGIN_STATION varchar(64) From STATIONS.NAME
|
||||
ORIGIN_DATETIME datetime
|
||||
|
@ -24,7 +24,7 @@
|
||||
/*
|
||||
* Current Database Version
|
||||
*/
|
||||
#define RD_VERSION_DATABASE 334
|
||||
#define RD_VERSION_DATABASE 335
|
||||
|
||||
|
||||
#endif // DBVERSION_H
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "rdtempdirectory.h"
|
||||
#include "rdupload.h"
|
||||
#include "rdwavefile.h"
|
||||
#include "rdxport_interface.h"
|
||||
|
||||
size_t __RDFeed_Readfunction_Callback(char *buffer,size_t size,size_t nitems,
|
||||
void *userdata)
|
||||
@ -1093,6 +1094,11 @@ unsigned RDFeed::postCut(const QString &cutname,Error *err)
|
||||
return 0;
|
||||
}
|
||||
emit postProgressChanged(3);
|
||||
|
||||
//
|
||||
// Save to Audio Store
|
||||
//
|
||||
SavePodcast(cast_id,tmpfile);
|
||||
unlink(tmpfile);
|
||||
delete upload;
|
||||
|
||||
@ -1225,6 +1231,10 @@ unsigned RDFeed::postFile(const QString &srcfile,Error *err)
|
||||
}
|
||||
delete upload;
|
||||
|
||||
//
|
||||
// Save to Audio Store
|
||||
//
|
||||
SavePodcast(cast_id,tmpfile);
|
||||
unlink(QString(tmpfile)+".wav");
|
||||
unlink(tmpfile);
|
||||
|
||||
@ -1349,6 +1359,10 @@ unsigned RDFeed::postLog(const QString &logname,const QTime &start_time,
|
||||
|
||||
emit postProgressChanged(2+log_event->size());
|
||||
|
||||
//
|
||||
// Save to Audio Store
|
||||
//
|
||||
SavePodcast(cast_id,tmpfile);
|
||||
unlink(tmpfile);
|
||||
|
||||
//
|
||||
@ -1673,6 +1687,80 @@ void RDFeed::renderLineStartedData(int lineno,int total_lines)
|
||||
}
|
||||
|
||||
|
||||
bool RDFeed::SavePodcast(unsigned cast_id,const QString &src_filename) const
|
||||
{
|
||||
long response_code;
|
||||
CURL *curl=NULL;
|
||||
CURLcode curl_err;
|
||||
struct curl_httppost *first=NULL;
|
||||
struct curl_httppost *last=NULL;
|
||||
|
||||
//
|
||||
// Generate POST Data
|
||||
//
|
||||
// We have to use multipart here because we have a file to send.
|
||||
//
|
||||
curl_formadd(&first,&last,CURLFORM_PTRNAME,"COMMAND",
|
||||
CURLFORM_COPYCONTENTS,
|
||||
(const char *)QString().sprintf("%u",RDXPORT_COMMAND_SAVE_PODCAST),
|
||||
CURLFORM_END);
|
||||
curl_formadd(&first,&last,CURLFORM_PTRNAME,"LOGIN_NAME",
|
||||
CURLFORM_COPYCONTENTS,rda->user()->name().toUtf8().constData(),
|
||||
CURLFORM_END);
|
||||
curl_formadd(&first,&last,CURLFORM_PTRNAME,"PASSWORD",
|
||||
CURLFORM_COPYCONTENTS,
|
||||
rda->user()->password().toUtf8().constData(),CURLFORM_END);
|
||||
curl_formadd(&first,&last,CURLFORM_PTRNAME,"ID",
|
||||
CURLFORM_COPYCONTENTS,
|
||||
(const char *)QString().sprintf("%u",cast_id),
|
||||
CURLFORM_END);
|
||||
curl_formadd(&first,&last,CURLFORM_PTRNAME,"FILENAME",
|
||||
CURLFORM_FILE,src_filename.toUtf8().constData(),
|
||||
CURLFORM_END);
|
||||
|
||||
//
|
||||
// Set up the transfer
|
||||
//
|
||||
if((curl=curl_easy_init())==NULL) {
|
||||
curl_formfree(first);
|
||||
return false;
|
||||
}
|
||||
curl_easy_setopt(curl,CURLOPT_WRITEDATA,stdout);
|
||||
curl_easy_setopt(curl,CURLOPT_HTTPPOST,first);
|
||||
curl_easy_setopt(curl,CURLOPT_USERAGENT,
|
||||
(const char *)rda->config()->userAgent());
|
||||
curl_easy_setopt(curl,CURLOPT_TIMEOUT,RD_CURL_TIMEOUT);
|
||||
curl_easy_setopt(curl,CURLOPT_NOPROGRESS,1);
|
||||
curl_easy_setopt(curl,CURLOPT_URL,
|
||||
rda->station()->webServiceUrl(rda->config()).toUtf8().constData());
|
||||
|
||||
//
|
||||
// Send it
|
||||
//
|
||||
if((curl_err=curl_easy_perform(curl))!=CURLE_OK) {
|
||||
curl_easy_cleanup(curl);
|
||||
curl_formfree(first);
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Clean up
|
||||
//
|
||||
curl_easy_getinfo(curl,CURLINFO_RESPONSE_CODE,&response_code);
|
||||
curl_easy_cleanup(curl);
|
||||
curl_formfree(first);
|
||||
|
||||
//
|
||||
// Process the results
|
||||
//
|
||||
if((response_code<200)||(response_code>299)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
unsigned RDFeed::CreateCast(QString *filename,int bytes,int msecs) const
|
||||
{
|
||||
QString sql;
|
||||
|
@ -160,6 +160,7 @@ class RDFeed : public QObject
|
||||
void renderLineStartedData(int lineno,int total_lines);
|
||||
|
||||
private:
|
||||
bool SavePodcast(unsigned cast_id,const QString &src_filename) const;
|
||||
unsigned CreateCast(QString *filename,int bytes,int msecs) const;
|
||||
QString ResolveChannelWildcards(const QString &tmplt,RDSqlQuery *chan_q,
|
||||
const QDateTime &build_datetime);
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "rdescape_string.h"
|
||||
#include "rdpodcast.h"
|
||||
#include "rdurl.h"
|
||||
#include "rdxport_interface.h"
|
||||
|
||||
//
|
||||
// CURL Callbacks
|
||||
@ -317,6 +318,18 @@ int RDPodcast::audioTime() const
|
||||
}
|
||||
|
||||
|
||||
QString RDPodcast::sha1Hash() const
|
||||
{
|
||||
return RDGetSqlValue("PODCASTS","ID",podcast_id,"SHA1_HASH").toString();
|
||||
}
|
||||
|
||||
|
||||
void RDPodcast::setSha1Hash(const QString &str) const
|
||||
{
|
||||
SetRow("SHA1_HASH",str);
|
||||
}
|
||||
|
||||
|
||||
void RDPodcast::setAudioTime(int msecs) const
|
||||
{
|
||||
SetRow("AUDIO_TIME",msecs);
|
||||
@ -367,6 +380,11 @@ bool RDPodcast::removeAudio(RDFeed *feed,QString *err_text,bool log_debug) const
|
||||
*err_text=RDDelete::errorText(conv_err);
|
||||
delete conv;
|
||||
|
||||
//
|
||||
// Delete from Audio Store
|
||||
//
|
||||
DeletePodcast(id());
|
||||
|
||||
return conv_err==RDDelete::ErrorOk;
|
||||
}
|
||||
|
||||
@ -385,29 +403,101 @@ QString RDPodcast::guid(const QString &full_url,unsigned feed_id,
|
||||
}
|
||||
|
||||
|
||||
bool RDPodcast::DeletePodcast(unsigned cast_id) const
|
||||
{
|
||||
long response_code;
|
||||
CURL *curl=NULL;
|
||||
CURLcode curl_err;
|
||||
struct curl_httppost *first=NULL;
|
||||
struct curl_httppost *last=NULL;
|
||||
|
||||
//
|
||||
// Generate POST Data
|
||||
//
|
||||
curl_formadd(&first,&last,CURLFORM_PTRNAME,"COMMAND",
|
||||
CURLFORM_COPYCONTENTS,
|
||||
(const char *)QString().sprintf("%u",RDXPORT_COMMAND_DELETE_PODCAST),
|
||||
CURLFORM_END);
|
||||
curl_formadd(&first,&last,CURLFORM_PTRNAME,"LOGIN_NAME",
|
||||
CURLFORM_COPYCONTENTS,rda->user()->name().toUtf8().constData(),
|
||||
CURLFORM_END);
|
||||
curl_formadd(&first,&last,CURLFORM_PTRNAME,"PASSWORD",
|
||||
CURLFORM_COPYCONTENTS,
|
||||
rda->user()->password().toUtf8().constData(),CURLFORM_END);
|
||||
curl_formadd(&first,&last,CURLFORM_PTRNAME,"ID",
|
||||
CURLFORM_COPYCONTENTS,
|
||||
(const char *)QString().sprintf("%u",cast_id),
|
||||
CURLFORM_END);
|
||||
|
||||
//
|
||||
// Set up the transfer
|
||||
//
|
||||
if((curl=curl_easy_init())==NULL) {
|
||||
curl_formfree(first);
|
||||
return false;
|
||||
}
|
||||
curl_easy_setopt(curl,CURLOPT_WRITEDATA,stdout);
|
||||
curl_easy_setopt(curl,CURLOPT_HTTPPOST,first);
|
||||
curl_easy_setopt(curl,CURLOPT_USERAGENT,
|
||||
(const char *)rda->config()->userAgent());
|
||||
curl_easy_setopt(curl,CURLOPT_TIMEOUT,RD_CURL_TIMEOUT);
|
||||
curl_easy_setopt(curl,CURLOPT_NOPROGRESS,1);
|
||||
curl_easy_setopt(curl,CURLOPT_URL,
|
||||
rda->station()->webServiceUrl(rda->config()).toUtf8().constData());
|
||||
|
||||
//
|
||||
// Send it
|
||||
//
|
||||
if((curl_err=curl_easy_perform(curl))!=CURLE_OK) {
|
||||
curl_easy_cleanup(curl);
|
||||
curl_formfree(first);
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Clean up
|
||||
//
|
||||
curl_easy_getinfo(curl,CURLINFO_RESPONSE_CODE,&response_code);
|
||||
curl_easy_cleanup(curl);
|
||||
curl_formfree(first);
|
||||
|
||||
//
|
||||
// Process the results
|
||||
//
|
||||
if((response_code<200)||(response_code>299)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void RDPodcast::SetRow(const QString ¶m,int value) const
|
||||
{
|
||||
RDSqlQuery *q;
|
||||
QString sql;
|
||||
|
||||
sql=QString("update PODCASTS set ")+
|
||||
param+QString().sprintf("=%d where ",value)+
|
||||
QString().sprintf("ID=%u",podcast_id);
|
||||
q=new RDSqlQuery(sql);
|
||||
delete q;
|
||||
RDSqlQuery::apply(sql);
|
||||
}
|
||||
|
||||
|
||||
void RDPodcast::SetRow(const QString ¶m,const QString &value) const
|
||||
{
|
||||
RDSqlQuery *q;
|
||||
QString sql;
|
||||
|
||||
sql=QString("update PODCASTS set ")+
|
||||
param+"=\""+RDEscapeString(value)+"\" where "+
|
||||
QString().sprintf("ID=%u",podcast_id);
|
||||
q=new RDSqlQuery(sql);
|
||||
delete q;
|
||||
if(value.isNull()) {
|
||||
sql=QString("update PODCASTS set ")+
|
||||
param+"=NULL where "+
|
||||
QString().sprintf("ID=%u",podcast_id);
|
||||
}
|
||||
else {
|
||||
sql=QString("update PODCASTS set ")+
|
||||
param+"=\""+RDEscapeString(value)+"\" where "+
|
||||
QString().sprintf("ID=%u",podcast_id);
|
||||
}
|
||||
RDSqlQuery::apply(sql);
|
||||
}
|
||||
|
||||
|
||||
|
@ -68,6 +68,8 @@ class RDPodcast
|
||||
void setAudioLength(int len) const;
|
||||
int audioTime() const;
|
||||
void setAudioTime(int msecs) const;
|
||||
QString sha1Hash() const;
|
||||
void setSha1Hash(const QString &str=QString()) const;
|
||||
QDateTime expirationDateTime() const;
|
||||
void setExpirationDateTime(const QDateTime &dt) const;
|
||||
RDPodcast::Status status() const;
|
||||
@ -79,6 +81,7 @@ class RDPodcast
|
||||
unsigned feed_id,unsigned cast_id);
|
||||
|
||||
private:
|
||||
bool DeletePodcast(unsigned cast_id) const;
|
||||
void SetRow(const QString ¶m,int value) const;
|
||||
void SetRow(const QString ¶m,const QString &value) const;
|
||||
void SetRow(const QString ¶m,const QDateTime &datetime,const QString &value) const;
|
||||
|
@ -389,60 +389,42 @@ void MainObject::RelinkAudio(const QString &srcdir) const
|
||||
QString hash=RDSha1Hash(filename);
|
||||
QString firstdest;
|
||||
bool delete_source=true;
|
||||
|
||||
//
|
||||
// Check against audio cuts
|
||||
//
|
||||
sql=QString("select CUTS.CUT_NAME,CART.TITLE from ")+
|
||||
"CUTS left join CART "+
|
||||
"on CUTS.CART_NUMBER=CART.NUMBER where "+
|
||||
"CUTS.SHA1_HASH=\""+RDEscapeString(hash)+"\"";
|
||||
q=new RDSqlQuery(sql);
|
||||
while(q->next()) {
|
||||
printf(" Recovering %06u/%03d [%s]...",
|
||||
RDCut::cartNumber(q->value(0).toString()),
|
||||
RDCut::cutNumber(q->value(0).toString()),
|
||||
(const char *)q->value(1).toString());
|
||||
fflush(stdout);
|
||||
if(db_relink_audio_move) {
|
||||
unlink(RDCut::pathName(q->value(0).toString()));
|
||||
if(link(filename,RDCut::pathName(q->value(0).toString()))<0) {
|
||||
if(errno==EXDEV) {
|
||||
if(firstdest.isEmpty()) {
|
||||
if(CopyFile(RDCut::pathName(q->value(0).toString()),filename)) {
|
||||
firstdest=RDCut::pathName(q->value(0).toString());
|
||||
}
|
||||
else {
|
||||
fprintf(stderr,"unable to copy file \"%s\"\n",
|
||||
(const char *)filename);
|
||||
delete_source=false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
unlink(RDCut::pathName(q->value(0).toString()));
|
||||
link(firstdest,RDCut::pathName(q->value(0).toString()));
|
||||
}
|
||||
}
|
||||
else {
|
||||
fprintf(stderr,"unable to move file \"%s\" [%s]\n",
|
||||
(const char *)filename,strerror(errno));
|
||||
delete_source=false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(firstdest.isEmpty()) {
|
||||
if(CopyFile(RDCut::pathName(q->value(0).toString()),filename)) {
|
||||
firstdest=RDCut::pathName(q->value(0).toString());
|
||||
}
|
||||
else {
|
||||
fprintf(stderr,"unable to copy file \"%s\"\n",
|
||||
(const char *)filename);
|
||||
}
|
||||
}
|
||||
else {
|
||||
unlink(RDCut::pathName(q->value(0).toString()));
|
||||
link(firstdest,RDCut::pathName(q->value(0).toString()));
|
||||
}
|
||||
}
|
||||
printf(" done.\n");
|
||||
RelinkCut(filename,q->value(0).toString(),q->value(1).toString(),
|
||||
&firstdest,&delete_source);
|
||||
}
|
||||
|
||||
//
|
||||
// Check against RSS posts
|
||||
//
|
||||
sql=QString("select ")+
|
||||
"FEEDS.KEY_NAME,"+ // 00
|
||||
"PODCASTS.ID,"+ // 01
|
||||
"PODCASTS.ITEM_TITLE,"+ // 02
|
||||
"PODCASTS.AUDIO_FILENAME "+ // 03
|
||||
"from PODCASTS left join FEEDS "+
|
||||
"on FEEDS.ID=PODCASTS.FEED_ID where "+
|
||||
"PODCASTS.SHA1_HASH=\""+RDEscapeString(hash)+"\"";
|
||||
q=new RDSqlQuery(sql);
|
||||
while(q->next()) {
|
||||
RelinkCast(filename,q->value(0).toString(),q->value(1).toUInt(),
|
||||
q->value(2).toString(),q->value(3).toString(),
|
||||
&firstdest,&delete_source);
|
||||
}
|
||||
delete q;
|
||||
|
||||
//
|
||||
// (Perhaps) delete the source file
|
||||
//
|
||||
if(db_relink_audio_move&&delete_source) {
|
||||
unlink(filename);
|
||||
}
|
||||
@ -450,6 +432,125 @@ void MainObject::RelinkAudio(const QString &srcdir) const
|
||||
}
|
||||
|
||||
|
||||
void MainObject::RelinkCut(const QString &src_filename,const QString &cutname,
|
||||
const QString &title,
|
||||
QString *firstdest,bool *delete_src) const
|
||||
{
|
||||
printf(" Recovering %06u/%03d [%s]...",
|
||||
RDCut::cartNumber(cutname),RDCut::cutNumber(cutname),
|
||||
title.toUtf8().constData());
|
||||
fflush(stdout);
|
||||
|
||||
if(db_relink_audio_move) {
|
||||
unlink(RDCut::pathName(cutname));
|
||||
if(link(src_filename,RDCut::pathName(cutname))<0) {
|
||||
if(errno==EXDEV) { // We're crossing filesystems, so do a copy
|
||||
if(firstdest->isEmpty()) {
|
||||
if(CopyToAudioStore(RDCut::pathName(cutname),src_filename)) {
|
||||
*firstdest=RDCut::pathName(cutname);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr,"unable to copy file \"%s\"\n",
|
||||
(const char *)src_filename);
|
||||
*delete_src=false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
unlink(RDCut::pathName(cutname));
|
||||
link(*firstdest,RDCut::pathName(cutname));
|
||||
}
|
||||
}
|
||||
else {
|
||||
fprintf(stderr,"unable to move file \"%s\" [%s]\n",
|
||||
(const char *)src_filename,strerror(errno));
|
||||
*delete_src=false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
chown(RDCut::pathName(cutname),db_config->uid(),db_config->gid());
|
||||
chmod(RDCut::pathName(cutname),S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(firstdest->isEmpty()) {
|
||||
if(CopyToAudioStore(RDCut::pathName(cutname),src_filename)) {
|
||||
*firstdest=RDCut::pathName(cutname);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr,"unable to copy file \"%s\"\n",
|
||||
(const char *)src_filename);
|
||||
}
|
||||
}
|
||||
else {
|
||||
unlink(RDCut::pathName(cutname));
|
||||
link(*firstdest,RDCut::pathName(cutname));
|
||||
}
|
||||
}
|
||||
printf(" done.\n");
|
||||
}
|
||||
|
||||
|
||||
void MainObject::RelinkCast(const QString &src_filename,const QString &keyname,
|
||||
unsigned cast_id,const QString &title,
|
||||
const QString &audio_filename,
|
||||
QString *firstdest,bool *delete_src) const
|
||||
{
|
||||
QString destpath=QString(RD_AUDIO_ROOT)+"/"+audio_filename;
|
||||
|
||||
printf(" Recovering RSS item %s:%u [%s]...",
|
||||
keyname.toUtf8().constData(),cast_id,title.toUtf8().constData());
|
||||
fflush(stdout);
|
||||
|
||||
if(db_relink_audio_move) {
|
||||
unlink(destpath);
|
||||
if(link(src_filename,destpath)<0) {
|
||||
if(errno==EXDEV) { // We're crossing filesystems, so do a copy
|
||||
if(firstdest->isEmpty()) {
|
||||
if(CopyToAudioStore(destpath,src_filename)) {
|
||||
*firstdest=destpath;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr,"unable to copy file \"%s\"\n",
|
||||
(const char *)src_filename);
|
||||
*delete_src=false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
unlink(destpath);
|
||||
link(*firstdest,destpath);
|
||||
}
|
||||
}
|
||||
else {
|
||||
fprintf(stderr,"unable to move file \"%s\" [%s]\n",
|
||||
(const char *)src_filename,strerror(errno));
|
||||
*delete_src=false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
chown(destpath,db_config->uid(),db_config->gid());
|
||||
chmod(destpath,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(firstdest->isEmpty()) {
|
||||
unlink(destpath);
|
||||
if(CopyToAudioStore(destpath,src_filename)) {
|
||||
*firstdest=destpath;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr,"unable to copy file \"%s\" [%s]\n",
|
||||
(const char *)src_filename,strerror(errno));
|
||||
}
|
||||
}
|
||||
else {
|
||||
unlink(destpath);
|
||||
link(*firstdest,destpath);
|
||||
}
|
||||
}
|
||||
printf(" done.\n");
|
||||
}
|
||||
|
||||
|
||||
void MainObject::CheckOrphanedTracks() const
|
||||
{
|
||||
QString sql="select NUMBER,TITLE,OWNER from CART where OWNER!=\"\"";
|
||||
@ -865,7 +966,8 @@ bool MainObject::UserResponse() const
|
||||
}
|
||||
|
||||
|
||||
bool MainObject::CopyFile(const QString &destfile,const QString &srcfile) const
|
||||
bool MainObject::CopyToAudioStore(const QString &destfile,
|
||||
const QString &srcfile) const
|
||||
{
|
||||
int src_fd=-1;
|
||||
struct stat src_stat;
|
||||
@ -896,10 +998,10 @@ bool MainObject::CopyFile(const QString &destfile,const QString &srcfile) const
|
||||
write(dest_fd,data,n);
|
||||
}
|
||||
free(data);
|
||||
fchown(dest_fd,150,150); // FIXME: do name lookup!
|
||||
fchown(dest_fd,db_config->uid(),db_config->gid());
|
||||
fchmod(dest_fd,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
|
||||
close(dest_fd);
|
||||
close(src_fd);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -50,6 +50,13 @@ class MainObject : public QObject
|
||||
const QString &new_filename,const QString &new_str,
|
||||
QString *err_msg);
|
||||
void RelinkAudio(const QString &srcdir) const;
|
||||
void RelinkCut(const QString &src_filename,const QString &cutname,
|
||||
const QString &title,
|
||||
QString *firstdest,bool *delete_src) const;
|
||||
void RelinkCast(const QString &src_filename,const QString &keyname,
|
||||
unsigned cast_id,const QString &title,
|
||||
const QString &audio_filename,
|
||||
QString *firstdest,bool *delete_src) const;
|
||||
void CheckOrphanedTracks() const;
|
||||
void CheckCutCounts() const;
|
||||
void CheckPendingCarts() const;
|
||||
@ -62,7 +69,7 @@ class MainObject : public QObject
|
||||
void RehashCut(const QString &cutnum) const;
|
||||
void SetCutLength(const QString &cutname,int len) const;
|
||||
void RemoveCart(unsigned cartnum);
|
||||
bool CopyFile(const QString &destfile,const QString &srcfile) const;
|
||||
bool CopyToAudioStore(const QString &destfile,const QString &srcfile) const;
|
||||
bool UserResponse() const;
|
||||
|
||||
//
|
||||
|
@ -40,6 +40,16 @@ bool MainObject::RevertSchema(int cur_schema,int set_schema,QString *err_msg)
|
||||
// NEW SCHEMA REVERSIONS GO HERE...
|
||||
|
||||
|
||||
//
|
||||
// Revert 335
|
||||
//
|
||||
if((cur_schema==335)&&(set_schema<cur_schema)) {
|
||||
DropIndex("PODCASTS","SHA1_HASH_IDX");
|
||||
DropColumn("PODCASTS","SHA1_HASH");
|
||||
|
||||
WriteSchemaVersion(--cur_schema);
|
||||
}
|
||||
|
||||
//
|
||||
// Revert 334
|
||||
//
|
||||
|
@ -161,7 +161,7 @@ void MainObject::InitializeSchemaMap() {
|
||||
global_version_map["3.2"]=311;
|
||||
global_version_map["3.3"]=314;
|
||||
global_version_map["3.4"]=317;
|
||||
global_version_map["4.0"]=334;
|
||||
global_version_map["4.0"]=335;
|
||||
}
|
||||
|
||||
|
||||
|
@ -10243,6 +10243,20 @@ bool MainObject::UpdateSchema(int cur_schema,int set_schema,QString *err_msg)
|
||||
WriteSchemaVersion(++cur_schema);
|
||||
}
|
||||
|
||||
if((cur_schema<335)&&(set_schema>cur_schema)) {
|
||||
sql=QString("alter table PODCASTS add column ")+
|
||||
"SHA1_HASH varchar(40) after AUDIO_TIME";
|
||||
if(!RDSqlQuery::apply(sql,err_msg)) {
|
||||
return false;
|
||||
}
|
||||
sql=QString("alter table PODCASTS add index SHA1_HASH_IDX(SHA1_HASH)");
|
||||
if(!RDSqlQuery::apply(sql,err_msg)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WriteSchemaVersion(++cur_schema);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <rdescape_string.h>
|
||||
#include <rdformpost.h>
|
||||
#include <rdgroup.h>
|
||||
#include <rdhash.h>
|
||||
#include <rdpodcast.h>
|
||||
#include <rduser.h>
|
||||
#include <rdweb.h>
|
||||
@ -83,6 +84,7 @@ void Xport::SavePodcast()
|
||||
delete cast;
|
||||
XmlExit(err_msg.toUtf8(),500,"podcasts.cpp",LINE_NUMBER);
|
||||
}
|
||||
cast->setSha1Hash(RDSha1Hash(destpath));
|
||||
|
||||
printf("Content-type: text/html; charset: UTF-8\n");
|
||||
printf("Status: 200\n\n");
|
||||
@ -191,6 +193,7 @@ void Xport::DeletePodcast()
|
||||
XmlExit(err_msg.toUtf8(),500,"podcasts.cpp",LINE_NUMBER);
|
||||
}
|
||||
}
|
||||
cast->setSha1Hash();
|
||||
|
||||
printf("Content-type: text/html; charset: UTF-8\n");
|
||||
printf("Status: 200\n\n");
|
||||
|
Loading…
x
Reference in New Issue
Block a user