Skip to content

Commit

Permalink
Merge pull request #1761 from owntone/mxml_to_libmxml_1
Browse files Browse the repository at this point in the history
  • Loading branch information
ejurgensen authored May 31, 2024
2 parents 75fe3f1 + f6ee669 commit f8d42a2
Show file tree
Hide file tree
Showing 10 changed files with 191 additions and 335 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ jobs:
# uses a compiled language
- run: |
sudo apt-get update
sudo apt-get install -yq build-essential clang clang-tools git autotools-dev autoconf libtool gettext gawk gperf bison flex libconfuse-dev libunistring-dev libsqlite3-dev libavcodec-dev libavformat-dev libavfilter-dev libswscale-dev libavutil-dev libasound2-dev libmxml-dev libgcrypt20-dev libavahi-client-dev zlib1g-dev libevent-dev libplist-dev libsodium-dev libcurl4-openssl-dev libjson-c-dev libprotobuf-c-dev libpulse-dev libwebsockets-dev libgnutls28-dev
sudo apt-get install -yq build-essential clang clang-tools git autotools-dev autoconf libtool gettext gawk gperf bison flex libconfuse-dev libunistring-dev libsqlite3-dev libavcodec-dev libavformat-dev libavfilter-dev libswscale-dev libavutil-dev libasound2-dev libxml2-dev libgcrypt20-dev libavahi-client-dev zlib1g-dev libevent-dev libplist-dev libsodium-dev libcurl4-openssl-dev libjson-c-dev libprotobuf-c-dev libpulse-dev libwebsockets-dev libgnutls28-dev
autoreconf -vi
./configure --enable-lastfm --enable-chromecast
scan-build --status-bugs -disable-checker deadcode.DeadStores --exclude src/parsers make
Expand Down
8 changes: 1 addition & 7 deletions .github/workflows/macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,6 @@ jobs:
sudo ln -s /usr/local/opt/bison/bin/bison /usr/local/bin/bison
sudo ln -s /usr/local/opt/flex/bin/flex /usr/local/bin/flex
- name: Install libmxml
# Homebrew by default comes with libmxml 4, but it isn't compatible with mxml 3 which we need
run: |
wget https://raw.githubusercontent.com/Homebrew/homebrew-core/71bfcd3624ee88eee1e2ea6653753dafd48e7fcf/Formula/lib/libmxml.rb
brew install --build-from-source libmxml.rb
- name: Install libinotify-kqueue
# brew does not have libinotify package
run: |
Expand Down Expand Up @@ -76,7 +70,7 @@ jobs:
- name: Install other dependencies
run: |
brew install libunistring confuse libplist libwebsockets libevent libgcrypt json-c protobuf-c libsodium gnutls pulseaudio openssl
brew install libxml2 libunistring confuse libplist libwebsockets libevent libgcrypt json-c protobuf-c libsodium gnutls pulseaudio openssl
- name: Configure
# We configure a non-privileged setup, since how to add a "owntone" system
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -yq build-essential clang clang-tools git autotools-dev autoconf libtool gettext gawk gperf bison flex libconfuse-dev libunistring-dev libsqlite3-dev libavcodec-dev libavformat-dev libavfilter-dev libswscale-dev libavutil-dev libasound2-dev libmxml-dev libgcrypt20-dev libavahi-client-dev zlib1g-dev libevent-dev libplist-dev libsodium-dev libcurl4-openssl-dev libjson-c-dev libprotobuf-c-dev libpulse-dev libwebsockets-dev libgnutls28-dev
sudo apt-get install -yq build-essential clang clang-tools git autotools-dev autoconf libtool gettext gawk gperf bison flex libconfuse-dev libunistring-dev libsqlite3-dev libavcodec-dev libavformat-dev libavfilter-dev libswscale-dev libavutil-dev libasound2-dev libxml2-dev libgcrypt20-dev libavahi-client-dev zlib1g-dev libevent-dev libplist-dev libsodium-dev libcurl4-openssl-dev libjson-c-dev libprotobuf-c-dev libpulse-dev libwebsockets-dev libgnutls28-dev
- name: Build and check
run: |
Expand Down
8 changes: 1 addition & 7 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,7 @@ OWNTONE_MODULES_CHECK([OWNTONE], [ZLIB], [zlib], [deflate], [zlib.h])
OWNTONE_MODULES_CHECK([OWNTONE], [CONFUSE], [libconfuse >= 3.0], [cfg_init], [confuse.h])
OWNTONE_MODULES_CHECK([OWNTONE], [LIBCURL], [libcurl], [curl_global_init], [curl/curl.h])
OWNTONE_MODULES_CHECK([OWNTONE], [LIBSODIUM], [libsodium], [sodium_init], [sodium.h])

OWNTONE_MODULES_CHECK([OWNTONE], [MINIXML], [mxml],
[mxmlNewElement], [mxml.h],
[
dnl See mxml-compat.h
AC_CHECK_FUNCS([mxmlGetOpaque] [mxmlGetText] [mxmlGetType] [mxmlGetFirstChild])
])
OWNTONE_MODULES_CHECK([OWNTONE], [LIBXML2], [libxml-2.0], [xmlInitParser], [libxml/parser.h])

OWNTONE_MODULES_CHECK([COMMON], [SQLITE3], [sqlite3 >= 3.5.0],
[sqlite3_initialize], [sqlite3.h],
Expand Down
10 changes: 4 additions & 6 deletions docs/building.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ sudo apt-get install \
build-essential git autotools-dev autoconf automake libtool gettext gawk \
gperf bison flex libconfuse-dev libunistring-dev libsqlite3-dev \
libavcodec-dev libavformat-dev libavfilter-dev libswscale-dev libavutil-dev \
libasound2-dev libmxml-dev libgcrypt20-dev libavahi-client-dev zlib1g-dev \
libasound2-dev libxml2-dev libgcrypt20-dev libavahi-client-dev zlib1g-dev \
libevent-dev libplist-dev libsodium-dev libjson-c-dev libwebsockets-dev \
libcurl4-openssl-dev libprotobuf-c-dev
```
Expand Down Expand Up @@ -73,7 +73,7 @@ will need ffmpeg. You can google how to do that. Then run:
```bash
sudo dnf install \
git automake autoconf gettext-devel gperf gawk libtool bison flex \
sqlite-devel libconfuse-devel libunistring-devel mxml-devel libevent-devel \
sqlite-devel libconfuse-devel libunistring-devel libxml2-devel libevent-devel \
avahi-devel libgcrypt-devel zlib-devel alsa-lib-devel ffmpeg-devel \
libplist-devel libsodium-devel json-c-devel libwebsockets-devel \
libcurl-devel protobuf-c-devel
Expand Down Expand Up @@ -137,11 +137,9 @@ Install MacPorts (which requires Xcode): <https://www.macports.org/install.php>
sudo port install \
autoconf automake libtool pkgconfig git gperf bison flex libgcrypt \
libunistring libconfuse ffmpeg libevent json-c libwebsockets curl \
libplist libsodium protobuf-c
libplist libsodium protobuf-c libxml2
```

Download, configure, build, and install the [Mini-XML library](https://www.msweet.org/mxml/)

Download, configure, build and install the [libinotify-kqueue library](https://github.com/libinotify-kqueue/libinotify-kqueue)

Add the following to `.bashrc`:
Expand Down Expand Up @@ -226,7 +224,7 @@ Libraries:
- [FFmpeg](https://ffmpeg.org/)
- [libconfuse](https://github.com/libconfuse/libconfuse)
- [libevent](https://libevent.org/) 2.1.4+
- [Mini-XML](https://www.msweet.org/mxml/) (aka mxml or libmxml)
- [libxml2](https://gitlab.gnome.org/GNOME/libxml2)
- [Libgcrypt](https://gnupg.org/software/libgcrypt/) 1.2.0+
- [zlib](https://zlib.net/)
- [libunistring](https://www.gnu.org/software/libunistring/) 0.9.3+
Expand Down
2 changes: 1 addition & 1 deletion owntone.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Url: https://github.com/owntone/owntone-server
Source0: https://github.com/owntone/%{name}/archive/%{version}/%{name}-%{version}.tar.xz
%{?systemd_ordering}
BuildRequires: gcc, make, bison, flex, systemd, pkgconfig, libunistring-devel
BuildRequires: pkgconfig(zlib), pkgconfig(libconfuse), pkgconfig(mxml)
BuildRequires: pkgconfig(zlib), pkgconfig(libconfuse), pkgconfig(libxml2)
BuildRequires: pkgconfig(sqlite3) >= 3.5.0, pkgconfig(libevent) >= 2.0.0
BuildRequires: pkgconfig(json-c), libgcrypt-devel >= 1.2.0
BuildRequires: libgpg-error-devel >= 1.6
Expand Down
2 changes: 1 addition & 1 deletion scripts/freebsd_install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ if [ "$yn" != "y" ]; then
fi

DEPS="gmake autoconf automake libtool gettext gperf glib pkgconf wget git \
ffmpeg libconfuse libevent mxml libgcrypt libunistring libiconv curl \
ffmpeg libconfuse libevent libxml2 libgcrypt libunistring libiconv curl \
libplist libinotify avahi sqlite3 alsa-lib libsodium json-c libwebsockets
protobuf-c bison flex"
echo "The script can install the following dependency packages for you:"
Expand Down
75 changes: 40 additions & 35 deletions src/httpd_rsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
#include "parsers/rsp_parser.h"

#define RSP_VERSION "1.0"
#define RSP_XML_ROOT "?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?"
#define RSP_XML_DECLARATION "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>"

#define F_FULL (1 << 0)
#define F_BROWSE (1 << 1)
Expand Down Expand Up @@ -124,7 +124,7 @@ xml_to_evbuf(struct evbuffer *evbuf, xml_node *tree)
char *xml;
int ret;

xml = xml_to_string(tree);
xml = xml_to_string(tree, RSP_XML_DECLARATION);
if (!xml)
{
DPRINTF(E_LOG, L_RSP, "Could not finalize RSP reply\n");
Expand All @@ -142,44 +142,53 @@ xml_to_evbuf(struct evbuffer *evbuf, xml_node *tree)
return 0;
}

static void
rsp_xml_response_new(xml_node **xml_ptr, xml_node **response_ptr, int errorcode, const char *errorstring, int records, int totalrecords)
static int
rsp_xml_response_new(xml_node **response_ptr, int errorcode, const char *errorstring, int records, int totalrecords)
{
xml_node *xml = xml_new_node(NULL, RSP_XML_ROOT, NULL);
xml_node *response = xml_new_node(xml, "response", NULL);
xml_node *node;
xml_node *response = xml_new_node(NULL, "response", NULL);
xml_node *status = xml_new_node(response, "status", NULL);

if (!response || !status)
return -1;

xml_new_node_textf(status, "errorcode", "%d", errorcode);
xml_new_node(status, "errorstring", errorstring);
node = xml_new_node(status, "errorstring", errorstring);
if (errorstring && *errorstring == '\0')
xml_new_text(node, ""); // Prevents sending <errorstring/> which the Soundbridge may not understand

xml_new_node_textf(status, "records", "%d", records);
xml_new_node_textf(status, "totalrecords", "%d", totalrecords);

if (response_ptr)
*response_ptr = response;
if (xml_ptr)
*xml_ptr = xml;

return 0;
}

static void
rsp_send_error(struct httpd_request *hreq, char *errmsg)
{
xml_node *xml;
xml_node *response = NULL;
int ret;

rsp_xml_response_new(&xml, NULL, 1, errmsg, 0, 0);
ret = xml_to_evbuf(hreq->out_body, xml);
xml_free(xml);
CHECK_ERR(L_RSP, rsp_xml_response_new(&response, 1, errmsg, 0, 0));

ret = xml_to_evbuf(hreq->out_body, response);
if (ret < 0)
{
httpd_send_error(hreq, HTTP_SERVUNAVAIL, "Internal Server Error");
return;
}
goto error;

httpd_header_add(hreq->out_headers, "Content-Type", "text/xml; charset=utf-8");
httpd_header_add(hreq->out_headers, "Connection", "close");

httpd_send_reply(hreq, HTTP_OK, "OK", HTTPD_SEND_NO_GZIP);

xml_free(response);
return;

error:
httpd_send_error(hreq, HTTP_SERVUNAVAIL, "Internal Server Error");
xml_free(response);
}

static int
Expand Down Expand Up @@ -305,7 +314,6 @@ rsp_request_authorize(struct httpd_request *hreq)
static int
rsp_reply_info(struct httpd_request *hreq)
{
xml_node *xml;
xml_node *response;
xml_node *info;
cfg_t *lib;
Expand All @@ -317,7 +325,7 @@ rsp_reply_info(struct httpd_request *hreq)
lib = cfg_getsec(cfg, "library");
library = cfg_getstr(lib, "name");

rsp_xml_response_new(&xml, &response, 0, "", 0, 0);
CHECK_ERR(L_RSP, rsp_xml_response_new(&response, 0, "", 0, 0));

info = xml_new_node(response, "info", NULL);

Expand All @@ -326,7 +334,7 @@ rsp_reply_info(struct httpd_request *hreq)
xml_new_node(info, "server-version", VERSION);
xml_new_node(info, "name", library);

rsp_send_reply(hreq, xml);
rsp_send_reply(hreq, response);
return 0;
}

Expand All @@ -336,7 +344,6 @@ rsp_reply_db(struct httpd_request *hreq)
struct query_params qp;
struct db_playlist_info dbpli;
char **strval;
xml_node *xml;
xml_node *response;
xml_node *pls;
xml_node *pl;
Expand All @@ -357,7 +364,7 @@ rsp_reply_db(struct httpd_request *hreq)
return -1;
}

rsp_xml_response_new(&xml, &response, 0, "", qp.results, qp.results);
CHECK_ERR(L_RSP, rsp_xml_response_new(&response, 0, "", qp.results, qp.results));

pls = xml_new_node(response, "playlists", NULL);

Expand Down Expand Up @@ -386,23 +393,23 @@ rsp_reply_db(struct httpd_request *hreq)
{
DPRINTF(E_LOG, L_RSP, "Error fetching results\n");

xml_free(xml);
xml_free(response);
db_query_end(&qp);
rsp_send_error(hreq, "Error fetching query results");
return -1;
}

/* HACK
* Add a dummy empty string to the playlists element if there is no data
* to return - this prevents mxml from sending out an empty <playlists/>
* to return - this prevents us from sending out an empty <playlists/>
* tag that the SoundBridge does not handle. It's hackish, but it works.
*/
if (qp.results == 0)
xml_new_text(pls, "");

db_query_end(&qp);

rsp_send_reply(hreq, xml);
rsp_send_reply(hreq, response);

return 0;
}
Expand Down Expand Up @@ -473,7 +480,6 @@ rsp_reply_playlist(struct httpd_request *hreq)
struct query_params qp;
const char *param;
const char *client_codecs;
xml_node *xml;
xml_node *response;
xml_node *items;
int mode;
Expand Down Expand Up @@ -538,7 +544,7 @@ rsp_reply_playlist(struct httpd_request *hreq)
if (qp.limit && (records > qp.limit))
records = qp.limit;

rsp_xml_response_new(&xml, &response, 0, "", records, qp.results);
CHECK_ERR(L_RSP, rsp_xml_response_new(&response, 0, "", records, qp.results));

// Add a parent items block (all items), and then one item per file
items = xml_new_node(response, "items", NULL);
Expand All @@ -554,23 +560,23 @@ rsp_reply_playlist(struct httpd_request *hreq)
{
DPRINTF(E_LOG, L_RSP, "Error fetching results\n");

xml_free(xml);
xml_free(response);
db_query_end(&qp);
rsp_send_error(hreq, "Error fetching query results");
return -1;
}

/* HACK
* Add a dummy empty string to the items element if there is no data
* to return - this prevents mxml from sending out an empty <items/>
* to return - this prevents us from sending out an empty <items/>
* tag that the SoundBridge does not handle. It's hackish, but it works.
*/
if (qp.results == 0)
xml_new_text(items, "");

db_query_end(&qp);

rsp_send_reply(hreq, xml);
rsp_send_reply(hreq, response);

return 0;
}
Expand All @@ -580,7 +586,6 @@ rsp_reply_browse(struct httpd_request *hreq)
{
struct query_params qp;
char *browse_item;
xml_node *xml;
xml_node *response;
xml_node *items;
int records;
Expand Down Expand Up @@ -643,7 +648,7 @@ rsp_reply_browse(struct httpd_request *hreq)
if (qp.limit && (records > qp.limit))
records = qp.limit;

rsp_xml_response_new(&xml, &response, 0, "", records, qp.results);
CHECK_ERR(L_RSP, rsp_xml_response_new(&response, 0, "", records, qp.results));

items = xml_new_node(response, "items", NULL);

Expand All @@ -660,23 +665,23 @@ rsp_reply_browse(struct httpd_request *hreq)
{
DPRINTF(E_LOG, L_RSP, "Error fetching results\n");

xml_free(xml);
xml_free(response);
db_query_end(&qp);
rsp_send_error(hreq, "Error fetching query results");
return -1;
}

/* HACK
* Add a dummy empty string to the items element if there is no data
* to return - this prevents mxml from sending out an empty <items/>
* to return - this prevents us from sending out an empty <items/>
* tag that the SoundBridge does not handle. It's hackish, but it works.
*/
if (qp.results == 0)
xml_new_text(items, "");

db_query_end(&qp);

rsp_send_reply(hreq, xml);
rsp_send_reply(hreq, response);

return 0;
}
Expand Down
Loading

0 comments on commit f8d42a2

Please sign in to comment.