mirror of
https://github.com/SuperBFG7/ympd
synced 2024-12-24 18:10:26 +00:00
Feat: add ability to define and execute system commands, eg. reboot and shutdown
This commit is contained in:
parent
91f5d4131d
commit
e371453b7b
@ -58,4 +58,5 @@ install(DIRECTORY htdocs/assets DESTINATION share/${PROJECT_NAME}/htdocs)
|
||||
install(DIRECTORY DESTINATION ../var/lib/${PROJECT_NAME}/pics)
|
||||
install(DIRECTORY DESTINATION ../var/lib/${PROJECT_NAME}/tmp)
|
||||
install(DIRECTORY DESTINATION ../var/lib/${PROJECT_NAME}/state)
|
||||
install(DIRECTORY DESTINATION ../etc/${PROJECT_NAME}/syscmds)
|
||||
install(DIRECTORY dist/smartpls DESTINATION ../var/lib/${PROJECT_NAME})
|
||||
|
1
dist/syscmds/Reboot
vendored
Normal file
1
dist/syscmds/Reboot
vendored
Normal file
@ -0,0 +1 @@
|
||||
sudo /sbin/reboot
|
1
dist/syscmds/Shutdown
vendored
Normal file
1
dist/syscmds/Shutdown
vendored
Normal file
@ -0,0 +1 @@
|
||||
sudo /sbin/halt
|
@ -34,6 +34,7 @@
|
||||
<a class="dropdown-item text-light bg-dark" href="#" data-toggle="modal" data-target="#modalSettings">Settings</a>
|
||||
<a class="dropdown-item text-light bg-dark" href="#" data-toggle="modal" data-target="#modalAbout">About</a>
|
||||
<a id="nav-add2homescreen" class="dropdown-item text-light bg-dark hide" href="#">Add2HomeScreen</a>
|
||||
<div id="syscmds"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-toolbar col-auto pl-0 pr-0">
|
||||
|
@ -379,13 +379,21 @@ function appInit() {
|
||||
addFilterLetter('BrowseDatabaseFilterLetters');
|
||||
addFilterLetter('BrowsePlaylistsFilterLetters');
|
||||
|
||||
document.getElementById('syscmds').addEventListener('click', function(event) {
|
||||
event.preventDefault();
|
||||
if (event.target.nodeName == 'A') {
|
||||
var cmd = JSON.parse(event.target.getAttribute('data-href'));
|
||||
if (typeof window[cmd.cmd] === 'function')
|
||||
window[cmd.cmd](... cmd.options);
|
||||
}
|
||||
}, false);
|
||||
|
||||
var hrefs = document.querySelectorAll('[data-href]');
|
||||
var hrefsLen = hrefs.length;
|
||||
for (var i = 0; i < hrefsLen; i++) {
|
||||
hrefs[i].classList.add('clickable');
|
||||
hrefs[i].addEventListener('click', function(event) {
|
||||
event.preventDefault();
|
||||
//event.stopPropagation();
|
||||
var cmd = JSON.parse(this.getAttribute('data-href'));
|
||||
if (typeof window[cmd.cmd] === 'function') {
|
||||
switch(cmd.cmd) {
|
||||
@ -934,9 +942,18 @@ function parseSettings(obj) {
|
||||
addTagList('searchqueuetag', true);
|
||||
addTagList('searchtags', true);
|
||||
|
||||
for (var i = 0; i < obj.data.tags.length; i++) {
|
||||
for (var i = 0; i < obj.data.tags.length; i++)
|
||||
app.apps.Browse.tabs.Database.views[obj.data.tags[i]] = { "state": "0/-/", "scrollPos": 0 };
|
||||
|
||||
var syscmdsList = '';
|
||||
var syscmdsListLen = obj.data.syscmds.length;
|
||||
if (syscmdsListLen > 0) {
|
||||
syscmdsList = '<div class="dropdown-divider"></div>';
|
||||
for (var i = 0; i < syscmdsListLen; i++)
|
||||
syscmdsList += '<a class="dropdown-item text-light bg-dark" href="#" data-href=\'{"cmd": "execSyscmd", "options": ["' +
|
||||
obj.data.syscmds[i] + '"]}\'>' + obj.data.syscmds[i] + '</a>';
|
||||
}
|
||||
document.getElementById('syscmds').innerHTML = syscmdsList;
|
||||
}
|
||||
|
||||
function getSettings() {
|
||||
@ -1605,6 +1622,10 @@ function parseSongDetails(obj) {
|
||||
modal.getElementsByTagName('tbody')[0].innerHTML = songDetails;
|
||||
}
|
||||
|
||||
function execSyscmd(cmd) {
|
||||
sendAPI({"cmd": "MPD_API_SYSCMD", "data": {"cmd": cmd}});
|
||||
}
|
||||
|
||||
function playlistDetails(uri) {
|
||||
document.getElementById('BrowsePlaylistsAllList').classList.add('opacity05');
|
||||
appGoto('Browse', 'Playlists', 'Detail', '0/-/' + uri);
|
||||
|
@ -109,6 +109,15 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) {
|
||||
n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"MPD stickers are disabled\"}");
|
||||
}
|
||||
break;
|
||||
case MPD_API_SYSCMD:
|
||||
je = json_scanf(msg.p, msg.len, "{data: {cmd: %Q}}", &p_charbuf1);
|
||||
if (je == 1) {
|
||||
int_buf1 = list_get_value(&syscmds, p_charbuf1);
|
||||
if (int_buf1 == 1)
|
||||
n = mympd_syscmd(mpd.buf, p_charbuf1);
|
||||
free(p_charbuf1);
|
||||
}
|
||||
break;
|
||||
case MPD_API_PLAYER_STATE:
|
||||
n = mympd_put_state(mpd.buf, &mpd.song_id, &mpd.next_song_id, &mpd.last_song_id, &mpd.queue_version, &mpd.queue_length);
|
||||
break;
|
||||
@ -1214,6 +1223,28 @@ bool mympd_state_set(char *name, char *value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int mympd_syscmd(char *buffer, char *cmd) {
|
||||
int len;
|
||||
char filename[400];
|
||||
char *line;
|
||||
size_t n = 0;
|
||||
ssize_t read;
|
||||
|
||||
snprintf(filename, 400, "%s/syscmds/%s", config.etcdir, cmd);
|
||||
FILE *fp = fopen(filename, "r");
|
||||
if (fp == NULL) {
|
||||
len = snprintf(buffer, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't execute cmd %s\"}", cmd);
|
||||
return len;
|
||||
}
|
||||
read = getline(&line, &n, fp);
|
||||
fclose(fp);
|
||||
strtok(line, "\n");
|
||||
system(line);
|
||||
len = snprintf(buffer, MAX_SIZE, "{\"type\": \"result\", \"data\": \"Executed cmd %s\"}", line);
|
||||
CHECK_RETURN_LEN();
|
||||
return len;
|
||||
}
|
||||
|
||||
int mympd_put_settings(char *buffer) {
|
||||
struct mpd_status *status;
|
||||
char *replaygain = strdup("");
|
||||
@ -1276,7 +1307,18 @@ int mympd_put_settings(char *buffer) {
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
len += json_printf(&out, "]}}");
|
||||
len += json_printf(&out, "], syscmds: [");
|
||||
|
||||
nr = 0;
|
||||
current = syscmds.list;
|
||||
while (current != NULL) {
|
||||
if (nr ++)
|
||||
len += json_printf(&out, ",");
|
||||
len += json_printf(&out, "%Q", current->data);
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
len += json_printf(&out, "]}}");
|
||||
|
||||
CHECK_RETURN_LEN();
|
||||
return len;
|
||||
@ -2148,6 +2190,7 @@ int mympd_smartpls_update_all() {
|
||||
printf("Can't parse file %s\n", filename);
|
||||
}
|
||||
free(smartpltype);
|
||||
free(content);
|
||||
}
|
||||
closedir (dir);
|
||||
} else {
|
||||
|
@ -109,6 +109,7 @@
|
||||
X(MPD_API_MESSAGE_SEND) \
|
||||
X(MPD_API_WELCOME) \
|
||||
X(MPD_API_LIKE) \
|
||||
X(MPD_API_SYSCMD) \
|
||||
X(MPD_API_UNKNOWN)
|
||||
|
||||
enum mpd_cmd_ids {
|
||||
@ -150,6 +151,8 @@ struct t_mpd {
|
||||
struct list mpd_tags;
|
||||
struct list mympd_tags;
|
||||
|
||||
struct list syscmds;
|
||||
|
||||
typedef struct {
|
||||
long mpdport;
|
||||
const char* mpdhost;
|
||||
@ -167,6 +170,7 @@ typedef struct {
|
||||
const char* taglist;
|
||||
bool smartpls;
|
||||
const char* varlibdir;
|
||||
const char* etcdir;
|
||||
long max_elements_per_page;
|
||||
} t_config;
|
||||
|
||||
@ -207,6 +211,7 @@ void mympd_get_sticker(const char *uri, t_sticker *sticker);
|
||||
void mympd_jukebox();
|
||||
bool mympd_state_get(char *name, char *value);
|
||||
bool mympd_state_set(char *name, char *value);
|
||||
int mympd_syscmd(char *buffer, char *cmd);
|
||||
int mympd_smartpls_save(char *smartpltype, char *playlist, char *tag, char *searchstr, int maxentries, int timerange);
|
||||
int mympd_smartpls_put(char *buffer, char *playlist);
|
||||
int mympd_smartpls_update_all();
|
||||
|
29
src/mympd.c
29
src/mympd.c
@ -29,6 +29,7 @@
|
||||
#include <sys/time.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#include "../dist/src/mongoose/mongoose.h"
|
||||
#include "../dist/src/frozen/frozen.h"
|
||||
@ -130,12 +131,8 @@ static int inihandler(void* user, const char* section, const char* name, const c
|
||||
|
||||
if (MATCH("mpdhost"))
|
||||
p_config->mpdhost = strdup(value);
|
||||
else if (MATCH("mpdhost"))
|
||||
p_config->mpdhost = strdup(value);
|
||||
else if (MATCH("mpdport"))
|
||||
p_config->mpdport = strtol(value, &crap, 10);
|
||||
else if (MATCH("mpdhost"))
|
||||
p_config->mpdhost = strdup(value);
|
||||
else if (MATCH("mpdpass"))
|
||||
p_config->mpdpass = strdup(value);
|
||||
else if (MATCH("webport"))
|
||||
@ -187,6 +184,23 @@ static int inihandler(void* user, const char* section, const char* name, const c
|
||||
return 1;
|
||||
}
|
||||
|
||||
void read_syscmds() {
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
char dirname[400];
|
||||
|
||||
snprintf(dirname, 400, "%s/syscmds", config.etcdir);
|
||||
printf("Reading syscmds: %s\n", dirname);
|
||||
if ((dir = opendir (dirname)) != NULL) {
|
||||
while ((ent = readdir(dir)) != NULL) {
|
||||
if (strncmp(ent->d_name, ".", 1) == 0)
|
||||
continue;
|
||||
list_push(&syscmds, ent->d_name, 1);
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
}
|
||||
|
||||
void read_statefiles() {
|
||||
char *crap;
|
||||
char value[400];
|
||||
@ -266,7 +280,7 @@ int main(int argc, char **argv) {
|
||||
config.sslport = "443";
|
||||
config.sslcert = "/etc/mympd/ssl/server.pem";
|
||||
config.sslkey = "/etc/mympd/ssl/server.key";
|
||||
config.user = "nobody";
|
||||
config.user = "mympd";
|
||||
config.streamport = 8000;
|
||||
config.coverimage = "folder.jpg";
|
||||
config.varlibdir = "/var/lib/mympd";
|
||||
@ -275,6 +289,8 @@ int main(int argc, char **argv) {
|
||||
config.taglist = "Artist,Album,AlbumArtist,Title,Track,Genre,Date,Composer,Performer";
|
||||
config.smartpls = true;
|
||||
config.max_elements_per_page = 100;
|
||||
char *etcdir = strdup(argv[1]);
|
||||
config.etcdir = dirname(etcdir);
|
||||
|
||||
mpd.timeout = 3000;
|
||||
mpd.last_update_sticker_song_id = -1;
|
||||
@ -380,6 +396,9 @@ int main(int argc, char **argv) {
|
||||
|
||||
read_statefiles();
|
||||
|
||||
list_init(&syscmds);
|
||||
read_syscmds();
|
||||
|
||||
list_init(&mpd_tags);
|
||||
list_init(&mympd_tags);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user