2022-11-17 Fred Gleason <fredg@paravelsystems.com>

* Simplified error return descriptions for the podcast methods in
	the Web API.
	* Removed the 'RDFeed::Error' enumeration.
	* Removed the 'RDFeed::errorString()' method.
	* Fixed bugs in rdcatchd(8) in handling errors when posting to
	RSS feeds.

Signed-off-by: Fred Gleason <fredg@paravelsystems.com>
This commit is contained in:
Fred Gleason
2022-11-17 15:55:26 -05:00
parent 7beec8dba1
commit d33fae60a7
8 changed files with 194 additions and 108 deletions

View File

@@ -41,6 +41,7 @@
#include "rdtempdirectory.h"
#include "rdupload.h"
#include "rdwavefile.h"
#include "rdwebresult.h"
#include "rdxport_interface.h"
int __RDFeed_Debug_Callback(CURL *handle,curl_infotype type,char *data,
@@ -56,6 +57,17 @@ int __RDFeed_Debug_Callback(CURL *handle,curl_infotype type,char *data,
}
size_t __RDFeed_Write_Callback(char *ptr,size_t size,size_t nmemb,
void *userdata)
{
static QByteArray *buffer=(QByteArray *)userdata;
*buffer+=QByteArray(ptr,size*nmemb);
return size*nmemb;
}
RDFeed::RDFeed(const QString &keyname,RDConfig *config,QObject *parent)
: QObject(parent)
{
@@ -819,7 +831,7 @@ bool RDFeed::deleteImage(int img_id,QString *err_msg)
}
bool RDFeed::postPodcast(unsigned cast_id) const
bool RDFeed::postPodcast(unsigned cast_id,QString *err_msg)
{
long response_code;
CURL *curl=NULL;
@@ -851,10 +863,13 @@ bool RDFeed::postPodcast(unsigned cast_id) const
//
if((curl=curl_easy_init())==NULL) {
curl_formfree(first);
*err_msg=tr("Internal error");
return false;
}
QStringList *err_msgs=SetupCurlLogging(curl);
curl_easy_setopt(curl,CURLOPT_WRITEDATA,stdout);
curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,__RDFeed_Write_Callback);
feed_curl_write_buffer.clear();
curl_easy_setopt(curl,CURLOPT_WRITEDATA,&feed_curl_write_buffer);
curl_easy_setopt(curl,CURLOPT_HTTPPOST,first);
curl_easy_setopt(curl,CURLOPT_USERAGENT,
rda->config()->userAgent().toUtf8().constData());
@@ -869,9 +884,12 @@ bool RDFeed::postPodcast(unsigned cast_id) const
// Send it
//
if((curl_err=curl_easy_perform(curl))!=CURLE_OK) {
*err_msg=curl_easy_strerror(curl_err);
curl_easy_cleanup(curl);
curl_formfree(first);
ProcessCurlLogging("RDFeed::postPodcast()",err_msgs);
delete err_msgs;
*err_msg=curl_easy_strerror(curl_err);
return false;
}
@@ -887,6 +905,15 @@ bool RDFeed::postPodcast(unsigned cast_id) const
//
if((response_code<200)||(response_code>299)) {
ProcessCurlLogging("RDFeed::postPodcast()",err_msgs);
RDWebResult *wr=new RDWebResult();
if(wr->readXml(QString::fromUtf8(feed_curl_write_buffer))) {
*err_msg=wr->text();
}
else {
*err_msg=tr("Unspecified error");
}
delete wr;
delete err_msgs;
return false;
}
delete err_msgs;
@@ -1260,9 +1287,9 @@ void RDFeed::removeAllImages()
}
unsigned RDFeed::postCut(const QString &cutname,Error *err)
unsigned RDFeed::postCut(const QString &cutname,QString *err_msg)
{
QString err_msg;
// QString err_msg;
QString tmpfile;
QString destfile;
RDPodcast *cast=NULL;
@@ -1279,7 +1306,7 @@ unsigned RDFeed::postCut(const QString &cutname,Error *err)
RDCut *cut=new RDCut(cutname);
if(!cut->exists()) {
delete cut;
*err=RDFeed::ErrorCannotOpenFile;
*err_msg=tr("No such cut");
return 0;
}
RDAudioExport *conv=new RDAudioExport(this);
@@ -1304,7 +1331,7 @@ unsigned RDFeed::postCut(const QString &cutname,Error *err)
case RDAudioExport::ErrorInvalidSettings:
delete settings;
delete conv;
*err=RDFeed::ErrorUnsupportedType;
*err_msg=tr("Unsupported audio settings");
unlink(tmpfile.toUtf8());
emit postProgressChanged(5);
return 0;
@@ -1319,7 +1346,7 @@ unsigned RDFeed::postCut(const QString &cutname,Error *err)
case RDAudioExport::ErrorConverter:
delete settings;
delete conv;
*err=RDFeed::ErrorGeneral;
*err_msg=tr("Audio converter error");
unlink(tmpfile.toUtf8());
emit postProgressChanged(5);
return 0;
@@ -1335,13 +1362,23 @@ unsigned RDFeed::postCut(const QString &cutname,Error *err)
int length=file.size();
unsigned cast_id=CreateCast(&destfile,length,cut->length());
cast=new RDPodcast(feed_config,cast_id);
SavePodcast(cast_id,tmpfile);
if(!SavePodcast(cast_id,tmpfile,err_msg)) {
AbandonCast(cast_id);
unlink(tmpfile.toUtf8());
emit postProgressChanged(5);
return 0;
}
unlink(tmpfile.toUtf8());
//
// Upload to remote archive
//
postPodcast(cast_id);
if(!postPodcast(cast_id,err_msg)) {
AbandonCast(cast_id);
unlink(tmpfile.toUtf8());
emit postProgressChanged(5);
return 0;
}
postProgressChanged(3);
//
@@ -1360,15 +1397,14 @@ unsigned RDFeed::postCut(const QString &cutname,Error *err)
//
postXml();
emit postProgressChanged(5);
*err=RDFeed::ErrorOk;
*err_msg=tr("OK");
return cast_id;
}
unsigned RDFeed::postFile(const QString &srcfile,Error *err)
unsigned RDFeed::postFile(const QString &srcfile,QString *err_msg)
{
QString err_msg;
QString cmd;
QString tmpfile;
QString tmpfile2;
@@ -1410,7 +1446,8 @@ unsigned RDFeed::postFile(const QString &srcfile,Error *err)
case RDAudioConvert::ErrorFormatNotSupported:
delete settings;
delete conv;
*err=RDFeed::ErrorUnsupportedType;
*err_msg=tr("Audio converter error");
// *err=RDFeed::ErrorUnsupportedType;
unlink(tmpfile.toUtf8());
emit postProgressChanged(6);
return 0;
@@ -1426,7 +1463,8 @@ unsigned RDFeed::postFile(const QString &srcfile,Error *err)
case RDAudioConvert::ErrorNoSpace:
delete settings;
delete conv;
*err=RDFeed::ErrorGeneral;
// *err=RDFeed::ErrorGeneral;
*err_msg=tr("Audio converter error");
unlink(tmpfile.toUtf8());
emit postProgressChanged(6);
return 0;
@@ -1442,7 +1480,7 @@ unsigned RDFeed::postFile(const QString &srcfile,Error *err)
int length=file.size();
unsigned cast_id=CreateCast(&destfile,length,time_length);
RDPodcast *cast=new RDPodcast(feed_config,cast_id);
SavePodcast(cast_id,tmpfile);
SavePodcast(cast_id,tmpfile,err_msg);
unlink((QString(tmpfile)+".wav").toUtf8());
unlink(tmpfile.toUtf8());
emit postProgressChanged(3);
@@ -1450,7 +1488,10 @@ unsigned RDFeed::postFile(const QString &srcfile,Error *err)
//
// Upload to remote archive
//
postPodcast(cast_id);
if(!postPodcast(cast_id,err_msg)) {
emit postProgressChanged(6);
return 0;
}
postProgressChanged(4);
//
@@ -1473,7 +1514,7 @@ unsigned RDFeed::postFile(const QString &srcfile,Error *err)
//
postXml();
emit postProgressChanged(6);
*err=RDFeed::ErrorOk;
// *err=RDFeed::ErrorOk;
return cast_id;
}
@@ -1481,11 +1522,10 @@ unsigned RDFeed::postFile(const QString &srcfile,Error *err)
unsigned RDFeed::postLog(const QString &logname,const QTime &start_time,
bool stop_at_stop,int start_line,int end_line,
RDFeed::Error *err)
QString *err_msg)
{
QString tmpfile;
QString destfile;
QString err_msg;
RDRenderer *renderer=NULL;
RDSettings *settings=NULL;
RDLogModel *log_model=NULL;
@@ -1502,7 +1542,7 @@ unsigned RDFeed::postLog(const QString &logname,const QTime &start_time,
log_model=new RDLogModel(logname,false,this);
log_model->load();
if(!log_model->exists()) {
*err=RDFeed::ErrorNoLog;
*err_msg=tr("No such log");
delete log_model;
return 0;
}
@@ -1525,12 +1565,12 @@ unsigned RDFeed::postLog(const QString &logname,const QTime &start_time,
this,SLOT(renderLineStartedData(int,int)));
if(!renderer->renderToFile(tmpfile,log_model,settings,start_time,stop_at_stop,
&err_msg,start_line,end_line)) {
*err=RDFeed::ErrorRenderError;
err_msg,start_line,end_line)) {
delete renderer;
delete settings;
delete log_model;
unlink(tmpfile.toUtf8());
emit postProgressChanged(4+(end_line-start_line));
return 0;
}
delete renderer;
@@ -1543,14 +1583,21 @@ unsigned RDFeed::postLog(const QString &logname,const QTime &start_time,
unsigned cast_id=
CreateCast(&destfile,f.size(),log_model->length(0,log_model->lineCount()));
RDPodcast *cast=new RDPodcast(feed_config,cast_id);
SavePodcast(cast_id,tmpfile);
SavePodcast(cast_id,tmpfile,err_msg);
unlink(tmpfile.toUtf8());
emit postProgressChanged(2+(end_line-start_line));
//
// Save to remote archive
//
postPodcast(cast_id);
if(!postPodcast(cast_id,err_msg)) {
emit postProgressChanged(4+(end_line-start_line));
delete renderer;
delete settings;
delete log_model;
delete cast;
return false;
}
emit postProgressChanged(3+(end_line-start_line));
//
@@ -1569,7 +1616,6 @@ unsigned RDFeed::postLog(const QString &logname,const QTime &start_time,
postXml();
emit postProgressChanged(4+(end_line-start_line));
*err=RDFeed::ErrorOk;
delete cast;
delete settings;
@@ -1788,47 +1834,6 @@ unsigned RDFeed::create(const QString &keyname,bool enable_users,
}
QString RDFeed::errorString(RDFeed::Error err)
{
QString ret=QString::asprintf("Unknown RDFeed Error [%d]",err);
switch(err) {
case RDFeed::ErrorOk:
ret="Ok";
break;
case RDFeed::ErrorNoFile:
ret="No such file or directory";
break;
case RDFeed::ErrorCannotOpenFile:
ret="Cannot open file";
break;
case RDFeed::ErrorUnsupportedType:
ret="Unsupported file format";
break;
case RDFeed::ErrorUploadFailed:
ret="Upload failed";
break;
case RDFeed::ErrorGeneral:
ret="General Error";
break;
case RDFeed::ErrorNoLog:
ret="No such log";
break;
case RDFeed::ErrorRenderError:
ret="Log rendering error";
break;
}
return ret;
}
QString RDFeed::imageFilename(int feed_id,int img_id,const QString &ext)
{
return QString::asprintf("img%06d_%06d.",feed_id,img_id)+ext;
@@ -1875,7 +1880,8 @@ void RDFeed::renderLineStartedData(int lineno,int total_lines)
}
bool RDFeed::SavePodcast(unsigned cast_id,const QString &src_filename) const
bool RDFeed::SavePodcast(unsigned cast_id,const QString &src_filename,
QString *err_msg)
{
long response_code;
CURL *curl=NULL;
@@ -1915,7 +1921,9 @@ bool RDFeed::SavePodcast(unsigned cast_id,const QString &src_filename) const
return false;
}
QStringList *err_msgs=SetupCurlLogging(curl);
curl_easy_setopt(curl,CURLOPT_WRITEDATA,stdout);
feed_curl_write_buffer.clear();
curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,__RDFeed_Write_Callback);
curl_easy_setopt(curl,CURLOPT_WRITEDATA,&feed_curl_write_buffer);
curl_easy_setopt(curl,CURLOPT_HTTPPOST,first);
curl_easy_setopt(curl,CURLOPT_USERAGENT,
rda->config()->userAgent().toUtf8().constData());
@@ -1932,6 +1940,7 @@ bool RDFeed::SavePodcast(unsigned cast_id,const QString &src_filename) const
if((curl_err=curl_easy_perform(curl))!=CURLE_OK) {
curl_easy_cleanup(curl);
curl_formfree(first);
*err_msg=curl_easy_strerror(curl_err);
ProcessCurlLogging("RDFeed::postPodcast()",err_msgs);
return false;
}
@@ -1948,6 +1957,7 @@ bool RDFeed::SavePodcast(unsigned cast_id,const QString &src_filename) const
//
if((response_code<200)||(response_code>299)) {
ProcessCurlLogging("RDFeed::postPodcast()",err_msgs);
*err_msg=QString::fromUtf8(feed_curl_write_buffer);
return false;
}
delete err_msgs;
@@ -2044,6 +2054,77 @@ unsigned RDFeed::CreateCast(QString *filename,int bytes,int msecs) const
}
void RDFeed::AbandonCast(unsigned cast_id) const
{
//
// Update the audio store
//
long response_code;
CURL *curl=NULL;
struct curl_httppost *first=NULL;
struct curl_httppost *last=NULL;
//
// Generate POST Data
//
curl_formadd(&first,&last,CURLFORM_PTRNAME,"COMMAND",
CURLFORM_COPYCONTENTS,
QString::asprintf("%u",RDXPORT_COMMAND_REMOVE_PODCAST).toUtf8().
constData(),
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,
QString::asprintf("%u",feed_id).toUtf8().constData(),
CURLFORM_END);
//
// Set up the transfer
//
if((curl=curl_easy_init())==NULL) {
curl_formfree(first);
}
else {
QStringList *err_msgs=SetupCurlLogging(curl);
curl_easy_setopt(curl,CURLOPT_WRITEDATA,stdout);
curl_easy_setopt(curl,CURLOPT_HTTPPOST,first);
curl_easy_setopt(curl,CURLOPT_USERAGENT,
rda->config()->userAgent().toUtf8().constData());
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());
rda->syslog(LOG_DEBUG,"using web service URL: %s",
rda->station()->webServiceUrl(rda->config()).toUtf8().constData());
//
// Send it
//
curl_easy_perform(curl); // May fail, which is OK
//
// Clean up
//
curl_easy_getinfo(curl,CURLINFO_RESPONSE_CODE,&response_code);
curl_easy_cleanup(curl);
curl_formfree(first);
delete err_msgs;
}
//
// Update database
//
QString sql=QString("delete from `PODCASTS` where ")+
QString::asprintf("`ID`=%u",cast_id);
RDSqlQuery::apply(sql);
}
QString RDFeed::ResolveChannelWildcards(const QString &tmplt,RDSqlQuery *chan_q,
const QDateTime &build_datetime)
{

View File

@@ -39,9 +39,6 @@ class RDFeed : public QObject
{
Q_OBJECT;
public:
enum Error {ErrorOk=0,ErrorNoFile=1,ErrorCannotOpenFile=2,
ErrorUnsupportedType=3,ErrorUploadFailed=4,ErrorGeneral=5,
ErrorNoLog=6,ErrorRenderError=7};
RDFeed(const QString &keyname,RDConfig *config,QObject *parent=0);
RDFeed(unsigned id,RDConfig *config,QObject *parent=0);
QString keyName() const;
@@ -135,7 +132,7 @@ class RDFeed : public QObject
int importImageFile(const QString &pathname,QString *err_msg,
QString desc="") const;
bool deleteImage(int img_id,QString *err_msg);
bool postPodcast(unsigned cast_id) const;
bool postPodcast(unsigned cast_id,QString *err_msg);
QString audioUrl(unsigned cast_id);
QString imageUrl(int img_id) const;
bool postXml();
@@ -144,14 +141,14 @@ class RDFeed : public QObject
bool postImage(int img_id) const;
bool removeImage(int img_id) const;
void removeAllImages();
unsigned postCut(const QString &cutname,Error *err);
unsigned postFile(const QString &srcfile,Error *err);
unsigned postCut(const QString &cutname,QString *err_msg);
unsigned postFile(const QString &srcfile,QString *err_msg);
unsigned postLog(const QString &logname,const QTime &start_time,
bool stop_at_stop,int start_line,int end_line,Error *err);
bool stop_at_stop,int start_line,int end_line,
QString *err_msg);
QString rssXml(QString *err_msg,const QDateTime &now,bool *ok=NULL);
static unsigned create(const QString &keyname,bool enable_users,
QString *err_msg);
static QString errorString(RDFeed::Error err);
static QString imageFilename(int feed_id,int img_id,const QString &ext);
static QString publicUrl(const QString &base_url,const QString &keyname);
static QString itunesCategoryXml(const QString &category,
@@ -166,8 +163,10 @@ class RDFeed : public QObject
void renderLineStartedData(int lineno,int total_lines);
private:
bool SavePodcast(unsigned cast_id,const QString &src_filename) const;
bool SavePodcast(unsigned cast_id,const QString &src_filename,
QString *err_msg);
unsigned CreateCast(QString *filename,int bytes,int msecs) const;
void AbandonCast(unsigned cast_id) const;
QString ResolveChannelWildcards(const QString &tmplt,RDSqlQuery *chan_q,
const QDateTime &build_datetime);
QString ResolveItemWildcards(const QString &tmplt,RDSqlQuery *item_q,
@@ -188,6 +187,7 @@ class RDFeed : public QObject
int feed_xml_ptr;
int feed_render_start_line;
int feed_render_end_line;
QByteArray feed_curl_write_buffer;
};