summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Rasmussen <sebrn@axis.com>2012-04-25 19:46:53 +0200
committerTim-Philipp Müller <tim.muller@collabora.co.uk>2012-05-12 11:59:01 +0100
commit3f20bbdcf4b437bf63a7426a5deac45a3c8267d7 (patch)
tree592f435990f3f56244be83ab2b2fa3733d495f75
parent766dd8bb717b1ba5317fbd2c5d7860d6beb34834 (diff)
downloadgstreamer-plugins-bad-3f20bbdcf4b437bf63a7426a5deac45a3c8267d7.tar.gz
curl: new curlsmtpsink element
https://bugzilla.gnome.org/show_bug.cgi?id=653741
-rw-r--r--docs/plugins/Makefile.am7
-rw-r--r--ext/curl/Makefile.am6
-rw-r--r--ext/curl/gstcurl.c5
-rw-r--r--ext/curl/gstcurlsmtpsink.c928
-rw-r--r--ext/curl/gstcurlsmtpsink.h87
-rw-r--r--tests/check/Makefile.am3
-rw-r--r--tests/check/elements/curlsmtpsink.c208
7 files changed, 1237 insertions, 7 deletions
diff --git a/docs/plugins/Makefile.am b/docs/plugins/Makefile.am
index 8f10bfc76..5a0978c89 100644
--- a/docs/plugins/Makefile.am
+++ b/docs/plugins/Makefile.am
@@ -61,16 +61,15 @@ IGNORE_CFILES =
EXAMPLE_CFILES = \
$(top_srcdir)/ext/directfb/dfb-example.c
-# $(top_srcdir)/ext/curl/gstcurlfilesink.h
-# $(top_srcdir)/ext/curl/gstcurlftpsink.h
-# $(top_srcdir)/ext/curl/gstcurlsmtpsink.h
-
EXTRA_HFILES = \
$(top_srcdir)/ext/assrender/gstassrender.h \
$(top_srcdir)/ext/celt/gstceltdec.h \
$(top_srcdir)/ext/celt/gstceltenc.h \
$(top_srcdir)/ext/curl/gstcurlbasesink.h \
+ $(top_srcdir)/ext/curl/gstcurlfilesink.h \
+ $(top_srcdir)/ext/curl/gstcurlftpsink.h \
$(top_srcdir)/ext/curl/gstcurlhttpsink.h \
+ $(top_srcdir)/ext/curl/gstcurlsmtpsink.h \
$(top_srcdir)/ext/curl/gstcurltlssink.h \
$(top_srcdir)/ext/dc1394/gstdc1394.h \
$(top_srcdir)/ext/directfb/dfbvideosink.h \
diff --git a/ext/curl/Makefile.am b/ext/curl/Makefile.am
index 2f68b7c1a..5d916b0fb 100644
--- a/ext/curl/Makefile.am
+++ b/ext/curl/Makefile.am
@@ -5,7 +5,8 @@ libgstcurl_la_SOURCES = gstcurl.c \
gstcurltlssink.c \
gstcurlhttpsink.c \
gstcurlfilesink.c \
- gstcurlftpsink.c
+ gstcurlftpsink.c \
+ gstcurlsmtpsink.c
libgstcurl_la_CFLAGS = \
$(GST_PLUGINS_BAD_CFLAGS) \
$(GST_BASE_CFLAGS) \
@@ -23,4 +24,5 @@ noinst_HEADERS = gstcurlbasesink.h \
gstcurltlssink.h \
gstcurlhttpsink.h \
gstcurlfilesink.h \
- gstcurlftpsink.h
+ gstcurlftpsink.h \
+ gstcurlsmtpsink.h
diff --git a/ext/curl/gstcurl.c b/ext/curl/gstcurl.c
index 5cf278cfc..c6b9df4c7 100644
--- a/ext/curl/gstcurl.c
+++ b/ext/curl/gstcurl.c
@@ -25,6 +25,7 @@
#include "gstcurlhttpsink.h"
#include "gstcurlfilesink.h"
#include "gstcurlftpsink.h"
+#include "gstcurlsmtpsink.h"
static gboolean
plugin_init (GstPlugin * plugin)
@@ -42,6 +43,10 @@ plugin_init (GstPlugin * plugin)
GST_TYPE_CURL_FTP_SINK))
return FALSE;
+ if (!gst_element_register (plugin, "curlsmtpsink", GST_RANK_NONE,
+ GST_TYPE_CURL_SMTP_SINK))
+ return FALSE;
+
return TRUE;
}
diff --git a/ext/curl/gstcurlsmtpsink.c b/ext/curl/gstcurlsmtpsink.c
new file mode 100644
index 000000000..283f86a3f
--- /dev/null
+++ b/ext/curl/gstcurlsmtpsink.c
@@ -0,0 +1,928 @@
+/* GStreamer
+ * Copyright (C) 2011 Axis Communications <dev-gstreamer@axis.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:element-curlsink
+ * @short_description: sink that uploads data to a server using libcurl
+ * @see_also:
+ *
+ * This is a network sink that uses libcurl as a client to upload data to
+ * an SMTP server.
+ *
+ * <refsect2>
+ * <title>Example launch line (upload a JPEG file to an SMTP server)</title>
+ * |[
+ * gst-launch filesrc location=image.jpg ! jpegparse ! curlsmtpsink \
+ * file-name=image.jpg \
+ * location=smtp://smtp.gmail.com:507 \
+ * user=test passwd=test \
+ * subject=my image \
+ * mail-from="me@gmail.com" \
+ * mail-rcpt="you@gmail.com,she@gmail.com" \
+ * use-ssl=TRUE \
+ * insecure=TRUE
+ * ]|
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <curl/curl.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <pwd.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "gstcurltlssink.h"
+#include "gstcurlsmtpsink.h"
+
+/* Default values */
+#define GST_CAT_DEFAULT gst_curl_smtp_sink_debug
+#define DEFAULT_USE_SSL FALSE
+#define DEFAULT_NBR_ATTACHMENTS 1
+
+/* MIME definitions */
+#define MIME_VERSION "MIME-version: 1.0"
+#define BOUNDARY_STRING "curlsink-boundary"
+#define BOUNDARY_STRING_END "--curlsink-boundary--"
+
+#define MAIL_RCPT_DELIMITER ","
+
+/* Plugin specific settings */
+
+GST_DEBUG_CATEGORY_STATIC (gst_curl_smtp_sink_debug);
+
+enum
+{
+ PROP_0,
+ PROP_MAIL_RCPT,
+ PROP_MAIL_FROM,
+ PROP_SUBJECT,
+ PROP_MESSAGE_BODY,
+ PROP_POP_USER_NAME,
+ PROP_POP_USER_PASSWD,
+ PROP_POP_LOCATION,
+ PROP_NBR_ATTACHMENTS,
+ PROP_CONTENT_TYPE,
+ PROP_USE_SSL
+};
+
+
+/* Object class function declarations */
+static void gst_curl_smtp_sink_finalize (GObject * gobject);
+static void gst_curl_smtp_sink_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_curl_smtp_sink_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+static gboolean gst_curl_smtp_sink_set_payload_headers_unlocked (GstCurlBaseSink
+ * sink);
+static gboolean
+gst_curl_smtp_sink_set_transfer_options_unlocked (GstCurlBaseSink * sink);
+static void gst_curl_smtp_sink_set_mime_type (GstCurlBaseSink * bcsink,
+ GstCaps * caps);
+static gboolean gst_curl_smtp_sink_prepare_transfer (GstCurlBaseSink * bcsink);
+static size_t gst_curl_smtp_sink_transfer_data_buffer (GstCurlBaseSink * sink,
+ void *curl_ptr, size_t block_size, guint * last_chunk);
+static size_t gst_curl_smtp_sink_flush_data_unlocked (GstCurlBaseSink * bcsink,
+ void *curl_ptr, size_t block_size, gboolean new_file);
+
+/* private functions */
+
+static size_t transfer_payload_headers (GstCurlSmtpSink * sink, void *curl_ptr,
+ size_t block_size);
+
+#define gst_curl_smtp_sink_parent_class parent_class
+G_DEFINE_TYPE (GstCurlSmtpSink, gst_curl_smtp_sink, GST_TYPE_CURL_TLS_SINK);
+
+static void
+gst_curl_smtp_sink_notify_transfer_end_unlocked (GstCurlSmtpSink * sink)
+{
+ GST_LOG ("transfer completed: %d", sink->transfer_end);
+ sink->transfer_end = TRUE;
+ g_cond_signal (sink->cond_transfer_end);
+}
+
+static void
+gst_curl_smtp_sink_wait_for_transfer_end_unlocked (GstCurlSmtpSink * sink)
+{
+ GST_LOG ("waiting for final data do be sent: %d", sink->transfer_end);
+
+ while (!sink->transfer_end) {
+ g_cond_wait (sink->cond_transfer_end, GST_OBJECT_GET_LOCK (sink));
+ }
+ GST_LOG ("final data sent");
+}
+
+static gboolean
+gst_curl_smtp_sink_event (GstBaseSink * bsink, GstEvent * event)
+{
+ GstCurlBaseSink *bcsink = GST_CURL_BASE_SINK (bsink);
+ GstCurlSmtpSink *sink = GST_CURL_SMTP_SINK (bsink);
+
+ GByteArray *array;
+ gchar *boundary_end;
+
+ switch (event->type) {
+ case GST_EVENT_EOS:
+ GST_DEBUG_OBJECT (sink, "received EOS");
+ gst_curl_base_sink_set_live (bcsink, FALSE);
+
+ GST_OBJECT_LOCK (sink);
+ sink->eos = TRUE;
+ GST_OBJECT_UNLOCK (sink);
+
+ if (sink->base64_chunk != NULL) {
+ gsize len;
+ gint save, state;
+ gchar *data_out;
+
+ array = sink->base64_chunk->chunk_array;
+ g_assert (array);
+
+ GST_DEBUG ("adding final boundary");
+
+ /* it will need up to 5 bytes if line-breaking is enabled
+ * additional byte is needed for <CR> as it is not automatically added by glib */
+ data_out = g_malloc (6);
+ save = sink->base64_chunk->save;
+ state = sink->base64_chunk->state;
+ len = g_base64_encode_close (TRUE, data_out, &state, &save);
+ /* workaround */
+ data_out[len - 1] = '\r';
+ data_out[len] = '\n';
+ /* +1 for CR */
+ g_byte_array_append (array, (guint8 *) data_out, (guint) (len + 1));
+ g_free (data_out);
+
+ boundary_end = g_strdup_printf ("\r\n%s\r\n", BOUNDARY_STRING_END);
+ g_byte_array_append (array, (guint8 *) boundary_end,
+ strlen (boundary_end));
+ g_free (boundary_end);
+ }
+
+ gst_curl_base_sink_transfer_thread_notify_unlocked (bcsink);
+
+ GST_OBJECT_LOCK (sink);
+ if (sink->base64_chunk != NULL && bcsink->flow_ret == GST_FLOW_OK) {
+ gst_curl_smtp_sink_wait_for_transfer_end_unlocked (sink);
+ }
+ GST_OBJECT_UNLOCK (sink);
+
+ gst_curl_base_sink_transfer_thread_close (bcsink);
+
+ break;
+
+ default:
+ break;
+ }
+ return TRUE;
+}
+
+static void
+gst_curl_smtp_sink_class_init (GstCurlSmtpSinkClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstBaseSinkClass *gstbasesink_class = (GstBaseSinkClass *) klass;
+ GstCurlBaseSinkClass *gstcurlbasesink_class = (GstCurlBaseSinkClass *) klass;
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+ GST_DEBUG_CATEGORY_INIT (gst_curl_smtp_sink_debug, "curlsmtpsink", 0,
+ "curl smtp sink element");
+ GST_DEBUG_OBJECT (klass, "class_init");
+
+ gst_element_class_set_details_simple (element_class,
+ "Curl smtp sink",
+ "Sink/Network",
+ "Upload data over SMTP protocol using libcurl",
+ "Patricia Muscalu <patricia@axis.com>");
+
+ gstcurlbasesink_class->set_protocol_dynamic_options_unlocked =
+ gst_curl_smtp_sink_set_payload_headers_unlocked;
+ gstcurlbasesink_class->set_options_unlocked =
+ gst_curl_smtp_sink_set_transfer_options_unlocked;
+ gstcurlbasesink_class->set_mime_type = gst_curl_smtp_sink_set_mime_type;
+ gstcurlbasesink_class->prepare_transfer = gst_curl_smtp_sink_prepare_transfer;
+ gstcurlbasesink_class->transfer_data_buffer =
+ gst_curl_smtp_sink_transfer_data_buffer;
+ gstcurlbasesink_class->flush_data_unlocked =
+ gst_curl_smtp_sink_flush_data_unlocked;
+
+ gstbasesink_class->event = gst_curl_smtp_sink_event;
+ gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_curl_smtp_sink_finalize);
+ gobject_class->set_property = gst_curl_smtp_sink_set_property;
+ gobject_class->get_property = gst_curl_smtp_sink_get_property;
+
+ g_object_class_install_property (gobject_class, PROP_MAIL_RCPT,
+ g_param_spec_string ("mail-rcpt", "Mail recipient",
+ "Single address that the given mail should get sent to", NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_MAIL_FROM,
+ g_param_spec_string ("mail-from", "Mail sender",
+ "Single address that the given mail should get sent from", NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_CONTENT_TYPE,
+ g_param_spec_string ("content-type", "Content type",
+ "The mime type of the body of the request", NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_SUBJECT,
+ g_param_spec_string ("subject", "UTF-8 encoded mail subject",
+ "Mail subject", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_MESSAGE_BODY,
+ g_param_spec_string ("message-body", "UTF-8 encoded message body",
+ "Message body", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_USE_SSL,
+ g_param_spec_boolean ("use-ssl", "Use SSL",
+ "Use SSL/TLS for the connection", DEFAULT_USE_SSL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_NBR_ATTACHMENTS,
+ g_param_spec_int ("nbr-attachments", "Number attachments",
+ "Number attachments to send", G_MININT, G_MAXINT,
+ DEFAULT_NBR_ATTACHMENTS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_POP_USER_NAME,
+ g_param_spec_string ("pop-user", "User name",
+ "User name to use for POP server authentication", NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_POP_USER_PASSWD,
+ g_param_spec_string ("pop-passwd", "User password",
+ "User password to use for POP server authentication", NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_POP_LOCATION,
+ g_param_spec_string ("pop-location", "POP location",
+ "URL POP used for authentication", NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+}
+
+static void
+gst_curl_smtp_sink_init (GstCurlSmtpSink * sink)
+{
+ sink->curl_recipients = NULL;
+ sink->mail_rcpt = NULL;
+ sink->mail_from = NULL;
+ sink->subject = NULL;
+ sink->message_body = NULL;
+ sink->payload_headers = NULL;
+ sink->base64_chunk = NULL;
+
+ sink->cond_transfer_end = g_cond_new ();
+ sink->transfer_end = FALSE;
+ sink->eos = FALSE;
+
+ sink->reset_transfer_options = FALSE;
+ sink->use_ssl = DEFAULT_USE_SSL;
+
+ sink->pop_user = NULL;
+ sink->pop_passwd = NULL;
+ sink->pop_location = NULL;
+ sink->pop_curl = NULL;
+}
+
+static void
+gst_curl_smtp_sink_finalize (GObject * gobject)
+{
+ GstCurlSmtpSink *this = GST_CURL_SMTP_SINK (gobject);
+
+ GST_DEBUG ("finalizing curlsmtpsink");
+
+ if (this->curl_recipients != NULL) {
+ curl_slist_free_all (this->curl_recipients);
+ }
+ g_free (this->mail_rcpt);
+ g_free (this->mail_from);
+ g_free (this->subject);
+ g_free (this->message_body);
+ g_free (this->content_type);
+
+ g_cond_free (this->cond_transfer_end);
+
+ if (this->base64_chunk != NULL) {
+ if (this->base64_chunk->chunk_array != NULL) {
+ g_byte_array_free (this->base64_chunk->chunk_array, TRUE);
+ }
+ g_free (this->base64_chunk);
+ }
+
+ if (this->payload_headers != NULL) {
+ g_byte_array_free (this->payload_headers, TRUE);
+ }
+
+ g_free (this->pop_user);
+ g_free (this->pop_passwd);
+ if (this->pop_curl != NULL) {
+ curl_easy_cleanup (this->pop_curl);
+ this->pop_curl = NULL;
+ }
+ g_free (this->pop_location);
+
+ G_OBJECT_CLASS (parent_class)->finalize (gobject);
+}
+
+static void
+gst_curl_smtp_sink_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstCurlSmtpSink *sink;
+ GstState cur_state;
+
+ g_return_if_fail (GST_IS_CURL_SMTP_SINK (object));
+ sink = GST_CURL_SMTP_SINK (object);
+
+ gst_element_get_state (GST_ELEMENT (sink), &cur_state, NULL, 0);
+ if (cur_state != GST_STATE_PLAYING && cur_state != GST_STATE_PAUSED) {
+ GST_OBJECT_LOCK (sink);
+
+ switch (prop_id) {
+ case PROP_MAIL_RCPT:
+ g_free (sink->mail_rcpt);
+ sink->mail_rcpt = g_value_dup_string (value);
+ GST_DEBUG_OBJECT (sink, "mail-rcpt set to %s", sink->mail_rcpt);
+ break;
+ case PROP_MAIL_FROM:
+ g_free (sink->mail_from);
+ sink->mail_from = g_value_dup_string (value);
+ GST_DEBUG_OBJECT (sink, "mail-from set to %s", sink->mail_from);
+ break;
+ case PROP_SUBJECT:
+ g_free (sink->subject);
+ sink->subject = g_value_dup_string (value);
+ GST_DEBUG_OBJECT (sink, "subject set to %s", sink->subject);
+ break;
+ case PROP_MESSAGE_BODY:
+ g_free (sink->message_body);
+ sink->message_body = g_value_dup_string (value);
+ GST_DEBUG_OBJECT (sink, "message-body set to %s", sink->message_body);
+ break;
+ case PROP_CONTENT_TYPE:
+ g_free (sink->content_type);
+ sink->content_type = g_value_dup_string (value);
+ GST_DEBUG_OBJECT (sink, "content-type set to %s", sink->content_type);
+ break;
+ case PROP_USE_SSL:
+ sink->use_ssl = g_value_get_boolean (value);
+ GST_DEBUG_OBJECT (sink, "use-ssl set to %d", sink->use_ssl);
+ break;
+ case PROP_NBR_ATTACHMENTS:
+ sink->nbr_attachments = g_value_get_int (value);
+ sink->nbr_attachments_left = sink->nbr_attachments;
+ GST_DEBUG_OBJECT (sink, "nbr-attachments set to %d",
+ sink->nbr_attachments);
+ break;
+ case PROP_POP_USER_NAME:
+ g_free (sink->pop_user);
+ sink->pop_user = g_value_dup_string (value);
+ GST_DEBUG_OBJECT (sink, "pop-user set to %s", sink->pop_user);
+ break;
+ case PROP_POP_USER_PASSWD:
+ g_free (sink->pop_passwd);
+ sink->pop_passwd = g_value_dup_string (value);
+ GST_DEBUG_OBJECT (sink, "pop-passwd set to %s", sink->pop_passwd);
+ break;
+ case PROP_POP_LOCATION:
+ g_free (sink->pop_location);
+ sink->pop_location = g_value_dup_string (value);
+ GST_DEBUG_OBJECT (sink, "pop-location set to %s", sink->pop_location);
+ break;
+
+ default:
+ GST_DEBUG_OBJECT (sink, "invalid property id %d", prop_id);
+ break;
+ }
+
+ GST_OBJECT_UNLOCK (sink);
+
+ return;
+ }
+
+ /* in PLAYING or PAUSED state */
+ GST_OBJECT_LOCK (sink);
+
+ switch (prop_id) {
+ case PROP_CONTENT_TYPE:
+ g_free (sink->content_type);
+ sink->content_type = g_value_dup_string (value);
+ GST_DEBUG_OBJECT (sink, "content type set to %s", sink->content_type);
+ break;
+ default:
+ GST_WARNING_OBJECT (sink, "cannot set property when PLAYING");
+ break;
+ }
+
+ GST_OBJECT_UNLOCK (sink);
+}
+
+static void
+gst_curl_smtp_sink_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstCurlSmtpSink *sink;
+
+ g_return_if_fail (GST_IS_CURL_SMTP_SINK (object));
+ sink = GST_CURL_SMTP_SINK (object);
+
+ switch (prop_id) {
+ case PROP_MAIL_RCPT:
+ g_value_set_string (value, sink->mail_rcpt);
+ break;
+ case PROP_MAIL_FROM:
+ g_value_set_string (value, sink->mail_from);
+ break;
+ case PROP_SUBJECT:
+ g_value_set_string (value, sink->subject);
+ break;
+ case PROP_MESSAGE_BODY:
+ g_value_set_string (value, sink->message_body);
+ break;
+ case PROP_CONTENT_TYPE:
+ g_value_set_string (value, sink->content_type);
+ break;
+ case PROP_USE_SSL:
+ g_value_set_boolean (value, sink->use_ssl);
+ break;
+ case PROP_NBR_ATTACHMENTS:
+ g_value_set_int (value, sink->nbr_attachments);
+ break;
+ case PROP_POP_USER_NAME:
+ g_value_set_string (value, sink->pop_user);
+ break;
+ case PROP_POP_USER_PASSWD:
+ g_value_set_string (value, sink->pop_passwd);
+ break;
+ case PROP_POP_LOCATION:
+ g_value_set_string (value, sink->pop_location);
+ break;
+
+ default:
+ GST_DEBUG_OBJECT (sink, "invalid property id");
+ break;
+ }
+}
+
+static gboolean
+gst_curl_smtp_sink_set_payload_headers_unlocked (GstCurlBaseSink * bcsink)
+{
+ GstCurlSmtpSink *sink = GST_CURL_SMTP_SINK (bcsink);
+ gchar *hdrs;
+ gboolean append_headers = FALSE;
+
+ if (sink->reset_transfer_options) {
+ g_assert (!bcsink->is_live);
+ sink->reset_transfer_options = FALSE;
+
+ /* all data has been sent in the previous transfer, setup headers for
+ * a new transfer */
+ gst_curl_smtp_sink_set_transfer_options_unlocked (bcsink);
+ append_headers = TRUE;
+ }
+
+ if (sink->payload_headers == NULL) {
+ sink->payload_headers = g_byte_array_new ();
+ append_headers = TRUE;
+ }
+
+ if (sink->base64_chunk == NULL) {
+ g_assert (!bcsink->is_live);
+ /* we are just about to send the very first attachment in this transfer.
+ * This is the only place where base64_chunk and its array are allocated.
+ */
+ sink->base64_chunk = g_malloc (sizeof (Base64Chunk));
+ sink->base64_chunk->chunk_array = g_byte_array_new ();
+ append_headers = TRUE;
+ } else {
+ g_assert (sink->base64_chunk->chunk_array != NULL);
+ g_assert (sink->base64_chunk->chunk_array->len == 0);
+ }
+
+ sink->base64_chunk->state = 0;
+ sink->base64_chunk->save = 0;
+
+ if (G_UNLIKELY (!append_headers)) {
+ if (sink->base64_chunk != NULL) {
+ g_byte_array_free (sink->base64_chunk->chunk_array, TRUE);
+ sink->base64_chunk->chunk_array = NULL;
+ g_free (sink->base64_chunk);
+ sink->base64_chunk = NULL;
+ }
+ return FALSE;
+ }
+
+ hdrs = g_strdup_printf ("\r\n\r\n--%s\r\n"
+ "Content-Type: application/octet-stream; name=\"%s\"\r\n"
+ /* TODO: support for other encodings */
+ "Content-Transfer-Encoding: BASE64\r\n"
+ "Content-Disposition: attachment; filename=\"%s\"\r\n\r\n"
+ "\r\n", BOUNDARY_STRING, bcsink->file_name, bcsink->file_name);
+ g_byte_array_append (sink->payload_headers, (guint8 *) hdrs, strlen (hdrs));
+ g_free (hdrs);
+
+ return TRUE;
+}
+
+/* MIME encoded-word syntax (RFC 2047):
+ * =?charset?encoding?encoded text?= */
+static gchar *
+generate_encoded_word (gchar * str)
+{
+ gchar *encoded_word;
+
+ g_assert (str);
+
+ if (g_utf8_validate (str, -1, NULL)) {
+ gchar *base64_str;
+
+ base64_str = g_base64_encode ((const guchar *) str, strlen (str));
+ encoded_word = g_strdup_printf ("=?utf-8?B?%s?=", base64_str);
+ g_free (base64_str);
+ } else {
+ GST_WARNING ("string is not a valid UTF-8 string");
+ encoded_word = g_strdup (str);
+ }
+
+ /* TODO: 75 character limit */
+ return encoded_word;
+}
+
+static gboolean
+gst_curl_smtp_sink_set_transfer_options_unlocked (GstCurlBaseSink * bcsink)
+{
+ GstCurlSmtpSink *sink = GST_CURL_SMTP_SINK (bcsink);
+ GstCurlTlsSinkClass *parent_class;
+ gchar *request_headers;
+ GDateTime *date;
+ gchar *date_str;
+ gchar **tmp_list = NULL;
+ gchar *subject_header = NULL;
+ gchar *message_body = NULL;
+ gchar *rcpt_header = NULL;
+ gchar *enc_rcpt;
+ gchar *from_header = NULL;
+ gchar *enc_from;
+ gint i;
+
+ g_assert (sink->payload_headers == NULL);
+ g_assert (sink->mail_rcpt != NULL);
+ g_assert (sink->mail_from != NULL);
+
+ /* time */
+ date = g_date_time_new_now_local ();
+ date_str = g_date_time_format (date, "%a %b %e %H:%M:%S %Y");
+ g_date_time_unref (date);
+
+ /* recipient, sender and subject are all UTF-8 strings, which are additionally
+ * base64-encoded */
+
+ /* recipient */
+ enc_rcpt = generate_encoded_word (sink->mail_rcpt);
+ rcpt_header = g_strdup_printf ("%s <%s>", enc_rcpt, sink->mail_rcpt);
+ g_free (enc_rcpt);
+
+ /* sender */
+ enc_from = generate_encoded_word (sink->mail_from);
+ from_header = g_strdup_printf ("%s <%s>", enc_from, sink->mail_from);
+ g_free (enc_from);
+
+ /* subject */
+ if (sink->subject != NULL) {
+ subject_header = generate_encoded_word (sink->subject);
+ }
+
+ /* message */
+ if (sink->message_body != NULL) {
+ message_body = g_base64_encode ((const guchar *) sink->message_body,
+ strlen (sink->message_body));
+ }
+
+ request_headers = g_strdup_printf (
+ /* headers */
+ "To: %s\r\n"
+ "From: %s\r\n"
+ "Subject: %s\r\n"
+ "Date: %s\r\n"
+ MIME_VERSION "\r\n"
+ "Content-Type: multipart/mixed; boundary=%s\r\n" "\r\n"
+ /* body headers */
+ "--" BOUNDARY_STRING "\r\n"
+ "Content-Type: text/plain; charset=utf-8\r\n"
+ "Content-Transfer-Encoding: BASE64\r\n"
+ /* message body */
+ "\r\n%s\r\n",
+ rcpt_header,
+ from_header,
+ subject_header ? subject_header : "",
+ date_str, BOUNDARY_STRING, message_body ? message_body : "");
+
+ sink->payload_headers = g_byte_array_new ();
+
+ g_byte_array_append (sink->payload_headers, (guint8 *) request_headers,
+ strlen (request_headers));
+ g_free (date_str);
+ g_free (subject_header);
+ g_free (message_body);
+ g_free (rcpt_header);
+ g_free (from_header);
+ g_free (request_headers);
+
+ curl_easy_setopt (bcsink->curl, CURLOPT_MAIL_FROM, sink->mail_from);
+
+ if (sink->curl_recipients != NULL) {
+ curl_slist_free_all (sink->curl_recipients);
+ sink->curl_recipients = NULL;
+ }
+
+ tmp_list = g_strsplit_set (sink->mail_rcpt, MAIL_RCPT_DELIMITER, -1);
+ for (i = 0; i < g_strv_length (tmp_list); i++) {
+ sink->curl_recipients = curl_slist_append (sink->curl_recipients,
+ tmp_list[i]);
+ }
+ g_strfreev (tmp_list);
+
+ /* note that the CURLOPT_MAIL_RCPT takes a list, not a char array */
+ curl_easy_setopt (bcsink->curl, CURLOPT_MAIL_RCPT, sink->curl_recipients);
+
+ parent_class = GST_CURL_TLS_SINK_GET_CLASS (sink);
+
+ if (sink->use_ssl) {
+ return parent_class->set_options_unlocked (bcsink);
+ }
+
+ return TRUE;
+}
+
+static void // FIXME: exactly the same function as in http sink
+gst_curl_smtp_sink_set_mime_type (GstCurlBaseSink * bcsink, GstCaps * caps)
+{
+ GstCurlSmtpSink *sink = GST_CURL_SMTP_SINK (bcsink);
+ GstStructure *structure;
+ const gchar *mime_type;
+
+ if (sink->content_type != NULL) {
+ return;
+ }
+
+ structure = gst_caps_get_structure (caps, 0);
+ mime_type = gst_structure_get_name (structure);
+ sink->content_type = g_strdup (mime_type);
+}
+
+static size_t
+gst_curl_smtp_sink_flush_data_unlocked (GstCurlBaseSink * bcsink,
+ void *curl_ptr, size_t block_size, gboolean new_file)
+{
+ GstCurlSmtpSink *sink = GST_CURL_SMTP_SINK (bcsink);
+ Base64Chunk *chunk = sink->base64_chunk;
+ gint state = chunk->state;
+ gint save = chunk->save;
+ GByteArray *array = chunk->chunk_array;
+ size_t bytes_to_send;
+ gint len;
+ gchar *data_out;
+
+ if ((bcsink->is_live && (sink->nbr_attachments_left == sink->nbr_attachments))
+ || (sink->nbr_attachments == 1) || sink->eos) {
+ bcsink->is_live = FALSE;
+ sink->reset_transfer_options = TRUE;
+
+ GST_DEBUG ("returning 0, no more data to send in this transfer");
+
+ return 0;
+ }
+
+ /* it will need up to 5 bytes if line-breaking is enabled, however an
+ * additional byte is needed for <CR> as it is not automatically added by glib */
+ data_out = g_malloc (6);
+ len = g_base64_encode_close (TRUE, data_out, &state, &save);
+ chunk->state = state;
+ chunk->save = save;
+ /* workaround */
+ data_out[len - 1] = '\r';
+ data_out[len] = '\n';
+ /* +1 for CR */
+ g_byte_array_append (array, (guint8 *) data_out, (guint) (len + 1));
+ g_free (data_out);
+
+ if (new_file) {
+ sink->nbr_attachments_left--;
+
+ bcsink->is_live = TRUE;
+ if (sink->nbr_attachments_left <= 1) {
+ sink->nbr_attachments_left = sink->nbr_attachments;
+ }
+
+ /* reset flag */
+ bcsink->new_file = FALSE;
+
+ /* set payload headers for new file */
+ gst_curl_smtp_sink_set_payload_headers_unlocked (bcsink);
+ }
+
+ bytes_to_send = MIN (block_size, array->len);
+ memcpy ((guint8 *) curl_ptr, array->data, bytes_to_send);
+ g_byte_array_remove_range (array, 0, bytes_to_send);
+
+ return bytes_to_send;
+}
+
+static size_t
+transfer_chunk (void *curl_ptr, TransferBuffer * buffer, Base64Chunk * chunk,
+ size_t block_size, guint * last_chunk)
+{
+ size_t bytes_to_send;
+ const guchar *data_in = buffer->ptr;
+ size_t data_in_offset = buffer->offset;
+ gint state = chunk->state;
+ gint save = chunk->save;
+ GByteArray *array = chunk->chunk_array;
+ gchar *data_out;
+
+ bytes_to_send = MIN (block_size, buffer->len);
+
+ if (bytes_to_send == 0) {
+ bytes_to_send = MIN (block_size, array->len);
+ }
+
+ /* base64 encode data */
+ if (buffer->len > 0) {
+ gsize len;
+ gchar *ptr_in;
+ gchar *ptr_out;
+ gsize size_out;
+ gint i;
+
+ /* if line-breaking is enabled, at least: ((len / 3 + 1) * 4 + 4) / 72 + 1
+ * bytes of extra space is required. However, additional <CR>'s are required,
+ * thus we need ((len / 3 + 2) * 4 + 4) / 72 + 2 extra bytes.
+ */
+ size_out = (bytes_to_send / 3 + 1) * 4 + 4 + bytes_to_send +
+ ((bytes_to_send / 3 + 2) * 4 + 4) / 72 + 2;
+
+ data_out = g_malloc (size_out);
+ len = g_base64_encode_step (data_in + data_in_offset, bytes_to_send, TRUE,
+ data_out, &state, &save);
+ chunk->state = state;
+ chunk->save = save;
+
+ /* LF->CRLF filter */
+ ptr_in = ptr_out = data_out;
+ for (i = 0; i < len; i++) {
+ if (*ptr_in == '\n') {
+ *ptr_in = '\r';
+ g_byte_array_append (array, (guint8 *) ptr_out, ptr_in - ptr_out);
+ g_byte_array_append (array, (guint8 *) "\r\n", strlen ("\r\n"));
+ ptr_out = ptr_in + 1;
+ }
+ ptr_in++;
+ }
+ if (ptr_in - ptr_out) {
+ g_byte_array_append (array, (guint8 *) ptr_out, ptr_in - ptr_out);
+ }
+
+ g_free (data_out);
+ data_out = NULL;
+
+ buffer->offset += bytes_to_send;
+ buffer->len -= bytes_to_send;
+
+ bytes_to_send = MIN (block_size, array->len);
+ memcpy ((guint8 *) curl_ptr, array->data, bytes_to_send);
+ g_byte_array_remove_range (array, 0, bytes_to_send);
+
+ if (array->len == 0) {
+ *last_chunk = 1;
+
+ }
+
+ return bytes_to_send;
+ }
+
+ /* at this point all data has been encoded */
+ memcpy ((guint8 *) curl_ptr, array->data, bytes_to_send);
+ g_byte_array_remove_range (array, 0, bytes_to_send);
+ if (array->len == 0) {
+ *last_chunk = 1;
+ }
+
+ return bytes_to_send;
+}
+
+static size_t
+gst_curl_smtp_sink_transfer_data_buffer (GstCurlBaseSink * bcsink,
+ void *curl_ptr, size_t block_size, guint * last_chunk)
+{
+ GstCurlSmtpSink *sink = GST_CURL_SMTP_SINK (bcsink);
+ size_t bytes_to_send;
+
+ if (sink->payload_headers && sink->payload_headers->len) {
+ return transfer_payload_headers (sink, curl_ptr, block_size);
+ }
+
+ if (sink->base64_chunk != NULL) {
+ bytes_to_send =
+ transfer_chunk (curl_ptr, bcsink->transfer_buf, sink->base64_chunk,
+ block_size, last_chunk);
+
+ GST_OBJECT_LOCK (sink);
+ if (sink->eos) {
+ gst_curl_smtp_sink_notify_transfer_end_unlocked (sink);
+ }
+ GST_OBJECT_UNLOCK (sink);
+
+ return bytes_to_send;
+ }
+
+ /* we should never get here */
+ return 0;
+}
+
+static size_t
+transfer_payload_headers (GstCurlSmtpSink * sink,
+ void *curl_ptr, size_t block_size)
+{
+ size_t bytes_to_send;
+ GByteArray *headers = sink->payload_headers;
+
+ bytes_to_send = MIN (block_size, headers->len);
+ memcpy ((guint8 *) curl_ptr, headers->data, bytes_to_send);
+ g_byte_array_remove_range (headers, 0, bytes_to_send);
+
+
+ if (headers->len == 0) {
+ g_byte_array_free (headers, TRUE);
+ sink->payload_headers = NULL;
+ }
+
+ return bytes_to_send;
+}
+
+
+static gboolean
+gst_curl_smtp_sink_prepare_transfer (GstCurlBaseSink * bcsink)
+{
+ GstCurlSmtpSink *sink = GST_CURL_SMTP_SINK (bcsink);
+ CURLcode res;
+ gboolean ret = TRUE;
+
+ if (sink->pop_location && strlen (sink->pop_location)) {
+ if ((sink->pop_curl = curl_easy_init ()) == NULL) {
+ GST_DEBUG_OBJECT (sink, "POP protocol: failed to create handler");
+ GST_ELEMENT_ERROR (sink, RESOURCE, WRITE,
+ ("POP protocol: failed to create handler"), (NULL));
+
+ return FALSE;
+ }
+
+ curl_easy_setopt (sink->pop_curl, CURLOPT_URL, sink->pop_location);
+ if (sink->pop_user != NULL && strlen (sink->pop_user) &&
+ sink->pop_passwd != NULL && strlen (sink->pop_passwd)) {
+ curl_easy_setopt (sink->pop_curl, CURLOPT_USERNAME, sink->pop_user);
+ curl_easy_setopt (sink->pop_curl, CURLOPT_PASSWORD, sink->pop_passwd);
+ }
+ }
+
+ if (sink->pop_curl == NULL) {
+ goto end;
+ }
+
+ /* ready to initialize connection to POP server */
+ res = curl_easy_perform (sink->pop_curl);
+ if (res != CURLE_OK) {
+ GST_DEBUG_OBJECT (sink, "POP transfer failed: %s",
+ curl_easy_strerror (res));
+ GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, ("POP transfer failed: %s",
+ curl_easy_strerror (res)), (NULL));
+
+ ret = FALSE;
+ }
+
+ curl_easy_cleanup (sink->pop_curl);
+ sink->pop_curl = NULL;
+
+end:
+ return ret;
+}
diff --git a/ext/curl/gstcurlsmtpsink.h b/ext/curl/gstcurlsmtpsink.h
new file mode 100644
index 000000000..ce8dc20cf
--- /dev/null
+++ b/ext/curl/gstcurlsmtpsink.h
@@ -0,0 +1,87 @@
+/* GStreamer
+ * Copyright (C) 2011 Axis Communications <dev-gstreamer@axis.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_CURL_SMTP_SINK__
+#define __GST_CURL_SMTP_SINK__
+
+#include <gst/gst.h>
+#include <gst/base/gstbasesink.h>
+#include <curl/curl.h>
+#include "gstcurltlssink.h"
+
+G_BEGIN_DECLS
+#define GST_TYPE_CURL_SMTP_SINK \
+ (gst_curl_smtp_sink_get_type())
+#define GST_CURL_SMTP_SINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_CURL_SMTP_SINK, GstCurlSmtpSink))
+#define GST_CURL_SMTP_SINK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_CURL_SMTP_SINK, GstCurlSmtpSinkClass))
+#define GST_IS_CURL_SMTP_SINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_CURL_SMTP_SINK))
+#define GST_IS_CURL_SMTP_SINK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_CURL_SMTP_SINK))
+typedef struct _GstCurlSmtpSink GstCurlSmtpSink;
+typedef struct _GstCurlSmtpSinkClass GstCurlSmtpSinkClass;
+
+typedef struct _Base64Chunk Base64Chunk;
+
+struct _Base64Chunk
+{
+ GByteArray *chunk_array;
+ gint save;
+ gint state;
+};
+
+struct _GstCurlSmtpSink
+{
+ GstCurlTlsSink parent;
+
+ /*< private > */
+ Base64Chunk *base64_chunk;
+ GByteArray *payload_headers;
+ struct curl_slist *curl_recipients;
+ gchar *mail_rcpt;
+ gchar *mail_from;
+ gchar *subject;
+ gchar *message_body;
+ gchar *content_type;
+ gboolean use_ssl;
+ gint nbr_attachments;
+ gchar *pop_user;
+ gchar *pop_passwd;
+ gchar *pop_location;
+ CURL *pop_curl;
+
+ gboolean transfer_end;
+ GCond *cond_transfer_end;
+
+ gint nbr_attachments_left;
+ gboolean reset_transfer_options;
+ gboolean eos;
+};
+
+struct _GstCurlSmtpSinkClass
+{
+ GstCurlTlsSinkClass parent_class;
+};
+
+GType gst_curl_smtp_sink_get_type (void);
+
+G_END_DECLS
+#endif
diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am
index a5c1ca229..e4e6aa9a6 100644
--- a/tests/check/Makefile.am
+++ b/tests/check/Makefile.am
@@ -150,7 +150,8 @@ endif
if USE_CURL
check_curl = elements/curlhttpsink \
elements/curlfilesink \
- elements/curlftpsink
+ elements/curlftpsink \
+ elements/curlsmtpsink
else
check_curl =
endif
diff --git a/tests/check/elements/curlsmtpsink.c b/tests/check/elements/curlsmtpsink.c
new file mode 100644
index 000000000..8b401e129
--- /dev/null
+++ b/tests/check/elements/curlsmtpsink.c
@@ -0,0 +1,208 @@
+/*
+ * Unittest for curlsmtpsink
+ */
+
+#include <gst/check/gstcheck.h>
+#include <glib/gstdio.h>
+#include <curl/curl.h>
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS_ANY);
+
+static GstPad *srcpad;
+
+static GstElement *sink;
+
+static GstElement *
+setup_curlsmtpsink (void)
+{
+ GST_DEBUG ("setup_curlsmtpsink");
+ sink = gst_check_setup_element ("curlsmtpsink");
+ srcpad = gst_check_setup_src_pad (sink, &srctemplate);
+ gst_pad_set_active (srcpad, TRUE);
+
+ return sink;
+}
+
+static void
+cleanup_curlsmtpsink (GstElement * sink)
+{
+ GST_DEBUG ("cleanup_curlsmtpsink");
+
+ gst_check_teardown_src_pad (sink);
+ gst_check_teardown_element (sink);
+}
+
+GST_START_TEST (test_properties)
+{
+ GstElement *sink;
+ gchar *res_location = NULL;
+ gchar *res_file_name = NULL;
+ gchar *res_mail_rcpt = NULL;
+ gchar *res_mail_from = NULL;
+ gchar *res_subj = NULL;
+ gchar *res_msg = NULL;
+ gchar *res_usr = NULL;
+ gchar *res_passwd = NULL;
+ gchar *res_pop_location = NULL;
+ gchar *res_pop_usr = NULL;
+ gchar *res_pop_passwd = NULL;
+ guint res_nbr_attach;
+ gboolean res_use_ssl;
+
+ sink = setup_curlsmtpsink ();
+
+ g_object_set (G_OBJECT (sink), "location", "mylocation", NULL);
+ g_object_set (G_OBJECT (sink), "file-name", "myfile", NULL);
+ g_object_set (G_OBJECT (sink), "user", "usr", NULL);
+ g_object_set (G_OBJECT (sink), "passwd", "passwd", NULL);
+ g_object_set (G_OBJECT (sink), "mail-rcpt", "rcpt", NULL);
+ g_object_set (G_OBJECT (sink), "mail-from", "sender", NULL);
+ g_object_set (G_OBJECT (sink), "subject", "subject", NULL);
+ g_object_set (G_OBJECT (sink), "message-body", "message", NULL);
+ g_object_set (G_OBJECT (sink), "nbr-attachments", 5, NULL);
+ g_object_set (G_OBJECT (sink), "use-ssl", TRUE, NULL);
+ g_object_set (G_OBJECT (sink), "pop-location", "poploc", NULL);
+ g_object_set (G_OBJECT (sink), "pop-user", "popusr", NULL);
+ g_object_set (G_OBJECT (sink), "pop-passwd", "poppasswd", NULL);
+
+ g_object_get (sink,
+ "location", &res_location,
+ "file-name", &res_file_name,
+ "user", &res_usr,
+ "passwd", &res_passwd,
+ "mail-rcpt", &res_mail_rcpt,
+ "mail-from", &res_mail_from,
+ "subject", &res_subj,
+ "message-body", &res_msg,
+ "nbr-attachments", &res_nbr_attach,
+ "use-ssl", &res_use_ssl,
+ "pop-location", &res_pop_location,
+ "pop_user", &res_pop_usr,
+ "pop-passwd", &res_pop_passwd,
+ NULL);
+
+ fail_unless (strncmp (res_location, "mylocation", strlen ("mylocation"))
+ == 0);
+ fail_unless (strncmp (res_file_name, "myfile", strlen ("myfile"))
+ == 0);
+ fail_unless (strncmp (res_usr, "usr", strlen ("usr"))
+ == 0);
+ fail_unless (strncmp (res_passwd, "passwd", strlen ("passwd"))
+ == 0);
+ fail_unless (strncmp (res_mail_rcpt, "rcpt", strlen ("rcpt"))
+ == 0);
+ fail_unless (strncmp (res_mail_from, "sender", strlen ("sender"))
+ == 0);
+ fail_unless (strncmp (res_subj, "subject", strlen ("subject"))
+ == 0);
+ fail_unless (strncmp (res_msg, "message", strlen ("message"))
+ == 0);
+ fail_unless (strncmp (res_pop_location, "poploc", strlen ("poploc"))
+ == 0);
+ fail_unless (strncmp (res_pop_usr, "popusr", strlen ("popusr"))
+ == 0);
+ fail_unless (strncmp (res_pop_passwd, "poppasswd", strlen ("poppasswd"))
+ == 0);
+ fail_unless (res_nbr_attach == 5);
+ fail_unless (res_use_ssl == TRUE);
+ g_free (res_location);
+ g_free (res_file_name);
+ g_free (res_usr);
+ g_free (res_passwd);
+ g_free (res_mail_rcpt);
+ g_free (res_mail_from);
+ g_free (res_subj);
+ g_free (res_msg);
+ g_free (res_pop_location);
+ g_free (res_pop_usr);
+ g_free (res_pop_passwd);
+
+ /* change properties */
+ g_object_set (G_OBJECT (sink), "location", "newlocation", NULL);
+ g_object_set (G_OBJECT (sink), "file-name", "newfilename", NULL);
+ g_object_set (G_OBJECT (sink), "user", "newusr", NULL);
+ g_object_set (G_OBJECT (sink), "passwd", "newpasswd", NULL);
+ g_object_set (G_OBJECT (sink), "mail-rcpt", "rcpt1,rcpt2,rcpt3", NULL);
+ g_object_set (G_OBJECT (sink), "mail-from", "newsender", NULL);
+ g_object_set (G_OBJECT (sink), "subject", "newsubject", NULL);
+ g_object_set (G_OBJECT (sink), "message-body", "newmessage", NULL);
+ g_object_set (G_OBJECT (sink), "nbr-attachments", 1, NULL);
+ g_object_set (G_OBJECT (sink), "use-ssl", FALSE, NULL);
+ g_object_set (G_OBJECT (sink), "pop-location", "newpoploc", NULL);
+ g_object_set (G_OBJECT (sink), "pop-user", "newpopusr", NULL);
+ g_object_set (G_OBJECT (sink), "pop-passwd", "newpoppasswd", NULL);
+
+ g_object_get (sink,
+ "location", &res_location,
+ "file-name", &res_file_name,
+ "user", &res_usr,
+ "passwd", &res_passwd,
+ "pop_user", &res_pop_usr,
+ "pop-passwd", &res_pop_passwd,
+ "pop-location", &res_pop_location,
+ "nbr-attachments", &res_nbr_attach,
+ "subject", &res_subj,
+ "use-ssl", &res_use_ssl,
+ "message-body", &res_msg,
+ "mail-from", &res_mail_from,
+ "mail-rcpt", &res_mail_rcpt,
+ NULL);
+
+ fail_unless (strncmp (res_location, "newlocation", strlen ("newlocation"))
+ == 0);
+ fail_unless (strncmp (res_file_name, "newfilename", strlen ("newfilename"))
+ == 0);
+ fail_unless (strncmp (res_usr, "newusr", strlen ("newusr"))
+ == 0);
+ fail_unless (strncmp (res_passwd, "newpasswd", strlen ("newpasswd"))
+ == 0);
+ fail_unless (strncmp (res_mail_rcpt, "rcpt1,rcpt2,rcpt3",
+ strlen ("rcpt1,rcpt2,rcpt3")) == 0);
+ fail_unless (strncmp (res_mail_from, "newsender", strlen ("newsender"))
+ == 0);
+ fail_unless (strncmp (res_subj, "newsubject", strlen ("newsubject"))
+ == 0);
+ fail_unless (strncmp (res_msg, "newmessage", strlen ("newmessage"))
+ == 0);
+ fail_unless (strncmp (res_pop_location, "newpoploc", strlen ("newpoploc"))
+ == 0);
+ fail_unless (strncmp (res_pop_usr, "newpopusr", strlen ("newpopusr"))
+ == 0);
+ fail_unless (strncmp (res_pop_passwd, "newpoppasswd", strlen ("newpoppasswd"))
+ == 0);
+
+ fail_unless (res_nbr_attach == 1);
+ fail_unless (res_use_ssl == FALSE);
+ g_free (res_location);
+ g_free (res_file_name);
+ g_free (res_usr);
+ g_free (res_passwd);
+ g_free (res_mail_from);
+ g_free (res_mail_rcpt);
+ g_free (res_subj);
+ g_free (res_msg);
+ g_free (res_pop_location);
+ g_free (res_pop_usr);
+ g_free (res_pop_passwd);
+
+ cleanup_curlsmtpsink (sink);
+}
+GST_END_TEST;
+
+static Suite *
+curlsink_suite (void)
+{
+ Suite *s = suite_create ("curlsmtpsink");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_set_timeout (tc_chain, 20);
+ tcase_add_test (tc_chain, test_properties);
+
+ return s;
+}
+
+GST_CHECK_MAIN (curlsink);