Revert previous commit. Damn svn, didn't mean to delete the whole dir.

SVN revision: 84558
This commit is contained in:
Tom Hacohen 2013-06-17 09:48:48 +00:00
parent 8fa561dcb2
commit e3da2b895a
22 changed files with 900 additions and 0 deletions

1
AUTHORS Normal file
View File

@ -0,0 +1 @@
Leif Middelschulte <leif.middelschulte@gmail.com>

32
COPYING Normal file
View File

@ -0,0 +1,32 @@
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies of the Software and its Copyright notices. In addition publicly
documented acknowledgment must be given that this software has been used if no
source code of this software is made available publicly. Making the source
available publicly means including the source for this software with the
distribution, or a method to get this software via some reasonable mechanism
(electronic transfer via a network or media) as well as making an offer to
supply the source on request. This Copyright notice serves as an offer to
supply the source on on request as well. Instead of this, supplying
acknowledgments of use of this software in either Copyright notices, Manuals,
Publicity and Marketing documents or any documentation provided with any
product containing this software. This License does not apply to any software
that links to the libraries provided by this software (statically or
dynamically), but only to the software provided.
Please see the COPYING-PLAIN for a plain-english explanation of this notice
and its intent.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

33
COPYING-PLAIN Normal file
View File

@ -0,0 +1,33 @@
Plain English Copyright Notice
This file is not intended to be the actual License. The reason this file
exists is that we here are programmers and engineers. We aren't lawyers. We
provide licenses that we THINK say the right things, but we have our own
intentions at heart. This is a plain-english explanation of what those
intentions are, and if you follow them you will be within the "spirit" of
the license.
The intent is for us to enjoy writing software that is useful to us (the
AUTHORS) and allow others to use it freely and also benefit from the work we
put into making it. We don't want to restrict others using it. They should
not *HAVE* to make the source code of the applications they write that
simply link to these libraries (be that statically or dynamically), or for
them to be limited as to what license they choose to use (be it open, closed
or anything else). But we would like to know you are using these libraries.
We simply would like to know that it has been useful to someone. This is why
we ask for acknowledgement of some sort.
You can do what you want with the source of this software - it doesn't
matter. We still have it here for ourselves and it is open and free to use
and download and play with. It can't be taken away. We don't really mind what
you do with the source to your software. We would simply like to know that
you are using it - especially if it makes it to a commerical product. If you
simply e-mail all the AUTHORS (see COPYING and AUTHORS files) telling us, and
then make sure you include a paragraph or page in the manual for the product
with the copyright notice and state that you used this software, we will be
very happy. If you want to contribute back modifications and fixes you may have
made we will welcome those too with open arms (generally). If you want help
with changes needed, ports needed or features to be added, arrangements can
be easily made with some dialogue.
Leif Middelschulte <leif.middelschulte@gmail.com>

0
ChangeLog Normal file
View File

11
INSTALL Normal file
View File

@ -0,0 +1,11 @@
COMPILING and INSTALLING:
If you got a official release tar archive do:
./autogen.sh
Then to compile:
make
To install:
make install

25
Makefile.am Normal file
View File

@ -0,0 +1,25 @@
MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess config.h.in \
config.sub configure depcomp install-sh ltmain.sh \
missing module.desktop config.rpath mkinstalldirs
SUBDIRS = src
EDJE_FLAGS = -v \
-id $(top_srcdir)/images
filesdir = $(datadir)
files_DATA = module.desktop e-module-share.edj
EXTRA_DIST = module.desktop.in \
e_modules-share.spec.in \
e-module-share.edc \
images/module_icon.png
%.edj: %.edc
$(EDJE_CC) $(EDJE_FLAGS) $< $@
clean-local:
rm -rf e-module-share.edj module.desktop e_modules-share.spec *~
uninstall:
rm -rf $(DESTDIR)$(datadir)

0
NEWS Normal file
View File

2
README Normal file
View File

@ -0,0 +1,2 @@
This module shall share data from the clipboard online.
The user shall be given a link to the share.

6
TODO Normal file
View File

@ -0,0 +1,6 @@
- Store and restore old links for every instance
- Enable HTTPS
Future:
- Share files
- Extend to more services (1Click hosters and local p2p)

16
autogen.sh Executable file
View File

@ -0,0 +1,16 @@
#!/bin/sh
rm -rf autom4te.cache
rm -f aclocal.m4 ltmain.sh
touch README
echo "Running aclocal..." ; aclocal $ACLOCAL_FLAGS || exit 1
echo "Running autoheader..." ; autoheader || exit 1
echo "Running autoconf..." ; autoconf || exit 1
echo "Running libtoolize..." ; (libtoolize --copy --automake || glibtoolize --automake) || exit 1
echo "Running automake..." ; automake --add-missing --copy --gnu || exit 1
if [ -z "$NOCONFIGURE" ]; then
./configure "$@"
fi

69
configure.ac Normal file
View File

@ -0,0 +1,69 @@
dnl Process this file with autoconf to produce a configure script.
# get rid of that stupid cache mechanism
rm -f config.cache
AC_INIT(share, 0.0.1, enlightenment-devel@lists.sourceforge.net)
AC_PREREQ(2.52)
AC_CONFIG_SRCDIR(configure.ac)
AC_CANONICAL_BUILD
AC_CANONICAL_HOST
AC_ISC_POSIX
AM_INIT_AUTOMAKE(1.6)
AC_CONFIG_HEADERS(config.h)
AC_PROG_CC
AC_HEADER_STDC
AC_C_CONST
define([AC_LIBTOOL_LANG_CXX_CONFIG], [:])dnl
define([AC_LIBTOOL_LANG_F77_CONFIG], [:])dnl
AC_PROG_LIBTOOL
PKG_CHECK_MODULES(E, [enlightenment])
release=$(pkg-config --variable=release enlightenment)
MODULE_ARCH="$host_os-$host_cpu-$release"
AC_SUBST(MODULE_ARCH)
AC_DEFINE_UNQUOTED(MODULE_ARCH, "$MODULE_ARCH", "Module architecture")
PKG_CHECK_MODULES(JSON, [json])
#
# Platform specific setup
#
#############################
case $host_os in
linux*)
PKG_CHECK_MODULES(BSD, [libbsd])
;;
esac
# Find edje_cc
PKG_CHECK_MODULES(EDJE, [edje >= 0.5.0])
AC_ARG_WITH(edje-cc,
AC_HELP_STRING([--with-edje-cc=PATH], [specify a specific path to edje_cc]),
[
v=$withval;
EDJE_CC=$v
],[
EDJE_CC=$(pkg-config --variable=prefix edje)/bin/edje_cc
]
)
AC_SUBST(EDJE_CC)
AC_MSG_CHECKING([Which edje_cc to use])
AC_MSG_RESULT(${EDJE_CC})
datadir=$(pkg-config --variable=modules enlightenment)/${PACKAGE}
AC_ARG_ENABLE(homedir-install,
AS_HELP_STRING([--enable-homedir-install], [Install module in homedir]),
[ datadir="${HOME}/.e/e/modules/${PACKAGE}" ]
)
AC_OUTPUT([
Makefile
src/Makefile
e_modules-share.spec
module.desktop
], [
])

74
e-module-share.edc Normal file
View File

@ -0,0 +1,74 @@
collections {
images.image: "module_icon.png" COMP;
group {
name: "icon";
max: 48 48;
parts {
part {
name: "image";
type: IMAGE;
mouse_events: 0;
description {
state: "default" 0.00;
visible: 1;
aspect: 1.00 1.00;
aspect_preference: BOTH;
rel1 {
relative: 0.00 0.00;
offset: 0 0;
}
rel2 {
relative: 1.00 1.00;
offset: -1 -1;
}
image.normal: "module_icon.png";
}
}
}
}
group {
name: "modules/share/main";
max: 128 128;
parts {
part { name: "logo";
type: IMAGE;
description { state: "default" 0.0;
aspect: 1.0 1.0;
aspect_preference: BOTH;
rel1.offset: 0 0;
rel2.offset: -1 -1;
image.normal: "module_icon.png";
}
description { state: "active" 0.0;
inherit: "default" 0.0;
color: 255 255 255 128;
}
}
part { name: "inout";
type: RECT;
mouse_events: 1;
description { state: "default" 0.0;
color: 255 255 255 0;
}
}
}
programs {
program { name: "go_active";
signal: "active";
source: "";
action: STATE_SET "active" 0.0;
target: "logo";
transition: LINEAR 0.5;
}
program { name: "go_passive";
signal: "passive";
source: "";
action: STATE_SET "default" 0.0;
target: "logo";
transition: LINEAR 0.5;
}
}
}
}

48
e_modules-share.spec.in Normal file
View File

@ -0,0 +1,48 @@
%define module_name share
%{!?_rel:%{expand:%%global _rel 0.enl%{?dist}}}
Summary: %{module_name} module for the Enlightenment window manager
Name: e_modules-%{module_name}
Version: @VERSION@
Release: %{_rel}
License: BSD
Group: User Interface/Desktops
URL: http://www.enlightenment.org/
Source: ftp://ftp.enlightenment.org/pub/enlightenment/%{module_name}-%{version}.tar.gz
Packager: %{?_packager:%{_packager}}%{!?_packager:Michael Jennings <mej@eterm.org>}
Vendor: %{?_vendorinfo:%{_vendorinfo}}%{!?_vendorinfo:The Enlightenment Project (http://www.enlightenment.org/)}
Distribution: %{?_distribution:%{_distribution}}%{!?_distribution:%{_vendor}}
BuildRequires: ecore-devel, evas-devel, edje-bin
BuildRequires: edje-devel, eet-devel, enlightenment-devel >= 0.16.999
Requires: enlightenment >= 0.16.999
BuildRoot: %{_tmppath}/%{name}-%{version}-root
%description
%{module_name} module for the Enlightenment window manager.
%prep
%setup -q -n %{module_name}-%{version}
%build
%{configure}
%{__make} %{?_smp_mflags} %{?mflags}
%install
%{__make} %{?mflags_install} DESTDIR=$RPM_BUILD_ROOT install
%{find_lang} %{module_name} || true > %{module_name}.lang
%clean
test "x$RPM_BUILD_ROOT" != "x/" && rm -rf $RPM_BUILD_ROOT
%post
/sbin/ldconfig
%postun
/sbin/ldconfig
%files -f %{module_name}.lang
%defattr(-, root, root)
%doc AUTHORS ChangeLog COPYING* INSTALL NEWS README
%{_libdir}/enlightenment/modules/%{module_name}*
%changelog

BIN
images/module_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

6
images/module_icon.svg Executable file
View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" width="95.421px" height="90.213px" viewBox="0 0 95.421 90.213" enable-background="new 0 0 95.421 90.213" xml:space="preserve">
<path d="M6.301,90.211C2.818,90.209,0.002,87.394,0,83.913l0,0V18.394c0.002-3.481,2.818-6.297,6.301-6.299l0,0h33.782l-9.003,9H9 v60.117l57.469,0.002V69.125l9.002-9l-0.002,23.788c-0.003,3.479-2.818,6.296-6.3,6.3l0,0L6.301,90.211L6.301,90.211z"/>
<path d="M66.171,11.301V0l29.25,29.25L66.046,58.625v-11.75c0,0-14.586-2.894-29.583,6.458 c-8.209,5.084-13.752,11.773-17.167,17.042c0,0,1.11-18.25,11.61-34.875C44.033,14.716,66.171,11.301,66.171,11.301z"/>
<path fill="#000000" d="M225.3,90.211c-3.482-0.002-6.299-2.817-6.301-6.298l0,0V18.394c0.002-3.481,2.818-6.297,6.301-6.299l0,0 h33.783l-9.004,9H228v60.117l57.47,0.002V69.125l9.002-9l-0.002,23.788c-0.003,3.479-2.818,6.296-6.3,6.3l0,0L225.3,90.211 L225.3,90.211z"/>
<path fill="#000000" d="M285.171,11.301V0l29.25,29.25l-29.375,29.375v-11.75c0,0-17.23-1.192-29.584,6.458 c-8.209,5.084-13.104,10.167-17.166,17.042c0,0,1.109-18.25,11.609-34.875C263.033,14.716,285.171,11.301,285.171,11.301z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

0
m4/.svnignore Normal file
View File

6
module.desktop.in Normal file
View File

@ -0,0 +1,6 @@
[Desktop Entry]
Type=Link
Name=Share
Icon=e-module-share
X-Enlightenment-ModuleType=utils
Comment=Gadget that shares your clipboard content online and puts a link to it into your clipboard

22
src/Makefile.am Normal file
View File

@ -0,0 +1,22 @@
MAINTAINERCLEANFILES = Makefile.in
INCLUDES = -I. \
-I$(top_srcdir) \
-I$(includedir) \
@E_CFLAGS@ \
@JSON_CFLAGS@ \
@BSD_CFLAGS@
pkgdir = $(datadir)/$(MODULE_ARCH)
pkg_LTLIBRARIES = module.la
module_la_SOURCES = e_mod_main.c \
e_mod_main.h \
e_share.h \
sourcedrop.c
module_la_LIBADD = @E_LIBS@ @JSON_LIBS@ @BSD_LIBS@ -lm
module_la_LDFLAGS = -module -avoid-version
module_la_DEPENDENCIES = $(top_builddir)/config.h
clean-local:
rm -rf *~

387
src/e_mod_main.c Normal file
View File

@ -0,0 +1,387 @@
#include "e_mod_main.h"
#include "e_share.h"
#include <string.h>
#define __UNUSED__
#define _(S) S
/* actual module specifics */
typedef struct _Instance Instance;
struct _Instance
{
E_Gadcon_Client *gcc;
E_Menu *menu;
Ecore_X_Window win;
Evas_Object *o_button;
Eina_List *handlers;
Eina_List *shares;
};
/* gadcon requirements */
static E_Gadcon_Client *_gc_init(E_Gadcon * gc, const char *name, const char *id, const char *style);
static void _gc_shutdown(E_Gadcon_Client * gcc);
static void _gc_orient(E_Gadcon_Client * gcc, E_Gadcon_Orient orient);
static const char *_gc_label(const E_Gadcon_Client_Class *client_class);
static Evas_Object *_gc_icon(const E_Gadcon_Client_Class *client_class, Evas * evas);
static const char *_gc_id_new(const E_Gadcon_Client_Class *client_class);
static void _share_button_cb_mouse_down(void *data, Evas *evas, Evas_Object *obj, Evas_Event_Mouse_Down *ev);
static Eina_Bool _share_x_selection_notify_handler(Instance *instance, int type, void *event);
static void _share_menu_post_cb(void *data, E_Menu *menu __UNUSED__);
static void _share_menu_share_request_click_cb(Instance *inst, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__);
static void _share_menu_share_item_click_cb(Share_Data *selected_share, E_Menu *m, E_Menu_Item *mi);
static void _share_open_link_in_browser(const Share_Data *sd);
static void _share_notify(const Share_Data *sd);
static void _share_notification_clicked_cb(void *data, unsigned int id);
static void _free_share_data(Share_Data *sd);
static E_Module *share_module = NULL;
/* and actually define the gadcon class that this module provides (just 1) */
static const E_Gadcon_Client_Class _gadcon_class = {
GADCON_CLIENT_CLASS_VERSION,
"share",
{
_gc_init, _gc_shutdown, _gc_orient, _gc_label, _gc_icon, _gc_id_new, NULL,
e_gadcon_site_is_not_toolbar
},
E_GADCON_CLIENT_STYLE_PLAIN
};
static E_Gadcon_Client *
_gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style)
{
Evas_Object *o;
E_Gadcon_Client *gcc;
Instance *inst;
inst = E_NEW(Instance, 1);
/*
char buf[PATH_MAX];
snprintf(buf, sizeof(buf), "%s/e-module-share.edj", e_module_dir_get(share_module));
o = edje_object_add(gc->evas);
if (!e_theme_edje_object_set(o, "base/theme/modules/share", "modules/share/main"))
edje_object_file_set(o, buf, "modules/share/main");
edje_object_signal_emit(o, "passive", "");
*/
o = e_icon_add(gc->evas);
e_icon_fdo_icon_set(o, "emblem-shared");
evas_object_show(o);
gcc = e_gadcon_client_new(gc, name, id, style, o);
gcc->data = inst;
inst->gcc = gcc;
inst->win = ecore_evas_window_get(gc->ecore_evas);
inst->o_button = o;
e_gadcon_client_util_menu_attach(gcc);
evas_object_event_callback_add(inst->o_button, EVAS_CALLBACK_MOUSE_DOWN, (Evas_Object_Event_Cb)_share_button_cb_mouse_down, inst);
E_LIST_HANDLER_APPEND(inst->handlers, ECORE_X_EVENT_SELECTION_NOTIFY, _share_x_selection_notify_handler, inst);
return gcc;
}
static void
_gc_shutdown(E_Gadcon_Client *gcc)
{
Instance *inst;
inst = gcc->data;
E_FREE_LIST(inst->handlers, ecore_event_handler_del);
inst->handlers = NULL;
if (inst->menu)
{
e_menu_post_deactivate_callback_set(inst->menu, NULL, NULL);
e_object_del(E_OBJECT(inst->menu));
inst->menu = NULL;
}
E_FREE_LIST(inst->shares, _free_share_data);
inst->shares = NULL;
evas_object_del(inst->o_button);
E_FREE(inst);
}
static void
_gc_orient(E_Gadcon_Client *gcc, E_Gadcon_Orient orient)
{
e_gadcon_client_aspect_set (gcc, 16, 16);
e_gadcon_client_min_size_set (gcc, 16, 16);
}
static const char *
_gc_label (const E_Gadcon_Client_Class *client_class)
{
return "Share";
}
static Evas_Object *
_gc_icon(const E_Gadcon_Client_Class *client_class, Evas * evas)
{
Evas_Object *o;
/*
char buf[PATH_MAX];
o = edje_object_add(evas);
snprintf (buf, sizeof(buf), "%s/e-module-share.edj", e_module_dir_get(share_module));
edje_object_file_set(o, buf, "icon");
*/
o = e_icon_add(evas);
e_icon_fdo_icon_set(o, "emblem-shared");
return o;
}
static const char *
_gc_id_new (const E_Gadcon_Client_Class *client_class)
{
return _gadcon_class.name;
}
static void
_share_button_cb_mouse_down(void *data, Evas *evas, Evas_Object *obj, Evas_Event_Mouse_Down *ev)
{
Instance *inst = (Instance*)data;
Evas_Coord x, y, w, h;
int cx, cy;
int dir;
E_Menu_Item *mi;
Eina_List *it;
Share_Data *share;
if (!inst) return;
if ((ev->button == 1) && (!inst->menu))
{
/* Coordinates and sizing */
evas_object_geometry_get(inst->o_button, &x, &y, &w, &h);
e_gadcon_canvas_zone_geometry_get(inst->gcc->gadcon, &cx, &cy,
NULL, NULL);
x += cx;
y += cy;
inst->menu = e_menu_new();
mi = e_menu_item_new(inst->menu);
e_menu_item_label_set(mi, _("Share Clipboard Content"));
e_menu_item_callback_set(mi, (E_Menu_Cb)_share_menu_share_request_click_cb, inst);
mi = e_menu_item_new(inst->menu);
e_menu_item_separator_set(mi, EINA_TRUE);
EINA_LIST_FOREACH(inst->shares, it, share)
{
mi = e_menu_item_new(inst->menu);
e_menu_item_label_set(mi, share->name);
e_menu_item_callback_set(mi, (E_Menu_Cb)_share_menu_share_item_click_cb, share);
}
e_menu_post_deactivate_callback_set(inst->menu,
_share_menu_post_cb, inst);
/* Proper menu orientation */
switch (inst->gcc->gadcon->orient)
{
case E_GADCON_ORIENT_TOP:
case E_GADCON_ORIENT_CORNER_TL:
case E_GADCON_ORIENT_CORNER_TR:
dir = E_MENU_POP_DIRECTION_DOWN;
break;
case E_GADCON_ORIENT_BOTTOM:
case E_GADCON_ORIENT_CORNER_BL:
case E_GADCON_ORIENT_CORNER_BR:
dir = E_MENU_POP_DIRECTION_UP;
break;
case E_GADCON_ORIENT_LEFT:
case E_GADCON_ORIENT_CORNER_LT:
case E_GADCON_ORIENT_CORNER_LB:
dir = E_MENU_POP_DIRECTION_RIGHT;
break;
case E_GADCON_ORIENT_RIGHT:
case E_GADCON_ORIENT_CORNER_RT:
case E_GADCON_ORIENT_CORNER_RB:
dir = E_MENU_POP_DIRECTION_LEFT;
break;
case E_GADCON_ORIENT_FLOAT:
case E_GADCON_ORIENT_HORIZ:
case E_GADCON_ORIENT_VERT:
default:
dir = E_MENU_POP_DIRECTION_AUTO;
break;
}
e_gadcon_locked_set(inst->gcc->gadcon, EINA_TRUE);
/* We display not relatively to the gadget, but similarly to
* the start menu - thus the need for direction etc.
*/
e_menu_activate_mouse(inst->menu,
e_util_zone_current_get
(e_manager_current_get()),
x, y, w, h, dir, ev->timestamp);
}
}
static Eina_Bool
_share_x_selection_notify_handler(Instance *instance, int type, void *event)
{
Ecore_X_Event_Selection_Notify *ev;
Share_Data *sd = NULL;
if (!instance)
return EINA_TRUE;
ev = event;
if ((ev->selection == ECORE_X_SELECTION_CLIPBOARD) &&
(strcmp(ev->target, ECORE_X_SELECTION_TARGET_UTF8_STRING) == 0))
{
Ecore_X_Selection_Data_Text *text_data;
text_data = ev->data;
if ((text_data->data.content == ECORE_X_SELECTION_CONTENT_TEXT) &&
(text_data->text))
{
char buf[20];
if (text_data->data.length == 0) return EINA_TRUE;
sd = E_NEW(Share_Data, 1);
sd->inst = instance;
snprintf(buf, ((text_data->data.length >= sizeof(buf)) ? (sizeof(buf) - 1) : text_data->data.length), text_data->text);
asprintf(&sd->name, "%s", buf);
asprintf(&sd->content, "%s", text_data->text);
sourcedrop_share(sd);
}
}
return ECORE_CALLBACK_PASS_ON;
}
/* Updates the X selection with the selected text of the entry */
void
_clipboard_update(const char *text, const Instance *inst)
{
EINA_SAFETY_ON_NULL_RETURN(inst);
EINA_SAFETY_ON_NULL_RETURN(text);
ecore_x_selection_clipboard_set(inst->win, text, strlen(text) + 1);
}
void e_share_upload_completed(Share_Data *sd)
{
if (!sd) return;
((Instance*)sd->inst)->shares = eina_list_append(((Instance*)sd->inst)->shares, sd);
_share_notify(sd);
_clipboard_update(sd->url, sd->inst);
}
static void
_share_menu_share_request_click_cb(Instance *inst, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
{
if (!inst) return;
ecore_x_selection_clipboard_request(inst->win,
ECORE_X_SELECTION_TARGET_UTF8_STRING);
}
static void
_share_menu_share_item_click_cb(Share_Data *selected_share, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
{
_share_open_link_in_browser(selected_share);
}
static void
_share_notify(const Share_Data *sd)
{
char buf[256];
E_Notification_Notify *n = E_NEW(E_Notification_Notify, 1);
if (!sd || !n)
return;
n->id = 0;
n->app_name = _("E Share");
n->sumary = _("Your content has been shared.");
snprintf(buf, (sizeof(buf) - 1), _("Your clipboard's content is now available at <highlight>%s</highlight>."), sd->url);
n->body = buf;
n->icon.icon = "e";
n->timeout = 2;
e_notification_client_send(n, NULL /*_share_notification_clicked_cb*/, sd);
}
static void
_share_open_link_in_browser(const Share_Data *sd)
{
char buf[256];
if (!sd)
return;
snprintf(buf, (sizeof(buf) - 1), "xdg-open %s", sd->url);
e_exec(e_gadcon_client_zone_get(((Instance*)sd->inst)->gcc), NULL, buf, NULL, NULL);
}
static void
_share_notification_clicked_cb(void *data, unsigned int id)
{
if (!data)
return;
_share_open_link_in_browser((Share_Data*)data);
}
static void
_share_menu_post_cb(void *data, E_Menu *menu __UNUSED__)
{
Instance *inst = data;
if (!inst) return;
e_gadcon_locked_set(inst->gcc->gadcon, EINA_FALSE);
inst->menu = NULL;
}
static void _free_share_data(Share_Data *sd)
{
free(sd->name);
free(sd->content);
free(sd->url);
free(sd);
}
/* module setup */
EAPI E_Module_Api e_modapi = {
E_MODULE_API_VERSION,
"Share"
};
EAPI void *
e_modapi_init (E_Module * m)
{
share_module = m;
sourcedrop_init();
e_gadcon_provider_register(&_gadcon_class);
return share_module;
}
EAPI int
e_modapi_shutdown (E_Module * m)
{
sourcedrop_shutdown();
share_module = NULL;
e_gadcon_provider_unregister(&_gadcon_class);
return 1;
}
EAPI int
e_modapi_save(E_Module * m)
{
return 1;
}

12
src/e_mod_main.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef E_MOD_MAIN_H
#define E_MOD_MAIN_H
#include <e.h>
EAPI extern E_Module_Api e_modapi;
EAPI void *e_modapi_init (E_Module *m);
EAPI int e_modapi_shutdown (E_Module *m);
EAPI int e_modapi_save (E_Module *m);
#endif

22
src/e_share.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef __E_SHARE_H__
#define __E_SHARE_H__
#undef LOG
#define LOG(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
typedef struct _Share_Data {
void *inst;
char *name;
char *content;
char *url;
} Share_Data;
/* API used by submodules */
void e_share_upload_completed(Share_Data *share_data);
/* Submodules' functions */
void sourcedrop_init(void);
void sourcedrop_share(Share_Data *share_data);
void sourcedrop_shutdown(void);
#endif

128
src/sourcedrop.c Normal file
View File

@ -0,0 +1,128 @@
#include <ctype.h>
#include <json/json.h>
#ifdef __linux__
#include <bsd/string.h> // strlcpy, etc. found in libbsd
#else
#include <string.h>
#endif
#include "e_mod_main.h"
#include "e_share.h"
#define BUFFER_SIZE_MAX 4096
#define DROPNAME "Sourcedrop"
#define SOURCEDROP_URL "http://www.sourcedrop.net/paste"
#define RECOGNITION_STRING "Location: "
static Ecore_Event_Handler *handler = NULL;
static Eina_Bool __upload_completed_cb(void *data, int type, Ecore_Con_Event_Url_Complete *ev);
static json_object *jarray, *jparent;
/* Converts an integer value to its hex character*/
char to_hex(const char code) {
static char hex[] = "0123456789abcdef";
return hex[code & 15];
}
/* Returns a url-encoded version of str */
/* IMPORTANT: be sure to free() the returned string after use */
char *url_encode(const char *str) {
const char *pstr = str;
char *buf = malloc(strlen(str) * 3 + 1), *pbuf = buf;
while (*pstr) {
if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~')
*pbuf++ = *pstr;
else if (*pstr == ' ')
*pbuf++ = '+';
else
*pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15);
pstr++;
}
*pbuf = '\0';
return buf;
}
const char *json_encode(const char *title, const char *content)
{
const char *encoded_string = NULL;
jarray = json_object_new_array();
jparent = json_object_new_object();
json_object_object_add(jparent, "title", json_object_new_string(title));
json_object_object_add(jparent, "content", json_object_new_string(content));
json_object_array_add(jarray, jparent);
encoded_string = json_object_to_json_string(jarray);
return encoded_string;
}
static Eina_Bool
__upload_completed_cb(void *data, int type, Ecore_Con_Event_Url_Complete *ev)
{
char buf[BUFFER_SIZE_MAX];
const Eina_List *headers = NULL, *it;
const char *header = NULL;
Share_Data *sd = NULL;
json_object_put(jarray);
jarray = NULL;
json_object_put(jparent);
jparent = NULL;
if (ev->status != 200)
{
LOG("E_SHARE/" DROPNAME ": This is not supposed to happen. The server returned status code: %d\n", ev->status);
return ECORE_CALLBACK_RENEW;
}
headers = ecore_con_url_response_headers_get(ev->url_con);
EINA_LIST_FOREACH(headers, it, header)
{
if (strncmp(header, RECOGNITION_STRING, (sizeof(RECOGNITION_STRING) - 1)) == 0)
{
sd = ecore_con_url_data_get(ev->url_con);
strlcpy(buf, (char*)(header + sizeof(RECOGNITION_STRING) - 1), sizeof(buf));
asprintf(&sd->url, "%s", buf);
e_share_upload_completed(sd);
ecore_con_url_free(ev->url_con);
break;
}
}
return ECORE_CALLBACK_CANCEL;
}
void sourcedrop_share(Share_Data *sd)
{
Ecore_Con_Url *request_url = NULL;
char post_data[BUFFER_SIZE_MAX];
const char *json_encoded = NULL;
char *url_encoded = NULL;
EINA_SAFETY_ON_NULL_RETURN(sd);
json_encoded = json_encode(sd->name, sd->content);
request_url = ecore_con_url_new(SOURCEDROP_URL);
url_encoded = url_encode(json_encoded);
snprintf(post_data, (sizeof(post_data) - 1), "data=%s", url_encoded);
free(url_encoded);
ecore_con_url_data_set(request_url, (void*)sd);
ecore_con_url_post(request_url, (void*)post_data, sizeof(post_data), "application/x-www-form-urlencoded");
}
void sourcedrop_init(void)
{
ecore_init();
ecore_con_init();
handler = ecore_event_handler_add(ECORE_CON_EVENT_URL_COMPLETE, (Ecore_Event_Handler_Cb)__upload_completed_cb, NULL);
}
void sourcedrop_shutdown(void)
{
ecore_event_handler_del(handler);
handler = NULL;
ecore_con_shutdown();
ecore_shutdown();
}