mirror of
https://github.com/ElvishArtisan/rivendell.git
synced 2025-04-10 14:58:21 +02:00
2018-05-24 Fred Gleason <fredg@paravelsystems.com>
* Added a WebGet web service.
This commit is contained in:
parent
97568f0c0d
commit
9e215e311f
@ -16896,3 +16896,5 @@
|
|||||||
* Modified caed(8) to start JACK clients after a 5 second delay.
|
* Modified caed(8) to start JACK clients after a 5 second delay.
|
||||||
2018-05-22 Fred Gleason <fredg@paravelsystems.com>
|
2018-05-22 Fred Gleason <fredg@paravelsystems.com>
|
||||||
* Incremented the package version to 2.19.2vlog01.
|
* Incremented the package version to 2.19.2vlog01.
|
||||||
|
2018-05-24 Fred Gleason <fredg@paravelsystems.com>
|
||||||
|
* Added a WebGet web service.
|
||||||
|
@ -532,6 +532,7 @@ AC_CONFIG_FILES([rivendell.spec \
|
|||||||
web/rdcastmanager/Makefile \
|
web/rdcastmanager/Makefile \
|
||||||
web/rdxport/Makefile \
|
web/rdxport/Makefile \
|
||||||
web/tests/Makefile \
|
web/tests/Makefile \
|
||||||
|
web/webget/Makefile \
|
||||||
conf/Makefile \
|
conf/Makefile \
|
||||||
docs/Makefile \
|
docs/Makefile \
|
||||||
docs/apis/Makefile \
|
docs/apis/Makefile \
|
||||||
|
@ -28,6 +28,8 @@ install-exec-am:
|
|||||||
cp redball.png $(DESTDIR)@libexecdir@
|
cp redball.png $(DESTDIR)@libexecdir@
|
||||||
cp whiteball.png $(DESTDIR)@libexecdir@
|
cp whiteball.png $(DESTDIR)@libexecdir@
|
||||||
cp progressbar.gif $(DESTDIR)@libexecdir@
|
cp progressbar.gif $(DESTDIR)@libexecdir@
|
||||||
|
mkdir -p $(DESTDIR)@libexecdir@/logos
|
||||||
|
cp webget_logo.png $(DESTDIR)@libexecdir@/logos/
|
||||||
mkdir -p $(DESTDIR)@prefix@/share/icons/hicolor/16x16/apps
|
mkdir -p $(DESTDIR)@prefix@/share/icons/hicolor/16x16/apps
|
||||||
cp rivendell-16x16.png $(DESTDIR)@prefix@/share/icons/hicolor/16x16/apps/rivendell.png
|
cp rivendell-16x16.png $(DESTDIR)@prefix@/share/icons/hicolor/16x16/apps/rivendell.png
|
||||||
mkdir -p $(DESTDIR)@prefix@/share/icons/hicolor/22x22/apps
|
mkdir -p $(DESTDIR)@prefix@/share/icons/hicolor/22x22/apps
|
||||||
@ -190,6 +192,7 @@ uninstall-local:
|
|||||||
rm -f $(DESTDIR)@libexecdir@/redball.png
|
rm -f $(DESTDIR)@libexecdir@/redball.png
|
||||||
rm -f $(DESTDIR)@libexecdir@/whiteball.png
|
rm -f $(DESTDIR)@libexecdir@/whiteball.png
|
||||||
rm -f $(DESTDIR)@libexecdir@/progressbar.gif
|
rm -f $(DESTDIR)@libexecdir@/progressbar.gif
|
||||||
|
rm -f $(DESTDIR)@libexecdir@/logos/webget_logo.png
|
||||||
rm -f $(DESTDIR)@prefix@/share/icons/hicolor/16x16/apps/rivendell.png
|
rm -f $(DESTDIR)@prefix@/share/icons/hicolor/16x16/apps/rivendell.png
|
||||||
rm -f $(DESTDIR)@prefix@/share/icons/hicolor/22x22/apps/rivendell.png
|
rm -f $(DESTDIR)@prefix@/share/icons/hicolor/22x22/apps/rivendell.png
|
||||||
rm -f $(DESTDIR)@prefix@/share/icons/hicolor/32x32/apps/rivendell.png
|
rm -f $(DESTDIR)@prefix@/share/icons/hicolor/32x32/apps/rivendell.png
|
||||||
@ -470,6 +473,7 @@ EXTRA_DIST = admin.xpm\
|
|||||||
trashcan-32x32.xpm\
|
trashcan-32x32.xpm\
|
||||||
upload.xpm\
|
upload.xpm\
|
||||||
user.xpm\
|
user.xpm\
|
||||||
|
webget_logo.png\
|
||||||
whiteball.png\
|
whiteball.png\
|
||||||
whiteball.xpm
|
whiteball.xpm
|
||||||
|
|
||||||
|
BIN
icons/webget_logo.png
Normal file
BIN
icons/webget_logo.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 4.8 KiB |
@ -112,11 +112,13 @@ mkdir $RPM_BUILD_ROOT/.qt
|
|||||||
touch $RPM_BUILD_ROOT/.qt/qt
|
touch $RPM_BUILD_ROOT/.qt/qt
|
||||||
rm -f $RPM_BUILD_ROOT/lib/security/pam_rd.la
|
rm -f $RPM_BUILD_ROOT/lib/security/pam_rd.la
|
||||||
rm -f $RPM_BUILD_ROOT/lib64/security/pam_rd.la
|
rm -f $RPM_BUILD_ROOT/lib64/security/pam_rd.la
|
||||||
|
rm -rf $RPM_BUILD_ROOT/@libexecdir@/logos
|
||||||
if test "@WIN32_SOURCE@" ; then
|
if test "@WIN32_SOURCE@" ; then
|
||||||
mkdir -p $RPM_BUILD_ROOT/var/win32
|
mkdir -p $RPM_BUILD_ROOT/var/win32
|
||||||
cp @WIN32_SOURCE@ $RPM_BUILD_ROOT/var/win32/
|
cp @WIN32_SOURCE@ $RPM_BUILD_ROOT/var/win32/
|
||||||
fi
|
fi
|
||||||
mkdir -p $RPM_BUILD_ROOT/@DOC_PATH@
|
mkdir -p $RPM_BUILD_ROOT/@DOC_PATH@/logos
|
||||||
|
cp icons/webget_logo.png $RPM_BUILD_ROOT/@DOC_PATH@/logos/
|
||||||
cp AUTHORS $RPM_BUILD_ROOT/@DOC_PATH@/
|
cp AUTHORS $RPM_BUILD_ROOT/@DOC_PATH@/
|
||||||
cp ChangeLog $RPM_BUILD_ROOT/@DOC_PATH@/
|
cp ChangeLog $RPM_BUILD_ROOT/@DOC_PATH@/
|
||||||
cp COPYING $RPM_BUILD_ROOT/@DOC_PATH@/
|
cp COPYING $RPM_BUILD_ROOT/@DOC_PATH@/
|
||||||
@ -220,6 +222,12 @@ fi
|
|||||||
if [ -x %{_bindir}/gtk-update-icon-cache ] ; then
|
if [ -x %{_bindir}/gtk-update-icon-cache ] ; then
|
||||||
%{_bindir}/gtk-update-icon-cache -f --quiet %{_datadir}/icons/hicolor || :
|
%{_bindir}/gtk-update-icon-cache -f --quiet %{_datadir}/icons/hicolor || :
|
||||||
fi
|
fi
|
||||||
|
if test ! -e @libexecdir@/logos ; then
|
||||||
|
mkdir -p @libexecdir@/logos
|
||||||
|
fi
|
||||||
|
if test ! -f @libexecdir@/logos/webget_logo.png ; then
|
||||||
|
cp @DOC_PATH@/logos/webget_logo.png @libexecdir@/logos/webget_logo.png
|
||||||
|
fi
|
||||||
exit 0
|
exit 0
|
||||||
|
|
||||||
|
|
||||||
@ -389,6 +397,7 @@ rm -rf $RPM_BUILD_ROOT
|
|||||||
/.qt/qt
|
/.qt/qt
|
||||||
@libexecdir@/*
|
@libexecdir@/*
|
||||||
%attr(6755,root,root) @libexecdir@/rdxport.cgi
|
%attr(6755,root,root) @libexecdir@/rdxport.cgi
|
||||||
|
%attr(6755,root,root) @libexecdir@/webget.cgi
|
||||||
@sysconfdir@/rd-bin.conf
|
@sysconfdir@/rd-bin.conf
|
||||||
@WIN32_PATH@
|
@WIN32_PATH@
|
||||||
/etc/pam.d/rivendell
|
/etc/pam.d/rivendell
|
||||||
|
@ -23,7 +23,8 @@
|
|||||||
SUBDIRS = rdcastmanager\
|
SUBDIRS = rdcastmanager\
|
||||||
rdfeed\
|
rdfeed\
|
||||||
rdxport\
|
rdxport\
|
||||||
tests
|
tests\
|
||||||
|
webget
|
||||||
|
|
||||||
AM_CPPFLAGS = -Wall -DPREFIX=\"$(prefix)\" -DQTDIR=\"@QT_DIR@\" @QT_CXXFLAGS@ -I$(top_srcdir)/lib
|
AM_CPPFLAGS = -Wall -DPREFIX=\"$(prefix)\" -DQTDIR=\"@QT_DIR@\" @QT_CXXFLAGS@ -I$(top_srcdir)/lib
|
||||||
LIBS = @QT_LIBS@ -L$(top_srcdir)/lib
|
LIBS = @QT_LIBS@ -L$(top_srcdir)/lib
|
||||||
|
52
web/webget/Makefile.am
Normal file
52
web/webget/Makefile.am
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
## Makefile.am
|
||||||
|
##
|
||||||
|
## (C) Copyright 2017-2018 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.
|
||||||
|
##
|
||||||
|
## Use automake to process this into a Makefile.in
|
||||||
|
|
||||||
|
AM_CPPFLAGS = -Wall -DPREFIX=\"$(prefix)\" -DQTDIR=\"@QT_DIR@\" @QT_CXXFLAGS@ -I$(top_srcdir)/lib
|
||||||
|
LIBS = @QT_LIBS@ -L$(top_srcdir)/lib
|
||||||
|
MOC = @QT_MOC@
|
||||||
|
|
||||||
|
# The dependency for qt's Meta Object Compiler (moc)
|
||||||
|
moc_%.cpp: %.h
|
||||||
|
$(MOC) $< -o $@
|
||||||
|
|
||||||
|
install-exec-local:
|
||||||
|
mkdir -p $(DESTDIR)@libexecdir@
|
||||||
|
cp webget.html $(DESTDIR)@libexecdir@/
|
||||||
|
cp webget.js $(DESTDIR)@libexecdir@/
|
||||||
|
|
||||||
|
install-exec-hook:
|
||||||
|
if test -z $(DESTDIR) ; then chown root $(DESTDIR)$(libexecdir)/webget.cgi ; chmod 4755 $(DESTDIR)$(libexecdir)/webget.cgi ; fi
|
||||||
|
|
||||||
|
uninstall-local:
|
||||||
|
rm -f $(DESTDIR)@libexecdir@/webget.html
|
||||||
|
rm -f $(DESTDIR)@libexecdir@/webget.js
|
||||||
|
|
||||||
|
libexec_PROGRAMS = webget.cgi
|
||||||
|
|
||||||
|
dist_webget_cgi_SOURCES = webget.cpp webget.h
|
||||||
|
|
||||||
|
nodist_webget_cgi_SOURCES = moc_webget.cpp
|
||||||
|
|
||||||
|
webget_cgi_LDADD = @LIB_RDLIBS@ -lsndfile @LIBVORBIS@
|
||||||
|
EXTRA_DIST = webget.html\
|
||||||
|
webget.js
|
||||||
|
|
||||||
|
CLEANFILES = *~
|
||||||
|
MAINTAINERCLEANFILES = *~\
|
||||||
|
Makefile.in
|
362
web/webget/webget.cpp
Normal file
362
web/webget/webget.cpp
Normal file
@ -0,0 +1,362 @@
|
|||||||
|
// webget.cpp
|
||||||
|
//
|
||||||
|
// Rivendell download utility
|
||||||
|
//
|
||||||
|
// (C) Copyright 2018 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 <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
|
||||||
|
#include <qapplication.h>
|
||||||
|
|
||||||
|
#include <rdapplication.h>
|
||||||
|
#include <rdescape_string.h>
|
||||||
|
#include <rdweb.h>
|
||||||
|
|
||||||
|
#include "webget.h"
|
||||||
|
|
||||||
|
MainObject::MainObject(QObject *parent)
|
||||||
|
:QObject(parent)
|
||||||
|
{
|
||||||
|
QString err_msg;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Open the Database
|
||||||
|
//
|
||||||
|
rda=new RDApplication("webget.cgi","webget.cgi",WEBGET_CGI_USAGE,this);
|
||||||
|
if(!rda->open(&err_msg)) {
|
||||||
|
XmlExit(err_msg,500,"webget.cpp",LINE_NUMBER);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Read Command Options
|
||||||
|
//
|
||||||
|
for(unsigned i=0;i<rda->cmdSwitch()->keys();i++) {
|
||||||
|
if(!rda->cmdSwitch()->processed(i)) {
|
||||||
|
XmlExit("unknown command option",500,"webget.cpp",LINE_NUMBER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Drop root permissions
|
||||||
|
//
|
||||||
|
if(setgid(rda->config()->gid())<0) {
|
||||||
|
XmlExit("Unable to set Rivendell group",500,"webget.cpp",LINE_NUMBER);
|
||||||
|
}
|
||||||
|
if(setuid(rda->config()->uid())<0) {
|
||||||
|
XmlExit("Unable to set Rivendell user",500,"webget.cpp",LINE_NUMBER);
|
||||||
|
}
|
||||||
|
if(getuid()==0) {
|
||||||
|
XmlExit("Rivendell user should never be \"root\"!",500,"webget.cpp",
|
||||||
|
LINE_NUMBER);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Determine Connection Type
|
||||||
|
//
|
||||||
|
if(getenv("REQUEST_METHOD")==NULL) {
|
||||||
|
XmlExit("missing REQUEST_METHOD",500,"webget.cpp",LINE_NUMBER);
|
||||||
|
}
|
||||||
|
if(QString(getenv("REQUEST_METHOD")).lower()!="post") {
|
||||||
|
XmlExit("invalid web method",500,"webget.cpp",LINE_NUMBER);
|
||||||
|
}
|
||||||
|
if(getenv("REMOTE_ADDR")!=NULL) {
|
||||||
|
webget_remote_address.setAddress(getenv("REMOTE_ADDR"));
|
||||||
|
}
|
||||||
|
if(getenv("REMOTE_HOST")!=NULL) {
|
||||||
|
webget_remote_hostname=getenv("REMOTE_HOST");
|
||||||
|
}
|
||||||
|
if(webget_remote_hostname.isEmpty()) {
|
||||||
|
webget_remote_hostname=webget_remote_address.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Generate Post
|
||||||
|
//
|
||||||
|
webget_post=new RDFormPost(RDFormPost::AutoEncoded,false);
|
||||||
|
if(webget_post->error()!=RDFormPost::ErrorOk) {
|
||||||
|
XmlExit(webget_post->errorString(webget_post->error()),400,"webget.cpp",
|
||||||
|
LINE_NUMBER);
|
||||||
|
Exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Authenticate Connection
|
||||||
|
//
|
||||||
|
if(!Authenticate()) {
|
||||||
|
printf("Content-type: text/html\n");
|
||||||
|
printf("Status: 400\n");
|
||||||
|
printf("\n");
|
||||||
|
printf("Invalid User name or Password!\n");
|
||||||
|
Exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Connect to ripcd(8)
|
||||||
|
//
|
||||||
|
connect(rda->ripc(),SIGNAL(connected(bool)),
|
||||||
|
this,SLOT(ripcConnectedData(bool)));
|
||||||
|
rda->ripc()->
|
||||||
|
connectHost("localhost",RIPCD_TCP_PORT,rda->config()->password());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainObject::ripcConnectedData(bool state)
|
||||||
|
{
|
||||||
|
if(!state) {
|
||||||
|
XmlExit("unable to connect to ripc service",500,"webget.cpp",LINE_NUMBER);
|
||||||
|
Exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString title;
|
||||||
|
if(!webget_post->getValue("title",&title)) {
|
||||||
|
XmlExit("missing \"title\"",400,"webget.cpp",LINE_NUMBER);
|
||||||
|
}
|
||||||
|
|
||||||
|
int samprate;
|
||||||
|
if(!webget_post->getValue("samprate",&samprate)) {
|
||||||
|
XmlExit("missing \"samprate\"",400,"webget.cpp",LINE_NUMBER);
|
||||||
|
}
|
||||||
|
|
||||||
|
int format;
|
||||||
|
if(!webget_post->getValue("format",&format)) {
|
||||||
|
XmlExit("missing \"format\"",400,"webget.cpp",LINE_NUMBER);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bitrate=0;
|
||||||
|
if((format==RDSettings::MpegL2)||(format==RDSettings::MpegL3)) {
|
||||||
|
if(!webget_post->getValue("bitrate",&bitrate)) {
|
||||||
|
XmlExit("missing \"bitrate\"",400,"webget.cpp",LINE_NUMBER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int quality=0;
|
||||||
|
if(format==RDSettings::OggVorbis) {
|
||||||
|
if(!webget_post->getValue("quality",&quality)) {
|
||||||
|
XmlExit("missing \"quality\"",400,"webget.cpp",LINE_NUMBER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned cartnum=0;
|
||||||
|
int cutnum=0;
|
||||||
|
QString sql=QString("select ")+
|
||||||
|
"CUTS.CUT_NAME from "+
|
||||||
|
"CART left join CUTS on CART.NUMBER=CUTS.CART_NUMBER where "+
|
||||||
|
"CART.TITLE=\""+RDEscapeString(title)+"\" && "+
|
||||||
|
QString().sprintf("CART.TYPE=%d",RDCart::Audio);
|
||||||
|
RDSqlQuery *q=new RDSqlQuery(sql);
|
||||||
|
if(q->first()) {
|
||||||
|
cartnum=RDCut::cartNumber(q->value(0).toString());
|
||||||
|
cutnum=RDCut::cutNumber(q->value(0).toString());
|
||||||
|
}
|
||||||
|
delete q;
|
||||||
|
if(cartnum==0) {
|
||||||
|
printf("Content-type: text/html\n");
|
||||||
|
printf("Status: 400\n");
|
||||||
|
printf("\n");
|
||||||
|
printf("No such cart!\n");
|
||||||
|
Exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Audio Settings
|
||||||
|
//
|
||||||
|
RDSettings *settings=new RDSettings();
|
||||||
|
settings->setFormat((RDSettings::Format)format);
|
||||||
|
settings->setChannels(1);
|
||||||
|
settings->setSampleRate(samprate);
|
||||||
|
settings->setBitRate(bitrate);
|
||||||
|
settings->setQuality(quality);
|
||||||
|
settings->setNormalizationLevel(-100);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Generate Metadata
|
||||||
|
//
|
||||||
|
RDCart *cart=new RDCart(cartnum);
|
||||||
|
RDCut *cut=new RDCut(cartnum,cutnum);
|
||||||
|
RDWaveData *wavedata=NULL;
|
||||||
|
QString rdxl;
|
||||||
|
float speed_ratio=1.0;
|
||||||
|
wavedata=new RDWaveData();
|
||||||
|
if(wavedata!=NULL) {
|
||||||
|
cart->getMetadata(wavedata);
|
||||||
|
cut->getMetadata(wavedata);
|
||||||
|
if(cart->enforceLength()) {
|
||||||
|
speed_ratio=(float)cut->length()/(float)cart->forcedLength();
|
||||||
|
}
|
||||||
|
rdxl=cart->xml(true,false,settings,cutnum);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Export Cut
|
||||||
|
//
|
||||||
|
int fd;
|
||||||
|
ssize_t n;
|
||||||
|
uint8_t data[2048];
|
||||||
|
QString err_msg;
|
||||||
|
RDTempDirectory *tempdir=new RDTempDirectory("rdxport-export");
|
||||||
|
if(!tempdir->create(&err_msg)) {
|
||||||
|
XmlExit("unable to create temporary directory ["+err_msg+"]",500);
|
||||||
|
}
|
||||||
|
QString tmpfile=tempdir->path()+"/exported_audio";
|
||||||
|
RDAudioConvert *conv=new RDAudioConvert(this);
|
||||||
|
conv->setSourceFile(RDCut::pathName(cartnum,cutnum));
|
||||||
|
conv->setDestinationFile(tmpfile);
|
||||||
|
conv->setDestinationSettings(settings);
|
||||||
|
conv->setDestinationWaveData(wavedata);
|
||||||
|
conv->setDestinationRdxl(rdxl);
|
||||||
|
conv->setRange(cut->startPoint(),cut->endPoint());
|
||||||
|
conv->setSpeedRatio(speed_ratio);
|
||||||
|
delete cut;
|
||||||
|
delete cart;
|
||||||
|
RDAudioConvert::ErrorCode conv_err;
|
||||||
|
int resp_code=0;
|
||||||
|
switch(conv_err=conv->convert()) {
|
||||||
|
case RDAudioConvert::ErrorOk:
|
||||||
|
switch(settings->format()) {
|
||||||
|
case RDSettings::Pcm16:
|
||||||
|
case RDSettings::Pcm24:
|
||||||
|
printf("Content-type: audio/x-wav\n\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RDSettings::MpegL1:
|
||||||
|
case RDSettings::MpegL2:
|
||||||
|
case RDSettings::MpegL2Wav:
|
||||||
|
case RDSettings::MpegL3:
|
||||||
|
printf("Content-type: audio/x-mpeg\n\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RDSettings::OggVorbis:
|
||||||
|
printf("Content-type: audio/ogg\n\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RDSettings::Flac:
|
||||||
|
printf("Content-type: audio/flac\n\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fflush(NULL);
|
||||||
|
if((fd=open(tmpfile,O_RDONLY))>=0) {
|
||||||
|
while((n=read(fd,data,2048))>0) {
|
||||||
|
write(1,data,n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
unlink(tmpfile);
|
||||||
|
delete tempdir;
|
||||||
|
Exit(0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RDAudioConvert::ErrorFormatNotSupported:
|
||||||
|
case RDAudioConvert::ErrorInvalidSettings:
|
||||||
|
resp_code=415;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RDAudioConvert::ErrorNoSource:
|
||||||
|
resp_code=404;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RDAudioConvert::ErrorNoDestination:
|
||||||
|
case RDAudioConvert::ErrorInvalidSource:
|
||||||
|
case RDAudioConvert::ErrorNoSpace:
|
||||||
|
case RDAudioConvert::ErrorInternal:
|
||||||
|
case RDAudioConvert::ErrorNoDisc:
|
||||||
|
case RDAudioConvert::ErrorNoTrack:
|
||||||
|
case RDAudioConvert::ErrorInvalidSpeed:
|
||||||
|
case RDAudioConvert::ErrorFormatError:
|
||||||
|
resp_code=500;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
delete conv;
|
||||||
|
delete settings;
|
||||||
|
if(wavedata!=NULL) {
|
||||||
|
delete wavedata;
|
||||||
|
}
|
||||||
|
delete tempdir;
|
||||||
|
if(resp_code==200) {
|
||||||
|
Exit(200);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
XmlExit(RDAudioConvert::errorText(conv_err),resp_code,"export.cpp",
|
||||||
|
LINE_NUMBER,conv_err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool MainObject::Authenticate()
|
||||||
|
{
|
||||||
|
QString name;
|
||||||
|
QString passwd;
|
||||||
|
|
||||||
|
if(!webget_post->getValue("LOGIN_NAME",&name)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(!webget_post->getValue("PASSWORD",&passwd)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
RDUser *user=new RDUser(name);
|
||||||
|
if((!user->exists())||
|
||||||
|
(!user->checkPassword(passwd,false))||
|
||||||
|
(!user->webgetLogin())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainObject::Exit(int code)
|
||||||
|
{
|
||||||
|
if(webget_post!=NULL) {
|
||||||
|
delete webget_post;
|
||||||
|
}
|
||||||
|
exit(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainObject::XmlExit(const QString &str,int code,const QString &srcfile,
|
||||||
|
int srcline,RDAudioConvert::ErrorCode err)
|
||||||
|
{
|
||||||
|
if(webget_post!=NULL) {
|
||||||
|
delete webget_post;
|
||||||
|
}
|
||||||
|
#ifdef RDXPORT_DEBUG
|
||||||
|
if(srcline>0) {
|
||||||
|
RDXMLResult(str+" \""+srcfile+"\" "+QString().sprintf("line %d",srcline),
|
||||||
|
code,err);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RDXMLResult(str,code,err);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
RDXMLResult(str,code,err);
|
||||||
|
#endif // RDXPORT_DEBUG
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc,char *argv[])
|
||||||
|
{
|
||||||
|
QApplication a(argc,argv,false);
|
||||||
|
new MainObject();
|
||||||
|
return a.exec();
|
||||||
|
}
|
55
web/webget/webget.h
Normal file
55
web/webget/webget.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
// webget.h
|
||||||
|
//
|
||||||
|
// Rivendell audio download utility
|
||||||
|
//
|
||||||
|
// (C) Copyright 2018 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 WEBGET_H
|
||||||
|
#define WEBGET_H
|
||||||
|
|
||||||
|
#include <qobject.h>
|
||||||
|
|
||||||
|
#include <rdaudioconvert.h>
|
||||||
|
#include <rdformpost.h>
|
||||||
|
|
||||||
|
#define STRINGIZE(x) STRINGIZE2(x)
|
||||||
|
#define STRINGIZE2(x) #x
|
||||||
|
#define LINE_NUMBER QString(STRINGIZE(__LINE__)).toInt()
|
||||||
|
#define WEBGET_CGI_USAGE "\n"
|
||||||
|
|
||||||
|
class MainObject : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT;
|
||||||
|
public:
|
||||||
|
MainObject(QObject *parent=0);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void ripcConnectedData(bool state);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool Authenticate();
|
||||||
|
void Exit(int code);
|
||||||
|
void XmlExit(const QString &msg,int code,
|
||||||
|
const QString &srcfile="",int line=-1,
|
||||||
|
RDAudioConvert::ErrorCode err=RDAudioConvert::ErrorOk);
|
||||||
|
RDFormPost *webget_post;
|
||||||
|
QString webget_remote_hostname;
|
||||||
|
QHostAddress webget_remote_address;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // WEBGET_H
|
106
web/webget/webget.html
Normal file
106
web/webget/webget.html
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Rivendell Webget</title>
|
||||||
|
<script src="webget.js" type="application/javascript"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<form method="post" action="webget.cgi" enctype="application/x-www-form-urlencoded">
|
||||||
|
<table style="margin: auto;padding: 10px 0" cellpadding="0" cellspacing="5" border="0">
|
||||||
|
<tr>
|
||||||
|
<td colspan="2"><img src="logos/webget_logo.png" border="0"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2"><strong>Get audio from Rivendell</strong></td>
|
||||||
|
</tr>
|
||||||
|
<tr><td colspan="2"><hr></td></tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: right">Cart Title:</td>
|
||||||
|
<td><input type="text" name="title" size="40" maxlength="255"></td>
|
||||||
|
</tr>
|
||||||
|
<tr><td cellspan="2"> </td></tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: right">Channels:</td>
|
||||||
|
<td>
|
||||||
|
<select name="channels" id="channels" value="1" onclick="formatChanged()">
|
||||||
|
<option value="1">Monaural</option>
|
||||||
|
<option value="2">Stereo</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: right">Sample Rate:</td>
|
||||||
|
<td>
|
||||||
|
<select name="samprate" id="samprate" onclick="samplerateChanged()">
|
||||||
|
<option value="8000">8000 samples/sec</option>
|
||||||
|
<option value="11025">11025 samples/sec</option>
|
||||||
|
<option value="12000">12000 samples/sec</option>
|
||||||
|
<option value="16000" selected>16000 samples/sec</option>
|
||||||
|
<option value="22050">22050 samples/sec</option>
|
||||||
|
<option value="24000">24000 samples/sec</option>
|
||||||
|
<option value="32000">32000 samples/sec</option>
|
||||||
|
<option value="44100">44100 samples/sec</option>
|
||||||
|
<option value="48000">48000 samples/sec</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: right">Format:</td>
|
||||||
|
<td>
|
||||||
|
<select name="format" id="format" onclick="formatChanged()">
|
||||||
|
<option value="4">FLAC</option>
|
||||||
|
<option value="5">OggVorbis</option>
|
||||||
|
<option value="2">MP2</option>
|
||||||
|
<option value="3" selected>MP3</option>
|
||||||
|
<option value="0">PCM16 [wav]</option>
|
||||||
|
<option value="7">PCM24 [wav]</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: right">Bit Rate:</td>
|
||||||
|
<td>
|
||||||
|
<select name="bitrate" id="bitrate">
|
||||||
|
<option value="16000" selected>16 kbit/sec</option>
|
||||||
|
<option value="32000">32 kbit/sec</option>
|
||||||
|
<option value="64000">64 kbit/sec</option>
|
||||||
|
<option value="128000">128 kbit/sec</option>
|
||||||
|
<option value="256000">256 kbit/sec</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: right">Quality:</td>
|
||||||
|
<td>
|
||||||
|
<select name="quality" id="quality" disabled>
|
||||||
|
<option value="0">0 (lowest)</option>
|
||||||
|
<option value="1">1</option>
|
||||||
|
<option value="2" selected>2 (default)</option>
|
||||||
|
<option value="3">3</option>
|
||||||
|
<option value="4">4</option>
|
||||||
|
<option value="5">5</option>
|
||||||
|
<option value="6">6</option>
|
||||||
|
<option value="7">7</option>
|
||||||
|
<option value="8">8</option>
|
||||||
|
<option value="9">9</option>
|
||||||
|
<option value="10">0 (highest)</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr><td cellspan="2"> </td></tr>
|
||||||
|
<td style="text-align: right">User Name:</td>
|
||||||
|
<td><input type="text" size="32" maxsize="255" name="LOGIN_NAME"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: right">Password:</td>
|
||||||
|
<td><input type="password" size="32" maxsize="32" name="PASSWORD"></td>
|
||||||
|
<tr><td cellspan="2"> </td></tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td><input type="submit" value="OK"></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
187
web/webget/webget.js
Normal file
187
web/webget/webget.js
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
// webget.js
|
||||||
|
//
|
||||||
|
// (C) Copyright 2018 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
function Id(id)
|
||||||
|
{
|
||||||
|
return document.getElementById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function GetMpegVersion(samprate)
|
||||||
|
{
|
||||||
|
mpeg_ver=1.0;
|
||||||
|
|
||||||
|
switch(samprate) {
|
||||||
|
case 32000:
|
||||||
|
case 44100:
|
||||||
|
case 48000:
|
||||||
|
mpeg_ver=1.0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 16000:
|
||||||
|
case 22050:
|
||||||
|
case 24000:
|
||||||
|
mpeg_ver=2.0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8000:
|
||||||
|
case 11025:
|
||||||
|
case 12000:
|
||||||
|
mpeg_ver=2.5;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return mpeg_ver;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function SetLayerII()
|
||||||
|
{
|
||||||
|
mpeg_ver=GetMpegVersion(parseInt(Id('samprate').value));
|
||||||
|
if(mpeg_ver==1.0) {
|
||||||
|
if(Id('channels').value=='1') {
|
||||||
|
Id('bitrate').innerHTML=
|
||||||
|
'<option value="32000">32 kbit/sec</option>\n'+
|
||||||
|
'<option value="48000" selected>48 kbit/sec</option>\n'+
|
||||||
|
'<option value="56000">56 kbit/sec</option>\n'+
|
||||||
|
'<option value="64000">64 kbit/sec</option>\n'+
|
||||||
|
'<option value="80000">80 kbit/sec</option>\n'+
|
||||||
|
'<option value="96000">96 kbit/sec</option>\n'+
|
||||||
|
'<option value="112000">112 kbit/sec</option>\n'+
|
||||||
|
'<option value="128000">128 kbit/sec</option>\n'+
|
||||||
|
'<option value="160000">160 kbit/sec</option>\n'+
|
||||||
|
'<option value="192000">192 kbit/sec</option>\n';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Id('bitrate').innerHTML=
|
||||||
|
'<option value="32000">32 kbit/sec</option>\n'+
|
||||||
|
'<option value="48000" selected>48 kbit/sec</option>\n'+
|
||||||
|
'<option value="56000">56 kbit/sec</option>\n'+
|
||||||
|
'<option value="64000">64 kbit/sec</option>\n'+
|
||||||
|
'<option value="80000">80 kbit/sec</option>\n'+
|
||||||
|
'<option value="96000">96 kbit/sec</option>\n'+
|
||||||
|
'<option value="112000">112 kbit/sec</option>\n'+
|
||||||
|
'<option value="128000">128 kbit/sec</option>\n'+
|
||||||
|
'<option value="160000">160 kbit/sec</option>\n'+
|
||||||
|
'<option value="192000">192 kbit/sec</option>\n'+
|
||||||
|
'<option value="224000">224 kbit/sec</option>\n'+
|
||||||
|
'<option value="256000">256 kbit/sec</option>\n'+
|
||||||
|
'<option value="320000">320 kbit/sec</option>\n'+
|
||||||
|
'<option value="384000">384 kbit/sec</option>\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(mpeg_ver==2.0) {
|
||||||
|
Id('bitrate').innerHTML=
|
||||||
|
'<option value="8000">8 kbit/sec</option>\n'+
|
||||||
|
'<option value="16000" selected>16 kbit/sec</option>\n'+
|
||||||
|
'<option value="24000">24 kbit/sec</option>\n'+
|
||||||
|
'<option value="32000">32 kbit/sec</option>\n'+
|
||||||
|
'<option value="40000">40 kbit/sec</option>\n'+
|
||||||
|
'<option value="48000">48 kbit/sec</option>\n'+
|
||||||
|
'<option value="56000">56 kbit/sec</option>\n'+
|
||||||
|
'<option value="64000">64 kbit/sec</option>\n'+
|
||||||
|
'<option value="80000">80 kbit/sec</option>\n'+
|
||||||
|
'<option value="96000">96 kbit/sec</option>\n'+
|
||||||
|
'<option value="112000">112 kbit/sec</option>\n'+
|
||||||
|
'<option value="128000">128 kbit/sec</option>\n'+
|
||||||
|
'<option value="144000">144 kbit/sec</option>\n'+
|
||||||
|
'<option value="160000">160 kbit/sec</option>\n';
|
||||||
|
}
|
||||||
|
if(mpeg_ver==2.5) {
|
||||||
|
Id('bitrate').innerHTML=
|
||||||
|
'<option value="8000">8 kbit/sec</option>\n'+
|
||||||
|
'<option value="16000" selected>16 kbit/sec</option>\n'+
|
||||||
|
'<option value="24000">24 kbit/sec</option>\n'+
|
||||||
|
'<option value="32000">32 kbit/sec</option>\n'+
|
||||||
|
'<option value="40000">40 kbit/sec</option>\n'+
|
||||||
|
'<option value="48000">48 kbit/sec</option>\n'+
|
||||||
|
'<option value="56000">56 kbit/sec</option>\n'+
|
||||||
|
'<option value="64000">64 kbit/sec</option>\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function SetLayerIII()
|
||||||
|
{
|
||||||
|
mpeg_ver=GetMpegVersion(parseInt(Id('samprate').value));
|
||||||
|
if(mpeg_ver==1.0) {
|
||||||
|
Id('bitrate').innerHTML=
|
||||||
|
'<option value="32000">32 kbit/sec</option>\n'+
|
||||||
|
'<option value="40000" selected>40 kbit/sec</option>\n'+
|
||||||
|
'<option value="48000">48 kbit/sec</option>\n'+
|
||||||
|
'<option value="56000">56 kbit/sec</option>\n'+
|
||||||
|
'<option value="64000">64 kbit/sec</option>\n'+
|
||||||
|
'<option value="80000">80 kbit/sec</option>\n'+
|
||||||
|
'<option value="96000">96 kbit/sec</option>\n'+
|
||||||
|
'<option value="112000">112 kbit/sec</option>\n'+
|
||||||
|
'<option value="128000">128 kbit/sec</option>\n'+
|
||||||
|
'<option value="160000">160 kbit/sec</option>\n'+
|
||||||
|
'<option value="192000">192 kbit/sec</option>\n'+
|
||||||
|
'<option value="224000">224 kbit/sec</option>\n'+
|
||||||
|
'<option value="256000">256 kbit/sec</option>\n'+
|
||||||
|
'<option value="320000">320 kbit/sec</option>\n';
|
||||||
|
}
|
||||||
|
if(mpeg_ver==2.0) {
|
||||||
|
Id('bitrate').innerHTML=
|
||||||
|
'<option value="8000">8 kbit/sec</option>\n'+
|
||||||
|
'<option value="16000" selected>16 kbit/sec</option>\n'+
|
||||||
|
'<option value="24000">24 kbit/sec</option>\n'+
|
||||||
|
'<option value="32000">32 kbit/sec</option>\n'+
|
||||||
|
'<option value="40000">40 kbit/sec</option>\n'+
|
||||||
|
'<option value="48000">48 kbit/sec</option>\n'+
|
||||||
|
'<option value="56000">56 kbit/sec</option>\n'+
|
||||||
|
'<option value="64000">64 kbit/sec</option>\n'+
|
||||||
|
'<option value="80000">80 kbit/sec</option>\n'+
|
||||||
|
'<option value="96000">96 kbit/sec</option>\n'+
|
||||||
|
'<option value="112000">112 kbit/sec</option>\n'+
|
||||||
|
'<option value="128000">128 kbit/sec</option>\n'+
|
||||||
|
'<option value="144000">144 kbit/sec</option>\n'+
|
||||||
|
'<option value="160000">160 kbit/sec</option>\n';
|
||||||
|
}
|
||||||
|
if(mpeg_ver==2.5) {
|
||||||
|
Id('bitrate').innerHTML=
|
||||||
|
'<option value="8000">8 kbit/sec</option>\n'+
|
||||||
|
'<option value="16000" selected>16 kbit/sec</option>\n'+
|
||||||
|
'<option value="24000">24 kbit/sec</option>\n'+
|
||||||
|
'<option value="32000">32 kbit/sec</option>\n'+
|
||||||
|
'<option value="40000">40 kbit/sec</option>\n'+
|
||||||
|
'<option value="48000">48 kbit/sec</option>\n'+
|
||||||
|
'<option value="56000">56 kbit/sec</option>\n'+
|
||||||
|
'<option value="64000">64 kbit/sec</option>\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function samplerateChanged()
|
||||||
|
{
|
||||||
|
if(Id('format').value=='2') {
|
||||||
|
SetLayerII();
|
||||||
|
}
|
||||||
|
if(Id('format').value=='3') {
|
||||||
|
SetLayerIII();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function formatChanged()
|
||||||
|
{
|
||||||
|
Id('bitrate').disabled=
|
||||||
|
!((Id('format').value=="2")||
|
||||||
|
(Id('format').value=="3"));
|
||||||
|
Id('quality').disabled=Id('format').value!="5";
|
||||||
|
samplerateChanged();
|
||||||
|
}
|
145
web/webget/webget.py
Executable file
145
web/webget/webget.py
Executable file
@ -0,0 +1,145 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import subprocess
|
||||||
|
import tempfile
|
||||||
|
import urllib
|
||||||
|
import ConfigParser
|
||||||
|
import mysql.connector
|
||||||
|
|
||||||
|
def eprint(*args,**kwargs):
|
||||||
|
print(*args,file=sys.stderr,**kwargs)
|
||||||
|
|
||||||
|
def GetDbCredentials():
|
||||||
|
config=ConfigParser.ConfigParser()
|
||||||
|
config.readfp(open('/etc/rd.conf'))
|
||||||
|
return (config.get('mySQL','Loginname'),config.get('mySQL','Password'),
|
||||||
|
config.get('mySQL','Hostname'),config.get('mySQL','Database'))
|
||||||
|
|
||||||
|
def OpenDb():
|
||||||
|
creds=GetDbCredentials()
|
||||||
|
return mysql.connector.connect(user=creds[0],password=creds[1],
|
||||||
|
host=creds[2],database=creds[3],
|
||||||
|
|
||||||
|
buffered=True)
|
||||||
|
|
||||||
|
def CgiError(msg,resp_code):
|
||||||
|
print('Content-type: text/html')
|
||||||
|
print('Status: '+str(resp_code))
|
||||||
|
print()
|
||||||
|
print(msg)
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
def AuthenticateUser(name,passwd,db):
|
||||||
|
sql='select WEBGET_LOGIN_PRIV from USERS where ';
|
||||||
|
sql+='LOGIN_NAME="'+name+'" && PASSWORD="'+passwd+'"'
|
||||||
|
q=db.cursor()
|
||||||
|
q.execute(sql)
|
||||||
|
if(len(q.fetchall())==0):
|
||||||
|
CgiError("Invalid User name or Password!",400)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Main Function
|
||||||
|
#
|
||||||
|
title=''
|
||||||
|
samprate=48000
|
||||||
|
format='MP3'
|
||||||
|
bitrate=32000
|
||||||
|
quality=2
|
||||||
|
login_name=''
|
||||||
|
password=''
|
||||||
|
|
||||||
|
#
|
||||||
|
# Get call fields
|
||||||
|
#
|
||||||
|
f0=os.environ['QUERY_STRING'].split('&')
|
||||||
|
for field in f0:
|
||||||
|
f1=field.split('=')
|
||||||
|
if(f1[0]=='title'):
|
||||||
|
title=urllib.unquote(f1[1])
|
||||||
|
if(f1[0]=='samprate'):
|
||||||
|
samprate=int(urllib.unquote(f1[1]))
|
||||||
|
if(f1[0]=='format'):
|
||||||
|
format=urllib.unquote(f1[1])
|
||||||
|
if(f1[0]=='bitrate'):
|
||||||
|
bitrate=int(urllib.unquote(f1[1]))
|
||||||
|
if(f1[0]=='quality'):
|
||||||
|
quality=int(urllib.unquote(f1[1]))
|
||||||
|
if(f1[0]=='login_name'):
|
||||||
|
login_name=urllib.unquote(f1[1])
|
||||||
|
if(f1[0]=='password'):
|
||||||
|
password=urllib.unquote(f1[1])
|
||||||
|
|
||||||
|
login_name=login_name.replace('+',' ')
|
||||||
|
password=password.replace('+',' ')
|
||||||
|
|
||||||
|
db=OpenDb()
|
||||||
|
AuthenticateUser(login_name,password,db)
|
||||||
|
|
||||||
|
if(len(title)==0):
|
||||||
|
CgiError('No title specified!',400)
|
||||||
|
title=title.replace('+',' ')
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generate file export
|
||||||
|
#
|
||||||
|
tempdir=tempfile.mkdtemp()
|
||||||
|
try:
|
||||||
|
filename=subprocess.check_output(('rdexport','--title='+title,
|
||||||
|
'--metadata-pattern=%t',
|
||||||
|
'--samplerate='+str(samprate),
|
||||||
|
'--format='+format,
|
||||||
|
'--bitrate='+str(bitrate),
|
||||||
|
'--quality='+str(quality),
|
||||||
|
tempdir))
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
os.rmdir(tempdir)
|
||||||
|
print('Content-type: text/html')
|
||||||
|
print('Status: 500')
|
||||||
|
print()
|
||||||
|
print('500 - unable to execute rdexport(1)')
|
||||||
|
sys.exit(0)
|
||||||
|
if(len(filename)==0):
|
||||||
|
os.rmdir(tempdir)
|
||||||
|
print('Content-type: text/html')
|
||||||
|
print('Status: 404')
|
||||||
|
print()
|
||||||
|
print('404 - no cart with that title');
|
||||||
|
sys.exit(0)
|
||||||
|
filename=filename[0:len(filename)-1]
|
||||||
|
filepath=tempdir+'/'+filename
|
||||||
|
try:
|
||||||
|
mimetype=subprocess.check_output(('file','--brief','--mime-type',filepath))
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
os.remove(filepath)
|
||||||
|
os.rmdir(tempdir)
|
||||||
|
print('Content-type: text/html')
|
||||||
|
print('Status: 500')
|
||||||
|
print()
|
||||||
|
print('500 - unable to determine output mime-type')
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Render the output
|
||||||
|
#
|
||||||
|
try:
|
||||||
|
f=open(filepath,'r')
|
||||||
|
except IOError, reason:
|
||||||
|
print('Content-type: text/html')
|
||||||
|
print()
|
||||||
|
print('500 - unable to open exported file "'+filepath+'" ['+str(reason)+']')
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
print('Content-Disposition: attachment; filename=\"'+filename+'\"')
|
||||||
|
print('Content-type: '+mimetype)
|
||||||
|
|
||||||
|
bytes=f.read(1024)
|
||||||
|
while(len(bytes)>0):
|
||||||
|
sys.stdout.write(bytes)
|
||||||
|
bytes=f.read(1024)
|
||||||
|
f.close()
|
||||||
|
os.remove(filepath)
|
||||||
|
os.rmdir(tempdir)
|
Loading…
x
Reference in New Issue
Block a user