mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
curl: new curlsmtpsink element
https://bugzilla.gnome.org/show_bug.cgi?id=653741
This commit is contained in:
parent
766dd8bb71
commit
3f20bbdcf4
7 changed files with 1237 additions and 7 deletions
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
928
ext/curl/gstcurlsmtpsink.c
Normal file
928
ext/curl/gstcurlsmtpsink.c
Normal file
|
@ -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;
|
||||
}
|
87
ext/curl/gstcurlsmtpsink.h
Normal file
87
ext/curl/gstcurlsmtpsink.h
Normal file
|
@ -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
|
|
@ -150,7 +150,8 @@ endif
|
|||
if USE_CURL
|
||||
check_curl = elements/curlhttpsink \
|
||||
elements/curlfilesink \
|
||||
elements/curlftpsink
|
||||
elements/curlftpsink \
|
||||
elements/curlsmtpsink
|
||||
else
|
||||
check_curl =
|
||||
endif
|
||||
|
|
208
tests/check/elements/curlsmtpsink.c
Normal file
208
tests/check/elements/curlsmtpsink.c
Normal file
|
@ -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);
|
Loading…
Reference in a new issue