pidgin/pidgin

aedbdb297552
Merged in rw_grim/pidgin (pull request #24)

1fb661b5f206
  • +0 -125
    libpurple/plugins/fortuneprofile.pl
  • +0 -22
    libpurple/plugins/mono/BooPlugin.boo
  • +0 -34
    libpurple/plugins/mono/GetBuddyBack.cs
  • +0 -38
    libpurple/plugins/mono/MPlugin.cs
  • +0 -19
    libpurple/plugins/mono/Makefile.am
  • +0 -4
    libpurple/plugins/mono/api/BlistNode.cs
  • +0 -9
    libpurple/plugins/mono/api/Buddy.cs
  • +0 -19
    libpurple/plugins/mono/api/BuddyList.cs
  • +0 -4
    libpurple/plugins/mono/api/Contact.cs
  • +0 -28
    libpurple/plugins/mono/api/Debug.cs
  • +0 -21
    libpurple/plugins/mono/api/Event.cs
  • +0 -4
    libpurple/plugins/mono/api/Group.cs
  • +0 -27
    libpurple/plugins/mono/api/Makefile.am
  • +0 -67
    libpurple/plugins/mono/api/PurplePlugin.cs
  • +0 -18
    libpurple/plugins/mono/api/Signal.cs
  • +0 -9
    libpurple/plugins/mono/api/Status.cs
  • +0 -25
    libpurple/plugins/mono/loader/Makefile.am
  • +0 -26
    libpurple/plugins/mono/loader/blist-glue.c
  • +0 -16
    libpurple/plugins/mono/loader/debug-glue.c
  • +0 -19
    libpurple/plugins/mono/loader/mono-glue.h
  • +0 -260
    libpurple/plugins/mono/loader/mono-helper.c
  • +0 -72
    libpurple/plugins/mono/loader/mono-helper.h
  • +0 -249
    libpurple/plugins/mono/loader/mono.c
  • +0 -131
    libpurple/plugins/mono/loader/signal-glue.c
  • +0 -16
    libpurple/plugins/mono/loader/status-glue.c
  • +0 -171
    libpurple/plugins/perl/Makefile.am
  • +0 -87
    libpurple/plugins/perl/Makefile.mingw
  • +0 -353
    libpurple/plugins/perl/common/Account.xs
  • +0 -166
    libpurple/plugins/perl/common/AccountOpts.xs
  • +0 -71
    libpurple/plugins/perl/common/BuddyIcon.xs
  • +0 -418
    libpurple/plugins/perl/common/BuddyList.xs
  • +0 -309
    libpurple/plugins/perl/common/Certificate.xs
  • +0 -329
    libpurple/plugins/perl/common/Cipher.xs
  • +0 -108
    libpurple/plugins/perl/common/Cmds.xs
  • +0 -87
    libpurple/plugins/perl/common/Connection.xs
  • +0 -435
    libpurple/plugins/perl/common/Conversation.xs
  • +0 -21
    libpurple/plugins/perl/common/Core.xs
  • +0 -72
    libpurple/plugins/perl/common/Debug.xs
  • +0 -12
    libpurple/plugins/perl/common/Idle.xs
  • +0 -129
    libpurple/plugins/perl/common/Log.xs
  • +0 -36
    libpurple/plugins/perl/common/MANIFEST
  • +0 -29
    libpurple/plugins/perl/common/Makefile.PL.in
  • +0 -128
    libpurple/plugins/perl/common/Makefile.mingw
  • +0 -42
    libpurple/plugins/perl/common/Network.xs
  • +0 -178
    libpurple/plugins/perl/common/Notify.xs
  • +0 -166
    libpurple/plugins/perl/common/Plugin.xs
  • +0 -188
    libpurple/plugins/perl/common/PluginPref.xs
  • +0 -126
    libpurple/plugins/perl/common/Pounce.xs
  • +0 -244
    libpurple/plugins/perl/common/Prefs.xs
  • +0 -102
    libpurple/plugins/perl/common/Presence.xs
  • +0 -86
    libpurple/plugins/perl/common/Proxy.xs
  • +0 -76
    libpurple/plugins/perl/common/Prpl.xs
  • +0 -129
    libpurple/plugins/perl/common/Purple.pm
  • +0 -108
    libpurple/plugins/perl/common/Purple.xs
  • +0 -648
    libpurple/plugins/perl/common/Request.xs
  • +0 -92
    libpurple/plugins/perl/common/Roomlist.xs
  • +0 -45
    libpurple/plugins/perl/common/SSLConn.xs
  • +0 -152
    libpurple/plugins/perl/common/SavedStatuses.xs
  • +0 -195
    libpurple/plugins/perl/common/Server.xs
  • +0 -34
    libpurple/plugins/perl/common/Signal.xs
  • +0 -37
    libpurple/plugins/perl/common/Sound.xs
  • +0 -267
    libpurple/plugins/perl/common/Status.xs
  • +0 -37
    libpurple/plugins/perl/common/Stringref.xs
  • +0 -437
    libpurple/plugins/perl/common/Util.xs
  • +0 -74
    libpurple/plugins/perl/common/Whiteboard.xs
  • +0 -122
    libpurple/plugins/perl/common/XMLNode.xs
  • +0 -179
    libpurple/plugins/perl/common/Xfer.xs
  • +0 -115
    libpurple/plugins/perl/common/fallback/const-c.inc
  • +0 -88
    libpurple/plugins/perl/common/fallback/const-xs.inc
  • +0 -310
    libpurple/plugins/perl/common/module.h
  • +0 -210
    libpurple/plugins/perl/common/typemap
  • +0 -18
    libpurple/plugins/perl/libpurpleperl.c
  • +0 -620
    libpurple/plugins/perl/perl-common.c
  • +0 -82
    libpurple/plugins/perl/perl-common.h
  • +0 -967
    libpurple/plugins/perl/perl-handlers.c
  • +0 -91
    libpurple/plugins/perl/perl-handlers.h
  • +0 -726
    libpurple/plugins/perl/perl.c
  • +0 -155
    libpurple/plugins/perl/scripts/account.pl
  • +0 -107
    libpurple/plugins/perl/scripts/buddy_list.pl
  • +0 -119
    libpurple/plugins/perl/scripts/conversation.pl
  • +0 -89
    libpurple/plugins/perl/scripts/count_down.pl
  • +0 -69
    libpurple/plugins/perl/scripts/function_list.pl
  • +0 -66
    libpurple/plugins/perl/scripts/gtk_frame_test.pl
  • +0 -58
    libpurple/plugins/perl/scripts/plugin_action.pl
  • +0 -103
    libpurple/plugins/perl/scripts/plugin_pref.pl
  • +0 -109
    libpurple/plugins/perl/scripts/request.pl
  • +0 -88
    libpurple/plugins/perl/scripts/signals-test.pl
  • +0 -23
    libpurple/plugins/tcl/Makefile.am
  • +0 -78
    libpurple/plugins/tcl/Makefile.mingw
  • +0 -123
    libpurple/plugins/tcl/signal-test.tcl
  • +0 -503
    libpurple/plugins/tcl/tcl.c
  • +0 -189
    libpurple/plugins/tcl/tcl_cmd.c
  • +0 -1769
    libpurple/plugins/tcl/tcl_cmds.c
  • +0 -259
    libpurple/plugins/tcl/tcl_glib.c
  • +0 -29
    libpurple/plugins/tcl/tcl_glib.h
  • +0 -118
    libpurple/plugins/tcl/tcl_purple.h
  • +0 -156
    libpurple/plugins/tcl/tcl_ref.c
  • +0 -404
    libpurple/plugins/tcl/tcl_signals.c
  • +0 -42
    libpurple/plugins/test.pl
  • --- a/libpurple/plugins/fortuneprofile.pl Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,125 +0,0 @@
    -# FORTUNE PROFILE
    -#
    -# Sets your AIM profile to a fortune (with a header and footer of your
    -# choice).
    -#
    -
    -# By Sean Egan
    -# seanegan@gmail.com
    -# AIM: SeanEgn
    -#
    -# Updated by Nathan Conrad, 31 January 2002
    -# Changes:
    -# * Fortunes have HTML tabs and newlines
    -# AIM: t98502
    -# ICQ: 16106363
    -#
    -# Updated by Mark Doliner, 15 October 2002
    -# Changes:
    -# * Modified to work with the changed perl interface of gaim 0.60
    -# * Fixed a bug where your info would be set to nothing if you had
    -# no pre and no post message
    -# AIM: lbdash
    -#
    -# Updated by Christian Hammond, 20 August 2003
    -# Changes:
    -# * Modified to work with the changed perl interface of gaim 0.68
    -# AIM: ChipX86
    -
    -# Copyright (C) 2001 Sean Egan
    -
    -# This program is free software; you can redistribute it and/or modify
    -# it under the terms of the GNU General Public License as published by
    -# the Free Software Foundation; either version 2 of the License, or
    -# (at your option) any later version.
    -#
    -# This program 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 General Public License for more details.
    -#
    -# You should have received a copy of the GNU General Public License
    -# along with this program; if not, write to the Free Software
    -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
    -
    -use Gaim;
    -
    -%PLUGIN_INFO = (
    - perl_api_version => 2,
    - name => "Fortune Profile",
    - version => "3.4",
    - summary => "Sets your AIM profile to a fortune (with a header and footer of your choice).",
    - description => "Sets your AIM profile to a fortune (with a header and footer of your choice).",
    - author => "Sean Egan <seanegan\@gmail.com>",
    - url => "https://pidgin.im/",
    -
    - load => "plugin_load"
    -);
    -
    -sub plugin_init {
    - return %PLUGIN_INFO;
    -}
    -
    -sub plugin_load {
    - $plugin = shift;
    -
    - $tab = "&nbsp;";
    - $tab = $tab . $tab . $tab . $tab;
    - $nl = "<BR>";
    -
    - $seconds = 30; # Delay before updating away messages.
    - $max = 1020; # Max length of an profile. It should be
    - # 1024, but I am being safe
    - $pre_message = ""; # This gets added before the fortune
    -
    - $post_message ="";
    -
    - $len = 0;
    - if ($pre_message ne "") {
    - $len += length( $pre_message . "---$nl" );
    - }
    - if ($post_message ne "") {
    - $len += length("---$nl" . $post_message);
    - }
    -
    - # Command to get dynamic message from
    - $command = "fortune -sn " . ($max - $len);
    -
    - # output the first message and start the timers...
    - # This is done as a timeout to prevent attempts to set the
    - # profile before logging in.
    - Gaim::timeout_add($plugin, $seconds, \&update_away, 0);
    -}
    -
    -sub update_away {
    - # The fortunes are expanded into HTML (the tabs and newlines) which
    - # causes the -s option of fortune to be a little bit meaningless. This
    - # will loop until it gets a fortune of a good size (after expansion).
    -
    - do {
    - do { #It's a while loop because it doesn't always work for some reason
    - $fortune = `$command`;
    - if ($? == -1) {
    - return;
    - }
    - } while ($fortune eq "");
    - $fortune =~ s/\n/$nl/g;
    - $fortune =~ s/\t/$tab/g;
    - } while ((length($fortune) + $len ) > $max);
    -
    - $message = $fortune;
    - if ($pre_message ne "") {
    - $message = $pre_message . "---$nl" . $message;
    - }
    - if ($post_message ne "") {
    - $message = $message . "---$nl" . $post_message ;
    - }
    -
    - foreach $account (Gaim::accounts()) {
    - if ($account->is_connected()) {
    - $account->set_user_info($message);
    - }
    - }
    -
    - Gaim::timeout_add($plugin, $seconds, \&update_away, 0);
    -}
    --- a/libpurple/plugins/mono/BooPlugin.boo Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,22 +0,0 @@
    -import Purple
    -
    -class BooPlugin(PurplePlugin):
    -
    - def handle(*args as (object)):
    - b as Buddy
    - b = args[0]
    - Debug.debug(Debug.INFO, "booplugin", "Boo Plugin knows that " + b.Alias + " is away\n")
    -
    - override def Load():
    - Debug.debug(Debug.INFO, "booplugin", "loading...\n")
    - BuddyList.OnBuddyAway.connect(self, handle)
    -
    - override def Unload():
    - Debug.debug(Debug.INFO, "booplugin", "unloading...\n")
    -
    - override def Destroy():
    - Debug.debug(Debug.INFO, "booplugin", "destroying...\n")
    -
    - override def Info():
    - return PurplePluginInfo("mono-boo", "Boo Plugin", "0.1", "Test Boo Plugin", "Longer Description", "Eoin Coffey", "urled")
    -
    --- a/libpurple/plugins/mono/GetBuddyBack.cs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,34 +0,0 @@
    -using Purple;
    -
    -public class GetBuddyBack : Plugin
    -{
    - private static PluginInfo info = new PluginInfo("mono-buddyback", "C# Get Buddy Back", "0.1", "Prints when a Buddy returns", "Longer Description", "Eoin Coffey", "urled");
    -
    - public GetBuddyBack()
    - : base (info)
    - {
    - }
    -
    - public void HandleSig(object[] args)
    - {
    - Buddy buddy = (Buddy)args[0];
    -
    - Debug.debug(Debug.INFO, "buddyback", "buddy " + buddy.Name + " is back!\n");
    - }
    -
    - public override void Load()
    - {
    - Debug.debug(Debug.INFO, "buddyback", "loading...\n");
    -
    - /*Signal.connect(BuddyList.GetHandle(), this, "buddy-back", new Signal.Handler(HandleSig));*/
    - BuddyList.OnBuddyStatusChanged.connect(this, new Signal.Handler(HandleSig));
    - }
    -
    - public override void Unload()
    - {
    - }
    -
    - public override void Destroy()
    - {
    - }
    -}
    --- a/libpurple/plugins/mono/MPlugin.cs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,38 +0,0 @@
    -using Purple;
    -
    -public class MPlugin : Plugin
    -{
    - private static PluginInfo info = new PluginInfo("mono-mplugin", "C# Plugin", "0.1", "Test C# Plugin", "Longer Description", "Eoin Coffey", "urled");
    -
    - public MPlugin()
    - : base(info)
    - {
    - }
    -
    - public void HandleSig(object[] args)
    - {
    - Buddy buddy = (Buddy)args[0];
    - Status old_status = (Status)args[1];
    - Status status = (Status)args[2];
    -
    - Debug.debug(Debug.INFO, "mplug", "buddy " + buddy.Name + " went from " + old_status.Id + " to " + status.Id + "\n");
    - }
    -
    - public override void Load()
    - {
    - Debug.debug(Debug.INFO, "mplug", "loading...\n");
    -
    - /*Signal.connect(BuddyList.GetHandle(), this, "buddy-away", new Signal.Handler(HandleSig));*/
    - BuddyList.OnBuddyStatusChanged.connect(this, new Signal.Handler(HandleSig));
    - }
    -
    - public override void Unload()
    - {
    - Debug.debug(Debug.INFO, "mplug", "unloading...\n");
    - }
    -
    - public override void Destroy()
    - {
    - Debug.debug(Debug.INFO, "mplug", "destroying...\n");
    - }
    -}
    --- a/libpurple/plugins/mono/Makefile.am Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,19 +0,0 @@
    -SUBDIRS = api loader
    -
    -mono_sources = GetBuddyBack.cs \
    - MPlugin.cs
    -
    -EXTRA_DIST = $(mono_sources)
    -
    -monodir = @PURPLE_PLUGINDIR@
    -mono_SCRIPTS = MPlugin.dll GetBuddyBack.dll
    -mono_build_sources = $(addprefix $(srcdir)/, $(mono_sources))
    -
    -all: $(mono_SCRIPTS)
    -
    -SUFFIXES = .cs .dll
    -.cs.dll: api/PurpleAPI.dll $(mono_build_sources)
    - mcs -t:library -lib:./api -out:$@ -r:PurpleAPI.dll $<
    -
    -clean-local:
    - rm -f $(mono_SCRIPTS)
    --- a/libpurple/plugins/mono/api/BlistNode.cs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,4 +0,0 @@
    -namespace Purple {
    - public abstract class BlistNode {
    - }
    -}
    --- a/libpurple/plugins/mono/api/Buddy.cs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,9 +0,0 @@
    -namespace Purple {
    - public class Buddy : BlistNode {
    - private string name;
    - private string alias;
    -
    - public string Name { get { return name; } set { name = value; } }
    - public string Alias { get { return alias; } set { alias = value; } }
    - }
    -}
    --- a/libpurple/plugins/mono/api/BuddyList.cs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,19 +0,0 @@
    -namespace Purple {
    - using System;
    - using System.Runtime.CompilerServices;
    -
    - public class BuddyList {
    - [MethodImplAttribute(MethodImplOptions.InternalCall)]
    - extern private static IntPtr _get_handle();
    -
    - private static IntPtr handle = _get_handle();
    -
    - public static Event OnBuddyStatusChanged =
    - new Event(handle, "buddy-status-changed");
    -
    - public static IntPtr GetHandle()
    - {
    - return _get_handle();
    - }
    - }
    -}
    --- a/libpurple/plugins/mono/api/Contact.cs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,4 +0,0 @@
    -namespace Purple {
    - public class Contact : BlistNode {
    - }
    -}
    --- a/libpurple/plugins/mono/api/Debug.cs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,28 +0,0 @@
    -using System;
    -using System.Runtime.CompilerServices;
    -
    -namespace Purple
    -{
    - public class Debug
    - {
    - public static int ALL = 0;
    - public static int MISC = 1;
    - public static int INFO = 2;
    - public static int WARNING = 3;
    - public static int ERROR = 4;
    - public static int FATAL = 5;
    -
    - [MethodImplAttribute(MethodImplOptions.InternalCall)]
    - extern private static void _debug(int type, string cat, string str);
    -
    - public static void debug(int type, string cat, string format)
    - {
    - _debug(type, cat, format);
    - }
    -
    - public static void debug(int type, string cat, string format, params object[] args)
    - {
    - _debug(type, cat, String.Format(format, args));
    - }
    - }
    -}
    --- a/libpurple/plugins/mono/api/Event.cs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,21 +0,0 @@
    -using System;
    -
    -namespace Purple
    -{
    - public class Event
    - {
    - private IntPtr handle;
    - private string signal;
    -
    - public Event(IntPtr h, string s)
    - {
    - handle = h;
    - signal = s;
    - }
    -
    - public void connect(object plugin, Signal.Handler handler)
    - {
    - Signal.connect(handle, plugin, signal, handler);
    - }
    - }
    -}
    --- a/libpurple/plugins/mono/api/Group.cs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,4 +0,0 @@
    -namespace Purple {
    - public class Group : BlistNode {
    - }
    -}
    --- a/libpurple/plugins/mono/api/Makefile.am Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,27 +0,0 @@
    -monodir=@PURPLE_PLUGINDIR@
    -
    -mono_sources = \
    - BlistNode.cs \
    - BuddyList.cs \
    - Buddy.cs \
    - Contact.cs \
    - Debug.cs \
    - Event.cs \
    - PurplePlugin.cs \
    - Group.cs \
    - Signal.cs \
    - Status.cs
    -
    -EXTRA_DIST = $(mono_sources)
    -
    -mono_SCRIPTS = PurpleAPI.dll
    -
    -mono_build_sources = $(addprefix $(srcdir)/, $(mono_sources))
    -
    -all: $(mono_SCRIPTS)
    -
    -$(mono_SCRIPTS): $(mono_build_sources)
    - mcs -t:library -out:$(mono_SCRIPTS) $(mono_build_sources)
    -
    -clean-local:
    - rm -rf $(mono_SCRIPTS)
    --- a/libpurple/plugins/mono/api/PurplePlugin.cs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,67 +0,0 @@
    -namespace Purple {
    - public class PluginInfo {
    - private string id;
    - private string name;
    - private string version;
    - private string summary;
    - private string description;
    - private string author;
    - private string homepage;
    -
    - public PluginInfo(string id, string name, string version, string summary,
    - string description, string author, string homepage)
    - {
    - this.id = id;
    - this.name = name;
    - this.version = version;
    - this.summary = summary;
    - this.description = description;
    - this.author = author;
    - this.homepage = homepage;
    - }
    -
    - public string Id {
    - get { return id; }
    - }
    -
    - public string Name {
    - get { return name; }
    - }
    -
    - public string Version {
    - get { return version; }
    - }
    -
    - public string Summary {
    - get { return summary; }
    - }
    -
    - public string Description {
    - get { return description; }
    - }
    -
    - public string Author {
    - get { return author; }
    - }
    -
    - public string Homepage {
    - get { return homepage; }
    - }
    - }
    -
    - abstract public class Plugin {
    - private PluginInfo info;
    -
    - public Plugin(PluginInfo info) {
    - this.info = info;
    - }
    -
    - public abstract void Load();
    - public abstract void Unload();
    - public abstract void Destroy();
    -
    - public PluginInfo Info {
    - get { return info; }
    - }
    - }
    -}
    --- a/libpurple/plugins/mono/api/Signal.cs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,18 +0,0 @@
    -using System;
    -using System.Runtime.CompilerServices;
    -
    -namespace Purple
    -{
    - public class Signal
    - {
    - [MethodImplAttribute(MethodImplOptions.InternalCall)]
    - extern private static int _connect(IntPtr handle, object plugin, string signal, object evnt);
    -
    - public delegate void Handler(object[] args);
    -
    - public static int connect(IntPtr handle, object plugin, string signal, object evnt)
    - {
    - return _connect(handle, plugin, signal, evnt);
    - }
    - }
    -}
    --- a/libpurple/plugins/mono/api/Status.cs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,9 +0,0 @@
    -namespace Purple
    -{
    - public class Status
    - {
    - private string id;
    -
    - public string Id { get { return id; } set { id = value; } }
    - }
    -}
    --- a/libpurple/plugins/mono/loader/Makefile.am Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,25 +0,0 @@
    -plugindir = @PURPLE_PLUGINDIR@
    -
    -plugin_LTLIBRARIES = mono.la
    -
    -mono_la_SOURCES = \
    - mono.c \
    - mono-glue.h \
    - mono-helper.c \
    - mono-helper.h \
    - debug-glue.c \
    - signal-glue.c \
    - blist-glue.c \
    - status-glue.c
    -
    -mono_la_LDFLAGS = -module @PLUGIN_LDFLAGS@
    -
    -mono_la_LIBADD = $(GPLUGIN_LIBS) $(MONO_LIBS)
    -
    -AM_CPPFLAGS = \
    - -I$(top_srcdir) \
    - -I$(top_srcdir)/libpurple \
    - $(DEBUG_CFLAGS) \
    - $(GPLUGIN_CFLAGS) \
    - $(PLUGIN_CFLAGS) \
    - $(MONO_CFLAGS)
    --- a/libpurple/plugins/mono/loader/blist-glue.c Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,26 +0,0 @@
    -#include <string.h>
    -#include "buddylist.h"
    -#include "mono-helper.h"
    -#include "mono-glue.h"
    -
    -MonoObject* purple_blist_get_handle_glue(void)
    -{
    - void *handle = purple_blist_get_handle();
    -
    - return mono_value_box(ml_get_domain(), mono_get_intptr_class(), &handle);
    -}
    -
    -MonoObject* purple_blist_build_buddy_object(void* data)
    -{
    - MonoObject *obj = NULL;
    -
    - PurpleBuddy *buddy = PURPLE_BUDDY(data);
    -
    - obj = ml_create_api_object("Buddy");
    - g_return_val_if_fail(obj != NULL, NULL);
    -
    - ml_set_prop_string(obj, "Name", (char*)purple_buddy_get_name(buddy));
    - ml_set_prop_string(obj, "Alias", (char*)purple_buddy_get_alias(buddy));
    -
    - return obj;
    -}
    --- a/libpurple/plugins/mono/loader/debug-glue.c Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,16 +0,0 @@
    -#include "mono-glue.h"
    -#include "debug.h"
    -
    -void purple_debug_glue(int type, MonoString *cat, MonoString *str)
    -{
    - char *ccat;
    - char *cstr;
    -
    - ccat = mono_string_to_utf8(cat);
    - cstr = mono_string_to_utf8(str);
    -
    - purple_debug(type, ccat, "%s", cstr);
    -
    - g_free(ccat);
    - g_free(cstr);
    -}
    --- a/libpurple/plugins/mono/loader/mono-glue.h Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,19 +0,0 @@
    -#ifndef _PURPLE_MONO_LOADER_GLUE_H_
    -#define _PURPLE_MONO_LOADER_GLUE_H_
    -
    -#include <mono/jit/jit.h>
    -#include <mono/metadata/object.h>
    -#include <mono/metadata/environment.h>
    -#include <mono/metadata/assembly.h>
    -
    -void purple_debug_glue(int type, MonoString *cat, MonoString *str);
    -
    -int purple_signal_connect_glue(MonoObject *h, MonoObject *plugin, MonoString *signal, MonoObject *func);
    -
    -MonoObject* purple_blist_get_handle_glue(void);
    -
    -MonoObject* purple_blist_build_buddy_object(void* buddy);
    -
    -MonoObject* purple_status_build_status_object(void* data);
    -
    -#endif
    --- a/libpurple/plugins/mono/loader/mono-helper.c Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,260 +0,0 @@
    -/*
    - * Mono Plugin Loader
    - *
    - * -- Thanks to the perl plugin loader for all the great tips ;-)
    - *
    - * Eoin Coffey
    - */
    -
    -#ifdef HAVE_CONFIG_H
    -#include <config.h>
    -#endif
    -
    -#include <glib.h>
    -#include <string.h>
    -#include "mono-helper.h"
    -#include "mono-glue.h"
    -#include "debug.h"
    -
    -static gboolean _runtime_active = FALSE;
    -
    -gboolean ml_init()
    -{
    - MonoDomain *d;
    -
    - g_return_val_if_fail(_runtime_active == FALSE, TRUE);
    -
    - d = mono_jit_init("purple");
    -
    - if (!d) {
    - ml_set_domain(NULL);
    - return FALSE;
    - }
    -
    - ml_set_domain(d);
    -
    - ml_init_internal_calls();
    -
    - _runtime_active = TRUE;
    -
    - return TRUE;
    -}
    -
    -void ml_uninit()
    -{
    - g_return_if_fail(_runtime_active == TRUE);
    -
    - mono_jit_cleanup(ml_get_domain());
    -
    - ml_set_domain(NULL);
    -
    - _runtime_active = FALSE;
    -}
    -
    -MonoObject* ml_delegate_invoke(MonoObject *method, void **params)
    -{
    - MonoObject *ret, *exception;
    -
    - ret = mono_runtime_delegate_invoke(method, params, &exception);
    - if (exception) {
    - purple_debug(PURPLE_DEBUG_ERROR, "mono", "caught exception: %s\n", mono_class_get_name(mono_object_get_class(exception)));
    - }
    -
    - return ret;
    -}
    -
    -MonoObject* ml_invoke(MonoMethod *method, void *obj, void **params)
    -{
    - MonoObject *ret, *exception;
    -
    - ret = mono_runtime_invoke(method, obj, params, &exception);
    - if (exception) {
    - purple_debug(PURPLE_DEBUG_ERROR, "mono", "caught exception: %s\n", mono_class_get_name(mono_object_get_class(exception)));
    - }
    -
    - return ret;
    -}
    -
    -MonoClass* ml_find_plugin_class(MonoImage *image)
    -{
    - MonoClass *klass, *pklass = NULL;
    - int i, total;
    -
    - total = mono_image_get_table_rows (image, MONO_TABLE_TYPEDEF);
    - for (i = 1; i <= total; ++i) {
    - klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
    -
    - pklass = mono_class_get_parent(klass);
    - if (pklass) {
    -
    - if (strcmp("Plugin", mono_class_get_name(pklass)) == 0)
    - return klass;
    - }
    - }
    -
    - return NULL;
    -}
    -
    -void ml_set_prop_string(MonoObject *obj, char *field, char *data)
    -{
    - MonoClass *klass;
    - MonoProperty *prop;
    - MonoString *str;
    - gpointer args[1];
    -
    - klass = mono_object_get_class(obj);
    -
    - prop = mono_class_get_property_from_name(klass, field);
    -
    - str = mono_string_new(ml_get_domain(), data);
    -
    - args[0] = str;
    -
    - mono_property_set_value(prop, obj, args, NULL);
    -}
    -
    -gchar* ml_get_prop_string(MonoObject *obj, char *field)
    -{
    - MonoClass *klass;
    - MonoProperty *prop;
    - MonoString *str;
    -
    - klass = mono_object_get_class(obj);
    -
    - prop = mono_class_get_property_from_name(klass, field);
    -
    - str = (MonoString*)mono_property_get_value(prop, obj, NULL, NULL);
    -
    - return mono_string_to_utf8(str);
    -}
    -
    -MonoObject* ml_get_info_prop(MonoObject *obj)
    -{
    - MonoClass *klass;
    - MonoProperty *prop;
    -
    - klass = mono_class_get_parent(mono_object_get_class(obj));
    -
    - prop = mono_class_get_property_from_name(klass, "Info");
    -
    - return mono_property_get_value(prop, obj, NULL, NULL);
    -}
    -
    -gboolean ml_is_api_dll(MonoImage *image)
    -{
    - MonoClass *klass;
    - int i, total;
    -
    - total = mono_image_get_table_rows (image, MONO_TABLE_TYPEDEF);
    - for (i = 1; i <= total; ++i) {
    - klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
    - if (strcmp(mono_class_get_name(klass), "Debug") == 0)
    - if (strcmp(mono_class_get_namespace(klass), "Purple") == 0) {
    - ml_set_api_image(image);
    - return TRUE;
    - }
    - }
    -
    - return FALSE;
    -}
    -
    -MonoObject* ml_object_from_purple_type(GType type, gpointer data)
    -{
    - MonoObject *obj = NULL;
    -
    - switch (type) {
    - case PURPLE_TYPE_BUDDY:
    - obj = purple_blist_build_buddy_object(data);
    - break;
    - case PURPLE_TYPE_STATUS:
    - obj = purple_status_build_status_object(data);
    - break;
    - default:
    - break;
    - }
    -
    - return obj;
    -}
    -
    -MonoObject* ml_create_api_object(char *class_name)
    -{
    - MonoObject *obj = NULL;
    - MonoClass *klass = NULL;
    -
    - klass = mono_class_from_name(ml_get_api_image(), "Purple", class_name);
    - if (!klass) {
    - purple_debug(PURPLE_DEBUG_FATAL, "mono", "couldn't find the '%s' class\n", class_name);
    - return NULL;
    - }
    -
    - obj = mono_object_new(ml_get_domain(), klass);
    - if (!obj) {
    - purple_debug(PURPLE_DEBUG_FATAL, "mono", "couldn't create the object from class '%s'\n", class_name);
    - return NULL;
    - }
    -
    - mono_runtime_object_init(obj);
    -
    - return obj;
    -}
    -
    -static MonoDomain *_domain = NULL;
    -
    -MonoDomain* ml_get_domain(void)
    -{
    - return _domain;
    -}
    -
    -void ml_set_domain(MonoDomain *d)
    -{
    - _domain = d;
    -}
    -
    -static MonoImage *_api_image = NULL;
    -
    -void ml_set_api_image(MonoImage *image)
    -{
    - _api_image = image;
    -}
    -
    -MonoImage* ml_get_api_image()
    -{
    - return _api_image;
    -}
    -
    -void ml_init_internal_calls(void)
    -{
    - mono_add_internal_call("Purple.Debug::_debug", purple_debug_glue);
    - mono_add_internal_call("Purple.Signal::_connect", purple_signal_connect_glue);
    - mono_add_internal_call("Purple.BuddyList::_get_handle", purple_blist_get_handle_glue);
    -}
    -
    -static GHashTable *plugins_hash = NULL;
    -
    -void ml_add_plugin(PurpleMonoPlugin *plugin)
    -{
    - if (!plugins_hash)
    - plugins_hash = g_hash_table_new(NULL, NULL);
    -
    - g_hash_table_insert(plugins_hash, plugin->klass, plugin);
    -}
    -
    -gboolean ml_remove_plugin(PurpleMonoPlugin *plugin)
    -{
    - return g_hash_table_remove(plugins_hash, plugin->klass);
    -}
    -
    -gpointer ml_find_plugin(PurpleMonoPlugin *plugin)
    -{
    - return g_hash_table_lookup(plugins_hash, plugin->klass);
    -}
    -
    -gpointer ml_find_plugin_by_class(MonoClass *klass)
    -{
    - return g_hash_table_lookup(plugins_hash, klass);
    -}
    -
    -GHashTable* ml_get_plugin_hash()
    -{
    - return plugins_hash;
    -}
    --- a/libpurple/plugins/mono/loader/mono-helper.h Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,72 +0,0 @@
    -#ifndef _PURPLE_MONO_LOADER_MONO_HELPER_H_
    -#define _PURPLE_MONO_LOADER_MONO_HELPER_H_
    -
    -#include <mono/jit/jit.h>
    -#include <mono/metadata/object.h>
    -#include <mono/metadata/environment.h>
    -#include <mono/metadata/assembly.h>
    -#include <mono/metadata/debug-helpers.h>
    -#include <mono/metadata/tokentype.h>
    -#include "plugins.h"
    -#include "debug.h"
    -
    -typedef struct {
    - PurplePlugin *plugin;
    -
    - MonoAssembly *assm;
    - MonoClass *klass;
    - MonoObject *obj;
    -
    - MonoMethod *init;
    - MonoMethod *load;
    - MonoMethod *unload;
    - MonoMethod *destroy;
    -
    - GList *signal_data;
    -} PurpleMonoPlugin;
    -
    -gboolean ml_init(void);
    -
    -void ml_uninit(void);
    -
    -MonoObject* ml_invoke(MonoMethod *method, void *obj, void **params);
    -
    -MonoObject* ml_delegate_invoke(MonoObject *method, void **params);
    -
    -MonoClass* ml_find_plugin_class(MonoImage *image);
    -
    -gchar* ml_get_prop_string(MonoObject *obj, char *field);
    -
    -void ml_set_prop_string(MonoObject *obj, char *field, char *data);
    -
    -MonoObject* ml_get_info_prop(MonoObject *obj);
    -
    -gboolean ml_is_api_dll(MonoImage *image);
    -
    -MonoDomain* ml_get_domain(void);
    -
    -void ml_set_domain(MonoDomain *d);
    -
    -void ml_init_internal_calls(void);
    -
    -MonoObject* ml_object_from_purple_type(GType type, gpointer data);
    -
    -MonoObject* ml_create_api_object(char *class_name);
    -
    -void ml_set_api_image(MonoImage *image);
    -
    -MonoImage* ml_get_api_image(void);
    -
    -/* hash table stuff; probably don't need it anymore */
    -
    -void ml_add_plugin(PurpleMonoPlugin *plugin);
    -
    -gboolean ml_remove_plugin(PurpleMonoPlugin *plugin);
    -
    -gpointer ml_find_plugin(PurpleMonoPlugin *plugin);
    -
    -gpointer ml_find_plugin_by_class(MonoClass *klass);
    -
    -GHashTable* ml_get_plugin_hash(void);
    -
    -#endif
    --- a/libpurple/plugins/mono/loader/mono.c Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,249 +0,0 @@
    -/*
    - * Mono Plugin Loader
    - *
    - * -- Thanks to the perl plugin loader for all the great tips ;-)
    - *
    - * Eoin Coffey
    - */
    -
    -#ifdef HAVE_CONFIG_H
    -# include <config.h>
    -#endif
    -
    -#include "internal.h"
    -#include "debug.h"
    -#include "plugins.h"
    -#include "version.h"
    -#include "mono-helper.h"
    -
    -#define MONO_PLUGIN_ID "core-mono"
    -
    -/******************************************************************************
    - * Loader Stuff
    - *****************************************************************************/
    -/* probes the given plugin to determine if its a plugin */
    -static gboolean probe_mono_plugin(PurplePlugin *plugin)
    -{
    - MonoAssembly *assm;
    - MonoMethod *m = NULL;
    - MonoObject *plugin_info;
    - gboolean found_load = FALSE, found_unload = FALSE, found_destroy = FALSE;
    - gpointer iter = NULL;
    -
    - PurplePluginInfo *info;
    - PurpleMonoPlugin *mplug;
    -
    - char *file = plugin->path;
    -
    - assm = mono_domain_assembly_open(ml_get_domain(), file);
    -
    - if (!assm) {
    - return FALSE;
    - }
    -
    - purple_debug(PURPLE_DEBUG_INFO, "mono", "Probing plugin\n");
    -
    - if (ml_is_api_dll(mono_assembly_get_image(assm))) {
    - purple_debug_info("mono", "Found our PurpleAPI.dll\n");
    - mono_assembly_close(assm);
    - return FALSE;
    - }
    -
    - mplug = g_new0(PurpleMonoPlugin, 1);
    -
    - mplug->signal_data = NULL;
    -
    - mplug->assm = assm;
    -
    - mplug->klass = ml_find_plugin_class(mono_assembly_get_image(mplug->assm));
    - if (!mplug->klass) {
    - purple_debug(PURPLE_DEBUG_ERROR, "mono", "no plugin class in \'%s\'\n", file);
    - mono_assembly_close(assm);
    - g_free(mplug);
    - return FALSE;
    - }
    -
    - mplug->obj = mono_object_new(ml_get_domain(), mplug->klass);
    - if (!mplug->obj) {
    - purple_debug(PURPLE_DEBUG_ERROR, "mono", "obj not valid\n");
    - mono_assembly_close(assm);
    - g_free(mplug);
    - return FALSE;
    - }
    -
    - mono_runtime_object_init(mplug->obj);
    -
    - while ((m = mono_class_get_methods(mplug->klass, &iter))) {
    - purple_debug_info("mono", "plugin method: %s\n", mono_method_get_name(m));
    - if (strcmp(mono_method_get_name(m), "Load") == 0) {
    - mplug->load = m;
    - found_load = TRUE;
    - } else if (strcmp(mono_method_get_name(m), "Unload") == 0) {
    - mplug->unload = m;
    - found_unload = TRUE;
    - } else if (strcmp(mono_method_get_name(m), "Destroy") == 0) {
    - mplug->destroy = m;
    - found_destroy = TRUE;
    - }
    - }
    -
    - if (!(found_load && found_unload && found_destroy)) {
    - purple_debug(PURPLE_DEBUG_ERROR, "mono", "did not find the required methods\n");
    - mono_assembly_close(assm);
    - g_free(mplug);
    - return FALSE;
    - }
    -
    - plugin_info = ml_get_info_prop(mplug->obj);
    -
    - /* now that the methods are filled out we can populate
    - the info struct with all the needed info */
    -
    - info = g_new0(PurplePluginInfo, 1);
    - info->id = ml_get_prop_string(plugin_info, "Id");
    - info->name = ml_get_prop_string(plugin_info, "Name");
    - info->version = ml_get_prop_string(plugin_info, "Version");
    - info->summary = ml_get_prop_string(plugin_info, "Summary");
    - info->description = ml_get_prop_string(plugin_info, "Description");
    - info->author = ml_get_prop_string(plugin_info, "Author");
    - info->homepage = ml_get_prop_string(plugin_info, "Homepage");
    -
    - info->magic = PURPLE_PLUGIN_MAGIC;
    - info->major_version = PURPLE_MAJOR_VERSION;
    - info->minor_version = PURPLE_MINOR_VERSION;
    - info->type = PURPLE_PLUGIN_STANDARD;
    -
    - /* this plugin depends on us; duh */
    - info->dependencies = g_list_append(info->dependencies, MONO_PLUGIN_ID);
    - mplug->plugin = plugin;
    -
    - plugin->info = info;
    - info->extra_info = mplug;
    -
    - ml_add_plugin(mplug);
    -
    - return purple_plugin_register(plugin);
    -}
    -
    -/* Loads a Mono Plugin by calling 'load' in the class */
    -static gboolean load_mono_plugin(PurplePlugin *plugin)
    -{
    - PurpleMonoPlugin *mplug;
    -
    - purple_debug(PURPLE_DEBUG_INFO, "mono", "Loading plugin\n");
    -
    - mplug = (PurpleMonoPlugin*)plugin->info->extra_info;
    -
    - ml_invoke(mplug->load, mplug->obj, NULL);
    -
    - return TRUE;
    -}
    -
    -/* Unloads a Mono Plugin by calling 'unload' in the class */
    -static gboolean unload_mono_plugin(PurplePlugin *plugin)
    -{
    - PurpleMonoPlugin *mplug;
    -
    - purple_debug(PURPLE_DEBUG_INFO, "mono", "Unloading plugin\n");
    -
    - mplug = (PurpleMonoPlugin*)plugin->info->extra_info;
    -
    - purple_signals_disconnect_by_handle((gpointer)mplug->klass);
    - g_list_foreach(mplug->signal_data, (GFunc)g_free, NULL);
    - g_list_free(mplug->signal_data);
    - mplug->signal_data = NULL;
    -
    - ml_invoke(mplug->unload, mplug->obj, NULL);
    -
    - return TRUE;
    -}
    -
    -static void destroy_mono_plugin(PurplePlugin *plugin)
    -{
    - PurpleMonoPlugin *mplug;
    -
    - purple_debug(PURPLE_DEBUG_INFO, "mono", "Destroying plugin\n");
    -
    - mplug = (PurpleMonoPlugin*)plugin->info->extra_info;
    -
    - ml_invoke(mplug->destroy, mplug->obj, NULL);
    -
    - if (plugin->info) {
    - g_free(plugin->info->name);
    - g_free(plugin->info->version);
    - g_free(plugin->info->summary);
    - g_free(plugin->info->description);
    - g_free(plugin->info->author);
    - g_free(plugin->info->homepage);
    - }
    -
    - if (mplug) {
    - if (mplug->assm) {
    - mono_assembly_close(mplug->assm);
    - }
    -
    - g_free(mplug);
    - mplug = NULL;
    - }
    -}
    -
    -/******************************************************************************
    - * Plugin Stuff
    - *****************************************************************************/
    -static void plugin_destroy(PurplePlugin *plugin)
    -{
    - ml_uninit();
    -}
    -
    -static PurplePluginLoaderInfo loader_info =
    -{
    - probe_mono_plugin,
    - load_mono_plugin,
    - unload_mono_plugin,
    - destroy_mono_plugin,
    -};
    -
    -static GPluginPluginInfo *
    -plugin_query(GError **error)
    -{
    - const gchar * const authors[] = {
    - "Eoin Coffey <ecoffey@simla.colostate.edu>",
    - NULL
    - };
    -
    - return gplugin_plugin_info_new(
    - "id", MONO_PLUGIN_ID,
    - "name", N_("Mono Plugin Loader"),
    - "version", DISPLAY_VERSION,
    - "category", N_("Loader"),
    - "summary", N_("Loads .NET plugins with Mono."),
    - "description", N_("Loads .NET plugins with Mono."),
    - "authors", authors,
    - "website", PURPLE_WEBSITE,
    - "abi-version", PURPLE_ABI_VERSION,
    - "internal", TRUE,
    - "load-on-query", TRUE,
    - NULL
    - );
    -}
    -
    -static gboolean
    -plugin_load(PurplePlugin *plugin, GError **error)
    -{
    - return TRUE;
    -}
    -
    -static gboolean
    -plugin_unload(PurplePlugin *plugin, GError **error)
    -{
    - return TRUE;
    -}
    -
    -static void init_plugin(PurplePlugin *plugin)
    -{
    - ml_init();
    -
    - loader_info.exts = g_list_append(loader_info.exts, "dll");
    -}
    -
    -PURPLE_PLUGIN_INIT(mono, plugin_query, plugin_load, plugin_unload);
    --- a/libpurple/plugins/mono/loader/signal-glue.c Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,131 +0,0 @@
    -#include "mono-glue.h"
    -#include "mono-helper.h"
    -#include "debug.h"
    -#include "buddylist.h"
    -#include "signals.h"
    -
    -typedef struct {
    - MonoObject *func;
    - char *signal;
    - GType *types;
    - GType ret_type;
    - int num_vals;
    -} SignalData;
    -
    -static PurpleCallback get_callback(SignalData *sig_data);
    -
    -static gpointer dispatch_callback(SignalData *sig_data, int num_vals, ...)
    -{
    - MonoArray *array;
    - MonoObject *obj;
    - int i;
    - gpointer meth_args[1];
    - gpointer purple_obj;
    -
    - va_list args;
    -
    - va_start(args, num_vals);
    -
    - array = mono_array_new(ml_get_domain(), mono_get_object_class(), num_vals);
    -
    - for (i = 0; i < num_vals; i++) {
    - purple_obj = va_arg(args, gpointer);
    - obj = ml_object_from_purple_type(sig_data->types[i], purple_obj);
    - mono_array_set(array, MonoObject*, i, obj);
    - }
    -
    - va_end(args);
    -
    - meth_args[0] = array;
    -
    - return ml_delegate_invoke(sig_data->func, meth_args);
    -}
    -
    -static void cb_void__pointer(void *arg1, void *data)
    -{
    - dispatch_callback((SignalData*)data, ((SignalData*)data)->num_vals, arg1);
    -}
    -
    -static void cb_void__pointer_pointer_pointer(void *arg1, void *arg2, void *arg3, void *data)
    -{
    - dispatch_callback((SignalData*)data, ((SignalData*)data)->num_vals, arg1, arg2, arg3);
    -}
    -
    -
    -int purple_signal_connect_glue(MonoObject* h, MonoObject *plugin, MonoString *signal, MonoObject *func)
    -{
    - char *sig;
    - void **instance = NULL;
    - SignalData *sig_data;
    - PurpleMonoPlugin *mplug;
    - MonoClass *klass;
    -
    - sig = mono_string_to_utf8(signal);
    - purple_debug(PURPLE_DEBUG_INFO, "mono", "connecting signal: %s\n", sig);
    -
    - instance = (void*)mono_object_unbox(h);
    -
    - sig_data = g_new0(SignalData, 1);
    -
    - sig_data->func = func;
    - sig_data->signal = sig;
    -
    - purple_signal_get_types(*instance, sig, &sig_data->ret_type, &sig_data->num_vals, &sig_data->types);
    -
    - klass = mono_object_get_class(plugin);
    -
    - mplug = ml_find_plugin_by_class(klass);
    -
    - mplug->signal_data = g_list_append(mplug->signal_data, (gpointer)sig_data);
    -
    - return purple_signal_connect(*instance, sig, (gpointer)klass, get_callback(sig_data), (gpointer)sig_data);
    -}
    -
    -static int determine_index(GType type)
    -{
    - switch (type) {
    - case G_TYPE_STRING:
    - case G_TYPE_POINTER:
    - return 1;
    - break;
    - default:
    - if (G_TYPE_IS_OBJECT(type) || G_TYPE_IS_BOXED(type))
    - return 1;
    - return type;
    - break;
    - }
    -}
    -
    -static gpointer callbacks[]= {
    - NULL,
    - cb_void__pointer,
    - NULL,
    - cb_void__pointer_pointer_pointer
    - };
    -
    -static int callbacks_array_size = sizeof(callbacks) / sizeof(PurpleCallback);
    -
    -
    -static PurpleCallback get_callback(SignalData *sig_data)
    -{
    - int i, index = 0;
    -
    - if (sig_data->ret_type == NULL)
    - index = 0;
    - else
    - index = determine_index(sig_data->ret_type);
    -
    - for (i = 0; i < sig_data->num_vals; i++) {
    - index += determine_index(sig_data->types[i]);
    - }
    -
    - purple_debug(PURPLE_DEBUG_INFO, "mono", "get_callback index = %d\n", index);
    -
    - if (index >= callbacks_array_size || callbacks[index] == NULL) {
    - purple_debug(PURPLE_DEBUG_ERROR, "mono", "couldn't find a callback function for signal: %s\n", sig_data->signal);
    - return NULL;
    - }
    -
    - purple_debug(PURPLE_DEBUG_MISC, "mono", "using callback at index: %d\n", index);
    - return PURPLE_CALLBACK(callbacks[index]);
    -}
    --- a/libpurple/plugins/mono/loader/status-glue.c Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,16 +0,0 @@
    -#include "status.h"
    -#include "mono-helper.h"
    -#include "mono-glue.h"
    -
    -MonoObject* purple_status_build_status_object(void* data)
    -{
    - MonoObject *obj = NULL;
    - PurpleStatus *status = (PurpleStatus*)data;
    -
    - obj = ml_create_api_object("Status");
    - g_return_val_if_fail(obj != NULL, NULL);
    -
    - ml_set_prop_string(obj, "Id", (char*)purple_status_get_id(status));
    -
    - return obj;
    -}
    --- a/libpurple/plugins/perl/Makefile.am Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,171 +0,0 @@
    -plugindir = @PURPLE_PLUGINDIR@
    -
    -perl_dirs = common
    -
    -plugin_LTLIBRARIES = perl.la
    -
    -perl_la_LDFLAGS = -module -avoid-version
    -perl_la_LIBADD = $(GLIB_LIBS) $(GPLUGIN_LIBS) $(PERL_LIBS)
    -perl_la_SOURCES = \
    - perl.c \
    - perl-common.c \
    - perl-common.h \
    - perl-handlers.c \
    - perl-handlers.h
    -
    -perl_la_DEPENDENCIES = \
    - .libs/libperl_orig.a \
    - .libs/DynaLoader.a
    -
    -.libs/libperl_orig.a:
    - @mkdir -p .libs
    - @rm -f .libs/libperl_orig.a
    - @if [ x$(LIBPERL_A) = x ]; then \
    - touch .libs/libperl_orig.a; \
    - else \
    - $(LN_S) $(LIBPERL_A) .libs/libperl_orig.a; \
    - fi
    -
    -.libs/DynaLoader.a:
    - @mkdir -p .libs
    - @rm -f .libs/DynaLoader.a
    - @if [ x$(DYNALOADER_A) = x ]; then \
    - touch .libs/DynaLoader.a; \
    - else \
    - $(LN_S) $(DYNALOADER_A) .libs/DynaLoader.a; \
    - fi
    -
    -common_sources = \
    - common/Account.xs \
    - common/AccountOpts.xs \
    - common/BuddyIcon.xs \
    - common/BuddyList.xs \
    - common/Certificate.xs \
    - common/Cipher.xs \
    - common/Cmds.xs \
    - common/Core.xs \
    - common/Connection.xs \
    - common/Conversation.xs \
    - common/Debug.xs \
    - common/Idle.xs \
    - common/Log.xs \
    - common/Makefile.PL.in \
    - common/Network.xs \
    - common/Notify.xs \
    - common/Plugin.xs \
    - common/PluginPref.xs \
    - common/Pounce.xs \
    - common/Prefs.xs \
    - common/Presence.xs \
    - common/Proxy.xs \
    - common/Prpl.xs \
    - common/Purple.pm \
    - common/Purple.xs \
    - common/Request.xs \
    - common/Roomlist.xs \
    - common/SSLConn.xs \
    - common/SavedStatuses.xs \
    - common/Server.xs \
    - common/Signal.xs \
    - common/Sound.xs \
    - common/Status.xs \
    - common/Stringref.xs \
    - common/Util.xs \
    - common/Whiteboard.xs \
    - common/Xfer.xs \
    - common/XMLNode.xs \
    - common/module.h \
    - common/typemap
    -# common/fallback/const-c.inc \
    -# common/fallback/const-xs.inc
    -
    -perl_scripts = \
    - scripts/function_list.pl \
    - scripts/signals-test.pl
    -
    -EXTRA_DIST = \
    - Makefile.mingw \
    - common/Makefile.mingw \
    - $(common_sources) \
    - $(perl_scripts)
    -
    -common/Makefile: common/Makefile.PL
    - $(AM_V_GEN)if test "x${top_srcdir}" != "x${top_builddir}"; then \
    - for f in ${common_sources}; do \
    - srcloc=${srcdir}; \
    - case $$srcloc in /*) ;; *) srcloc=../${srcdir} ;; esac; \
    - ${LN_S} -f $$srcloc/$$f $$f; \
    - done; \
    - fi
    - $(AM_V_at)cd common && $(perlpath) Makefile.PL > /dev/null
    -
    -common/Makefile.PL: common/Makefile.PL.in $(top_builddir)/config.status
    - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
    -
    -all-local: common/Makefile
    - @for dir in $(perl_dirs); do \
    - cd $$dir && \
    - if [ ! -f Makefile ]; then \
    - $(perlpath) Makefile.PL; \
    - fi && \
    - ($(MAKE) CC="@$(abs_top_srcdir)/libpurple/tag.sh CC $(CC)" LD="@$(abs_top_srcdir)/libpurple/tag.sh LD $(CC)" PERLRUN="@$(abs_top_srcdir)/libpurple/tag.sh PERL $(PERL)" CCFLAGS="$(PERL_CFLAGS) $(CFLAGS)" CP="@cp" RM_F="@rm -f" CHMOD="@chmod" $(PERL_EXTRA_OPTS) || \
    - $(MAKE) CC="@$(abs_top_srcdir)/libpurple/tag.sh CC $(CC)" LD="@$(abs_top_srcdir)/libpurple/tag.sh LD $(CC)" PERLRUN="@$(abs_top_srcdir)/libpurple/tag.sh PERL $(PERL)" CCFLAGS="$(PERL_CFLAGS) $(CFLAGS)" CP="@cp" RM_F="@rm -f" CHMOD="@chmod" $(PERL_EXTRA_OPTS)) && \
    - cd ..; \
    - done
    -
    -install-exec-local:
    - @for dir in $(perl_dirs); do \
    - cd $$dir; \
    - $(MAKE) install; \
    - cd ..; \
    - done
    -
    -# Evil Hack (TM)
    -# ... which doesn't work with DESTDIR installs. FIXME?
    -uninstall-local:
    - @for dir in $(perl_dirs); do \
    - cd $$dir && \
    - `$(MAKE) uninstall | grep unlink | sed -e 's#/usr#${prefix}#' -e 's#unlink#rm -f#'` && \
    - cd ..; \
    - done
    -
    -clean-generic:
    - @for dir in $(perl_dirs); do \
    - cd $$dir; \
    - $(MAKE) clean; \
    - cd ..; \
    - done
    - cd common ; rm -rf *.c *.o pm_to_blib Purple.bs MYMETA.* blib/*/.exists blib/*/auto/Purple blib/*/Purple.*pm ; cd ..
    - rm -f *.so
    -
    -distclean-generic:
    - @for dir in $(perl_dirs); do \
    - cd $$dir; \
    - $(MAKE) realclean; \
    - rm -f Makefile.PL; \
    - rm -f Makefile.old; \
    - rm -f Makefile; \
    - cd ..; \
    - done
    -
    - @rm -f Makefile
    -# @rm -f common/const-c.inc common/const-xs.inc
    -
    - @if test "x${top_srcdir}" != "x${top_builddir}"; then \
    - for f in ${common_sources}; do \
    - srcloc=${srcdir}; \
    - case $$srcloc in /*) ;; *) srcloc=../${srcdir} ;; esac; \
    - ${LN_S} -f $$srcloc/$$f $$f; \
    - done; \
    - fi
    -
    -AM_CPPFLAGS = \
    - -I$(top_srcdir) \
    - -I$(top_srcdir)/libpurple \
    - -I$(top_builddir)/libpurple \
    - $(DEBUG_CFLAGS) \
    - $(GLIB_CFLAGS) \
    - $(GPLUGIN_CFLAGS) \
    - $(PLUGIN_CFLAGS) \
    - $(PERL_CFLAGS) \
    - -Wno-float-equal
    --- a/libpurple/plugins/perl/Makefile.mingw Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,87 +0,0 @@
    -#
    -# Makefile.mingw
    -#
    -# Description: Makefile for perl plugin loader plugin.
    -#
    -
    -PIDGIN_TREE_TOP := ../../..
    -include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
    -
    -#we cannot include win32dep.h, but we need struct sockaddr_in6 definition
    -CFLAGS += -include ws2tcpip.h
    -
    -DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES))
    -
    -TARGET = perl
    -
    -# Perl headers with /* /* */ type comments.. Turn off warnings.
    -GCCWARNINGS += -Wno-comment
    -
    -##
    -## INCLUDE PATHS
    -##
    -INCLUDE_PATHS += -I. \
    - -I$(PIDGIN_TREE_TOP) \
    - -I$(PURPLE_TOP) \
    - -I$(PURPLE_TOP)/win32 \
    - -I$(GTK_TOP)/include \
    - -I$(GTK_TOP)/include/glib-2.0 \
    - -I$(GTK_TOP)/lib/glib-2.0/include \
    - -I$(PERL_LIB_TOP)/include
    -
    -LIB_PATHS += -L$(GTK_TOP)/lib \
    - -L$(PURPLE_TOP) \
    - -L$(PERL_LIB_TOP)/lib
    -
    -##
    -## SOURCES, OBJECTS
    -##
    -C_SRC = perl.c \
    - perl-common.c \
    - perl-handlers.c
    -
    -OBJECTS = $(C_SRC:%.c=%.o)
    -
    -##
    -## LIBRARIES
    -##
    -LIBS = \
    - -lglib-2.0 \
    - -lgmodule-2.0 \
    - -lgobject-2.0 \
    - -lws2_32 \
    - -lintl \
    - -lpurple \
    - -lperl520
    -
    -include $(PIDGIN_COMMON_RULES)
    -
    -##
    -## TARGET DEFINITIONS
    -##
    -.PHONY: all install clean
    -
    -all: $(TARGET).dll
    - $(MAKE_at) $(MAKE) -C ./common -f $(MINGW_MAKEFILE)
    -
    -install: all $(PURPLE_INSTALL_PLUGINS_DIR)
    - cp $(TARGET).dll $(PURPLE_INSTALL_PLUGINS_DIR)
    - $(MAKE_at) $(MAKE) -C ./common -f $(MINGW_MAKEFILE) install
    -
    -$(OBJECTS): $(PURPLE_CONFIG_H)
    -
    -##
    -## BUILD DLL
    -##
    -$(TARGET).dll $(TARGET).dll.a: $(PURPLE_DLL).a $(OBJECTS)
    - $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -Wl,--export-all-symbols -Wl,--out-implib,$(TARGET).dll.a -o $(TARGET).dll
    -
    -##
    -## CLEAN RULES
    -##
    -clean:
    - rm -rf $(OBJECTS)
    - rm -rf $(TARGET).dll $(TARGET).dll.a
    - $(MAKE_at) $(MAKE) -C ./common -f $(MINGW_MAKEFILE) clean
    -
    -include $(PIDGIN_COMMON_TARGETS)
    --- a/libpurple/plugins/perl/common/Account.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,353 +0,0 @@
    -#include "module.h"
    -#include "../perl-handlers.h"
    -
    -MODULE = Purple::Account PACKAGE = Purple::Accounts PREFIX = purple_accounts_
    -PROTOTYPES: ENABLE
    -
    -void
    -purple_accounts_add(account)
    - Purple::Account account
    -
    -void
    -purple_accounts_remove(account)
    - Purple::Account account
    -
    -void
    -purple_accounts_delete(account)
    - Purple::Account account
    -
    -void
    -purple_accounts_reorder(account, new_index)
    - Purple::Account account
    - size_t new_index
    -
    -void
    -purple_accounts_get_all()
    -PREINIT:
    - GList *l;
    -PPCODE:
    - for (l = purple_accounts_get_all(); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Account")));
    - }
    -
    -void
    -purple_accounts_get_all_active()
    -PREINIT:
    - GList *list, *iter;
    -PPCODE:
    - list = purple_accounts_get_all_active();
    - for (iter = list; iter != NULL; iter = iter->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(iter->data, "Purple::Account")));
    - }
    - g_list_free(list);
    -
    -void
    -purple_accounts_restore_current_statuses()
    -
    -Purple::Account
    -purple_accounts_find(name, protocol)
    - const char * name
    - const char * protocol
    -
    -Purple::Handle
    -purple_accounts_get_handle()
    -
    -MODULE = Purple::Account PACKAGE = Purple::Account PREFIX = purple_account_
    -PROTOTYPES: ENABLE
    -
    -Purple::Presence
    -purple_account_get_presence(account)
    - Purple::Account account
    -
    -Purple::Account
    -purple_account_new(class, username, protocol_id)
    - const char * username
    - const char * protocol_id
    - C_ARGS:
    - username, protocol_id
    -
    -void
    -purple_account_connect(account)
    - Purple::Account account
    -
    -void
    -purple_account_register(account)
    - Purple::Account account
    -
    -void
    -purple_account_disconnect(account)
    - Purple::Account account
    -
    -void
    -purple_account_request_change_password(account)
    - Purple::Account account
    -
    -void
    -purple_account_request_change_user_info(account)
    - Purple::Account account
    -
    -void
    -purple_account_set_username(account, username)
    - Purple::Account account
    - const char * username
    -
    -void
    -purple_account_set_password(account, password, func, data = 0)
    - Purple::Account account
    - const char * password
    - SV *func
    - SV *data
    -CODE:
    - purple_perl_account_set_password(account, password, func, data);
    -
    -void
    -purple_account_set_private_alias(account, alias)
    - Purple::Account account
    - const char * alias
    -
    -void
    -purple_account_set_user_info(account, user_info)
    - Purple::Account account
    - const char *user_info
    -
    -void
    -purple_account_set_buddy_icon_path(account, icon)
    - Purple::Account account
    - const char *icon
    -
    -void
    -purple_account_set_connection(account, gc)
    - Purple::Account account
    - Purple::Connection gc
    -
    -void
    -purple_account_set_remember_password(account, value)
    - Purple::Account account
    - gboolean value
    -
    -void
    -purple_account_set_check_mail(account, value)
    - Purple::Account account
    - gboolean value
    -
    -void purple_account_set_enabled(account, ui, value)
    - Purple::Account account
    - const char *ui
    - gboolean value
    -
    -void
    -purple_account_set_proxy_info(account, info)
    - Purple::Account account
    - Purple::ProxyInfo info
    -
    -void
    -purple_account_set_status(account, status_id, active)
    - Purple::Account account
    - const char *status_id
    - gboolean active
    -CODE:
    - purple_account_set_status(account, status_id, active, NULL);
    -
    -void
    -purple_account_set_status_types(account, status_types)
    - Purple::Account account
    - SV * status_types
    -PREINIT:
    - GList *t_GL;
    - int i, t_len;
    -PPCODE:
    - t_GL = NULL;
    - t_len = av_len((AV *)SvRV(status_types));
    -
    - for (i = 0; i <= t_len; i++)
    - t_GL = g_list_append(t_GL, SvPVutf8_nolen(*av_fetch((AV *)SvRV(status_types), i, 0)));
    -
    - purple_account_set_status_types(account, t_GL);
    -
    -void
    -purple_account_clear_settings(account)
    - Purple::Account account
    -
    -void
    -purple_account_set_int(account, name, value)
    - Purple::Account account
    - const char *name
    - int value
    -
    -gboolean
    -purple_account_is_connected(account)
    - Purple::Account account
    -
    -const char *
    -purple_account_get_username(account)
    - Purple::Account account
    -
    -void
    -purple_account_get_password(account, func, data = 0)
    - Purple::Account account
    - SV *func
    - SV *data
    -CODE:
    - purple_perl_account_get_password(account, func, data);
    -
    -const char *
    -purple_account_get_private_alias(account)
    - Purple::Account account
    -
    -const char *
    -purple_account_get_user_info(account)
    - Purple::Account account
    -
    -const char *
    -purple_account_get_buddy_icon_path(account)
    - Purple::Account account
    -
    -const char *
    -purple_account_get_protocol_id(account)
    - Purple::Account account
    -
    -const char *
    -purple_account_get_protocol_name(account)
    - Purple::Account account
    -
    -Purple::Connection
    -purple_account_get_connection(account)
    - Purple::Account account
    -
    -gboolean
    -purple_account_get_remember_password(account)
    - Purple::Account account
    -
    -gboolean
    -purple_account_get_check_mail(account)
    - Purple::Account account
    -
    -gboolean
    -purple_account_get_enabled(account, ui)
    - Purple::Account account
    - const char *ui
    -
    -Purple::ProxyInfo
    -purple_account_get_proxy_info(account)
    - Purple::Account account
    -
    -Purple::Status
    -purple_account_get_active_status(account)
    - Purple::Account account
    -
    -void
    -purple_account_get_status_types(account)
    - Purple::Account account
    -PREINIT:
    - GList *l;
    -PPCODE:
    - for (l = purple_account_get_status_types(account); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::StatusType")));
    - }
    -
    -Purple::Log
    -purple_account_get_log(account, create)
    - Purple::Account account
    - gboolean create
    -
    -void
    -purple_account_destroy_log(account)
    - Purple::Account account
    -
    -void
    -purple_account_add_buddies(account, list, message)
    - Purple::Account account
    - SV * list
    - const char *message
    -PREINIT:
    - GList *t_GL;
    - int i, t_len;
    -PPCODE:
    - t_GL = NULL;
    - t_len = av_len((AV *)SvRV(list));
    -
    - for (i = 0; i <= t_len; i++)
    - t_GL = g_list_append(t_GL, SvPVutf8_nolen(*av_fetch((AV *)SvRV(list), i, 0)));
    -
    - purple_account_add_buddies(account, t_GL, message);
    - g_list_free(t_GL);
    -
    -void
    -purple_account_add_buddy(account, buddy, message)
    - Purple::Account account
    - Purple::BuddyList::Buddy buddy
    - const char * message
    -
    -void
    -purple_account_change_password(account, a, b)
    - Purple::Account account
    - const char * a
    - const char * b
    -
    -void
    -purple_account_remove_buddies(account, A, B)
    - Purple::Account account
    - SV * A
    - SV * B
    -PREINIT:
    - GList *t_GL1, *t_GL2;
    - int i, t_len;
    -PPCODE:
    - t_GL1 = NULL;
    - t_len = av_len((AV *)SvRV(A));
    -
    - for (i = 0; i <= t_len; i++)
    - t_GL1 = g_list_append(t_GL1, SvPVutf8_nolen(*av_fetch((AV *)SvRV(A), i, 0)));
    -
    - t_GL2 = NULL;
    - t_len = av_len((AV *)SvRV(B));
    -
    - for (i = 0; i <= t_len; i++)
    - t_GL2 = g_list_append(t_GL2, SvPVutf8_nolen(*av_fetch((AV *)SvRV(B), i, 0)));
    -
    - purple_account_remove_buddies(account, t_GL1, t_GL2);
    - g_list_free(t_GL1);
    - g_list_free(t_GL2);
    -
    -void
    -purple_account_remove_buddy(account, buddy, group)
    - Purple::Account account
    - Purple::BuddyList::Buddy buddy
    - Purple::BuddyList::Group group
    -
    -void
    -purple_account_remove_group(account, group)
    - Purple::Account account
    - Purple::BuddyList::Group group
    -
    -MODULE = Purple::Account PACKAGE = Purple::Account::Privacy PREFIX = purple_account_privacy_
    -PROTOTYPES: ENABLE
    -
    -gboolean
    -purple_account_privacy_permit_add(account, name, local_only)
    - Purple::Account account
    - const char * name
    - gboolean local_only
    -
    -gboolean
    -purple_account_privacy_permit_remove(account, name, local_only)
    - Purple::Account account
    - const char * name
    - gboolean local_only
    -
    -gboolean
    -purple_account_privacy_deny_add(account, name, local_only)
    - Purple::Account account
    - const char * name
    - gboolean local_only
    -
    -gboolean
    -purple_account_privacy_deny_remove(account, name, local_only)
    - Purple::Account account
    - const char * name
    - gboolean local_only
    -
    -gboolean
    -purple_account_privacy_check(account, who)
    - Purple::Account account
    - const char * who
    --- a/libpurple/plugins/perl/common/AccountOpts.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,166 +0,0 @@
    -#include "module.h"
    -
    -MODULE = Purple::Account::Option PACKAGE = Purple::Account::Option PREFIX = purple_account_option_
    -PROTOTYPES: ENABLE
    -
    -void
    -purple_account_option_destroy(option)
    - Purple::Account::Option option
    -
    -const char *
    -purple_account_option_get_default_string(option)
    - Purple::Account::Option option
    -
    -void
    -purple_account_option_add_list_item(option, key, value)
    - Purple::Account::Option option
    - const char * key
    - const char * value
    -
    -void
    -purple_account_option_set_default_string(option, value);
    - Purple::Account::Option option
    - const char * value
    -
    -void
    -purple_account_option_set_default_int(option, value);
    - Purple::Account::Option option
    - int value
    -
    -void
    -purple_account_option_set_default_bool(option, value);
    - Purple::Account::Option option
    - gboolean value
    -
    -Purple::Account::Option
    -purple_account_option_list_new(class, text, pref_name, values)
    - const char * text
    - const char * pref_name
    - SV * values
    -PREINIT:
    - GList *t_GL;
    - int i, t_len;
    -CODE:
    - t_GL = NULL;
    - t_len = av_len((AV *)SvRV(values));
    -
    - for (i = 0; i <= t_len; i++)
    - t_GL = g_list_append(t_GL, SvPVutf8_nolen(*av_fetch((AV *)SvRV(values), i, 0)));
    -
    - RETVAL = purple_account_option_list_new(text, pref_name, t_GL);
    -OUTPUT:
    - RETVAL
    -
    -Purple::Account::Option
    -purple_account_option_string_new(class, text, pref_name, default_value)
    - const char * text
    - const char * pref_name
    - const char * default_value
    - C_ARGS:
    - text, pref_name, default_value
    -
    -Purple::Account::Option
    -purple_account_option_int_new(class, text, pref_name, default_value)
    - const char * text
    - const char * pref_name
    - gboolean default_value
    - C_ARGS:
    - text, pref_name, default_value
    -
    -Purple::Account::Option
    -purple_account_option_bool_new(class, text, pref_name, default_value)
    - const char * text
    - const char * pref_name
    - gboolean default_value
    - C_ARGS:
    - text, pref_name, default_value
    -
    -Purple::Account::Option
    -purple_account_option_new(class, type, text, pref_name)
    - Purple::PrefType type
    - const char * text
    - const char * pref_name
    - C_ARGS:
    - type, text, pref_name
    -
    -void
    -purple_account_option_get_list(option)
    - Purple::Account::Option option
    -PREINIT:
    - GList *l;
    -PPCODE:
    - for (l = purple_account_option_get_list(option); l != NULL; l = l->next) {
    - /* XXX These are actually PurpleKeyValuePairs but we don't have a
    - * type for that and even if we did I don't think there's
    - * anything perl could do with them, so I'm just going to
    - * leave this as a Purple::ListEntry for now. */
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::ListEntry")));
    - }
    -
    -Purple::PrefType
    -purple_account_option_get_pref_type(option)
    - Purple::Account::Option option
    -
    -gboolean
    -purple_account_option_string_get_masked(option)
    - Purple::Account::Option option
    -
    -int
    -purple_account_option_get_default_int(option)
    - Purple::Account::Option option;
    -
    -gboolean
    -purple_account_option_get_default_bool(option)
    - Purple::Account::Option option;
    -
    -const char *
    -purple_account_option_get_setting(option)
    - Purple::Account::Option option
    -
    -const char *
    -purple_account_option_get_text(option)
    - Purple::Account::Option option
    -
    -void
    -purple_account_option_set_list(option, values)
    - Purple::Account::Option option
    - SV * values
    -PREINIT:
    - GList *t_GL;
    - int i, t_len;
    -PPCODE:
    - t_GL = NULL;
    - t_len = av_len((AV *)SvRV(values));
    -
    - for (i = 0; i <= t_len; i++)
    - t_GL = g_list_append(t_GL, SvPVutf8_nolen(*av_fetch((AV *)SvRV(values), i, 0)));
    -
    - purple_account_option_set_list(option, t_GL);
    -
    -void
    -purple_account_option_string_set_masked(option, masked)
    - Purple::Account::Option option
    - gboolean masked
    -
    -MODULE = Purple::Account::Option PACKAGE = Purple::Account::UserSplit PREFIX = purple_account_user_split_
    -PROTOTYPES: ENABLE
    -
    -Purple::Account::UserSplit
    -purple_account_user_split_new(class, text, default_value, sep)
    - const char * text
    - const char * default_value
    - char sep
    - C_ARGS:
    - text, default_value, sep
    -
    -char
    -purple_account_user_split_get_separator(split)
    - Purple::Account::UserSplit split
    -
    -const char *
    -purple_account_user_split_get_text(split)
    - Purple::Account::UserSplit split
    -
    -void
    -purple_account_user_split_destroy(split)
    - Purple::Account::UserSplit split
    --- a/libpurple/plugins/perl/common/BuddyIcon.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,71 +0,0 @@
    -#include "module.h"
    -
    -MODULE = Purple::Buddy::Icon PACKAGE = Purple::Buddy::Icon PREFIX = purple_buddy_icon_
    -PROTOTYPES: ENABLE
    -
    -Purple::Buddy::Icon
    -purple_buddy_icon_ref(icon)
    - Purple::Buddy::Icon icon
    -
    -void
    -purple_buddy_icon_unref(icon)
    - Purple::Buddy::Icon icon
    -
    -void
    -purple_buddy_icon_update(icon)
    - Purple::Buddy::Icon icon
    -
    -void
    -purple_buddy_icon_set_data(icon, data, len, checksum)
    - Purple::Buddy::Icon icon
    - void * data
    - size_t len
    - char *checksum
    -
    -Purple::Account
    -purple_buddy_icon_get_account(icon)
    - Purple::Buddy::Icon icon
    -
    -const char *
    -purple_buddy_icon_get_username(icon)
    - Purple::Buddy::Icon icon
    -
    -const void *
    -purple_buddy_icon_get_data(icon, len)
    - Purple::Buddy::Icon icon
    - size_t &len
    -
    -const char *
    -purple_buddy_icon_get_extension(icon)
    - Purple::Buddy::Icon icon
    -
    -void
    -purple_buddy_icon_spec_get_scaled_size(spec, width, height)
    - Purple::Buddy::Icon::Spec spec
    - int *width
    - int *height
    -
    -const gchar *
    -purple_buddy_icon_get_full_path(icon);
    - Purple::Buddy::Icon icon
    -
    -MODULE = Purple::Buddy::Icon PACKAGE = Purple::Buddy::Icons PREFIX = purple_buddy_icons_
    -PROTOTYPES: ENABLE
    -
    -void
    -purple_buddy_icons_set_caching(caching)
    - gboolean caching
    -
    -gboolean
    -purple_buddy_icons_is_caching()
    -
    -void
    -purple_buddy_icons_set_cache_dir(cache_dir)
    - const char *cache_dir
    -
    -const char *
    -purple_buddy_icons_get_cache_dir();
    -
    -Purple::Handle
    -purple_buddy_icons_get_handle();
    -
    --- a/libpurple/plugins/perl/common/BuddyList.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,418 +0,0 @@
    -#undef PURPLE_DISABLE_DEPRECATED
    -#include "module.h"
    -#include "../perl-handlers.h"
    -
    -static void
    -chat_components_foreach(gpointer key, gpointer value, gpointer user_data)
    -{
    - HV *hv = user_data;
    - if (hv_store(hv, key, strlen(key), newSVpv(value, 0), 0) == NULL)
    - purple_debug_error("perl", "hv_store failed\n");
    -}
    -
    -MODULE = Purple::BuddyList PACKAGE = Purple::Find PREFIX = purple_
    -PROTOTYPES: ENABLE
    -
    -gboolean
    -purple_group_on_account(group, account)
    - Purple::BuddyList::Group group
    - Purple::Account account
    -
    -MODULE = Purple::BuddyList PACKAGE = Purple::BuddyList::Contact PREFIX = purple_contact_
    -PROTOTYPES: ENABLE
    -
    -Purple::BuddyList::Contact
    -purple_contact_new();
    -
    -Purple::BuddyList::Buddy
    -purple_contact_get_priority_buddy(contact)
    - Purple::BuddyList::Contact contact
    -
    -const char *
    -purple_contact_get_alias(contact)
    - Purple::BuddyList::Contact contact
    -
    -gboolean
    -purple_contact_on_account(contact, account)
    - Purple::BuddyList::Contact contact
    - Purple::Account account
    -
    -void
    -purple_contact_invalidate_priority_buddy(contact)
    - Purple::BuddyList::Contact contact
    -
    -void
    -purple_contact_merge(source, node)
    - Purple::BuddyList::Contact source
    - Purple::BuddyList::Node node
    -
    -MODULE = Purple::BuddyList PACKAGE = Purple::BuddyList::Group PREFIX = purple_group_
    -PROTOTYPES: ENABLE
    -
    -Purple::BuddyList::Group
    -purple_group_new(name)
    - const char *name
    -
    -void
    -purple_group_get_accounts(group)
    - Purple::BuddyList::Group group
    -PREINIT:
    - GSList *l, *ll;
    -PPCODE:
    - ll = purple_group_get_accounts(group);
    - for (l = ll; l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Account")));
    - }
    - g_slist_free(ll);
    -
    -gboolean
    -purple_group_on_account(group, account)
    - Purple::BuddyList::Group group
    - Purple::Account account
    -
    -void
    -purple_group_set_name(group, name)
    - Purple::BuddyList::Group group
    - const char * name
    -
    -const char *
    -purple_group_get_name(group)
    - Purple::BuddyList::Group group
    -
    -MODULE = Purple::BuddyList PACKAGE = Purple::BuddyList PREFIX = purple_blist_
    -PROTOTYPES: ENABLE
    -
    -Purple::BuddyList
    -purple_blist_get_buddy_list()
    -
    -Purple::BuddyList::Buddy
    -purple_blist_find_buddy(account, name)
    - Purple::Account account
    - const char * name
    -
    -void
    -purple_blist_find_buddies(account, name)
    - Purple::Account account
    - const char * name
    -PREINIT:
    - GSList *l, *ll;
    -PPCODE:
    - ll = purple_blist_find_buddies(account, name);
    - for (l = ll; l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::BuddyList::Buddy")));
    - }
    - g_slist_free(ll);
    -
    -Purple::BuddyList::Group
    -purple_blist_find_group(name)
    - const char *name
    -
    -void
    -purple_blist_add_contact(contact, group, node)
    - Purple::BuddyList::Contact contact
    - Purple::BuddyList::Group group
    - Purple::BuddyList::Node node
    -
    -void
    -purple_blist_add_group(group, node)
    - Purple::BuddyList::Group group
    - Purple::BuddyList::Node node
    -
    -void
    -purple_blist_add_buddy(buddy, contact, group, node)
    - Purple::BuddyList::Buddy buddy
    - Purple::BuddyList::Contact contact
    - Purple::BuddyList::Group group
    - Purple::BuddyList::Node node
    -
    -void
    -purple_blist_remove_buddy(buddy)
    - Purple::BuddyList::Buddy buddy
    -
    -void
    -purple_blist_remove_contact(contact)
    - Purple::BuddyList::Contact contact
    -
    -void
    -purple_blist_remove_chat(chat)
    - Purple::BuddyList::Chat chat
    -
    -void
    -purple_blist_remove_group(group)
    - Purple::BuddyList::Group group
    -
    -Purple::BuddyList::Chat
    -purple_blist_find_chat(account, name)
    - Purple::Account account
    - const char *name
    -
    -void
    -purple_blist_add_chat(chat, group, node)
    - Purple::BuddyList::Chat chat
    - Purple::BuddyList::Group group
    - Purple::BuddyList::Node node
    -
    -void
    -purple_blist_show()
    -
    -void
    -purple_blist_set_visible(show)
    - gboolean show
    -
    -void
    -purple_blist_add_account(account)
    - Purple::Account account
    -
    -void
    -purple_blist_remove_account(account)
    - Purple::Account account
    -
    -void
    -purple_blist_schedule_save()
    -
    -void
    -purple_blist_request_add_group()
    -
    -Purple::Handle
    -purple_blist_get_handle()
    -
    -Purple::BuddyList::Node
    -purple_blist_get_root()
    -
    -MODULE = Purple::BuddyList PACKAGE = Purple::BuddyList::Node PREFIX = purple_blist_node_
    -PROTOTYPES: ENABLE
    -
    -void
    -purple_blist_node_get_extended_menu(node)
    - Purple::BuddyList::Node node
    -PREINIT:
    - GList *l, *ll;
    -PPCODE:
    - ll = purple_blist_node_get_extended_menu(node);
    - for (l = ll; l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Menu::Action")));
    - }
    - /* We can free the list here but the script needs to free the
    - * Purple::Menu::Action 'objects' itself. */
    - g_list_free(ll);
    -
    -void
    -purple_blist_node_set_bool(node, key, value)
    - Purple::BuddyList::Node node
    - const char * key
    - gboolean value
    -
    -gboolean
    -purple_blist_node_get_bool(node, key)
    - Purple::BuddyList::Node node
    - const char * key
    -
    -void
    -purple_blist_node_set_int(node, key, value)
    - Purple::BuddyList::Node node
    - const char * key
    - int value
    -
    -int
    -purple_blist_node_get_int(node, key)
    - Purple::BuddyList::Node node
    - const char * key
    -
    -const char *
    -purple_blist_node_get_string(node, key)
    - Purple::BuddyList::Node node
    - const char * key
    -
    -void
    -purple_blist_node_set_transient(node, transient)
    - Purple::BuddyList::Node node
    - gboolean transient
    -
    -gboolean
    -purple_blist_node_is_transient(node);
    - Purple::BuddyList::Node node
    -
    -void
    -purple_blist_node_remove_setting(node, key)
    - Purple::BuddyList::Node node
    - const char * key
    -
    -MODULE = Purple::BuddyList PACKAGE = Purple::BuddyList::CountingNode PREFIX = purple_counting_node_
    -PROTOTYPES: ENABLE
    -
    -int
    -purple_counting_node_get_total_size(counter);
    - Purple::BuddyList::CountingNode counter
    -
    -int
    -purple_counting_node_get_current_size(counter);
    - Purple::BuddyList::CountingNode counter
    -
    -int
    -purple_counting_node_get_online_count(counter);
    - Purple::BuddyList::CountingNode counter
    -
    -void
    -purple_counting_node_change_total_size(counter, delta);
    - Purple::BuddyList::CountingNode counter
    - int delta
    -
    -void
    -purple_counting_node_change_current_size(counter, delta);
    - Purple::BuddyList::CountingNode counter
    - int delta
    -
    -void
    -purple_counting_node_change_online_count(counter, delta);
    - Purple::BuddyList::CountingNode counter
    - int delta
    -
    -void
    -purple_counting_node_set_total_size(counter, totalsize);
    - Purple::BuddyList::CountingNode counter
    - int totalsize
    -
    -void
    -purple_counting_node_set_current_size(counter, currentsize);
    - Purple::BuddyList::CountingNode counter
    - int currentsize
    -
    -void
    -purple_counting_node_set_online_count(counter, onlinecount);
    - Purple::BuddyList::CountingNode counter
    - int onlinecount
    -
    -MODULE = Purple::BuddyList PACKAGE = Purple::BuddyList::Chat PREFIX = purple_chat_
    -PROTOTYPES: ENABLE
    -
    -Purple::BuddyList::Group
    -purple_chat_get_group(chat)
    - Purple::BuddyList::Chat chat
    -
    -void
    -purple_chat_set_alias(chat, alias)
    - Purple::BuddyList::Chat chat
    - const char * alias
    -
    -const char *
    -purple_chat_get_name(chat)
    - Purple::BuddyList::Chat chat
    -
    -const char *
    -purple_chat_get_name_only(chat)
    - Purple::BuddyList::Chat chat
    -
    -HV *
    -purple_chat_get_components(chat)
    - Purple::BuddyList::Chat chat
    -INIT:
    - HV * t_HV;
    - GHashTable * t_GHash;
    -CODE:
    - t_GHash = purple_chat_get_components(chat);
    - RETVAL = t_HV = newHV();
    - g_hash_table_foreach(t_GHash, chat_components_foreach, t_HV);
    -OUTPUT:
    - RETVAL
    -
    -Purple::BuddyList::Chat
    -purple_chat_new(account, alias, components)
    - Purple::Account account
    - const char * alias
    - SV * components
    -INIT:
    - HV * t_HV;
    - HE * t_HE;
    - SV * t_SV;
    - GHashTable * t_GHash;
    - I32 len;
    - char *t_key, *t_value;
    -CODE:
    - t_HV = (HV *)SvRV(components);
    - t_GHash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
    -
    - for (t_HE = hv_iternext(t_HV); t_HE != NULL; t_HE = hv_iternext(t_HV) ) {
    - t_key = hv_iterkey(t_HE, &len);
    - t_SV = *hv_fetch(t_HV, t_key, len, 0);
    - t_value = SvPVutf8_nolen(t_SV);
    -
    - g_hash_table_insert(t_GHash, g_strdup(t_key), g_strdup(t_value));
    - }
    -
    - RETVAL = purple_chat_new(account, alias, t_GHash);
    -OUTPUT:
    - RETVAL
    -
    -MODULE = Purple::BuddyList PACKAGE = Purple::BuddyList::Buddy PREFIX = purple_buddy_
    -PROTOTYPES: ENABLE
    -
    -Purple::BuddyList::Buddy
    -purple_buddy_new(account, name, alias)
    - Purple::Account account
    - const char *name
    - const char *alias
    -
    -void
    -purple_buddy_update_status(buddy, old_status)
    - Purple::BuddyList::Buddy buddy
    - Purple::Status old_status
    -
    -void
    -purple_buddy_set_name(buddy, name)
    - Purple::BuddyList::Buddy buddy
    - const char * name
    -
    -void
    -purple_buddy_set_local_alias(buddy, alias)
    - Purple::BuddyList::Buddy buddy
    - const char * alias
    -
    -void
    -purple_buddy_set_server_alias(buddy, alias)
    - Purple::BuddyList::Buddy buddy
    - const char * alias
    -
    -const char *
    -purple_buddy_get_server_alias(buddy)
    - Purple::BuddyList::Buddy buddy
    -
    -void
    -purple_buddy_set_icon(buddy, icon)
    - Purple::BuddyList::Buddy buddy
    - Purple::Buddy::Icon icon
    -
    -Purple::Account
    -purple_buddy_get_account(buddy)
    - Purple::BuddyList::Buddy buddy
    -
    -Purple::BuddyList::Group
    -purple_buddy_get_group(buddy)
    - Purple::BuddyList::Buddy buddy
    -
    -const char *
    -purple_buddy_get_name(buddy)
    - Purple::BuddyList::Buddy buddy
    -
    -Purple::Buddy::Icon
    -purple_buddy_get_icon(buddy)
    - Purple::BuddyList::Buddy buddy
    -
    -Purple::BuddyList::Contact
    -purple_buddy_get_contact(buddy)
    - Purple::BuddyList::Buddy buddy
    -
    -Purple::Presence
    -purple_buddy_get_presence(buddy)
    - Purple::BuddyList::Buddy buddy
    -
    -const char *
    -purple_buddy_get_alias_only(buddy)
    - Purple::BuddyList::Buddy buddy
    -
    -const char *
    -purple_buddy_get_contact_alias(buddy)
    - Purple::BuddyList::Buddy buddy
    -
    -const char *
    -purple_buddy_get_alias(buddy)
    - Purple::BuddyList::Buddy buddy
    --- a/libpurple/plugins/perl/common/Certificate.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,309 +0,0 @@
    -#include "module.h"
    -
    -struct cb_data {
    - SV *cb;
    - SV *user_data;
    -};
    -
    -static void cb_cert_verify(PurpleCertificateVerificationStatus st, struct cb_data *d) {
    - dSP;
    -
    - ENTER;
    - SAVETMPS;
    -
    - PUSHMARK(SP);
    -
    - XPUSHs(sv_2mortal(newSViv(st)));
    - XPUSHs(d->user_data);
    -
    - PUTBACK;
    -
    - call_sv(d->cb, G_VOID | G_EVAL);
    -
    - if(SvTRUE(ERRSV)) {
    - STRLEN l_a;
    - purple_debug_warning("perl", "Failed to run 'certificate verify' callback: %s\n", SvPV(ERRSV, l_a));
    - }
    -
    - FREETMPS;
    - LEAVE;
    -
    - SvREFCNT_dec(d->cb);
    - SvREFCNT_dec(d->user_data);
    -
    - g_free(d);
    -}
    -
    -MODULE = Purple::Certificate PACKAGE = Purple::Certificate PREFIX = purple_certificate_
    -PROTOTYPES: ENABLE
    -
    -BOOT:
    -{
    - HV *stash = gv_stashpv("Purple::Certificate", 1);
    -
    - static const constiv *civ, const_iv[] = {
    -#define const_iv(name) {#name, (IV)PURPLE_CERTIFICATE_##name}
    - const_iv(UNKNOWN_ERROR),
    - const_iv(VALID),
    - const_iv(NON_FATALS_MASK),
    - const_iv(SELF_SIGNED),
    - const_iv(CA_UNKNOWN),
    - const_iv(NOT_ACTIVATED),
    - const_iv(EXPIRED),
    - const_iv(NAME_MISMATCH),
    - const_iv(NO_CA_POOL),
    - const_iv(FATALS_MASK),
    - const_iv(INVALID_CHAIN),
    - const_iv(REVOKED),
    - const_iv(REJECTED),
    - const_iv(LAST),
    - };
    -
    - for (civ = const_iv + sizeof(const_iv) / sizeof(const_iv[0]); civ-- > const_iv; )
    - newCONSTSUB(stash, (char *)civ->name, newSViv(civ->iv));
    -}
    -
    -void
    -purple_certificate_add_ca_search_path(path)
    - const char* path
    -
    -gboolean
    -purple_certificate_check_subject_name(crt, name)
    - Purple::Certificate crt
    - const gchar* name
    -
    -Purple::Certificate
    -purple_certificate_copy(crt)
    - Purple::Certificate crt
    -
    -void
    -purple_certificate_destroy(crt)
    - Purple::Certificate crt
    -
    -## changed order of arguments, so that $cert->export($file) could be used
    -gboolean
    -purple_certificate_export(crt, filename)
    - const gchar* filename
    - Purple::Certificate crt
    - C_ARGS:
    - filename, crt
    -
    -Purple::Certificate::Pool
    -purple_certificate_find_pool(scheme_name, pool_name)
    - const gchar* scheme_name
    - const gchar* pool_name
    -
    -Purple::Certificate::Scheme
    -purple_certificate_find_scheme(name)
    - const gchar* name
    -
    -Purple::Certificate::Verifier
    -purple_certificate_find_verifier(scheme_name, ver_name)
    - const gchar* scheme_name
    - const gchar* ver_name
    -
    -Purple::Handle
    -purple_certificate_get_handle()
    -
    -gchar_own*
    -purple_certificate_get_issuer_unique_id(crt)
    - Purple::Certificate crt
    -
    -gchar_own*
    -purple_certificate_get_subject_name(crt)
    - Purple::Certificate crt
    -
    -gchar_own*
    -purple_certificate_get_unique_id(crt)
    - Purple::Certificate crt
    -
    -Purple::Certificate
    -purple_certificate_import(scheme, filename)
    - Purple::Certificate::Scheme scheme
    - const gchar* filename
    -
    -gboolean
    -purple_certificate_register_pool(pool)
    - Purple::Certificate::Pool pool
    -
    -gboolean
    -purple_certificate_register_scheme(scheme)
    - Purple::Certificate::Scheme scheme
    -
    -gboolean
    -purple_certificate_register_verifier(vr)
    - Purple::Certificate::Verifier vr
    -
    -gboolean
    -purple_certificate_signed_by(crt, issuer)
    - Purple::Certificate crt
    - Purple::Certificate issuer
    -
    -gboolean
    -purple_certificate_unregister_pool(pool)
    - Purple::Certificate::Pool pool
    -
    -gboolean
    -purple_certificate_unregister_scheme(scheme)
    - Purple::Certificate::Scheme scheme
    -
    -gboolean
    -purple_certificate_unregister_verifier(vr)
    - Purple::Certificate::Verifier vr
    -
    -void
    -purple_certificate_verify_complete(vrq, st)
    - Purple::Certificate::VerificationRequest vrq
    - Purple::Certificate::VerificationStatus st
    -
    -gboolean
    -purple_certificate_get_times(crt, OUTLIST gint64 activation, OUTLIST gint64 expiration)
    - Purple::Certificate crt
    - PROTOTYPE: $
    -
    -void
    -purple_certificate_destroy_list(...)
    - PREINIT:
    - GList* l = NULL;
    - int i = 0;
    - CODE:
    - for(i = 0; i < items; i++) { /* PurpleCertificate */
    - l = g_list_prepend(l, purple_perl_ref_object(ST(i)));
    - }
    - purple_certificate_destroy_list(l);
    -
    -void
    -purple_certificate_get_pools()
    - PREINIT:
    - GList *l;
    - PPCODE:
    - for(l = purple_certificate_get_pools(); l; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Certificate::Pool")));
    - }
    -
    -void
    -purple_certificate_get_schemes()
    - PREINIT:
    - GList *l;
    - PPCODE:
    - for(l = purple_certificate_get_schemes(); l; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Certificate::Scheme")));
    - }
    -
    -void
    -purple_certificate_get_verifiers()
    - PREINIT:
    - GList *l;
    - PPCODE:
    - for(l = purple_certificate_get_verifiers(); l; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Certificate::Verifier")));
    - }
    -
    -void
    -purple_certificate_check_signature_chain(...)
    - PREINIT:
    - GList *l = NULL;
    - gboolean ret;
    - int i;
    - PPCODE:
    - for(i = 0; i < items; i++) { /* PurpleCertificate */
    - l = g_list_prepend(l, purple_perl_ref_object(ST(i)));
    - }
    - l = g_list_reverse(l);
    - ret = purple_certificate_check_signature_chain(l, NULL);
    - g_list_free(l);
    - if(ret) XSRETURN_YES;
    - XSRETURN_NO;
    -
    -SV*
    -purple_certificate_get_fingerprint_sha1(crt)
    - Purple::Certificate crt
    - PREINIT:
    - GByteArray *gba = NULL;
    - CODE:
    - gba = purple_certificate_get_fingerprint_sha1(crt);
    - RETVAL = newSVpv((gchar *)gba->data, gba->len);
    - g_byte_array_free(gba, TRUE);
    - OUTPUT:
    - RETVAL
    -
    -void
    -purple_certificate_verify(verifier, subject_name, cert_chain, cb, cb_data)
    - Purple::Certificate::Verifier verifier
    - const gchar* subject_name
    - AV* cert_chain
    - SV *cb_data
    - PREINIT:
    - GList *l = NULL;
    - int len = 0, i = 0;
    - struct cb_data *d = NULL;
    - PPCODE:
    - len = av_len(cert_chain);
    - for(i = 0; i <= len; i++) {
    - SV **sv = av_fetch(cert_chain, i, 0);
    - if(!sv || !purple_perl_is_ref_object(*sv)) {
    - g_list_free(l);
    - warn("Purple::Certificate::verify: cert_chain: non-purple object in array...");
    - XSRETURN_UNDEF;
    - }
    - l = g_list_prepend(l, purple_perl_ref_object(*sv));
    - }
    - l = g_list_reverse(l);
    -
    - d = g_new0(struct cb_data, 1);
    - d->cb = newSVsv(ST(3));
    - d->user_data = newSVsv(cb_data);
    -
    - purple_certificate_verify(verifier, subject_name, l, (PurpleCertificateVerifiedCallback) cb_cert_verify, d);
    -
    - g_list_free(l);
    -
    -MODULE = Purple::Certificate PACKAGE = Purple::Certificate::Pool PREFIX = purple_certificate_pool_
    -PROTOTYPES: ENABLE
    -
    -void
    -purple_certificate_pool_get_idlist(pool)
    - Purple::Certificate::Pool pool
    - PREINIT:
    - GList *l, *b;
    - PPCODE:
    - b = purple_certificate_pool_get_idlist(pool);
    - for(l = b; l; l = l->next) {
    - XPUSHs(sv_2mortal(newSVpv(l->data, 0)));
    - }
    - purple_certificate_pool_destroy_idlist(b);
    -
    -gboolean
    -purple_certificate_pool_contains(pool, id)
    - Purple::Certificate::Pool pool
    - const gchar* id
    -
    -gboolean
    -purple_certificate_pool_delete(pool, id)
    - Purple::Certificate::Pool pool
    - const gchar* id
    -
    -Purple::Certificate::Scheme
    -purple_certificate_pool_get_scheme(pool)
    - Purple::Certificate::Pool pool
    -
    -gchar_own*
    -purple_certificate_pool_mkpath(pool, id)
    - Purple::Certificate::Pool pool
    - const gchar* id
    -
    -Purple::Certificate
    -purple_certificate_pool_retrieve(pool, id)
    - Purple::Certificate::Pool pool
    - const gchar* id
    -
    -gboolean
    -purple_certificate_pool_store(pool, id, crt)
    - Purple::Certificate::Pool pool
    - const gchar* id
    - Purple::Certificate crt
    -
    -gboolean
    -purple_certificate_pool_usable(pool)
    - Purple::Certificate::Pool pool
    -
    --- a/libpurple/plugins/perl/common/Cipher.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,329 +0,0 @@
    -#include "module.h"
    -
    -MODULE = Purple::Cipher PACKAGE = Purple::Cipher PREFIX = purple_cipher_
    -PROTOTYPES: ENABLE
    -
    -BOOT:
    -{
    - HV *stash = gv_stashpv("Purple::Cipher::BatchMode", 1);
    -
    - static const constiv *civ, const_iv[] = {
    -#define const_iv(name) {#name, (IV)PURPLE_CIPHER_BATCH_MODE_##name}
    - const_iv(ECB),
    - const_iv(CBC),
    -#undef const_iv
    - };
    -
    - for (civ = const_iv + sizeof(const_iv) / sizeof(const_iv[0]); civ-- > const_iv; )
    - newCONSTSUB(stash, (char *)civ->name, newSViv(civ->iv));
    -}
    -
    -gchar_own*
    -purple_http_digest_calculate_response(algorithm, method, digest_uri, qop, entity, nonce, nonce_count, client_nonce, session_key)
    - const gchar* algorithm
    - const gchar* method
    - const gchar* digest_uri
    - const gchar* qop
    - const gchar* entity
    - const gchar* nonce
    - const gchar* nonce_count
    - const gchar* client_nonce
    - const gchar* session_key
    -
    -gchar_own*
    -purple_http_digest_calculate_session_key(algorithm, username, realm, password, nonce, client_nonce)
    - const gchar* algorithm
    - const gchar* username
    - const gchar* realm
    - const gchar* password
    - const gchar* nonce
    - const gchar* client_nonce
    -
    -void
    -purple_cipher_reset(cipher)
    - Purple::Cipher cipher
    -
    -void
    -purple_cipher_set_iv(Purple::Cipher cipher, guchar *iv, size_t length(iv))
    - PROTOTYPE: $$
    -
    -void
    -purple_cipher_append(Purple::Cipher cipher, guchar *data, size_t length(data))
    - PROTOTYPE: $$
    -
    -gboolean
    -purple_cipher_digest(cipher, digest)
    - Purple::Cipher cipher
    - SV *digest
    - PREINIT:
    - guchar *buff = NULL;
    - size_t digest_size;
    - CODE:
    - digest_size = purple_cipher_get_digest_size(cipher);
    - SvUPGRADE_common(digest, SVt_PV);
    - buff = (guchar *)SvGROW(digest, digest_size);
    - if (purple_cipher_digest(cipher, buff, digest_size)) {
    - SvCUR_set(digest, digest_size);
    - /* coverity[extra_comma] */
    - SvPOK_only(digest);
    - RETVAL = 1;
    - } else {
    - SvSetSV_nosteal(digest, &PL_sv_undef);
    - RETVAL = 0;
    - }
    - OUTPUT:
    - RETVAL
    -
    -gboolean
    -purple_cipher_digest_to_str(cipher, digest_s)
    - Purple::Cipher cipher
    - SV *digest_s
    - PREINIT:
    - gchar *buff = NULL;
    - size_t digest_size, str_len;
    - CODE:
    - digest_size = purple_cipher_get_digest_size(cipher);
    - str_len = 2 * digest_size;
    - SvUPGRADE_common(digest_s, SVt_PV);
    - buff = SvGROW(digest_s, str_len + 1);
    - if (purple_cipher_digest_to_str(cipher, buff, str_len + 1)) {
    - SvCUR_set(digest_s, str_len);
    - /* coverity[extra_comma] */
    - SvPOK_only(digest_s);
    - RETVAL = 1;
    - } else {
    - SvSetSV_nosteal(digest_s, &PL_sv_undef);
    - RETVAL = 0;
    - }
    - OUTPUT:
    - RETVAL
    -
    -gboolean
    -purple_cipher_encrypt(cipher, input, output)
    - Purple::Cipher cipher
    - SV *input
    - SV *output
    - PREINIT:
    - size_t input_len, output_len;
    - ssize_t ret;
    - guchar *buff = NULL;
    - guchar *data = NULL;
    - CODE:
    - data = (guchar *)SvPV(input, input_len);
    - output_len = input_len + purple_cipher_get_block_size(cipher);
    - SvUPGRADE_common(output, SVt_PV);
    - buff = (guchar *)SvGROW(output, output_len);
    - ret = purple_cipher_encrypt(cipher, data, input_len, buff, output_len);
    - if (ret >= 0) {
    - RETVAL = 1;
    - /* coverity[extra_comma] */
    - SvPOK_only(output);
    - SvCUR_set(output, ret);
    - } else {
    - RETVAL = 0;
    - SvSetSV_nosteal(output, &PL_sv_undef);
    - }
    - OUTPUT:
    - RETVAL
    -
    -gboolean
    -purple_cipher_decrypt(cipher, input, output)
    - Purple::Cipher cipher
    - SV *input
    - SV *output
    - PREINIT:
    - size_t input_len, output_len;
    - ssize_t ret;
    - guchar *buff = NULL;
    - guchar *data = NULL;
    - CODE:
    - data = (guchar *)SvPV(input, input_len);
    - output_len = input_len + purple_cipher_get_block_size(cipher);
    - SvUPGRADE_common(output, SVt_PV);
    - buff = (guchar *)SvGROW(output, output_len);
    - ret = purple_cipher_decrypt(cipher, data, input_len, buff, output_len);
    - if (ret >= 0) {
    - RETVAL = 1;
    - /* coverity[extra_comma] */
    - SvPOK_only(output);
    - SvCUR_set(output, ret);
    - } else {
    - RETVAL = 0;
    - SvSetSV_nosteal(output, &PL_sv_undef);
    - }
    - OUTPUT:
    - RETVAL
    -
    -void
    -purple_cipher_set_salt(cipher, salt, len)
    - Purple::Cipher cipher
    - guchar *salt
    - size_t len
    -
    -void
    -purple_cipher_set_key(cipher, key, len)
    - Purple::Cipher cipher
    - guchar *key
    - size_t len
    -
    -size_t
    -purple_cipher_get_key_size(cipher)
    - Purple::Cipher cipher
    -
    -Purple::Cipher::BatchMode
    -purple_cipher_get_batch_mode(cipher)
    - Purple::Cipher cipher
    -
    -size_t
    -purple_cipher_get_block_size(cipher)
    - Purple::Cipher cipher
    -
    -void
    -purple_cipher_set_batch_mode(cipher, mode)
    - Purple::Cipher cipher
    - Purple::Cipher::BatchMode mode
    -
    -MODULE = Purple::Cipher PACKAGE = Purple::AESCipher PREFIX = purple_aes_cipher_
    -PROTOTYPES: ENABLE
    -
    -Purple::Cipher
    -purple_aes_cipher_new()
    -
    -MODULE = Purple::Cipher PACKAGE = Purple::DES3Cipher PREFIX = purple_des3_cipher_
    -PROTOTYPES: ENABLE
    -
    -Purple::Cipher
    -purple_des3_cipher_new()
    -
    -MODULE = Purple::Cipher PACKAGE = Purple::DESCipher PREFIX = purple_des_cipher_
    -PROTOTYPES: ENABLE
    -
    -Purple::Cipher
    -purple_des_cipher_new()
    -
    -MODULE = Purple::Cipher PACKAGE = Purple::HMACCipher PREFIX = purple_hmac_cipher_
    -PROTOTYPES: ENABLE
    -
    -Purple::Cipher
    -purple_hmac_cipher_new(hash)
    - Purple::Hash hash
    -
    -MODULE = Purple::Cipher PACKAGE = Purple::PBKDF2Cipher PREFIX = purple_pbkdf2_cipher_
    -PROTOTYPES: ENABLE
    -
    -Purple::Cipher
    -purple_pbkdf2_cipher_new(hash)
    - Purple::Hash hash
    -
    -MODULE = Purple::Cipher PACKAGE = Purple::RC4Cipher PREFIX = purple_rc4_cipher_
    -PROTOTYPES: ENABLE
    -
    -Purple::Cipher
    -purple_rc4_cipher_new()
    -
    -MODULE = Purple::Cipher PACKAGE = Purple::Hash PREFIX = purple_hash_
    -PROTOTYPES: ENABLE
    -
    -gchar_own*
    -purple_http_digest_calculate_response(algorithm, method, digest_uri, qop, entity, nonce, nonce_count, client_nonce, session_key)
    - const gchar* algorithm
    - const gchar* method
    - const gchar* digest_uri
    - const gchar* qop
    - const gchar* entity
    - const gchar* nonce
    - const gchar* nonce_count
    - const gchar* client_nonce
    - const gchar* session_key
    -
    -gchar_own*
    -purple_http_digest_calculate_session_key(algorithm, username, realm, password, nonce, client_nonce)
    - const gchar* algorithm
    - const gchar* username
    - const gchar* realm
    - const gchar* password
    - const gchar* nonce
    - const gchar* client_nonce
    -
    -void
    -purple_hash_reset(hash)
    - Purple::Hash hash
    -
    -void
    -purple_hash_append(Purple::Hash hash, guchar *data, size_t length(data))
    - PROTOTYPE: $$
    -
    -gboolean
    -purple_hash_digest(hash, digest)
    - Purple::Hash hash
    - SV *digest
    - PREINIT:
    - guchar *buff = NULL;
    - size_t digest_size;
    - CODE:
    - digest_size = purple_hash_get_digest_size(hash);
    - SvUPGRADE_common(digest, SVt_PV);
    - buff = (guchar *)SvGROW(digest, digest_size);
    - if (purple_hash_digest(hash, buff, digest_size)) {
    - SvCUR_set(digest, digest_size);
    - /* coverity[extra_comma] */
    - SvPOK_only(digest);
    - RETVAL = 1;
    - } else {
    - SvSetSV_nosteal(digest, &PL_sv_undef);
    - RETVAL = 0;
    - }
    - OUTPUT:
    - RETVAL
    -
    -gboolean
    -purple_hash_digest_to_str(hash, digest_s)
    - Purple::Hash hash
    - SV *digest_s
    - PREINIT:
    - gchar *buff = NULL;
    - size_t digest_size, str_len;
    - CODE:
    - digest_size = purple_hash_get_digest_size(hash);
    - str_len = 2 * digest_size;
    - SvUPGRADE_common(digest_s, SVt_PV);
    - buff = SvGROW(digest_s, str_len + 1);
    - if (purple_hash_digest_to_str(hash, buff, str_len + 1)) {
    - SvCUR_set(digest_s, str_len);
    - /* coverity[extra_comma] */
    - SvPOK_only(digest_s);
    - RETVAL = 1;
    - } else {
    - SvSetSV_nosteal(digest_s, &PL_sv_undef);
    - RETVAL = 0;
    - }
    - OUTPUT:
    - RETVAL
    -
    -size_t
    -purple_hash_get_block_size(hash)
    - Purple::Hash hash
    -
    -MODULE = Purple::Hash PACKAGE = Purple::MD4Hash PREFIX = purple_md4_hash_
    -PROTOTYPES: ENABLE
    -
    -Purple::Hash
    -purple_md4_hash_new()
    -
    -MODULE = Purple::Hash PACKAGE = Purple::MD5Hash PREFIX = purple_md5_hash_
    -PROTOTYPES: ENABLE
    -
    -Purple::Hash
    -purple_md5_hash_new()
    -
    -MODULE = Purple::Hash PACKAGE = Purple::SHA1Hash PREFIX = purple_sha1_hash_
    -PROTOTYPES: ENABLE
    -
    -Purple::Hash
    -purple_sha1_hash_new()
    -
    -MODULE = Purple::Hash PACKAGE = Purple::SHA256Hash PREFIX = purple_sha256_hash_
    -PROTOTYPES: ENABLE
    -
    -Purple::Hash
    -purple_sha256_hash_new()
    --- a/libpurple/plugins/perl/common/Cmds.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,108 +0,0 @@
    -#include "module.h"
    -#include "../perl-handlers.h"
    -
    -MODULE = Purple::Cmd PACKAGE = Purple::Cmd PREFIX = purple_cmd_
    -PROTOTYPES: ENABLE
    -
    -BOOT:
    -{
    - HV *status_stash = gv_stashpv("Purple::Cmd::Status", 1);
    - HV *ret_stash = gv_stashpv("Purple::Cmd::Return", 1);
    - HV *p_stash = gv_stashpv("Purple::Cmd::Priority", 1);
    - HV *flag_stash = gv_stashpv("Purple::Cmd::Flag", 1);
    -
    - static const constiv *civ, status_const_iv[] = {
    -#define const_iv(name) {#name, (IV)PURPLE_CMD_STATUS_##name}
    - const_iv(OK),
    - const_iv(FAILED),
    - const_iv(NOT_FOUND),
    - const_iv(WRONG_ARGS),
    - const_iv(WRONG_PROTOCOL),
    - const_iv(WRONG_TYPE),
    - };
    - static const constiv ret_const_iv[] = {
    -#undef const_iv
    -#define const_iv(name) {#name, (IV)PURPLE_CMD_RET_##name}
    - const_iv(OK),
    - const_iv(FAILED),
    - const_iv(CONTINUE),
    - };
    - static const constiv p_const_iv[] = {
    -#undef const_iv
    -#define const_iv(name) {#name, (IV)PURPLE_CMD_P_##name}
    - const_iv(VERY_LOW),
    - const_iv(LOW),
    - const_iv(DEFAULT),
    - const_iv(PROTOCOL),
    - const_iv(PLUGIN),
    - const_iv(ALIAS),
    - const_iv(HIGH),
    - const_iv(VERY_HIGH),
    - };
    - static const constiv flag_const_iv[] = {
    -#undef const_iv
    -#define const_iv(name) {#name, (IV)PURPLE_CMD_FLAG_##name}
    - const_iv(IM),
    - const_iv(CHAT),
    - const_iv(PROTOCOL_ONLY),
    - const_iv(ALLOW_WRONG_ARGS),
    - };
    -
    - for (civ = status_const_iv + sizeof(status_const_iv) / sizeof(status_const_iv[0]); civ-- > status_const_iv;)
    - newCONSTSUB(status_stash, (char *)civ->name, newSViv(civ->iv));
    -
    - for (civ = ret_const_iv + sizeof(ret_const_iv) / sizeof(ret_const_iv[0]); civ-- > ret_const_iv;)
    - newCONSTSUB(ret_stash, (char *)civ->name, newSViv(civ->iv));
    -
    - for (civ = p_const_iv + sizeof(p_const_iv) / sizeof(p_const_iv[0]); civ-- > p_const_iv;)
    - newCONSTSUB(p_stash, (char *)civ->name, newSViv(civ->iv));
    -
    - for (civ = flag_const_iv + sizeof(flag_const_iv) / sizeof(flag_const_iv[0]); civ-- > flag_const_iv;)
    - newCONSTSUB(flag_stash, (char *)civ->name, newSViv(civ->iv));
    -}
    -
    -void
    -purple_cmd_help(conv, command)
    - Purple::Conversation conv
    - const gchar *command
    -PREINIT:
    - GList *l, *ll;
    -PPCODE:
    - for (l = ll = purple_cmd_help(conv, command); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(newSVpv(l->data, 0)));
    - }
    - g_list_free(ll);
    -
    -void
    -purple_cmd_list(conv)
    - Purple::Conversation conv
    -PREINIT:
    - GList *l, *ll;
    -PPCODE:
    - for (l = ll = purple_cmd_list(conv); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(newSVpv(l->data, 0)));
    - }
    - g_list_free(ll);
    -
    -Purple::Cmd::Id
    -purple_cmd_register(plugin, command, args, priority, flag, protocol_id, func, helpstr, data = 0)
    - Purple::Plugin plugin
    - const gchar *command
    - const gchar *args
    - Purple::Cmd::Priority priority
    - Purple::Cmd::Flag flag
    - const gchar *protocol_id
    - SV *func
    - const gchar *helpstr
    - SV *data
    -CODE:
    - RETVAL = purple_perl_cmd_register(plugin, command, args, priority, flag,
    - protocol_id, func, helpstr, data);
    -OUTPUT:
    - RETVAL
    -
    -void
    -purple_cmd_unregister(id)
    - Purple::Cmd::Id id
    -CODE:
    - purple_perl_cmd_unregister(id);
    --- a/libpurple/plugins/perl/common/Connection.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,87 +0,0 @@
    -#include "module.h"
    -
    -MODULE = Purple::Connection PACKAGE = Purple::Connection PREFIX = purple_connection_
    -PROTOTYPES: ENABLE
    -
    -BOOT:
    -{
    - HV *stash = gv_stashpv("Purple::Connection::State", 1);
    -
    - static const constiv *civ, const_iv[] = {
    -#define const_iv(name) {#name, (IV)PURPLE_CONNECTION_##name}
    - const_iv(DISCONNECTED),
    - const_iv(CONNECTED),
    - const_iv(CONNECTING),
    - };
    -
    - for (civ = const_iv + sizeof(const_iv) / sizeof(const_iv[0]); civ-- > const_iv; )
    - newCONSTSUB(stash, (char *)civ->name, newSViv(civ->iv));
    -}
    -
    -Purple::Account
    -purple_connection_get_account(gc)
    - Purple::Connection gc
    -
    -const char *
    -purple_connection_get_password(gc)
    - Purple::Connection gc
    -
    -void
    -purple_connection_get_active_chats(gc)
    - Purple::Connection gc
    -PREINIT:
    - GSList *l;
    -PPCODE:
    - for (l = purple_connection_get_active_chats(gc); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::ChatConversation")));
    - }
    -
    -const char *
    -purple_connection_get_display_name(gc)
    - Purple::Connection gc
    -
    -void
    -purple_connection_notice(gc, text)
    - Purple::Connection gc
    - const char *text
    -
    -void
    -purple_connection_set_state(gc, state)
    - Purple::Connection gc
    - Purple::ConnectionState state
    -
    -void
    -purple_connection_set_display_name(gc, name)
    - Purple::Connection gc
    - const char *name
    -
    -Purple::ConnectionState
    -purple_connection_get_state(gc)
    - Purple::Connection gc
    -
    -MODULE = Purple::Connection PACKAGE = Purple::Connections PREFIX = purple_connections_
    -PROTOTYPES: ENABLE
    -
    -void
    -purple_connections_disconnect_all()
    -
    -void
    -purple_connections_get_all()
    -PREINIT:
    - GList *l;
    -PPCODE:
    - for (l = purple_connections_get_all(); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Connection")));
    - }
    -
    -void
    -purple_connections_get_connecting()
    -PREINIT:
    - GList *l;
    -PPCODE:
    - for (l = purple_connections_get_connecting(); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Connection")));
    - }
    -
    -Purple::Handle
    -purple_connections_get_handle()
    --- a/libpurple/plugins/perl/common/Conversation.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,435 +0,0 @@
    -#include "module.h"
    -
    -MODULE = Purple::Conversation PACKAGE = Purple PREFIX = purple_
    -PROTOTYPES: ENABLE
    -
    -BOOT:
    -{
    - HV *update_stash = gv_stashpv("Purple::Conversation::UpdateType", 1);
    - HV *typing_stash = gv_stashpv("Purple::IMTypingState", 1);
    - HV *flags_stash = gv_stashpv("Purple::MessageFlags", 1);
    - HV *cbflags_stash = gv_stashpv("Purple::ChatUser::Flags", 1);
    -
    - static const constiv *civ, update_const_iv[] = {
    -#undef const_iv
    -#define const_iv(name) {#name, (IV)PURPLE_CONVERSATION_UPDATE_##name}
    - const_iv(ADD),
    - const_iv(REMOVE),
    - const_iv(ACCOUNT),
    - const_iv(TYPING),
    - const_iv(UNSEEN),
    - const_iv(LOGGING),
    - const_iv(TOPIC),
    -/*
    - const_iv(ONLINE),
    - const_iv(OFFLINE),
    -*/
    - const_iv(AWAY),
    - const_iv(ICON),
    - const_iv(TITLE),
    - const_iv(CHATLEFT),
    - const_iv(FEATURES),
    - };
    - static const constiv typing_const_iv[] = {
    -#undef const_iv
    -#define const_iv(name) {#name, (IV)PURPLE_IM_##name}
    - const_iv(NOT_TYPING),
    - const_iv(TYPING),
    - const_iv(TYPED),
    - };
    - static const constiv flags_const_iv[] = {
    -#undef const_iv
    -#define const_iv(name) {#name, (IV)PURPLE_MESSAGE_##name}
    - const_iv(SEND),
    - const_iv(RECV),
    - const_iv(SYSTEM),
    - const_iv(AUTO_RESP),
    - const_iv(ACTIVE_ONLY),
    - const_iv(NICK),
    - const_iv(NO_LOG),
    - const_iv(ERROR),
    - const_iv(DELAYED),
    - const_iv(RAW),
    - const_iv(IMAGES),
    - const_iv(NOTIFY),
    - const_iv(NO_LINKIFY),
    - };
    - static const constiv cbflags_const_iv[] = {
    -#undef const_iv
    -#define const_iv(name) {#name, (IV)PURPLE_CHAT_USER_##name}
    - const_iv(NONE),
    - const_iv(VOICE),
    - const_iv(HALFOP),
    - const_iv(OP),
    - const_iv(FOUNDER),
    - const_iv(TYPING),
    - };
    -
    - for (civ = update_const_iv + sizeof(update_const_iv) / sizeof(update_const_iv[0]); civ-- > update_const_iv; )
    - newCONSTSUB(update_stash, (char *)civ->name, newSViv(civ->iv));
    -
    - for (civ = typing_const_iv + sizeof(typing_const_iv) / sizeof(typing_const_iv[0]); civ-- > typing_const_iv; )
    - newCONSTSUB(typing_stash, (char *)civ->name, newSViv(civ->iv));
    -
    - for (civ = flags_const_iv + sizeof(flags_const_iv) / sizeof(flags_const_iv[0]); civ-- > flags_const_iv; )
    - newCONSTSUB(flags_stash, (char *)civ->name, newSViv(civ->iv));
    -
    - for (civ = cbflags_const_iv + sizeof(cbflags_const_iv) / sizeof(cbflags_const_iv[0]); civ-- > cbflags_const_iv; )
    - newCONSTSUB(cbflags_stash, (char *)civ->name, newSViv(civ->iv));
    -}
    -
    -MODULE = Purple::Conversation PACKAGE = Purple::Conversations PREFIX = purple_conversations_
    -PROTOTYPES: ENABLE
    -
    -void
    -purple_conversations_add(conv)
    - Purple::Conversation conv
    -
    -void
    -purple_conversations_remove(conv)
    - Purple::Conversation conv
    -
    -Purple::Handle
    -purple_conversations_get_handle()
    -
    -Purple::ChatConversation
    -purple_conversations_find_chat(gc, id)
    - Purple::Connection gc
    - int id
    -
    -void
    -purple_conversations_get_ims()
    -PREINIT:
    - GList *l;
    -PPCODE:
    - for (l = purple_conversations_get_ims(); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::IMConversation")));
    - }
    -
    -void
    -purple_conversations_get_all()
    -PREINIT:
    - GList *l;
    -PPCODE:
    - for (l = purple_conversations_get_all(); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Conversation")));
    - }
    -
    -void
    -purple_conversations_get_chats()
    -PREINIT:
    - GList *l;
    -PPCODE:
    - for (l = purple_conversations_get_chats(); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::ChatConversation")));
    - }
    -
    -Purple::Conversation
    -purple_conversations_find_with_account(name, account)
    - const char *name
    - Purple::Account account
    -
    -Purple::ChatConversation
    -purple_conversations_find_chat_with_account(name, account)
    - const char *name
    - Purple::Account account
    -
    -Purple::IMConversation
    -purple_conversations_find_im_with_account(name, account)
    - const char *name
    - Purple::Account account
    -
    -MODULE = Purple::Conversation PACKAGE = Purple::Conversation PREFIX = purple_conversation_
    -PROTOTYPES: ENABLE
    -
    -Purple::Account
    -purple_conversation_get_account(conv)
    - Purple::Conversation conv
    -
    -Purple::Connection
    -purple_conversation_get_connection(conv)
    - Purple::Conversation conv
    -
    -void
    -purple_conversation_set_title(conv, title);
    - Purple::Conversation conv
    - const char * title
    -
    -const char *
    -purple_conversation_get_title(conv)
    - Purple::Conversation conv
    -
    -void
    -purple_conversation_autoset_title(conv)
    - Purple::Conversation conv
    -
    -void
    -purple_conversation_set_name(conv, name)
    - Purple::Conversation conv
    - const char *name
    -
    -const char *
    -purple_conversation_get_name(conv)
    - Purple::Conversation conv
    -
    -void
    -purple_conversation_set_logging(conv, log)
    - Purple::Conversation conv
    - gboolean log
    -
    -gboolean
    -purple_conversation_is_logging(conv)
    - Purple::Conversation conv
    -
    -Purple::ConnectionFlags
    -purple_conversation_get_features(conv)
    - Purple::Conversation conv
    -
    -gboolean
    -purple_conversation_has_focus(conv)
    - Purple::Conversation conv
    -
    -void
    -purple_conversation_update(conv, type)
    - Purple::Conversation conv
    - Purple::Conversation::UpdateType type
    -
    -void
    -purple_conversation_set_account(conv, account);
    - Purple::Conversation conv
    - Purple::Account account
    -
    -void
    -purple_conversation_send(conv, message)
    - Purple::Conversation conv
    - const char *message
    -
    -void
    -purple_conversation_send_with_flags(conv, message, flags)
    - Purple::Conversation conv
    - const char *message
    - Purple::MessageFlags flags
    -
    -gboolean
    -purple_conversation_do_command(conv, cmdline, markup, error)
    - Purple::Conversation conv
    - const char *cmdline
    - const char *markup
    - char **error
    -
    -MODULE = Purple::Conversation PACKAGE = Purple::IMConversation PREFIX = purple_im_conversation_
    -PROTOTYPES: ENABLE
    -
    -Purple::IMConversation
    -purple_im_conversation_new(class, account, name)
    - Purple::Account account
    - const char *name
    - C_ARGS:
    - account, name
    -
    -void
    -purple_im_conversation_set_icon(im, icon)
    - Purple::IMConversation im
    - Purple::Buddy::Icon icon
    -
    -Purple::Buddy::Icon
    -purple_im_conversation_get_icon(im)
    - Purple::IMConversation im
    -
    -void
    -purple_im_conversation_set_typing_state(im, state)
    - Purple::IMConversation im
    - Purple::IMTypingState state
    -
    -Purple::IMTypingState
    -purple_im_conversation_get_typing_state(im)
    - Purple::IMConversation im
    -
    -void
    -purple_im_conversation_start_typing_timeout(im, timeout)
    - Purple::IMConversation im
    - int timeout
    -
    -void
    -purple_im_conversation_stop_typing_timeout(im)
    - Purple::IMConversation im
    -
    -guint
    -purple_im_conversation_get_typing_timeout(im)
    - Purple::IMConversation im
    -
    -void
    -purple_im_conversation_set_type_again(im, val)
    - Purple::IMConversation im
    - time_t val
    -
    -time_t
    -purple_im_conversation_get_type_again(im)
    - Purple::IMConversation im
    -
    -void
    -purple_im_conversation_start_send_typed_timeout(im)
    - Purple::IMConversation im
    -
    -void
    -purple_im_conversation_stop_send_typed_timeout(im)
    - Purple::IMConversation im
    -
    -guint
    -purple_im_conversation_get_send_typed_timeout(im)
    - Purple::IMConversation im
    -
    -void
    -purple_im_conversation_update_typing(im)
    - Purple::IMConversation im
    -
    -MODULE = Purple::Conversation PACKAGE = Purple::Conversation::Helper PREFIX = purple_conversation_helper_
    -PROTOTYPES: ENABLE
    -
    -gboolean
    -purple_conversation_present_error(who, account, what)
    - const char *who
    - Purple::Account account
    - const char *what
    -
    -MODULE = Purple::Conversation PACKAGE = Purple::Conversation PREFIX = purple_conversation_
    -PROTOTYPES: ENABLE
    -
    -MODULE = Purple::Conversation PACKAGE = Purple::ChatConversation PREFIX = purple_chat_conversation_
    -PROTOTYPES: ENABLE
    -
    -Purple::ChatConversation
    -purple_chat_conversation_new(class, account, name)
    - Purple::Account account
    - const char *name
    - C_ARGS:
    - account, name
    -
    -void
    -purple_chat_conversation_get_users(chat)
    - Purple::ChatConversation chat
    -PREINIT:
    - GList *l, *users;
    -PPCODE:
    - users = purple_chat_conversation_get_users(chat);
    - for (l = users; l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::ListEntry")));
    - }
    - g_list_free(users);
    -
    -void
    -purple_chat_conversation_ignore(chat, name)
    - Purple::ChatConversation chat
    - const char *name
    -
    -void
    -purple_chat_conversation_unignore(chat, name)
    - Purple::ChatConversation chat
    - const char *name
    -
    -void
    -purple_chat_conversation_set_ignored(chat, ignored)
    - Purple::ChatConversation chat
    - SV * ignored
    -PREINIT:
    - GList *l, *t_GL;
    - int i, t_len;
    -PPCODE:
    - t_GL = NULL;
    - t_len = av_len((AV *)SvRV(ignored));
    -
    - for (i = 0; i <= t_len; i++)
    - t_GL = g_list_append(t_GL, SvPVutf8_nolen(*av_fetch((AV *)SvRV(ignored), i, 0)));
    -
    - for (l = purple_chat_conversation_set_ignored(chat, t_GL); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::ListEntry")));
    - }
    -
    -void
    -purple_chat_conversation_get_ignored(chat)
    - Purple::ChatConversation chat
    -PREINIT:
    - GList *l;
    -PPCODE:
    - for (l = purple_chat_conversation_get_ignored(chat); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::ListEntry")));
    - }
    -
    -const char *
    -purple_chat_conversation_get_topic(chat)
    - Purple::ChatConversation chat
    -
    -void
    -purple_chat_conversation_set_id(chat, id)
    - Purple::ChatConversation chat
    - int id
    -
    -int
    -purple_chat_conversation_get_id(chat)
    - Purple::ChatConversation chat
    -
    -void
    -purple_chat_conversation_add_users(chat, users, extra_msgs, flags, new_arrivals)
    - Purple::ChatConversation chat
    - SV * users
    - SV * extra_msgs
    - SV * flags
    - gboolean new_arrivals
    -PREINIT:
    - GList *t_GL_users, *t_GL_extra_msgs, *t_GL_flags;
    - int i, t_len;
    -PPCODE:
    - t_GL_users = NULL;
    - t_len = av_len((AV *)SvRV(users));
    -
    - for (i = 0; i <= t_len; i++)
    - t_GL_users = g_list_append(t_GL_users, SvPVutf8_nolen(*av_fetch((AV *)SvRV(users), i, 0)));
    -
    - t_GL_flags = NULL;
    - t_len = av_len((AV *)SvRV(flags));
    -
    - for (i = 0; i <= t_len; i++)
    - t_GL_flags = g_list_append(t_GL_flags, SvPVutf8_nolen(*av_fetch((AV *)SvRV(flags), i, 0)));
    -
    - t_GL_extra_msgs = NULL;
    - t_len = av_len((AV *)SvRV(extra_msgs));
    -
    - for (i = 0; i <= t_len; i++)
    - t_GL_extra_msgs = g_list_append(t_GL_extra_msgs, SvPVutf8_nolen(*av_fetch((AV *)SvRV(extra_msgs), i, 0)));
    -
    - purple_chat_conversation_add_users(chat, t_GL_users, t_GL_extra_msgs, t_GL_flags, new_arrivals);
    -
    - g_list_free(t_GL_users);
    - g_list_free(t_GL_extra_msgs);
    - g_list_free(t_GL_flags);
    -
    -gboolean
    -purple_chat_conversation_has_user(chat, user)
    - Purple::ChatConversation chat
    - const char * user
    -
    -void purple_chat_conversation_clear_users(chat)
    - Purple::ChatConversation chat
    -
    -void purple_chat_conversation_set_nick(chat, nick)
    - Purple::ChatConversation chat
    - const char * nick
    -
    -const char *
    -purple_chat_conversation_get_nick(chat)
    - Purple::ChatConversation chat
    -
    -void purple_chat_conversation_leave(chat)
    - Purple::ChatConversation chat
    -
    -gboolean purple_chat_conversation_has_left(chat)
    - Purple::ChatConversation chat
    -
    -Purple::ChatUser
    -purple_chat_conversation_find_user(chat, name)
    - Purple::ChatConversation chat
    - const char *name
    -
    -const char *
    -purple_chat_user_get_name(cb)
    - Purple::ChatUser cb
    --- a/libpurple/plugins/perl/common/Core.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,21 +0,0 @@
    -#include "module.h"
    -
    -MODULE = Purple::Core PACKAGE = Purple::Core PREFIX = purple_core_
    -PROTOTYPES: ENABLE
    -
    -gboolean
    -purple_core_quit_cb()
    -PPCODE:
    - /* The argument to purple_core_quit_cb is not used,
    - * so there's little point in requiring it on the
    - * Perl side. */
    - RETVAL = purple_core_quit_cb(NULL);
    - ST(0) = boolSV(RETVAL);
    - sv_2mortal(ST(0));
    -
    -const char *
    -purple_core_get_version()
    -
    -const char *
    -purple_core_get_ui()
    -
    --- a/libpurple/plugins/perl/common/Debug.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,72 +0,0 @@
    -#include "module.h"
    -
    -MODULE = Purple::Debug PACKAGE = Purple::Debug PREFIX = purple_debug_
    -PROTOTYPES: ENABLE
    -
    -BOOT:
    -{
    - HV *stash = gv_stashpv("Purple::Debug", 1);
    -
    - static const constiv *civ, const_iv[] = {
    -#define const_iv(name) {#name, (IV)PURPLE_DEBUG_##name}
    - const_iv(ALL),
    - const_iv(MISC),
    - const_iv(INFO),
    - const_iv(WARNING),
    - const_iv(ERROR),
    - const_iv(FATAL),
    - };
    -
    - for (civ = const_iv + sizeof(const_iv) / sizeof(const_iv[0]); civ-- > const_iv; )
    - newCONSTSUB(stash, (char *)civ->name, newSViv(civ->iv));
    -}
    -
    -void
    -purple_debug(level, category, string)
    - Purple::DebugLevel level
    - const char *category
    - const char *string
    -CODE:
    - purple_debug(level, category, "%s", string);
    -
    -void
    -purple_debug_misc(category, string)
    - const char *category
    - const char *string
    -CODE:
    - purple_debug_misc(category, "%s", string);
    -
    -void
    -purple_debug_info(category, string)
    - const char *category
    - const char *string
    -CODE:
    - purple_debug_info(category, "%s", string);
    -
    -void
    -purple_debug_warning(category, string)
    - const char *category
    - const char *string
    -CODE:
    - purple_debug_warning(category, "%s", string);
    -
    -void
    -purple_debug_error(category, string)
    - const char *category
    - const char *string
    -CODE:
    - purple_debug_error(category, "%s", string);
    -
    -void
    -purple_debug_fatal(category, string)
    - const char *category
    - const char *string
    -CODE:
    - purple_debug_fatal(category, "%s", string);
    -
    -void
    -purple_debug_set_enabled(enabled)
    - gboolean enabled
    -
    -gboolean
    -purple_debug_is_enabled()
    --- a/libpurple/plugins/perl/common/Idle.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,12 +0,0 @@
    -#include "module.h"
    -
    -MODULE = Purple::Idle PACKAGE = Purple::Idle PREFIX = purple_idle_
    -PROTOTYPES: ENABLE
    -
    -void
    -purple_idle_touch()
    -
    -void
    -purple_idle_set(time)
    - time_t time
    -
    --- a/libpurple/plugins/perl/common/Log.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,129 +0,0 @@
    -#include "module.h"
    -
    -MODULE = Purple::Log PACKAGE = Purple::Log PREFIX = purple_log_
    -PROTOTYPES: ENABLE
    -
    -BOOT:
    -{
    - HV *type_stash = gv_stashpv("Purple::Log::Type", 1);
    - HV *flags_stash = gv_stashpv("Purple::Log::ReadFlags", 1);
    -
    - static const constiv *civ, type_const_iv[] = {
    -#define const_iv(name) {#name, (IV)PURPLE_LOG_##name}
    - const_iv(IM),
    - const_iv(CHAT),
    - const_iv(SYSTEM),
    - };
    - static const constiv flags_const_iv[] = {
    -#undef const_iv
    -#define const_iv(name) {#name, (IV)PURPLE_LOG_READ_##name}
    - const_iv(NO_NEWLINE),
    - };
    -
    - for (civ = type_const_iv + sizeof(type_const_iv) / sizeof(type_const_iv[0]); civ-- > type_const_iv; )
    - newCONSTSUB(type_stash, (char *)civ->name, newSViv(civ->iv));
    -
    - for (civ = flags_const_iv + sizeof(flags_const_iv) / sizeof(flags_const_iv[0]); civ-- > flags_const_iv; )
    - newCONSTSUB(flags_stash, (char *)civ->name, newSViv(civ->iv));
    -}
    -
    -Purple::Handle
    -purple_log_get_handle()
    -
    -int
    -purple_log_common_sizer(log)
    - Purple::Log log
    -
    -void
    -purple_log_common_writer(log, ext)
    - Purple::Log log
    - const char *ext
    -
    -gint
    -purple_log_compare(y, z)
    - gconstpointer y
    - gconstpointer z
    -
    -void
    -purple_log_free(log)
    - Purple::Log log
    -
    -gchar_own *
    -purple_log_get_log_dir(type, name, account)
    - Purple::LogType type
    - const char *name
    - Purple::Account account
    -
    -void
    -purple_log_get_log_sets()
    -PREINIT:
    - GHashTable *l;
    -PPCODE:
    - l = purple_log_get_log_sets();
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l, "GHashTable")));
    -
    -void
    -purple_log_get_logs(type, name, account)
    - Purple::LogType type
    - const char *name
    - Purple::Account account
    -PREINIT:
    - GList *l, *ll;
    -PPCODE:
    - ll = purple_log_get_logs(type, name, account);
    - for (l = ll; l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Log")));
    - }
    - /* We can free the list here but the script needs to free the
    - * Purple::Log 'objects' itself. */
    - g_list_free(ll);
    -
    -int
    -purple_log_get_size(log)
    - Purple::Log log
    -
    -void
    -purple_log_get_system_logs(account)
    - Purple::Account account
    -PREINIT:
    - GList *l, *ll;
    -PPCODE:
    - ll = purple_log_get_system_logs(account);
    - for (l = ll; l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Log")));
    - }
    - /* We can free the list here but the script needs to free the
    - * Purple::Log 'objects' itself. */
    - g_list_free(ll);
    -
    -int
    -purple_log_get_total_size(type, name, account)
    - Purple::LogType type
    - const char *name
    - Purple::Account account
    -
    -void
    -purple_log_logger_free(logger)
    - Purple::Log::Logger logger
    -
    -void
    -purple_log_logger_get_options()
    -PREINIT:
    - GList *l, *ll;
    -PPCODE:
    - /* This might want to be massaged to a hash, since that's essentially
    - * what the key/value list is emulating. */
    - for (l = ll = purple_log_logger_get_options(); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(newSVpv(l->data, 0)));
    - }
    - g_list_free(ll);
    -
    -gchar_own *
    -purple_log_read(log, flags)
    - Purple::Log log
    - Purple::Log::ReadFlags flags
    -
    -gint
    -purple_log_set_compare(y, z)
    - gconstpointer y
    - gconstpointer z
    --- a/libpurple/plugins/perl/common/MANIFEST Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,36 +0,0 @@
    -Account.xs
    -AccountOpts.xs
    -BuddyIcon.xs
    -BuddyList.xs
    -Cipher.xs
    -Cmds.xs
    -Connection.xs
    -Conversation.xs
    -Debug.xs
    -Log.xs
    -Makefile.PL
    -Network.xs
    -Notify.xs
    -Plugin.xs
    -PluginPref.xs
    -Pounce.xs
    -Prefs.xs
    -Presence.xs
    -Proxy.xs
    -Prpl.xs
    -Purple.pm
    -Purple.xs
    -Request.xs
    -Roomlist.xs
    -SSLConn.xs
    -SavedStatuses.xs
    -Server.xs
    -Signal.xs
    -Sound.xs
    -Status.xs
    -Stringref.xs
    -Util.xs
    -Xfer.xs
    -XMLNode.xs
    -MANIFEST
    -typemap
    --- a/libpurple/plugins/perl/common/Makefile.PL.in Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,29 +0,0 @@
    -use 5.006;
    -use ExtUtils::MakeMaker;
    -# See lib/ExtUtils/MakeMaker.pm for details of how to influence the contents
    -# of the Makefile that is written.
    -WriteMakefile(
    - 'NAME' => 'Purple',
    - 'VERSION' => '@VERSION@',
    - 'PREREQ_PM' => {}, # e.g., Module::Name => 1.1
    - ($] >= 5.005 ? ## Add these new keywords supported since 5.005
    - (ABSTRACT_FROM => '@srcdir@/Purple.pm', # finds $ABSTRACT
    - AUTHOR => 'Purple <https://pidgin.im/>') : ()),
    - 'DEFINE' => '@DEBUG_CFLAGS@ -Wno-float-equal',
    - 'dynamic_lib' => { 'OTHERLDFLAGS' => '@LDFLAGS@' },
    - 'INC' => '-I. -I@srcdir@ -I@top_srcdir@ -I@top_builddir@ -I@top_srcdir@/libpurple @GLIB_CFLAGS@ -DHAVE_CONFIG_H',
    - 'OBJECT' => '$(O_FILES)', # link all the C files too
    -# 'OPTIMIZE' => '-g', # For debugging
    - 'INSTALLDIRS' => 'vendor',
    - 'INSTALL_BASE' => '$(prefix)',
    - 'INSTALLVENDORARCH' => '$(libdir)/purple-$(PURPLE_MAJOR_VERSION)/perl',
    - 'INSTALLVENDORMAN3DIR' => '$(mandir)/man3',
    - 'macro' => {
    - 'prefix' => '@prefix@',
    - 'exec_prefix' => '@exec_prefix@',
    - 'libdir' => '@libdir@',
    - 'mandir' => '@mandir@',
    - 'datarootdir' => '@datarootdir@',
    - 'PURPLE_MAJOR_VERSION' => '@PURPLE_MAJOR_VERSION@',
    - },
    -);
    --- a/libpurple/plugins/perl/common/Makefile.mingw Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,128 +0,0 @@
    -#
    -# Makefile.mingw
    -#
    -# Description: Makefile for Purple perl module.
    -#
    -
    -PIDGIN_TREE_TOP := ../../../..
    -include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
    -
    -#we cannot include win32dep.h, but we need struct sockaddr_in6 definition
    -CFLAGS += -include ws2tcpip.h
    -
    -GCCWARNINGS += -Wno-comment -Wno-unused -Wno-nested-externs
    -
    -DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES))
    -
    -TARGET = Purple
    -AUTOSPLIT = lib/auto/Purple/autosplit.ix
    -PERL_PLUGIN_TOP := ..
    -
    -##
    -## INCLUDE PATHS
    -##
    -INCLUDE_PATHS += -I. \
    - -I$(PIDGIN_TREE_TOP) \
    - -I$(PURPLE_TOP) \
    - -I$(PURPLE_TOP)/win32 \
    - -I$(GTK_TOP)/include \
    - -I$(GTK_TOP)/include/glib-2.0 \
    - -I$(GTK_TOP)/lib/glib-2.0/include \
    - -I$(PERL_LIB_TOP)/include
    -
    -LIB_PATHS += \
    - -L$(PERL_LIB_TOP)/lib \
    - -L$(PERL_PLUGIN_TOP) \
    - -L$(PURPLE_TOP) \
    - -L$(GTK_TOP)/lib
    -
    -##
    -## SOURCES, OBJECTS
    -##
    -XS_FILES = Account.xs \
    - AccountOpts.xs \
    - BuddyIcon.xs \
    - BuddyList.xs \
    - Cipher.xs \
    - Cmds.xs \
    - Certificate.xs \
    - Connection.xs \
    - Conversation.xs \
    - Core.xs \
    - Debug.xs \
    - Idle.xs \
    - Purple.xs \
    - Log.xs \
    - Network.xs \
    - Notify.xs \
    - Plugin.xs \
    - PluginPref.xs \
    - Pounce.xs \
    - Prefs.xs \
    - Presence.xs \
    - Proxy.xs \
    - Prpl.xs \
    - Request.xs \
    - Roomlist.xs \
    - SSLConn.xs \
    - SavedStatuses.xs \
    - Server.xs \
    - Signal.xs \
    - Sound.xs \
    - Status.xs \
    - Stringref.xs \
    - Util.xs \
    - Xfer.xs \
    - Whiteboard.xs \
    - XMLNode.xs
    -
    -#FALLBACKS = const-c.inc const-xs.inc
    -C_FILES = $(XS_FILES:%.xs=%.c)
    -OBJECTS = $(C_FILES:%.c=%.o)
    -
    -##
    -## LIBRARIES
    -##
    -LIBS = -lperl520 \
    - -lperl \
    - -lpurple \
    - -lglib-2.0 \
    - -lgobject-2.0
    -
    -include $(PIDGIN_COMMON_RULES)
    -
    -%.inc:
    - cp fallback/$@ ./
    -
    -##
    -## TARGETS
    -##
    -.PHONY: all install clean
    -
    -all: $(TARGET).dll $(AUTOSPLIT)
    -
    -install: all
    - rm -rf $(PURPLE_INSTALL_PERL_DIR)
    - mkdir -p $(PURPLE_INSTALL_PERL_DIR)
    - cp -R lib/* $(PURPLE_INSTALL_PERL_DIR)
    - cp $(TARGET).dll $(PURPLE_INSTALL_PERL_DIR)/auto/Purple
    -
    -$(C_FILES): $(PURPLE_CONFIG_H)
    -
    -$(AUTOSPLIT):
    - @echo -e " GEN\t$@"
    - @mkdir -p ./lib/auto
    - @cp Purple.pm ./lib
    - @$(PERL) -MAutoSplit -e 'autosplit("lib/Purple.pm")'
    -
    -$(TARGET).dll: $(PURPLE_DLL).a $(PURPLE_PERL_DLL).a $(FALLBACKS) $(OBJECTS)
    - $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
    -
    -##
    -## CLEAN
    -##
    -clean:
    - rm -rf $(TARGET).dll $(FALLBACKS) lib
    - rm -f *.o $(C_FILES)
    -
    -include $(PIDGIN_COMMON_TARGETS)
    --- a/libpurple/plugins/perl/common/Network.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,42 +0,0 @@
    -#include "module.h"
    -
    -MODULE = Purple::Network PACKAGE = Purple::Network PREFIX = purple_network_
    -PROTOTYPES: ENABLE
    -
    -const char *
    -purple_network_get_local_system_ip(fd)
    - int fd
    -
    -const char *
    -purple_network_get_my_ip(fd)
    - int fd
    -
    -unsigned short
    -purple_network_get_port_from_fd(fd)
    - int fd
    -
    -const char *
    -purple_network_get_public_ip()
    -
    -Purple::NetworkListenData
    -purple_network_listen(port, socket_family, socket_type, map_external, cb, cb_data)
    - unsigned short port
    - int socket_family
    - int socket_type
    - gboolean map_external
    - Purple::NetworkListenCallback cb
    - gpointer cb_data
    -
    -Purple::NetworkListenData
    -purple_network_listen_range(start, end, socket_family, socket_type, map_external, cb, cb_data)
    - unsigned short start
    - unsigned short end
    - int socket_family
    - int socket_type
    - gboolean map_external
    - Purple::NetworkListenCallback cb
    - gpointer cb_data
    -
    -void
    -purple_network_set_public_ip(ip)
    - const char *ip
    --- a/libpurple/plugins/perl/common/Notify.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,178 +0,0 @@
    -#include "module.h"
    -
    -MODULE = Purple::Notify PACKAGE = Purple::Notify PREFIX = purple_notify_
    -PROTOTYPES: ENABLE
    -
    -BOOT:
    -{
    - HV *type_stash = gv_stashpv("Purple::Notify::Type", 1);
    - HV *msg_type_stash = gv_stashpv("Purple::Notify::Msg", 1);
    - HV *user_info_stash = gv_stashpv("Purple::NotifyUserInfo::Type", 1);
    -
    - static const constiv *civ, type_const_iv[] = {
    -#define const_iv(name) {#name, (IV)PURPLE_NOTIFY_##name}
    - const_iv(MESSAGE),
    - const_iv(EMAIL),
    - const_iv(EMAILS),
    - const_iv(FORMATTED),
    - const_iv(SEARCHRESULTS),
    - const_iv(USERINFO),
    - const_iv(URI),
    - };
    - static const constiv msg_type_const_iv[] = {
    -#undef const_iv
    -#define const_iv(name) {#name, (IV)PURPLE_NOTIFY_MSG_##name}
    - const_iv(ERROR),
    - const_iv(WARNING),
    - const_iv(INFO),
    - };
    - static const constiv user_info_const_iv[] = {
    -#undef const_iv
    -#define const_iv(name) {#name, (IV)PURPLE_NOTIFY_USER_INFO_ENTRY_##name}
    - const_iv(PAIR),
    - const_iv(SECTION_BREAK),
    - const_iv(SECTION_HEADER),
    - };
    -
    - for (civ = type_const_iv + sizeof(type_const_iv) / sizeof(type_const_iv[0]); civ-- > type_const_iv; )
    - newCONSTSUB(type_stash, (char *)civ->name, newSViv(civ->iv));
    -
    - for (civ = msg_type_const_iv + sizeof(msg_type_const_iv) / sizeof(msg_type_const_iv[0]); civ-- > msg_type_const_iv; )
    - newCONSTSUB(msg_type_stash, (char *)civ->name, newSViv(civ->iv));
    -
    - for (civ = user_info_const_iv + sizeof(user_info_const_iv) / sizeof(user_info_const_iv[0]); civ-- > user_info_const_iv; )
    - newCONSTSUB(user_info_stash, (char *)civ->name, newSViv(civ->iv));
    -}
    -
    -void
    -purple_notify_close(type, ui_handle)
    - Purple::NotifyType type
    - void * ui_handle
    -
    -void
    -purple_notify_close_with_handle(handle)
    - void * handle
    -
    -void *
    -purple_notify_email(handle, subject, from, to, url, cb, user_data)
    - void * handle
    - const char *subject
    - const char *from
    - const char *to
    - const char *url
    - Purple::NotifyCloseCallback cb
    - gpointer user_data
    -
    -void *
    -purple_notify_emails(handle, count, detailed, subjects, froms, tos, urls, cb, user_data)
    - void * handle
    - size_t count
    - gboolean detailed
    - const char **subjects
    - const char **froms
    - const char **tos
    - const char **urls
    - Purple::NotifyCloseCallback cb
    - gpointer user_data
    -
    -void *
    -purple_notify_formatted(handle, title, primary, secondary, text, cb, user_data)
    - void * handle
    - const char *title
    - const char *primary
    - const char *secondary
    - const char *text
    - Purple::NotifyCloseCallback cb
    - gpointer user_data
    -
    -void *
    -purple_notify_userinfo(gc, who, user_info, cb, user_data)
    - Purple::Connection gc
    - const char *who
    - Purple::NotifyUserInfo user_info
    - Purple::NotifyCloseCallback cb
    - gpointer user_data
    -
    -void *
    -purple_notify_message(handle, type, title, primary, secondary, cb, user_data)
    - void * handle
    - Purple::NotifyMsgType type
    - const char *title
    - const char *primary
    - const char *secondary
    - Purple::NotifyCloseCallback cb
    - gpointer user_data
    -CODE:
    - RETVAL = purple_notify_message(handle, type, title, primary, secondary, NULL, cb, user_data);
    -OUTPUT:
    - RETVAL
    -
    -void *
    -purple_notify_searchresults(gc, title, primary, secondary, results, cb, user_data)
    - Purple::Connection gc
    - const char *title
    - const char *primary
    - const char *secondary
    - Purple::NotifySearchResults results
    - Purple::NotifyCloseCallback cb
    - gpointer user_data
    -
    -void *
    -purple_notify_uri(handle, uri)
    - void * handle
    - const char *uri
    -
    -MODULE = Purple::Notify PACKAGE = Purple::NotifyUserInfo PREFIX = purple_notify_user_info_
    -PROTOTYPES: ENABLE
    -
    -Purple::NotifyUserInfo
    -purple_notify_user_info_new(class)
    - C_ARGS: /* void */
    -
    -void
    -purple_notify_user_info_destroy(user_info)
    - Purple::NotifyUserInfo user_info
    -
    -void
    -purple_notify_user_info_get_entries(user_info)
    - Purple::NotifyUserInfo user_info
    -PREINIT:
    - GList *l;
    -PPCODE:
    - l = purple_notify_user_info_get_entries(user_info)->head;
    - for (; l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::NotifyUserInfoEntry")));
    - }
    -
    -gchar_own *
    -purple_notify_user_info_get_text_with_newline(user_info, newline)
    - Purple::NotifyUserInfo user_info
    - const char *newline
    -
    -void purple_notify_user_info_add_pair_html(user_info, label, value)
    - Purple::NotifyUserInfo user_info
    - const char *label
    - const char *value
    -
    -void purple_notify_user_info_prepend_pair_html(user_info, label, value)
    - Purple::NotifyUserInfo user_info
    - const char *label
    - const char *value
    -
    -void purple_notify_user_info_add_section_break(user_info)
    - Purple::NotifyUserInfo user_info
    -
    -void purple_notify_user_info_add_section_header(user_info, label)
    - Purple::NotifyUserInfo user_info
    - const char *label
    -
    -void purple_notify_user_info_remove_last_item(user_info)
    - Purple::NotifyUserInfo user_info
    -
    -const gchar *
    -purple_notify_user_info_entry_get_label(user_info_entry)
    - Purple::NotifyUserInfoEntry user_info_entry
    -
    -const gchar *
    -purple_notify_user_info_entry_get_value(user_info_entry)
    - Purple::NotifyUserInfoEntry user_info_entry
    --- a/libpurple/plugins/perl/common/Plugin.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,166 +0,0 @@
    -#include "module.h"
    -
    -MODULE = Purple::Plugin PACKAGE = Purple::Plugin PREFIX = purple_plugin_
    -PROTOTYPES: ENABLE
    -
    -BOOT:
    -{
    - HV *stash = gv_stashpv("Purple::Plugin::Type", 1);
    -
    - static const constiv *civ, const_iv[] = {
    -#define const_iv(name) {#name, (IV)PURPLE_PLUGIN_##name}
    - const_iv(UNKNOWN),
    - const_iv(STANDARD),
    - const_iv(LOADER),
    - const_iv(PROTOCOL),
    - };
    -
    - for (civ = const_iv + sizeof(const_iv) / sizeof(const_iv[0]); civ-- > const_iv; )
    - newCONSTSUB(stash, (char *)civ->name, newSViv(civ->iv));
    -}
    -
    -Purple::Plugin
    -purple_plugin_new(native, path)
    - gboolean native
    - const char *path
    -
    -Purple::Plugin
    -purple_plugin_probe(filename)
    - const char *filename
    -
    -gboolean
    -purple_plugin_register(plugin)
    - Purple::Plugin plugin
    -
    -gboolean
    -purple_plugin_load(plugin)
    - Purple::Plugin plugin
    -
    -gboolean
    -purple_plugin_unload(plugin)
    - Purple::Plugin plugin
    -
    -gboolean
    -purple_plugin_reload(plugin)
    - Purple::Plugin plugin
    -
    -void
    -purple_plugin_destroy(plugin)
    - Purple::Plugin plugin
    -
    -gboolean
    -purple_plugin_is_loaded(plugin)
    - Purple::Plugin plugin
    -
    -gboolean
    -purple_plugin_is_unloadable(plugin)
    - Purple::Plugin plugin
    -
    -const gchar *
    -purple_plugin_get_id(plugin)
    - Purple::Plugin plugin
    -
    -const gchar *
    -purple_plugin_get_name(plugin)
    - Purple::Plugin plugin
    -
    -const gchar *
    -purple_plugin_get_version(plugin)
    - Purple::Plugin plugin
    -
    -const gchar *
    -purple_plugin_get_summary(plugin)
    - Purple::Plugin plugin
    -
    -const gchar *
    -purple_plugin_get_description(plugin)
    - Purple::Plugin plugin
    -
    -const gchar *
    -purple_plugin_get_author(plugin)
    - Purple::Plugin plugin
    -
    -const gchar *
    -purple_plugin_get_homepage(plugin)
    - Purple::Plugin plugin
    -
    -MODULE = Purple::Plugin PACKAGE = Purple::Plugin::IPC PREFIX = purple_plugin_ipc_
    -
    -void
    -purple_plugin_ipc_unregister(plugin, command)
    - Purple::Plugin plugin
    - const char *command
    -
    -void
    -purple_plugin_ipc_unregister_all(plugin)
    - Purple::Plugin plugin
    -
    -MODULE = Purple::Plugin PACKAGE = Purple::Plugins PREFIX = purple_plugins_
    -PROTOTYPES: ENABLE
    -
    -void
    -purple_plugins_add_search_path(path)
    - const char *path
    -
    -void
    -purple_plugins_unload_all()
    -
    -void
    -purple_plugins_destroy_all()
    -
    -void
    -purple_plugins_load_saved(key)
    - const char *key
    -
    -void
    -purple_plugins_probe(ext)
    - const char *ext
    -
    -gboolean
    -purple_plugins_enabled()
    -
    -Purple::Plugin
    -purple_plugins_find_with_name(name)
    - const char *name
    -
    -Purple::Plugin
    -purple_plugins_find_with_filename(filename)
    - const char *filename
    -
    -Purple::Plugin
    -purple_plugins_find_with_basename(basename)
    - const char *basename
    -
    -Purple::Plugin
    -purple_plugins_find_with_id(id)
    - const char *id
    -
    -void
    -purple_plugins_get_loaded()
    -PREINIT:
    - GList *l;
    -PPCODE:
    - for (l = purple_plugins_get_loaded(); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Plugin")));
    - }
    -
    -void
    -purple_plugins_get_protocols()
    -PREINIT:
    - GList *l;
    -PPCODE:
    - for (l = purple_plugins_get_protocols(); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Plugin")));
    - }
    -
    -void
    -purple_plugins_get_all()
    -PREINIT:
    - GList *l;
    -PPCODE:
    - for (l = purple_plugins_get_all(); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Plugin")));
    - }
    -
    -Purple::Handle
    -purple_plugins_get_handle()
    --- a/libpurple/plugins/perl/common/PluginPref.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,188 +0,0 @@
    -#include "module.h"
    -
    -MODULE = Purple::PluginPref PACKAGE = Purple::PluginPref::Frame PREFIX = purple_plugin_pref_frame_
    -PROTOTYPES: ENABLE
    -
    -BOOT:
    -{
    - HV *string_format_stash = gv_stashpv("Purple::String::Format::Type", 1);
    - HV *plugin_pref_stash = gv_stashpv("Purple::PluginPref::Type", 1);
    -
    - static const constiv *civ, string_format_const_iv[] = {
    -#define const_iv(name) {#name, (IV)PURPLE_STRING_FORMAT_TYPE_##name}
    - const_iv(NONE),
    - const_iv(MULTILINE),
    - const_iv(HTML),
    - };
    - static const constiv plugin_pref_const_iv[] = {
    -#undef const_iv
    -#define const_iv(name) {#name, (IV)PURPLE_PLUGIN_PREF_##name}
    - const_iv(NONE),
    - const_iv(CHOICE),
    - const_iv(INFO),
    - const_iv(STRING_FORMAT),
    - };
    -
    - for (civ = string_format_const_iv + sizeof(string_format_const_iv) / sizeof(string_format_const_iv[0]); civ-- > string_format_const_iv; )
    - newCONSTSUB(string_format_stash, (char *)civ->name, newSViv(civ->iv));
    -
    - for (civ = plugin_pref_const_iv + sizeof(plugin_pref_const_iv) / sizeof(plugin_pref_const_iv[0]); civ-- > plugin_pref_const_iv; )
    - newCONSTSUB(plugin_pref_stash, (char *)civ->name, newSViv(civ->iv));
    -}
    -
    -void
    -purple_plugin_pref_frame_add(frame, pref)
    - Purple::PluginPref::Frame frame
    - Purple::PluginPref pref
    -
    -void
    -purple_plugin_pref_frame_destroy(frame)
    - Purple::PluginPref::Frame frame
    -
    -void
    -purple_plugin_pref_frame_get_prefs(frame)
    - Purple::PluginPref::Frame frame
    -PREINIT:
    - GList *l;
    -PPCODE:
    - for (l = purple_plugin_pref_frame_get_prefs(frame); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::PluginPref")));
    - }
    -
    -Purple::PluginPref::Frame
    -purple_plugin_pref_frame_new(class)
    - C_ARGS: /* void */
    -
    -MODULE = Purple::PluginPref PACKAGE = Purple::PluginPref PREFIX = purple_plugin_pref_
    -PROTOTYPES: ENABLE
    -
    -void
    -purple_plugin_pref_add_choice(pref, label, choice)
    - Purple::PluginPref pref
    - const char *label
    -# Do the appropriate conversion based on the perl type specified.
    -# Currently only Strings and Ints will work.
    - gpointer choice = (SvPOKp($arg) ? SvPVutf8_nolen($arg) : (SvIOKp($arg) ? GINT_TO_POINTER(SvIV($arg)) : NULL));
    -
    -void
    -purple_plugin_pref_destroy(pref)
    - Purple::PluginPref pref
    -
    -
    -void
    -purple_plugin_pref_get_bounds(pref, OUTLIST int min, OUTLIST int max)
    - Purple::PluginPref pref
    - # According to the perlxs manual page we shouldn't need to specify a
    - # prototype here because "[p]arameters preceded by OUTLIST keyword do
    - # not appear in the usage signature of the generated Perl function."
    - # however that appears to only work for the usage error message and
    - # not for the call to newXSproto. Since I can't find any documentation
    - # for newXSproto at the moment I have no idea if that matters so
    - # override the prototype here.
    - PROTOTYPE: $
    -
    -void
    -purple_plugin_pref_get_choices(pref)
    - Purple::PluginPref pref
    -PREINIT:
    - GList *l;
    -PPCODE:
    - for (l = purple_plugin_pref_get_choices(pref); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::ListItem")));
    - }
    -
    -const char *
    -purple_plugin_pref_get_label(pref)
    - Purple::PluginPref pref
    -
    -gboolean
    -purple_plugin_pref_get_masked(pref)
    - Purple::PluginPref pref
    -
    -Purple::String::Format::Type
    -purple_plugin_pref_get_format_type(pref)
    - Purple::PluginPref pref
    -
    -unsigned int
    -purple_plugin_pref_get_max_length(pref)
    - Purple::PluginPref pref
    -
    -const char *
    -purple_plugin_pref_get_name(pref)
    - Purple::PluginPref pref
    -
    -Purple::PluginPrefType
    -purple_plugin_pref_get_pref_type(pref)
    - Purple::PluginPref pref
    -
    -Purple::PluginPref
    -purple_plugin_pref_new(class)
    - C_ARGS: /* void */
    -
    -Purple::PluginPref
    -purple_plugin_pref_new_with_label(class, label)
    - const char *label
    - C_ARGS:
    - label
    -
    -Purple::PluginPref
    -purple_plugin_pref_new_with_name(class, name)
    - const char *name
    - C_ARGS:
    - name
    -
    -Purple::PluginPref
    -purple_plugin_pref_new_with_name_and_label(class, name, label)
    - const char *name
    - const char *label
    - C_ARGS:
    - name, label
    -
    -void
    -purple_plugin_pref_set_bounds(pref, min, max)
    - Purple::PluginPref pref
    - int min
    - int max
    -
    -void
    -purple_plugin_pref_set_label(pref, label)
    - Purple::PluginPref pref
    - const char *label
    -
    -void
    -purple_plugin_pref_set_masked(pref, mask)
    - Purple::PluginPref pref
    - gboolean mask
    -
    -void
    -purple_plugin_pref_set_format_type(pref, format)
    - Purple::PluginPref pref
    - Purple::String::Format::Type format
    -
    -void
    -purple_plugin_pref_set_max_length(pref, max_length)
    - Purple::PluginPref pref
    - unsigned int max_length
    -
    -void
    -purple_plugin_pref_set_name(pref, name)
    - Purple::PluginPref pref
    - const char *name
    -
    -void
    -purple_plugin_pref_set_pref_type(pref, type)
    - Purple::PluginPref pref
    - Purple::PluginPrefType type
    -PREINIT:
    - PurplePluginPrefType gpp_type;
    -CODE:
    - gpp_type = PURPLE_PLUGIN_PREF_NONE;
    -
    - if (type == 1) {
    - gpp_type = PURPLE_PLUGIN_PREF_CHOICE;
    - } else if (type == 2) {
    - gpp_type = PURPLE_PLUGIN_PREF_INFO;
    - } else if (type == 3) {
    - gpp_type = PURPLE_PLUGIN_PREF_STRING_FORMAT;
    - }
    - purple_plugin_pref_set_pref_type(pref, gpp_type);
    --- a/libpurple/plugins/perl/common/Pounce.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,126 +0,0 @@
    -#include "module.h"
    -
    -MODULE = Purple::Pounce PACKAGE = Purple::Pounce PREFIX = purple_pounce_
    -PROTOTYPES: ENABLE
    -
    -BOOT:
    -{
    - HV *event_stash = gv_stashpv("Purple::Pounce::Event", 1);
    - HV *option_stash = gv_stashpv("Purple::Pounce::Option", 1);
    -
    - static const constiv *civ, event_const_iv[] = {
    -#define const_iv(name) {#name, (IV)PURPLE_POUNCE_##name}
    - const_iv(NONE),
    - const_iv(SIGNON),
    - const_iv(SIGNOFF),
    - const_iv(AWAY),
    - const_iv(AWAY_RETURN),
    - const_iv(IDLE),
    - const_iv(IDLE_RETURN),
    - const_iv(TYPING),
    - const_iv(TYPED),
    - const_iv(TYPING_STOPPED),
    - const_iv(MESSAGE_RECEIVED),
    - };
    - static const constiv option_const_iv[] = {
    -#undef const_iv
    -#define const_iv(name) {#name, (IV)PURPLE_POUNCE_OPTION_##name}
    - const_iv(NONE),
    - const_iv(AWAY),
    - };
    -
    - for (civ = event_const_iv + sizeof(event_const_iv) / sizeof(event_const_iv[0]); civ-- > event_const_iv; )
    - newCONSTSUB(event_stash, (char *)civ->name, newSViv(civ->iv));
    -
    - for (civ = option_const_iv + sizeof(option_const_iv) / sizeof(option_const_iv[0]); civ-- > option_const_iv; )
    - newCONSTSUB(option_stash, (char *)civ->name, newSViv(civ->iv));
    -}
    -
    -void
    -purple_pounce_action_register(pounce, name)
    - Purple::Pounce pounce
    - const char *name
    -
    -void
    -purple_pounce_destroy(pounce)
    - Purple::Pounce pounce
    -
    -void
    -purple_pounce_destroy_all_by_account(account)
    - Purple::Account account
    -
    -void *
    -purple_pounce_get_data(pounce)
    - Purple::Pounce pounce
    -
    -Purple::PounceEvent
    -purple_pounce_get_events(pounce)
    - Purple::Pounce pounce
    -
    -const char *
    -purple_pounce_get_pouncee(pounce)
    - Purple::Pounce pounce
    -
    -Purple::Account
    -purple_pounce_get_pouncer(pounce)
    - Purple::Pounce pounce
    -
    -gboolean
    -purple_pounce_get_save(pounce)
    - Purple::Pounce pounce
    -
    -void
    -purple_pounce_set_data(pounce, data)
    - Purple::Pounce pounce
    - void * data
    -
    -void
    -purple_pounce_set_events(pounce, events)
    - Purple::Pounce pounce
    - Purple::PounceEvent events
    -
    -void
    -purple_pounce_set_pouncee(pounce, pouncee)
    - Purple::Pounce pounce
    - const char *pouncee
    -
    -void
    -purple_pounce_set_pouncer(pounce, pouncer)
    - Purple::Pounce pounce
    - Purple::Account pouncer
    -
    -void
    -purple_pounce_set_save(pounce, save)
    - Purple::Pounce pounce
    - gboolean save
    -
    -MODULE = Purple::Pounce PACKAGE = Purple::Pounces PREFIX = purple_pounces_
    -PROTOTYPES: ENABLE
    -
    -void
    -purple_pounces_get_all()
    -PREINIT:
    - GList *l;
    -PPCODE:
    - for (l = purple_pounces_get_all(); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Pounce")));
    - }
    -
    -void
    -purple_pounces_get_all_for_ui(ui)
    - const char *ui
    -PREINIT:
    - GList *l, *ll;
    -PPCODE:
    - ll = purple_pounces_get_all_for_ui(ui);
    - for (l = ll; l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Pounce")));
    - }
    - g_list_free(ll);
    -
    -Purple::Handle
    -purple_pounces_get_handle()
    -
    -void
    -purple_pounces_unregister_handler(ui)
    - const char *ui
    --- a/libpurple/plugins/perl/common/Prefs.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,244 +0,0 @@
    -#include "module.h"
    -#include "../perl-handlers.h"
    -
    -MODULE = Purple::Prefs PACKAGE = Purple::Prefs PREFIX = purple_prefs_
    -PROTOTYPES: ENABLE
    -
    -BOOT:
    -{
    - HV *stash = gv_stashpv("Purple::Pref::Type", 1);
    -
    - static const constiv *civ, const_iv[] = {
    -#define const_iv(name) {#name, (IV)PURPLE_PREF_##name}
    - const_iv(NONE),
    - const_iv(BOOLEAN),
    - const_iv(INT),
    - const_iv(STRING),
    - const_iv(STRING_LIST),
    - const_iv(PATH),
    - const_iv(PATH_LIST),
    - };
    -
    - for (civ = const_iv + sizeof(const_iv) / sizeof(const_iv[0]); civ-- > const_iv; )
    - newCONSTSUB(stash, (char *)civ->name, newSViv(civ->iv));
    -}
    -
    -void
    -purple_prefs_add_bool(name, value)
    - const char *name
    - gboolean value
    -
    -void
    -purple_prefs_add_int(name, value)
    - const char *name
    - int value
    -
    -void
    -purple_prefs_add_none(name)
    - const char *name
    -
    -void
    -purple_prefs_add_string(name, value)
    - const char *name
    - const char *value
    -
    -void
    -purple_prefs_add_string_list(name, value)
    - const char *name
    - SV *value
    -PREINIT:
    - GList *t_GL;
    - int i, t_len;
    -PPCODE:
    - t_GL = NULL;
    - t_len = av_len((AV *)SvRV(value));
    -
    - for (i = 0; i <= t_len; i++)
    - t_GL = g_list_append(t_GL, SvPVutf8_nolen(*av_fetch((AV *)SvRV(value), i, 0)));
    -
    - purple_prefs_add_string_list(name, t_GL);
    - g_list_free(t_GL);
    -
    -void
    -purple_prefs_add_path(name, value)
    - const char *name
    - const char *value
    -
    -void
    -purple_prefs_add_path_list(name, value)
    - const char *name
    - SV *value
    -PREINIT:
    - GList *t_GL;
    - int i, t_len;
    -PPCODE:
    - t_GL = NULL;
    - t_len = av_len((AV *)SvRV(value));
    -
    - for (i = 0; i <= t_len; i++)
    - t_GL = g_list_append(t_GL, SvPVutf8_nolen(*av_fetch((AV *)SvRV(value), i, 0)));
    -
    - purple_prefs_add_path_list(name, t_GL);
    - g_list_free(t_GL);
    -
    -void
    -purple_prefs_destroy()
    -
    -guint
    -purple_prefs_connect_callback(plugin, name, callback, data = 0);
    - Purple::Plugin plugin
    - const char *name
    - SV *callback
    - SV *data
    -CODE:
    - RETVAL = purple_perl_prefs_connect_callback(plugin, name, callback, data);
    -OUTPUT:
    - RETVAL
    -
    -void
    -purple_prefs_disconnect_by_handle(plugin)
    - Purple::Plugin plugin
    -CODE:
    - purple_perl_pref_cb_clear_for_plugin(plugin);
    -
    -void
    -purple_prefs_disconnect_callback(callback_id)
    - guint callback_id
    -CODE:
    - purple_perl_prefs_disconnect_callback(callback_id);
    -
    -gboolean
    -purple_prefs_exists(name)
    - const char *name
    -
    -const char *
    -purple_prefs_get_path(name)
    - const char *name
    -
    -void
    -purple_prefs_get_path_list(name)
    - const char *name
    -PREINIT:
    - GList *l;
    -PPCODE:
    - for (l = purple_prefs_get_path_list(name); l != NULL; l = g_list_delete_link(l, l)) {
    - XPUSHs(sv_2mortal(newSVpv(l->data, 0)));
    - g_free(l->data);
    - }
    -
    -gboolean
    -purple_prefs_get_bool(name)
    - const char *name
    -
    -Purple::Handle
    -purple_prefs_get_handle()
    -
    -int
    -purple_prefs_get_int(name)
    - const char *name
    -
    -const char *
    -purple_prefs_get_string(name)
    - const char *name
    -
    -void
    -purple_prefs_get_string_list(name)
    - const char *name
    -PREINIT:
    - GList *l;
    -PPCODE:
    - for (l = purple_prefs_get_string_list(name); l != NULL; l = g_list_delete_link(l, l)) {
    - XPUSHs(sv_2mortal(newSVpv(l->data, 0)));
    - g_free(l->data);
    - }
    -
    -Purple::PrefType
    -purple_prefs_get_pref_type(name)
    - const char *name
    -
    -gboolean
    -purple_prefs_load()
    -
    -void
    -purple_prefs_remove(name)
    - const char *name
    -
    -void
    -purple_prefs_rename(oldname, newname)
    - const char *oldname
    - const char *newname
    -
    -void
    -purple_prefs_rename_boolean_toggle(oldname, newname)
    - const char *oldname
    - const char *newname
    -
    -void
    -purple_prefs_set_bool(name, value)
    - const char *name
    - gboolean value
    -
    -void
    -purple_prefs_set_int(name, value)
    - const char *name
    - int value
    -
    -void
    -purple_prefs_set_string(name, value)
    - const char *name
    - const char *value
    -
    -void
    -purple_prefs_set_string_list(name, value)
    - const char *name
    - SV *value
    -PREINIT:
    - GList *t_GL;
    - int i, t_len;
    -PPCODE:
    - t_GL = NULL;
    - t_len = av_len((AV *)SvRV(value));
    -
    - for (i = 0; i <= t_len; i++)
    - t_GL = g_list_append(t_GL, SvPVutf8_nolen(*av_fetch((AV *)SvRV(value), i, 0)));
    -
    - purple_prefs_set_string_list(name, t_GL);
    - g_list_free(t_GL);
    -
    -void
    -purple_prefs_set_path(name, value)
    - const char *name
    - const char *value
    -
    -void
    -purple_prefs_set_path_list(name, value)
    - const char *name
    - SV *value
    -PREINIT:
    - GList *t_GL;
    - int i, t_len;
    -PPCODE:
    - t_GL = NULL;
    - t_len = av_len((AV *)SvRV(value));
    -
    - for (i = 0; i <= t_len; i++)
    - t_GL = g_list_append(t_GL, SvPVutf8_nolen(*av_fetch((AV *)SvRV(value), i, 0)));
    -
    - purple_prefs_set_path_list(name, t_GL);
    - g_list_free(t_GL);
    -
    -
    -void
    -purple_prefs_trigger_callback(name)
    - const char *name
    -
    -void
    -purple_prefs_get_children_names(name)
    - const char *name
    -PREINIT:
    - GList *l;
    -PPCODE:
    - for (l = purple_prefs_get_children_names(name); l != NULL; l = g_list_delete_link(l, l)) {
    - XPUSHs(sv_2mortal(newSVpv(l->data, 0)));
    - g_free(l->data);
    - }
    --- a/libpurple/plugins/perl/common/Presence.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,102 +0,0 @@
    -#include "module.h"
    -
    -MODULE = Purple::Presence PACKAGE = Purple::Presence PREFIX = purple_presence_
    -PROTOTYPES: ENABLE
    -
    -Purple::Status
    -purple_presence_get_active_status(presence)
    - Purple::Presence presence
    -
    -time_t
    -purple_presence_get_idle_time(presence)
    - Purple::Presence presence
    -
    -time_t
    -purple_presence_get_login_time(presence)
    - Purple::Presence presence
    -
    -Purple::Status
    -purple_presence_get_status(presence, status_id)
    - Purple::Presence presence
    - const char *status_id
    -
    -void
    -purple_presence_get_statuses(presence)
    - Purple::Presence presence
    -PREINIT:
    - GList *l;
    -PPCODE:
    - for (l = purple_presence_get_statuses(presence); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Status")));
    - }
    -
    -gboolean
    -purple_presence_is_available(presence)
    - Purple::Presence presence
    -
    -gboolean
    -purple_presence_is_idle(presence)
    - Purple::Presence presence
    -
    -gboolean
    -purple_presence_is_online(presence)
    - Purple::Presence presence
    -
    -gboolean
    -purple_presence_is_status_active(presence, status_id)
    - Purple::Presence presence
    - const char *status_id
    -
    -gboolean
    -purple_presence_is_status_primitive_active(presence, primitive)
    - Purple::Presence presence
    - Purple::StatusPrimitive primitive
    -
    -void
    -purple_presence_set_idle(presence, idle, idle_time)
    - Purple::Presence presence
    - gboolean idle
    - time_t idle_time
    -
    -void
    -purple_presence_set_login_time(presence, login_time)
    - Purple::Presence presence
    - time_t login_time
    -
    -void
    -purple_presence_set_status_active(presence, status_id, active)
    - Purple::Presence presence
    - const char *status_id
    - gboolean active
    -
    -void
    -purple_presence_switch_status(presence, status_id)
    - Purple::Presence presence
    - const char *status_id
    -
    -MODULE = Purple::Presence PACKAGE = Purple::AccountPresence PREFIX = purple_account_presence_
    -PROTOTYPES: ENABLE
    -
    -Purple::Account
    -purple_account_presence_get_account(presence)
    - Purple::AccountPresence presence
    -
    -Purple::AccountPresence
    -purple_account_presence_new(account)
    - Purple::Account account
    -
    -MODULE = Purple::Presence PACKAGE = Purple::BuddyPresence PREFIX = purple_buddy_presence_
    -PROTOTYPES: ENABLE
    -
    -gint
    -purple_buddy_presence_compare(presence1, presence2)
    - Purple::BuddyPresence presence1
    - Purple::BuddyPresence presence2
    -
    -Purple::BuddyList::Buddy
    -purple_buddy_presence_get_buddy(presence)
    - Purple::BuddyPresence presence
    -
    -Purple::BuddyPresence
    -purple_buddy_presence_new(buddy)
    - Purple::BuddyList::Buddy buddy
    --- a/libpurple/plugins/perl/common/Proxy.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,86 +0,0 @@
    -#include "module.h"
    -
    -MODULE = Purple::Proxy PACKAGE = Purple::Proxy PREFIX = purple_proxy_
    -PROTOTYPES: ENABLE
    -
    -BOOT:
    -{
    - HV *stash = gv_stashpv("Purple::ProxyType", 1);
    -
    - static const constiv *civ, const_iv[] = {
    -#define const_iv(name) {#name, (IV)PURPLE_PROXY_##name}
    - const_iv(USE_GLOBAL),
    - const_iv(NONE),
    - const_iv(HTTP),
    - const_iv(SOCKS4),
    - const_iv(SOCKS5),
    - const_iv(USE_ENVVAR),
    - };
    -
    - for (civ = const_iv + sizeof(const_iv) / sizeof(const_iv[0]); civ-- > const_iv; )
    - newCONSTSUB(stash, (char *)civ->name, newSViv(civ->iv));
    -}
    -
    -Purple::Handle
    -purple_proxy_get_handle()
    -
    -MODULE = Purple::Proxy PACKAGE = Purple::ProxyInfo PREFIX = purple_proxy_info_
    -PROTOTYPES: ENABLE
    -
    -void
    -purple_proxy_info_destroy(info)
    - Purple::ProxyInfo info
    -
    -const char *
    -purple_proxy_info_get_host(info)
    - Purple::ProxyInfo info
    -
    -const char *
    -purple_proxy_info_get_password(info)
    - Purple::ProxyInfo info
    -
    -int
    -purple_proxy_info_get_port(info)
    - Purple::ProxyInfo info
    -
    -Purple::ProxyType
    -purple_proxy_info_get_proxy_type(info)
    - Purple::ProxyInfo info
    -
    -const char *
    -purple_proxy_info_get_username(info)
    - Purple::ProxyInfo info
    -
    -Purple::ProxyInfo
    -purple_proxy_info_new()
    -
    -void
    -purple_proxy_info_set_host(info, host)
    - Purple::ProxyInfo info
    - const char *host
    -
    -void
    -purple_proxy_info_set_password(info, password)
    - Purple::ProxyInfo info
    - const char *password
    -
    -void
    -purple_proxy_info_set_port(info, port)
    - Purple::ProxyInfo info
    - int port
    -
    -void
    -purple_proxy_info_set_proxy_type(info, type)
    - Purple::ProxyInfo info
    - Purple::ProxyType type
    -
    -void
    -purple_proxy_info_set_username(info, username)
    - Purple::ProxyInfo info
    - const char *username
    -
    -MODULE = Purple::Proxy PACKAGE = Purple::Proxy PREFIX = purple_
    -PROTOTYPES: ENABLE
    -
    -Purple::ProxyInfo
    -purple_global_proxy_get_info()
    --- a/libpurple/plugins/perl/common/Prpl.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,76 +0,0 @@
    -#include "module.h"
    -
    -MODULE = Purple::Prpl PACKAGE = Purple::Find PREFIX = purple_protocols_
    -PROTOTYPES: ENABLE
    -
    -Purple::Plugin
    -purple_protocols_find(id)
    - const char *id
    -
    -MODULE = Purple::Prpl PACKAGE = Purple::Prpl PREFIX = purple_protocol_
    -PROTOTYPES: ENABLE
    -
    -void
    -purple_protocol_change_account_status(account, old_status, new_status)
    - Purple::Account account
    - Purple::Status old_status
    - Purple::Status new_status
    -
    -void
    -purple_protocol_get_statuses(account, presence)
    - Purple::Account account
    - Purple::Presence presence
    -PREINIT:
    - GList *l, *ll;
    -PPCODE:
    - ll = purple_protocol_get_statuses(account,presence);
    - for (l = ll; l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Status")));
    - }
    - /* We can free the list here but the script needs to free the
    - * Purple::Status 'objects' itself. */
    - g_list_free(ll);
    -
    -void
    -purple_protocol_got_account_idle(account, idle, idle_time)
    - Purple::Account account
    - gboolean idle
    - time_t idle_time
    -
    -void
    -purple_protocol_got_account_login_time(account, login_time)
    - Purple::Account account
    - time_t login_time
    -
    -void
    -purple_protocol_got_user_idle(account, name, idle, idle_time)
    - Purple::Account account
    - const char *name
    - gboolean idle
    - time_t idle_time
    -
    -void
    -purple_protocol_got_user_login_time(account, name, login_time)
    - Purple::Account account
    - const char *name
    - time_t login_time
    -
    -int
    -purple_protocol_send_raw(gc, str)
    - Purple::Connection gc
    - const char *str
    -PREINIT:
    - PurpleProtocol *protocol;
    -CODE:
    - if (!gc)
    - RETVAL = 0;
    - else {
    - protocol = purple_connection_get_protocol(gc);
    - if (protocol)
    - RETVAL = purple_protocol_iface_send_raw(protocol, gc, str, strlen(str));
    - else
    - RETVAL = 0;
    - }
    -OUTPUT:
    - RETVAL
    -
    --- a/libpurple/plugins/perl/common/Purple.pm Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,129 +0,0 @@
    -package Purple;
    -
    -use 5.008;
    -use strict;
    -use warnings;
    -use Carp;
    -
    -require Exporter;
    -use AutoLoader;
    -
    -our @ISA = qw(Exporter);
    -
    -# Items to export into callers namespace by default. Note: do not export
    -# names by default without a very good reason. Use EXPORT_OK instead.
    -# Do not simply export all your public functions/methods/constants.
    -
    -# This allows declaration use Purple ':all';
    -# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
    -# will save memory.
    -our %EXPORT_TAGS = ( 'all' => [ qw(
    -
    -) ] );
    -
    -our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
    -
    -our @EXPORT = qw(
    -
    -);
    -
    -sub AUTOLOAD {
    - # This AUTOLOAD is used to 'autoload' constants from the constant()
    - # XS function.
    -
    - my $constname;
    - our $AUTOLOAD;
    - ($constname = $AUTOLOAD) =~ s/.*:://;
    - croak "&Purple::constant not defined" if $constname eq 'constant';
    - my ($error, $val) = constant($constname);
    - if ($error) { croak $error; }
    - {
    - no strict 'refs';
    -
    - *$AUTOLOAD = sub { $val };
    - }
    -
    - goto &$AUTOLOAD;
    -}
    -
    -require XSLoader;
    -XSLoader::load('Purple', $VERSION);
    -
    -# Preloaded methods go here.
    -
    -1;
    -__END__
    -
    -=head1 NAME
    -
    -Purple - Perl extension to the libpurple instant messenger library.
    -
    -=head1 SYNOPSIS
    -
    - use Purple;
    -
    -=head1 ABSTRACT
    -
    - This module provides the interface for using perl scripts as plugins
    - in libpurple.
    -
    -=head1 DESCRIPTION
    -
    -This module provides the interface for using perl scripts as plugins
    -in Purple. With this, developers can write perl scripts that can be
    -loaded in Purple as plugins. The scripts can interact with IMs, chats,
    -accounts, the buddy list, libpurple signals, and more.
    -
    -The API for the perl interface is very similar to that of the Purple C
    -API, which can be viewed at https://developer.pidgin.im/doxygen/ or in
    -the header files in the Purple source tree.
    -
    -=head1 FUNCTIONS
    -
    -=over
    -
    -=item @accounts = Purple::accounts
    -
    -Returns a list of all accounts, online or offline.
    -
    -=item @chats = Purple::chats
    -
    -Returns a list of all chats currently open.
    -
    -=item @connections = Purple::connections
    -
    -Returns a list of all active connections.
    -
    -=item @conversations = Purple::conversations
    -
    -Returns a list of all conversations, both IM and chat, currently open.
    -
    -=item @conv_windows = Purple::conv_windows
    -
    -Returns a list of all conversation windows currently open.
    -
    -=item @ims = Purple::ims
    -
    -Returns a list of all instant messages currently open.
    -
    -=back
    -
    -=head1 SEE ALSO
    -
    -Purple C API documentation - https://developer.pidgin.im/doxygen/
    -
    -Purple website - https://pidgin.im/
    -
    -=head1 AUTHOR
    -
    -Christian Hammond, E<lt>chipx86@gnupdate.orgE<gt>
    -
    -=head1 COPYRIGHT AND LICENSE
    -
    -Copyright 2003 by Christian Hammond
    -
    -This library is free software; you can redistribute it and/or modify
    -it under the terms of the General Public License (GPL). For
    -more information, see http://www.fsf.org/licenses/gpl.txt
    -
    -=cut
    --- a/libpurple/plugins/perl/common/Purple.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,108 +0,0 @@
    -#include "module.h"
    -#include "../perl-handlers.h"
    -
    -/* Prototypes for the BOOT section below. */
    -PURPLE_PERL_BOOT_PROTO(Account);
    -PURPLE_PERL_BOOT_PROTO(Account__Option);
    -PURPLE_PERL_BOOT_PROTO(Buddy__Icon);
    -PURPLE_PERL_BOOT_PROTO(BuddyList);
    -PURPLE_PERL_BOOT_PROTO(Certificate);
    -PURPLE_PERL_BOOT_PROTO(Cmd);
    -PURPLE_PERL_BOOT_PROTO(Connection);
    -PURPLE_PERL_BOOT_PROTO(Conversation);
    -PURPLE_PERL_BOOT_PROTO(Core);
    -PURPLE_PERL_BOOT_PROTO(Debug);
    -PURPLE_PERL_BOOT_PROTO(Hash);
    -PURPLE_PERL_BOOT_PROTO(Xfer);
    -PURPLE_PERL_BOOT_PROTO(Idle);
    -PURPLE_PERL_BOOT_PROTO(Log);
    -PURPLE_PERL_BOOT_PROTO(Network);
    -PURPLE_PERL_BOOT_PROTO(Notify);
    -PURPLE_PERL_BOOT_PROTO(Plugin);
    -PURPLE_PERL_BOOT_PROTO(PluginPref);
    -PURPLE_PERL_BOOT_PROTO(Pounce);
    -PURPLE_PERL_BOOT_PROTO(Prefs);
    -PURPLE_PERL_BOOT_PROTO(Proxy);
    -PURPLE_PERL_BOOT_PROTO(Prpl);
    -PURPLE_PERL_BOOT_PROTO(Request);
    -PURPLE_PERL_BOOT_PROTO(Roomlist);
    -PURPLE_PERL_BOOT_PROTO(SSL);
    -PURPLE_PERL_BOOT_PROTO(SavedStatus);
    -PURPLE_PERL_BOOT_PROTO(Serv);
    -PURPLE_PERL_BOOT_PROTO(Signal);
    -PURPLE_PERL_BOOT_PROTO(Sound);
    -PURPLE_PERL_BOOT_PROTO(Status);
    -PURPLE_PERL_BOOT_PROTO(Stringref);
    -PURPLE_PERL_BOOT_PROTO(Util);
    -PURPLE_PERL_BOOT_PROTO(Whiteboard);
    -PURPLE_PERL_BOOT_PROTO(XMLNode);
    -
    -MODULE = Purple PACKAGE = Purple PREFIX = purple_
    -PROTOTYPES: ENABLE
    -
    -BOOT:
    - PURPLE_PERL_BOOT(Account);
    - PURPLE_PERL_BOOT(Account__Option);
    - PURPLE_PERL_BOOT(Buddy__Icon);
    - PURPLE_PERL_BOOT(BuddyList);
    - PURPLE_PERL_BOOT(Certificate);
    - PURPLE_PERL_BOOT(Cmd);
    - PURPLE_PERL_BOOT(Connection);
    - PURPLE_PERL_BOOT(Conversation);
    - PURPLE_PERL_BOOT(Core);
    - PURPLE_PERL_BOOT(Debug);
    - PURPLE_PERL_BOOT(Hash);
    - PURPLE_PERL_BOOT(Xfer);
    - PURPLE_PERL_BOOT(Idle);
    - PURPLE_PERL_BOOT(Log);
    - PURPLE_PERL_BOOT(Network);
    - PURPLE_PERL_BOOT(Notify);
    - PURPLE_PERL_BOOT(Plugin);
    - PURPLE_PERL_BOOT(PluginPref);
    - PURPLE_PERL_BOOT(Pounce);
    - PURPLE_PERL_BOOT(Prefs);
    - PURPLE_PERL_BOOT(Proxy);
    - PURPLE_PERL_BOOT(Prpl);
    - PURPLE_PERL_BOOT(Request);
    - PURPLE_PERL_BOOT(Roomlist);
    - PURPLE_PERL_BOOT(SSL);
    - PURPLE_PERL_BOOT(SavedStatus);
    - PURPLE_PERL_BOOT(Serv);
    - PURPLE_PERL_BOOT(Signal);
    - PURPLE_PERL_BOOT(Sound);
    - PURPLE_PERL_BOOT(Status);
    - PURPLE_PERL_BOOT(Stringref);
    - PURPLE_PERL_BOOT(Util);
    - PURPLE_PERL_BOOT(Whiteboard);
    - PURPLE_PERL_BOOT(XMLNode);
    -
    -guint
    -timeout_add(plugin, seconds, callback, data = 0)
    - Purple::Plugin plugin
    - int seconds
    - SV *callback
    - SV *data
    -CODE:
    - RETVAL = purple_perl_timeout_add(plugin, seconds, callback, data);
    -OUTPUT:
    - RETVAL
    -
    -gboolean
    -timeout_remove(handle)
    - guint handle
    -CODE:
    - RETVAL = purple_perl_timeout_remove(handle);
    -OUTPUT:
    - RETVAL
    -
    -void
    -deinit()
    -CODE:
    - purple_perl_timeout_clear();
    -
    -
    -MODULE = Purple PACKAGE = Purple PREFIX = purple_
    -PROTOTYPES: ENABLE
    -
    -Purple::Core
    -purple_get_core()
    --- a/libpurple/plugins/perl/common/Request.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,648 +0,0 @@
    -#include "module.h"
    -
    -/* This breaks on faceprint's amd64 box
    -void *
    -purple_request_action_varg(handle, title, primary, secondary, default_action, user_data, action_count, actions)
    - void * handle
    - const char *title
    - const char *primary
    - const char *secondary
    - unsigned int default_action
    - void *user_data
    - size_t action_count
    - va_list actions
    - */
    -
    -
    -typedef struct {
    - SV *ok_fun;
    - SV *cancel_fun;
    -} PurplePerlRequestData;
    -
    -static void
    -purple_perl_request_data_free(PurplePerlRequestData *ppr)
    -{
    - if (ppr->ok_fun)
    - SvREFCNT_dec(ppr->ok_fun);
    - if (ppr->cancel_fun)
    - SvREFCNT_dec(ppr->cancel_fun);
    - g_free(ppr);
    -}
    -
    -/********************************************************/
    -/* */
    -/* Callback function that calls a perl subroutine */
    -/* */
    -/* The void * field data is being used as a way to hide */
    -/* the perl sub's name in a PurplePerlRequestData */
    -/* */
    -/********************************************************/
    -static void
    -purple_perl_request_ok_cb(void * data, PurpleRequestFields *fields)
    -{
    - PurplePerlRequestData *gpr = (PurplePerlRequestData *)data;
    -
    - dSP;
    - ENTER;
    - SAVETMPS;
    - PUSHMARK(sp);
    -
    - XPUSHs(sv_2mortal(purple_perl_bless_object(fields, "Purple::Request::Fields")));
    - PUTBACK;
    - call_sv(gpr->ok_fun, G_EVAL | G_SCALAR);
    - SPAGAIN;
    -
    - PUTBACK;
    - FREETMPS;
    - LEAVE;
    -
    - purple_perl_request_data_free(gpr);
    -}
    -
    -static void
    -purple_perl_request_cancel_cb(void * data, PurpleRequestFields *fields)
    -{
    - PurplePerlRequestData *gpr = (PurplePerlRequestData *)data;
    -
    - dSP;
    - ENTER;
    - SAVETMPS;
    - PUSHMARK(sp);
    -
    - XPUSHs(sv_2mortal(purple_perl_bless_object(fields, "Purple::Request::Fields")));
    - PUTBACK;
    - call_sv(gpr->cancel_fun, G_EVAL | G_SCALAR);
    - SPAGAIN;
    -
    - PUTBACK;
    - FREETMPS;
    - LEAVE;
    -
    - purple_perl_request_data_free(gpr);
    -}
    -
    -MODULE = Purple::Request PACKAGE = Purple::Request PREFIX = purple_request_
    -PROTOTYPES: ENABLE
    -
    -BOOT:
    -{
    - HV *request_stash = gv_stashpv("Purple::RequestType", 1);
    - HV *request_field_stash = gv_stashpv("Purple::RequestFieldType", 1);
    -
    - static const constiv *civ, request_const_iv[] = {
    -#define const_iv(name) {#name, (IV)PURPLE_REQUEST_##name}
    - const_iv(INPUT),
    - const_iv(CHOICE),
    - const_iv(ACTION),
    - const_iv(FIELDS),
    - const_iv(FILE),
    - const_iv(FOLDER),
    - };
    - static const constiv request_field_const_iv[] = {
    -#undef const_iv
    -#define const_iv(name) {#name, (IV)PURPLE_REQUEST_FIELD_##name}
    - const_iv(NONE),
    - const_iv(STRING),
    - const_iv(INTEGER),
    - const_iv(BOOLEAN),
    - const_iv(CHOICE),
    - const_iv(LIST),
    - const_iv(LABEL),
    - const_iv(IMAGE),
    - const_iv(ACCOUNT),
    - };
    -
    - for (civ = request_const_iv + sizeof(request_const_iv) / sizeof(request_const_iv[0]); civ-- > request_const_iv; )
    - newCONSTSUB(request_stash, (char *)civ->name, newSViv(civ->iv));
    -
    - for (civ = request_field_const_iv + sizeof(request_field_const_iv) / sizeof(request_field_const_iv[0]); civ-- > request_field_const_iv; )
    - newCONSTSUB(request_field_stash, (char *)civ->name, newSViv(civ->iv));
    -}
    -
    -void *
    -purple_request_input(handle, title, primary, secondary, default_value, multiline, masked, hint, ok_text, ok_cb, cancel_text, cancel_cb)
    - Purple::Plugin handle
    - const char * title
    - const char * primary
    - const char * secondary
    - const char * default_value
    - gboolean multiline
    - gboolean masked
    - gchar * hint
    - const char * ok_text
    - SV * ok_cb
    - const char * cancel_text
    - SV * cancel_cb
    -CODE:
    - PurplePerlRequestData *gpr;
    - char *basename;
    -
    - basename = g_path_get_basename(handle->path);
    - purple_perl_normalize_script_name(basename);
    - gpr = g_new(PurplePerlRequestData, 1);
    - gpr->ok_fun = purple_perl_sv_from_fun(handle, ok_cb);
    - gpr->cancel_fun = purple_perl_sv_from_fun(handle, cancel_cb);
    - g_free(basename);
    -
    - RETVAL = purple_request_input(handle, title, primary, secondary, default_value, multiline, masked, hint, ok_text, G_CALLBACK(purple_perl_request_ok_cb), cancel_text, G_CALLBACK(purple_perl_request_cancel_cb), NULL, gpr);
    -OUTPUT:
    - RETVAL
    -
    -void *
    -purple_request_file(handle, title, filename, savedialog, ok_cb, cancel_cb)
    - Purple::Plugin handle
    - const char * title
    - const char * filename
    - gboolean savedialog
    - SV * ok_cb
    - SV * cancel_cb
    -CODE:
    - PurplePerlRequestData *gpr;
    - char *basename;
    -
    - basename = g_path_get_basename(handle->path);
    - purple_perl_normalize_script_name(basename);
    - gpr = g_new(PurplePerlRequestData, 1);
    - gpr->ok_fun = purple_perl_sv_from_fun(handle, ok_cb);
    - gpr->cancel_fun = purple_perl_sv_from_fun(handle, cancel_cb);
    - g_free(basename);
    -
    - RETVAL = purple_request_file(handle, title, filename, savedialog, G_CALLBACK(purple_perl_request_ok_cb), G_CALLBACK(purple_perl_request_cancel_cb), NULL, gpr);
    -OUTPUT:
    - RETVAL
    -
    -void *
    -purple_request_fields(handle, title, primary, secondary, fields, ok_text, ok_cb, cancel_text, cancel_cb)
    - Purple::Plugin handle
    - const char * title
    - const char * primary
    - const char * secondary
    - Purple::Request::Fields fields
    - const char * ok_text
    - SV * ok_cb
    - const char * cancel_text
    - SV * cancel_cb
    -CODE:
    - PurplePerlRequestData *gpr;
    - char *basename;
    -
    - basename = g_path_get_basename(handle->path);
    - purple_perl_normalize_script_name(basename);
    - gpr = g_new(PurplePerlRequestData, 1);
    - gpr->ok_fun = purple_perl_sv_from_fun(handle, ok_cb);
    - gpr->cancel_fun = purple_perl_sv_from_fun(handle, cancel_cb);
    - g_free(basename);
    -
    - RETVAL = purple_request_fields(handle, title, primary, secondary, fields, ok_text, G_CALLBACK(purple_perl_request_ok_cb), cancel_text, G_CALLBACK(purple_perl_request_cancel_cb), NULL, gpr);
    -OUTPUT:
    - RETVAL
    -
    -void
    -purple_request_close(type, uihandle)
    - Purple::RequestType type
    - void * uihandle
    -
    -void
    -purple_request_close_with_handle(handle)
    - void * handle
    -
    -
    -MODULE = Purple::Request PACKAGE = Purple::Request::Field PREFIX = purple_request_field_
    -PROTOTYPES: ENABLE
    -
    -Purple::Request::Field
    -purple_request_field_account_new(class, id, text, account = NULL)
    - const char *id
    - const char *text
    - Purple::Account account
    - C_ARGS: id, text, account
    -
    -Purple::Account
    -purple_request_field_account_get_default_value(field)
    - Purple::Request::Field field
    -
    -IV
    -purple_request_field_account_get_filter(field)
    - Purple::Request::Field field
    -CODE:
    - RETVAL = PTR2IV(purple_request_field_account_get_filter(field));
    -OUTPUT:
    - RETVAL
    -
    -gboolean
    -purple_request_field_account_get_show_all(field)
    - Purple::Request::Field field
    -
    -Purple::Account
    -purple_request_field_account_get_value(field)
    - Purple::Request::Field field
    -
    -void
    -purple_request_field_account_set_default_value(field, default_value)
    - Purple::Request::Field field
    - Purple::Account default_value
    -
    -void
    -purple_request_field_account_set_show_all(field, show_all)
    - Purple::Request::Field field
    - gboolean show_all
    -
    -void
    -purple_request_field_account_set_value(field, value)
    - Purple::Request::Field field
    - Purple::Account value
    -
    -MODULE = Purple::Request PACKAGE = Purple::Request::Field PREFIX = purple_request_field_
    -PROTOTYPES: ENABLE
    -
    -Purple::Request::Field
    -purple_request_field_bool_new(class, id, text, default_value = TRUE)
    - const char *id
    - const char *text
    - gboolean default_value
    - C_ARGS: id, text, default_value
    -
    -gboolean
    -purple_request_field_bool_get_default_value(field)
    - Purple::Request::Field field
    -
    -gboolean
    -purple_request_field_bool_get_value(field)
    - Purple::Request::Field field
    -
    -void
    -purple_request_field_bool_set_default_value(field, default_value)
    - Purple::Request::Field field
    - gboolean default_value
    -
    -void
    -purple_request_field_bool_set_value(field, value)
    - Purple::Request::Field field
    - gboolean value
    -
    -MODULE = Purple::Request PACKAGE = Purple::Request::Field PREFIX = purple_request_field_
    -PROTOTYPES: ENABLE
    -
    -Purple::Request::Field
    -purple_request_field_choice_new(class, id, text, default_value = 0)
    - const char *id
    - const char *text
    - gpointer default_value
    - C_ARGS: id, text, default_value
    -
    -void
    -purple_request_field_choice_add(field, label, value)
    - Purple::Request::Field field
    - const char *label
    - gpointer value
    -
    -gpointer
    -purple_request_field_choice_get_default_value(field)
    - Purple::Request::Field field
    -
    - # I'm not sure, if this is the correct implementation - if anyone will need it,
    - # he will add this back to API.
    - #void
    - #purple_request_field_choice_get_elements(field)
    - # Purple::Request::Field field
    - #PREINIT:
    - # GList *l;
    - #PPCODE:
    - # for (l = purple_request_field_choice_get_elements(field); l != NULL; l = l->next) {
    - # XPUSHs(sv_2mortal(newSVpv(l->data, 0)));
    - # l = l->next;
    - # if (l == NULL)
    - # break;
    - # XPUSHs(l->data);
    - # }
    -
    -gpointer
    -purple_request_field_choice_get_value(field)
    - Purple::Request::Field field
    -
    -void
    -purple_request_field_choice_set_default_value(field, default_value)
    - Purple::Request::Field field
    - gpointer default_value
    -
    -void
    -purple_request_field_choice_set_value(field, value)
    - Purple::Request::Field field
    - gpointer value
    -
    -MODULE = Purple::Request PACKAGE = Purple::Request::Field PREFIX = purple_request_field_
    -PROTOTYPES: ENABLE
    -
    -Purple::Request::Field
    -purple_request_field_int_new(clas, id, text, default_value = 0, lower_bound = INT_MIN, upper_bound = INT_MAX)
    - const char *id
    - const char *text
    - int default_value
    - int lower_bound
    - int upper_bound
    - C_ARGS: id, text, default_value, lower_bound, upper_bound
    -
    -int
    -purple_request_field_int_get_default_value(field)
    - Purple::Request::Field field
    -
    -int
    -purple_request_field_int_get_value(field)
    - Purple::Request::Field field
    -
    -void
    -purple_request_field_int_set_default_value(field, default_value)
    - Purple::Request::Field field
    - int default_value
    -
    -void
    -purple_request_field_int_set_value(field, value)
    - Purple::Request::Field field
    - int value
    -
    -gboolean
    -purple_request_field_is_required(field)
    - Purple::Request::Field field
    -
    -MODULE = Purple::Request PACKAGE = Purple::Request::Field PREFIX = purple_request_field_
    -PROTOTYPES: ENABLE
    -
    -Purple::Request::Field
    -purple_request_field_label_new(class, id, text)
    - const char *id
    - const char *text
    - C_ARGS: id, text
    -
    -MODULE = Purple::Request PACKAGE = Purple::Request::Field PREFIX = purple_request_field_
    -PROTOTYPES: ENABLE
    -
    -Purple::Request::Field
    -purple_request_field_list_new(class, id, text)
    - const char *id
    - const char *text
    - C_ARGS: id, text
    -
    -void
    -purple_request_field_list_add_icon(field, item, icon_path, data)
    - Purple::Request::Field field
    - const char *item
    - const char *icon_path
    - void * data
    -
    -void
    -purple_request_field_list_add_selected(field, item)
    - Purple::Request::Field field
    - const char *item
    -
    -void
    -purple_request_field_list_clear_selected(field)
    - Purple::Request::Field field
    -
    -void *
    -purple_request_field_list_get_data(field, text)
    - Purple::Request::Field field
    - const char *text
    -
    -void
    -purple_request_field_list_get_items(field)
    - Purple::Request::Field field
    -PREINIT:
    - GList *l;
    -PPCODE:
    - for (l = purple_request_field_list_get_items(field); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(newSVpv(l->data, 0)));
    - }
    -
    -gboolean
    -purple_request_field_list_get_multi_select(field)
    - Purple::Request::Field field
    -
    -void
    -purple_request_field_list_get_selected(field)
    - Purple::Request::Field field
    -PREINIT:
    - GList *l;
    -PPCODE:
    - for (l = purple_request_field_list_get_selected(field); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(newSVpv(l->data, 0)));
    - }
    -
    -gboolean
    -purple_request_field_list_is_selected(field, item)
    - Purple::Request::Field field
    - const char *item
    -
    -void
    -purple_request_field_list_set_multi_select(field, multi_select)
    - Purple::Request::Field field
    - gboolean multi_select
    -
    -MODULE = Purple::Request PACKAGE = Purple::Request::Field PREFIX = purple_request_field_
    -PROTOTYPES: ENABLE
    -
    -Purple::Request::Field
    -purple_request_field_new(class, id, text, type)
    - const char *id
    - const char *text
    - Purple::RequestFieldType type
    - C_ARGS: id, text, type
    -
    -void
    -purple_request_field_set_label(field, label)
    - Purple::Request::Field field
    - const char *label
    -
    -void
    -purple_request_field_set_required(field, required)
    - Purple::Request::Field field
    - gboolean required
    -
    -void
    -purple_request_field_set_type_hint(field, type_hint)
    - Purple::Request::Field field
    - const char *type_hint
    -
    -void
    -purple_request_field_set_visible(field, visible)
    - Purple::Request::Field field
    - gboolean visible
    -
    -MODULE = Purple::Request PACKAGE = Purple::Request::Field PREFIX = purple_request_field_
    -PROTOTYPES: ENABLE
    -
    -Purple::Request::Field
    -purple_request_field_string_new(class, id, text, default_value, multiline)
    - const char *id
    - const char *text
    - const char *default_value
    - gboolean multiline
    - C_ARGS: id, text, default_value, multiline
    -
    -const char *
    -purple_request_field_string_get_default_value(field)
    - Purple::Request::Field field
    -
    -const char *
    -purple_request_field_string_get_value(field)
    - Purple::Request::Field field
    -
    -gboolean
    -purple_request_field_string_is_masked(field)
    - Purple::Request::Field field
    -
    -gboolean
    -purple_request_field_string_is_multiline(field)
    - Purple::Request::Field field
    -
    -void
    -purple_request_field_string_set_default_value(field, default_value)
    - Purple::Request::Field field
    - const char *default_value
    -
    -void
    -purple_request_field_string_set_masked(field, masked)
    - Purple::Request::Field field
    - gboolean masked
    -
    -void
    -purple_request_field_string_set_value(field, value)
    - Purple::Request::Field field
    - const char *value
    -
    -MODULE = Purple::Request PACKAGE = Purple::Request::Field::Group PREFIX = purple_request_field_group_
    -PROTOTYPES: ENABLE
    -
    -void
    -purple_request_field_group_add_field(group, field)
    - Purple::Request::Field::Group group
    - Purple::Request::Field field
    -
    -void
    -purple_request_field_group_destroy(group)
    - Purple::Request::Field::Group group
    -
    -void
    -purple_request_field_group_get_fields(group)
    - Purple::Request::Field::Group group
    -PREINIT:
    - GList *l;
    -PPCODE:
    - for (l = purple_request_field_group_get_fields(group); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Request::Field")));
    - }
    -
    -const char *
    -purple_request_field_group_get_title(group)
    - Purple::Request::Field::Group group
    -
    -Purple::Request::Field::Group
    -purple_request_field_group_new(class, title)
    - const char *title
    - C_ARGS: title
    -
    -MODULE = Purple::Request PACKAGE = Purple::Request::Field PREFIX = purple_request_field_
    -PROTOTYPES: ENABLE
    -
    -void
    -purple_request_field_destroy(field)
    - Purple::Request::Field field
    -
    -const char *
    -purple_request_field_get_id(field)
    - Purple::Request::Field field
    -
    -const char *
    -purple_request_field_get_label(field)
    - Purple::Request::Field field
    -
    -Purple::RequestFieldType
    -purple_request_field_get_field_type(field)
    - Purple::Request::Field field
    -
    -const char *
    -purple_request_field_get_field_type_hint(field)
    - Purple::Request::Field field
    -
    -gboolean
    -purple_request_field_is_visible(field)
    - Purple::Request::Field field
    -
    -MODULE = Purple::Request PACKAGE = Purple::Request::Fields PREFIX = purple_request_fields_
    -PROTOTYPES: ENABLE
    -
    -Purple::Request::Fields
    -purple_request_fields_new(class)
    - C_ARGS: /* void */
    -
    -void
    -purple_request_fields_add_group(fields, group)
    - Purple::Request::Fields fields
    - Purple::Request::Field::Group group
    -
    -gboolean
    -purple_request_fields_all_required_filled(fields)
    - Purple::Request::Fields fields
    -
    -void
    -purple_request_fields_destroy(fields)
    - Purple::Request::Fields fields
    -
    -gboolean
    -purple_request_fields_exists(fields, id)
    - Purple::Request::Fields fields
    - const char *id
    -
    -Purple::Account
    -purple_request_fields_get_account(fields, id)
    - Purple::Request::Fields fields
    - const char *id
    -
    -gboolean
    -purple_request_fields_get_bool(fields, id)
    - Purple::Request::Fields fields
    - const char *id
    -
    -gpointer
    -purple_request_fields_get_choice(fields, id)
    - Purple::Request::Fields fields
    - const char *id
    -
    -Purple::Request::Field
    -purple_request_fields_get_field(fields, id)
    - Purple::Request::Fields fields
    - const char *id
    -
    -void
    -purple_request_fields_get_groups(fields)
    - Purple::Request::Fields fields
    -PREINIT:
    - GList *l;
    -PPCODE:
    - for (l = purple_request_fields_get_groups(fields); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Request::Field::Group")));
    - }
    -
    -int
    -purple_request_fields_get_integer(fields, id)
    - Purple::Request::Fields fields
    - const char *id
    -
    -void
    -purple_request_fields_get_required(fields)
    - Purple::Request::Fields fields
    -PREINIT:
    - const GList *l;
    -PPCODE:
    - for (l = purple_request_fields_get_required(fields); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Request::Field")));
    - }
    -
    -const char *
    -purple_request_fields_get_string(fields, id)
    - Purple::Request::Fields fields
    - const char *id
    -
    -gboolean
    -purple_request_fields_is_field_required(fields, id)
    - Purple::Request::Fields fields
    - const char *id
    --- a/libpurple/plugins/perl/common/Roomlist.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,92 +0,0 @@
    -#include "module.h"
    -
    -MODULE = Purple::Roomlist PACKAGE = Purple::Roomlist PREFIX = purple_roomlist_
    -PROTOTYPES: ENABLE
    -
    -BOOT:
    -{
    - HV *room_stash = gv_stashpv("Purple::Roomlist::Room::Type", 1);
    - HV *field_stash = gv_stashpv("Purple::Roomlist::Field::Type", 1);
    -
    - static const constiv *civ, room_const_iv[] = {
    -#define const_iv(name) {#name, (IV)PURPLE_ROOMLIST_ROOMTYPE_##name}
    - const_iv(CATEGORY),
    - const_iv(ROOM),
    - };
    - static const constiv field_const_iv[] = {
    -#undef const_iv
    -#define const_iv(name) {#name, (IV)PURPLE_ROOMLIST_FIELD_##name}
    - const_iv(BOOL),
    - const_iv(INT),
    - const_iv(STRING),
    - };
    -
    - for (civ = room_const_iv + sizeof(room_const_iv) / sizeof(room_const_iv[0]); civ-- > room_const_iv; )
    - newCONSTSUB(room_stash, (char *)civ->name, newSViv(civ->iv));
    -
    - for (civ = field_const_iv + sizeof(field_const_iv) / sizeof(field_const_iv[0]); civ-- > field_const_iv; )
    - newCONSTSUB(field_stash, (char *)civ->name, newSViv(civ->iv));
    -}
    -
    -void
    -purple_roomlist_cancel_get_list(list)
    - Purple::Roomlist list
    -
    -void
    -purple_roomlist_expand_category(list, category)
    - Purple::Roomlist list
    - Purple::Roomlist::Room category
    -
    -gboolean
    -purple_roomlist_get_in_progress(list)
    - Purple::Roomlist list
    -
    -Purple::Roomlist
    -purple_roomlist_get_list(gc)
    - Purple::Connection gc
    -
    -Purple::Roomlist
    -purple_roomlist_new(account)
    - Purple::Account account
    -
    -void
    -purple_roomlist_room_add(list, room)
    - Purple::Roomlist list
    - Purple::Roomlist::Room room
    -
    -void
    -purple_roomlist_room_add_field(list, room, field)
    - Purple::Roomlist list
    - Purple::Roomlist::Room room
    - gconstpointer field
    -
    -void
    -purple_roomlist_room_join(list, room)
    - Purple::Roomlist list
    - Purple::Roomlist::Room room
    -
    -void
    -purple_roomlist_set_fields(list, fields)
    - Purple::Roomlist list
    - SV *fields
    -PREINIT:
    - GList *t_GL;
    - int i, t_len;
    -PPCODE:
    - t_GL = NULL;
    - t_len = av_len((AV *)SvRV(fields));
    -
    - for (i = 0; i <= t_len; i++)
    - t_GL = g_list_append(t_GL, SvPVutf8_nolen(*av_fetch((AV *)SvRV(fields), i, 0)));
    -
    - purple_roomlist_set_fields(list, t_GL);
    -
    -void
    -purple_roomlist_set_in_progress(list, in_progress)
    - Purple::Roomlist list
    - gboolean in_progress
    -
    -void
    -purple_roomlist_show_with_account(account)
    - Purple::Account account
    -
    --- a/libpurple/plugins/perl/common/SSLConn.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,45 +0,0 @@
    -#include "module.h"
    -
    -/* TODO
    -
    -
    -Purple::Ssl::Connection
    -purple_ssl_connect(account, host, port, func, error_func, data)
    - Purple::Account account
    - const char *host
    - int port
    - PurpleSslInputFunction func
    - PurpleSslErrorFunction error_func
    -
    -void
    -purple_ssl_input_add(gsc, func, data)
    - Purple::Ssl::Connection gsc
    - Purple::SslInputFunction func
    -
    -*/
    -
    -MODULE = Purple::SSL PACKAGE = Purple::SSL PREFIX = purple_ssl_
    -PROTOTYPES: ENABLE
    -
    -void
    -purple_ssl_close(gsc)
    - Purple::Ssl::Connection gsc
    -
    -Purple::Ssl::Ops
    -purple_ssl_get_ops()
    -
    -size_t
    -purple_ssl_read(gsc, buffer, len)
    - Purple::Ssl::Connection gsc
    - void * buffer
    - size_t len
    -
    -void
    -purple_ssl_set_ops(ops)
    - Purple::Ssl::Ops ops
    -
    -size_t
    -purple_ssl_write(gsc, buffer, len)
    - Purple::Ssl::Connection gsc
    - void * buffer
    - size_t len
    --- a/libpurple/plugins/perl/common/SavedStatuses.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,152 +0,0 @@
    -#include "module.h"
    -
    -/* I can't get this to work, both with and without the const on the return
    - * type I get errors from gcc. One way about ignoring types in a cast, and the
    - * other about assigning to read-only variables.
    -const Purple::StatusType
    -purple_savedstatus_substatus_get_status_type(substatus)
    - const Purple::SavedStatus::Sub substatus
    -*/
    -
    -MODULE = Purple::SavedStatus PACKAGE = Purple::SavedStatus PREFIX = purple_savedstatus_
    -PROTOTYPES: ENABLE
    -
    -Purple::SavedStatus
    -purple_savedstatus_new(title, type)
    - const char *title
    - Purple::StatusPrimitive type
    -
    -void
    -purple_savedstatus_set_title(status, title)
    - Purple::SavedStatus status
    - const char *title
    -
    -void
    -purple_savedstatus_set_primitive_type(status, type)
    - Purple::SavedStatus status
    - Purple::StatusPrimitive type
    -
    -void
    -purple_savedstatus_set_message(status, message)
    - Purple::SavedStatus status
    - const char *message
    -
    -void
    -purple_savedstatus_set_substatus(status, account, type, message)
    - Purple::SavedStatus status
    - Purple::Account account
    - Purple::StatusType type
    - const char *message
    -
    -void
    -purple_savedstatus_unset_substatus(status, account)
    - Purple::SavedStatus status
    - Purple::Account account
    -
    -gboolean
    -purple_savedstatus_delete(title)
    - const char *title
    -
    -Purple::SavedStatus
    -purple_savedstatus_get_current()
    -
    -Purple::SavedStatus
    -purple_savedstatus_get_default()
    -
    -Purple::SavedStatus
    -purple_savedstatus_get_idleaway()
    -
    -gboolean
    -purple_savedstatus_is_idleaway()
    -
    -void
    -purple_savedstatus_set_idleaway(idleaway)
    - gboolean idleaway
    -
    -Purple::SavedStatus
    -purple_savedstatus_get_startup()
    -
    -Purple::SavedStatus
    -purple_savedstatus_find(title)
    - const char *title
    -
    -Purple::SavedStatus
    -purple_savedstatus_find_by_creation_time(creation_time)
    - time_t creation_time
    -
    -Purple::SavedStatus
    -purple_savedstatus_find_transient_by_type_and_message(type, message)
    - Purple::StatusPrimitive type
    - const char *message
    -
    -gboolean
    -purple_savedstatus_is_transient(saved_status)
    - const Purple::SavedStatus saved_status
    -
    -const char *
    -purple_savedstatus_get_title(saved_status)
    - const Purple::SavedStatus saved_status
    -
    -Purple::StatusPrimitive
    -purple_savedstatus_get_primitive_type(saved_status)
    - const Purple::SavedStatus saved_status
    -
    -const char *
    -purple_savedstatus_get_message(saved_status)
    - const Purple::SavedStatus saved_status
    -
    -time_t
    -purple_savedstatus_get_creation_time(saved_status)
    - const Purple::SavedStatus saved_status
    -
    -gboolean
    -purple_savedstatus_has_substatuses(saved_status)
    - const Purple::SavedStatus saved_status
    -
    -Purple::SavedStatus::Sub
    -purple_savedstatus_get_substatus(saved_status, account)
    - Purple::SavedStatus saved_status
    - Purple::Account account
    -
    -void
    -purple_savedstatus_activate(saved_status)
    - Purple::SavedStatus saved_status
    -
    -void
    -purple_savedstatus_activate_for_account(saved_status, account)
    - const Purple::SavedStatus saved_status
    - Purple::Account account
    -
    -MODULE = Purple::SavedStatus::Sub PACKAGE = Purple::SavedStatus::Sub PREFIX = purple_savedstatus_substatus_
    -PROTOTYPES: ENABLE
    -
    -const char *
    -purple_savedstatus_substatus_get_message(substatus)
    - const Purple::SavedStatus::Sub substatus
    -
    -MODULE = Purple::SavedStatus PACKAGE = Purple::SavedStatuses PREFIX = purple_savedstatuses_
    -PROTOTYPES: ENABLE
    -
    -void
    -purple_savedstatuses_get_all()
    -PREINIT:
    - GList *l;
    -PPCODE:
    - for (l = purple_savedstatuses_get_all(); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::SavedStatus")));
    - }
    -
    -void
    -purple_savedstatuses_get_popular(how_many)
    - unsigned int how_many
    -PREINIT:
    - GList *l, *ll;
    -PPCODE:
    - ll = purple_savedstatuses_get_popular(how_many);
    - for (l = ll; l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::SavedStatus")));
    - }
    - g_list_free(ll);
    -
    -Purple::Handle
    -purple_savedstatuses_get_handle()
    --- a/libpurple/plugins/perl/common/Server.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,195 +0,0 @@
    -#include "module.h"
    -
    -MODULE = Purple::Serv PACKAGE = Purple::Serv PREFIX = serv_
    -PROTOTYPES: ENABLE
    -
    -
    -void
    -purple_serv_add_deny(con, a)
    - Purple::Connection con
    - const char * a
    -
    -void
    -purple_serv_add_permit(a, b)
    - Purple::Connection a
    - const char * b
    -
    -void
    -purple_serv_alias_buddy(buddy)
    - Purple::BuddyList::Buddy buddy
    -
    -void
    -purple_serv_chat_invite(con, a, b, c)
    - Purple::Connection con
    - int a
    - const char * b
    - const char * c
    -
    -void
    -purple_serv_chat_leave(a, b)
    - Purple::Connection a
    - int b
    -
    -void
    -purple_serv_get_info(con, a)
    - Purple::Connection con
    - const char * a
    -
    -void
    -purple_serv_got_alias(gc, who, alias)
    - Purple::Connection gc
    - const char *who
    - const char *alias
    -
    -void
    -purple_serv_got_chat_in(g, id, who, chatflags, message, mtime)
    - Purple::Connection g
    - int id
    - const char *who
    - Purple::MessageFlags chatflags
    - const char *message
    - time_t mtime
    -
    -void
    -purple_serv_got_chat_invite(gc, name, who, message, components)
    - Purple::Connection gc
    - const char *name
    - const char *who
    - const char *message
    - SV * components
    -INIT:
    - HV * t_HV;
    - HE * t_HE;
    - SV * t_SV;
    - GHashTable * t_GHash;
    - I32 len;
    - char *t_key, *t_value;
    -CODE:
    - t_HV = (HV *)SvRV(components);
    - t_GHash = g_hash_table_new(g_str_hash, g_str_equal);
    -
    - for (t_HE = hv_iternext(t_HV); t_HE != NULL; t_HE = hv_iternext(t_HV) ) {
    - t_key = hv_iterkey(t_HE, &len);
    - t_SV = *hv_fetch(t_HV, t_key, len, 0);
    - t_value = SvPVutf8_nolen(t_SV);
    -
    - g_hash_table_insert(t_GHash, t_key, t_value);
    - }
    - purple_serv_got_chat_invite(gc, name, who, message, t_GHash);
    -
    -void
    -purple_serv_got_chat_left(g, id)
    - Purple::Connection g
    - int id
    -
    -void
    -purple_serv_got_im(gc, who, msg, imflags, mtime)
    - Purple::Connection gc
    - const char *who
    - const char *msg
    - Purple::MessageFlags imflags
    - time_t mtime
    -
    -Purple::ChatConversation
    -purple_serv_got_joined_chat(gc, id, name)
    - Purple::Connection gc
    - int id
    - const char *name
    -
    -void
    -purple_serv_got_typing(gc, name, timeout, state)
    - Purple::Connection gc
    - const char *name
    - int timeout
    - Purple::IMTypingState state
    -
    -void
    -purple_serv_got_typing_stopped(gc, name)
    - Purple::Connection gc
    - const char *name
    -
    -void
    -purple_serv_join_chat(conn, components)
    - Purple::Connection conn
    - HV * components
    -PREINIT:
    - HE *t_HE;
    - SV *t_SV;
    - I32 len;
    - GHashTable *t_GHash;
    - char *t_key, *t_value;
    -CODE:
    - t_GHash = g_hash_table_new(g_str_hash, g_str_equal);
    -
    - for (t_HE = hv_iternext(components); t_HE != NULL;
    - t_HE = hv_iternext(components)) {
    - t_key = hv_iterkey(t_HE, &len);
    - t_SV = *hv_fetch(components, t_key, len, 0);
    - t_value = SvPVutf8_nolen(t_SV);
    -
    - g_hash_table_insert(t_GHash, t_key, t_value);
    - }
    - purple_serv_join_chat(conn, t_GHash);
    - g_hash_table_destroy(t_GHash);
    -
    -void
    -purple_serv_move_buddy(buddy, group1, group2)
    - Purple::BuddyList::Buddy buddy
    - Purple::BuddyList::Group group1
    - Purple::BuddyList::Group group2
    -
    -void
    -purple_serv_reject_chat(con, components)
    - Purple::Connection con
    - SV * components
    -INIT:
    - HV * t_HV;
    - HE * t_HE;
    - SV * t_SV;
    - GHashTable * t_GHash;
    - I32 len;
    - char *t_key, *t_value;
    -CODE:
    - t_HV = (HV *)SvRV(components);
    - t_GHash = g_hash_table_new(g_str_hash, g_str_equal);
    -
    - for (t_HE = hv_iternext(t_HV); t_HE != NULL; t_HE = hv_iternext(t_HV) ) {
    - t_key = hv_iterkey(t_HE, &len);
    - t_SV = *hv_fetch(t_HV, t_key, len, 0);
    - t_value = SvPVutf8_nolen(t_SV);
    -
    - g_hash_table_insert(t_GHash, t_key, t_value);
    - }
    - purple_serv_reject_chat(con, t_GHash);
    -
    -void
    -purple_serv_rem_deny(con, a)
    - Purple::Connection con
    - const char * a
    -
    -void
    -purple_serv_rem_permit(con, a)
    - Purple::Connection con
    - const char * a
    -
    -void
    -purple_serv_send_file(gc, who, file)
    - Purple::Connection gc
    - const char *who
    - const char *file
    -
    -int
    -purple_serv_send_typing(con, a, state)
    - Purple::Connection con
    - const char * a
    - Purple::IMTypingState state
    -
    -void
    -purple_serv_set_info(con, a)
    - Purple::Connection con
    - const char * a
    -
    -void
    -purple_serv_set_permit_deny(con)
    - Purple::Connection con
    -
    --- a/libpurple/plugins/perl/common/Signal.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,34 +0,0 @@
    -#include "module.h"
    -#include "../perl-handlers.h"
    -
    -MODULE = Purple::Signal PACKAGE = Purple::Signal PREFIX = purple_signal_
    -PROTOTYPES: ENABLE
    -
    -void
    -purple_signal_connect_priority(instance, signal, plugin, callback, priority, data = 0)
    - Purple::Handle instance
    - const char *signal
    - Purple::Plugin plugin
    - SV *callback
    - int priority
    - SV *data
    -CODE:
    - purple_perl_signal_connect(plugin, instance, signal, callback, data, priority);
    -
    -void
    -purple_signal_connect(instance, signal, plugin, callback, data = 0)
    - Purple::Handle instance
    - const char *signal
    - Purple::Plugin plugin
    - SV *callback
    - SV *data
    -CODE:
    - purple_perl_signal_connect(plugin, instance, signal, callback, data, PURPLE_SIGNAL_PRIORITY_DEFAULT);
    -
    -void
    -purple_signal_disconnect(instance, signal, plugin)
    - Purple::Handle instance
    - const char *signal
    - Purple::Plugin plugin
    -CODE:
    - purple_perl_signal_disconnect(plugin, instance, signal);
    --- a/libpurple/plugins/perl/common/Sound.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,37 +0,0 @@
    -#include "module.h"
    -
    -MODULE = Purple::Sound PACKAGE = Purple::Sound PREFIX = purple_sound_
    -PROTOTYPES: ENABLE
    -
    -BOOT:
    -{
    - HV *stash = gv_stashpv("Purple::SoundEventID", 1);
    -
    - static const constiv *civ, const_iv[] = {
    -#define const_iv(name) {#name, (IV)PURPLE_SOUND_##name}
    - const_iv(BUDDY_ARRIVE),
    - const_iv(BUDDY_LEAVE),
    - const_iv(RECEIVE),
    - const_iv(FIRST_RECEIVE),
    - const_iv(SEND),
    - const_iv(CHAT_JOIN),
    - const_iv(CHAT_LEAVE),
    - const_iv(CHAT_YOU_SAY),
    - const_iv(CHAT_SAY),
    - const_iv(POUNCE_DEFAULT),
    - const_iv(CHAT_NICK),
    - };
    -
    - for (civ = const_iv + sizeof(const_iv) / sizeof(const_iv[0]); civ-- > const_iv; )
    - newCONSTSUB(stash, (char *)civ->name, newSViv(civ->iv));
    -}
    -
    -void
    -purple_sound_play_event(event, account)
    - Purple::SoundEventID event
    - Purple::Account account
    -
    -void
    -purple_sound_play_file(filename, account)
    - const char *filename
    - Purple::Account account
    --- a/libpurple/plugins/perl/common/Status.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,267 +0,0 @@
    -#include "module.h"
    -
    -/* TODO
    -
    -void
    -purple_status_type_add_attrs(status_type, id, name, value, purple_status_type_add_attrs)
    - Purple::StatusType status_type
    - const char *id
    - const char *name
    - Purple::Value value
    - ...
    -
    -Purple::StatusType
    -purple_status_type_new_with_attrs(primitive, id, name, saveable, user_settable, independent, attr_id, attr_name, attr_value, purple_status_type_new_with_attrs)
    - Purple::StatusPrimitive primitive
    - const char *id
    - const char *name
    - gboolean saveable
    - gboolean user_settable
    - gboolean independent
    - const char *attr_id
    - const char *attr_name
    - Purple::Value attr_value
    - ...
    -
    -*/
    -
    -/* These break on faceprint's amd64 box
    -void
    -purple_status_type_add_attrs_vargs(status_type, args)
    - Purple::StatusType status_type
    - va_list args
    -
    -void
    -purple_status_set_active_with_attrs(status, active, args)
    - Purple::Status status
    - gboolean active
    - va_list args
    -
    - */
    -
    -MODULE = Purple::Status PACKAGE = Purple::Primitive PREFIX = purple_primitive_
    -PROTOTYPES: ENABLE
    -
    -BOOT:
    -{
    - HV *primitive_stash = gv_stashpv("Purple::Status::Primitive", 1);
    -
    - static const constiv *civ, primitive_const_iv[] = {
    -#undef const_iv
    -#define const_iv(name) {#name, (IV)PURPLE_STATUS_##name}
    - const_iv(UNSET),
    - const_iv(OFFLINE),
    - const_iv(AVAILABLE),
    - const_iv(UNAVAILABLE),
    - const_iv(INVISIBLE),
    - const_iv(AWAY),
    - const_iv(EXTENDED_AWAY),
    - const_iv(MOBILE),
    - };
    -
    - for (civ = primitive_const_iv + sizeof(primitive_const_iv) / sizeof(primitive_const_iv[0]); civ-- > primitive_const_iv; )
    - newCONSTSUB(primitive_stash, (char *)civ->name, newSViv(civ->iv));
    -}
    -
    -const char *
    -purple_primitive_get_id_from_type(type)
    - Purple::StatusPrimitive type
    -
    -const char *
    -purple_primitive_get_name_from_type(type)
    - Purple::StatusPrimitive type
    -
    -Purple::StatusPrimitive
    -purple_primitive_get_type_from_id(id)
    - const char *id
    -
    -MODULE = Purple::Status PACKAGE = Purple::StatusAttr PREFIX = purple_status_attribute_
    -PROTOTYPES: ENABLE
    -
    -void
    -purple_status_attribute_destroy(attr)
    - Purple::StatusAttr attr
    -
    -const char *
    -purple_status_attribute_get_id(attr)
    - Purple::StatusAttr attr
    -
    -const char *
    -purple_status_attribute_get_name(attr)
    - Purple::StatusAttr attr
    -
    -GValue *
    -purple_status_attribute_get_value(attr)
    - Purple::StatusAttr attr
    -
    -Purple::StatusAttr
    -purple_status_attribute_new(id, name, value_type)
    - const char *id
    - const char *name
    - GValue *value_type
    -
    -MODULE = Purple::Status PACKAGE = Purple::Status PREFIX = purple_status_
    -PROTOTYPES: ENABLE
    -
    -gint
    -purple_status_compare(status1, status2)
    - Purple::Status status1
    - Purple::Status status2
    -
    -gboolean
    -purple_status_get_attr_boolean(status, id)
    - Purple::Status status
    - const char *id
    -
    -int
    -purple_status_get_attr_int(status, id)
    - Purple::Status status
    - const char *id
    -
    -const char *
    -purple_status_get_attr_string(status, id)
    - Purple::Status status
    - const char *id
    -
    -GValue *
    -purple_status_get_attr_value(status, id)
    - Purple::Status status
    - const char *id
    -
    -Purple::Handle
    -purple_statuses_get_handle()
    -
    -const char *
    -purple_status_get_id(status)
    - Purple::Status status
    -
    -const char *
    -purple_status_get_name(status)
    - Purple::Status status
    -
    -Purple::Presence
    -purple_status_get_presence(status)
    - Purple::Status status
    -
    -Purple::StatusType
    -purple_status_get_status_type(status)
    - Purple::Status status
    -
    -gboolean
    -purple_status_is_active(status)
    - Purple::Status status
    -
    -gboolean
    -purple_status_is_available(status)
    - Purple::Status status
    -
    -gboolean
    -purple_status_is_exclusive(status)
    - Purple::Status status
    -
    -gboolean
    -purple_status_is_independent(status)
    - Purple::Status status
    -
    -gboolean
    -purple_status_is_online(status)
    - Purple::Status status
    -
    -Purple::Status
    -purple_status_new(status_type, presence)
    - Purple::StatusType status_type
    - Purple::Presence presence
    -
    -void
    -purple_status_set_active(status, active)
    - Purple::Status status
    - gboolean active
    -
    -MODULE = Purple::Status PACKAGE = Purple::StatusType PREFIX = purple_status_type_
    -PROTOTYPES: ENABLE
    -
    -void
    -purple_status_type_destroy(status_type)
    - Purple::StatusType status_type
    -
    -Purple::StatusAttr
    -purple_status_type_get_attr(status_type, id)
    - Purple::StatusType status_type
    - const char *id
    -
    -void
    -purple_status_type_get_attrs(status_type)
    - Purple::StatusType status_type
    -PREINIT:
    - GList *l;
    -PPCODE:
    - for (l = purple_status_type_get_attrs(status_type); l != NULL; l = l->next) {
    - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::StatusAttr")));
    - }
    -
    -Purple::StatusType
    -purple_status_type_find_with_id(status_types, id)
    - SV *status_types
    - const char *id
    -PREINIT:
    - GList *t_GL;
    - int i, t_len;
    -CODE:
    - t_GL = NULL;
    - t_len = av_len((AV *)SvRV(status_types));
    -
    - for (i = 0; i <= t_len; i++) {
    - t_GL = g_list_append(t_GL, SvPVutf8_nolen(*av_fetch((AV *)SvRV(status_types), i, 0)));
    - }
    - RETVAL = (PurpleStatusType *)purple_status_type_find_with_id(t_GL, id);
    - g_list_free(t_GL);
    -OUTPUT:
    - RETVAL
    -
    -const char *
    -purple_status_type_get_id(status_type)
    - Purple::StatusType status_type
    -
    -const char *
    -purple_status_type_get_name(status_type)
    - Purple::StatusType status_type
    -
    -Purple::StatusPrimitive
    -purple_status_type_get_primitive(status_type)
    - Purple::StatusType status_type
    -
    -gboolean
    -purple_status_type_is_available(status_type)
    - Purple::StatusType status_type
    -
    -gboolean
    -purple_status_type_is_exclusive(status_type)
    - Purple::StatusType status_type
    -
    -gboolean
    -purple_status_type_is_independent(status_type)
    - Purple::StatusType status_type
    -
    -gboolean
    -purple_status_type_is_saveable(status_type)
    - Purple::StatusType status_type
    -
    -gboolean
    -purple_status_type_is_user_settable(status_type)
    - Purple::StatusType status_type
    -
    -Purple::StatusType
    -purple_status_type_new(primitive, id, name, user_settable)
    - Purple::StatusPrimitive primitive
    - const char *id
    - const char *name
    - gboolean user_settable
    -
    -Purple::StatusType
    -purple_status_type_new_full(primitive, id, name, saveable, user_settable, independent)
    - Purple::StatusPrimitive primitive
    - const char *id
    - const char *name
    - gboolean saveable
    - gboolean user_settable
    - gboolean independent
    --- a/libpurple/plugins/perl/common/Stringref.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,37 +0,0 @@
    -#include "module.h"
    -
    -MODULE = Purple::Stringref PACKAGE = Purple::Stringref PREFIX = purple_stringref_
    -PROTOTYPES: ENABLE
    -
    -int
    -purple_stringref_cmp(s1, s2)
    - Purple::Stringref s1
    - Purple::Stringref s2
    -
    -size_t
    -purple_stringref_len(stringref)
    - Purple::Stringref stringref
    -
    -Purple::Stringref
    -purple_stringref_new(class, value)
    - const char *value
    - C_ARGS:
    - value
    -
    -Purple::Stringref
    -purple_stringref_new_noref(class, value)
    - const char *value
    - C_ARGS:
    - value
    -
    -Purple::Stringref
    -purple_stringref_ref(stringref)
    - Purple::Stringref stringref
    -
    -void
    -purple_stringref_unref(stringref)
    - Purple::Stringref stringref
    -
    -const char *
    -purple_stringref_value(stringref)
    - Purple::Stringref stringref
    --- a/libpurple/plugins/perl/common/Util.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,437 +0,0 @@
    -#include "module.h"
    -
    -static void markup_find_tag_foreach(GQuark key_id, char *data, HV *hv) {
    - const char *key = NULL;
    - key = g_quark_to_string(key_id);
    - if (hv_store(hv, key, strlen(key), newSVpv(data, 0), 0) == NULL)
    - purple_debug_error("perl", "hv_store failed\n");
    -}
    -
    -MODULE = Purple::Util PACKAGE = Purple::Util PREFIX = purple_
    -PROTOTYPES: ENABLE
    -
    -gboolean
    -purple_running_gnome()
    -
    -gboolean
    -purple_running_kde()
    -
    -gboolean
    -purple_running_osx()
    -
    -int
    -purple_build_dir(path, mode)
    - const char *path
    - int mode
    -
    -gboolean
    -purple_email_is_valid(address)
    - const char *address
    -
    -const char *
    -purple_escape_filename(str)
    - const char *str
    -
    -gchar_own *
    -purple_fd_get_ip(fd)
    - int fd
    -
    -const gchar *
    -purple_home_dir()
    -
    -gchar_own*
    -purple_message_meify(SV *msg)
    - PREINIT:
    - char *message = NULL;
    - gboolean ret;
    - gsize len;
    - CODE:
    - message = SvPV(msg, len);
    - message = g_strndup(message, len);
    - ret = purple_message_meify(message, len);
    - if(ret) {
    - /* message will get g_free()'d later on, since RETVAL is gchar_own* */
    - RETVAL = message;
    - } else {
    - RETVAL = NULL;
    - g_free(message);
    - }
    - OUTPUT:
    - RETVAL
    -
    -FILE *
    -purple_mkstemp(OUTLIST gchar_own *path, binary)
    - gboolean binary
    - PROTOTYPE: $
    -
    -const char *
    -purple_normalize(account, str)
    - Purple::Account account
    - const char *str
    -
    -gboolean
    -purple_program_is_valid(program)
    - const char *program
    -
    -gchar_own *
    -purple_strdup_withhtml(src)
    - const gchar *src
    -
    -gchar_own *
    -purple_text_strip_mnemonic(in)
    - const char *in
    -
    -time_t
    -purple_time_build(year, month, day, hour, min, sec)
    - int year
    - int month
    - int day
    - int hour
    - int min
    - int sec
    -
    -const char *
    -purple_time_format(tm)
    - const struct tm *tm
    -
    -const char *
    -purple_unescape_filename(str)
    - const char *str
    -
    -gchar_own *
    -purple_unescape_html(html)
    - const char *html
    -
    -const char *
    -purple_url_decode(str)
    - const char *str
    -
    -const char *
    -purple_url_encode(str)
    - const char *str
    -
    -const char *
    -purple_user_dir()
    -
    -const char *
    -purple_utf8_strftime(const char *format, const struct tm *tm);
    -
    -gboolean
    -purple_utf8_has_word(haystack, needle)
    - const char* haystack
    - const char* needle
    -
    -gchar_own*
    -purple_utf8_ncr_decode(in)
    - const char* in
    -
    -gchar_own*
    -purple_utf8_ncr_encode(in)
    - const char* in
    -
    -gchar_own*
    -purple_utf8_salvage(str)
    - const char* str
    -
    -int
    -purple_utf8_strcasecmp(a, b)
    - const char* a
    - const char* b
    -
    -gchar_own*
    -purple_utf8_try_convert(str)
    - const char* str
    -
    -gboolean
    -purple_ip_address_is_valid(ip)
    - const char* ip
    -
    -gboolean
    -purple_ipv4_address_is_valid(ip)
    - const char* ip
    -
    -gboolean
    -purple_ipv6_address_is_valid(ip)
    - const char* ip
    -
    -const char*
    -purple_normalize_nocase(account, str)
    - Purple::Account account
    - const char* str
    -
    -const gchar*
    -purple_gai_strerror(errnum)
    - gint errnum
    -
    -void
    -purple_got_protocol_handler_uri(uri)
    - const char* uri
    -
    -gchar_own*
    -purple_base16_encode(const guchar *data, gsize length(data))
    - PROTOTYPE: $
    -
    -gchar_own*
    -purple_base16_encode_chunked(const guchar *data, gsize length(data))
    - PROTOTYPE: $
    -
    -gchar_own*
    -purple_base64_encode(const guchar *data, gsize length(data))
    - PROTOTYPE: $
    -
    -void
    -purple_restore_default_signal_handlers()
    -
    -SV *
    -purple_base16_decode(str)
    - const char* str
    - PREINIT:
    - gsize len;
    - guchar *ret;
    - CODE:
    - ret = purple_base16_decode(str, &len);
    - if(ret && len > 0) {
    - RETVAL = newSVpv((gchar *)ret, len);
    - } else {
    - g_free(ret);
    - XSRETURN_UNDEF;
    - }
    - g_free(ret);
    - OUTPUT:
    - RETVAL
    -
    -SV*
    -purple_base64_decode(str)
    - const char* str
    - PREINIT:
    - gsize len;
    - guchar *ret;
    - CODE:
    - ret = purple_base64_decode(str, &len);
    - if(ret && len > 0) {
    - RETVAL = newSVpv((gchar *)ret, len);
    - } else {
    - g_free(ret);
    - XSRETURN_UNDEF;
    - }
    - g_free(ret);
    - OUTPUT:
    - RETVAL
    -
    -SV*
    -purple_quotedp_decode(str)
    - const char* str
    - PREINIT:
    - gsize len;
    - guchar *ret;
    - CODE:
    - ret = purple_quotedp_decode(str, &len);
    - if(len) {
    - RETVAL = newSVpv((gchar *)ret, len);
    - } else {
    - g_free(ret);
    - XSRETURN_UNDEF;
    - }
    - g_free(ret);
    - OUTPUT:
    - RETVAL
    -
    -void
    -purple_uri_list_extract_uris(uri_list)
    - const gchar* uri_list
    - PREINIT:
    - GList *l = NULL, *gl = NULL;
    - PPCODE:
    - gl = purple_uri_list_extract_uris(uri_list);
    - for(l = gl; l; l = l->next) {
    - XPUSHs(sv_2mortal(newSVpv(l->data, 0)));
    - g_free(l->data);
    - }
    - g_list_free(gl);
    -
    -void
    -purple_uri_list_extract_filenames(uri_list)
    - const gchar* uri_list
    - PREINIT:
    - GList *l = NULL, *gl = NULL;
    - PPCODE:
    - gl = purple_uri_list_extract_filenames(uri_list);
    - for(l = gl; l; l = l->next) {
    - XPUSHs(sv_2mortal(newSVpv(l->data, 0)));
    - g_free(l->data);
    - }
    - g_list_free(gl);
    -
    -MODULE = Purple::Util PACKAGE = Purple::Util::Str PREFIX = purple_str_
    -PROTOTYPES: ENABLE
    -
    -gchar_own *
    -purple_str_add_cr(str)
    - const char *str
    -
    -gchar_own *
    -purple_str_binary_to_ascii(const unsigned char *binary, guint length(binary))
    - PROTOTYPE: $
    -
    -gboolean
    -purple_str_has_prefix(s, p)
    - const char *s
    - const char *p
    -
    -gboolean
    -purple_str_has_suffix(s, x)
    - const char *s
    - const char *x
    -
    -gchar_own *
    -purple_str_seconds_to_string(sec)
    - guint sec
    -
    -gchar_own *
    -purple_str_size_to_units(size)
    - size_t size
    -
    -time_t
    -purple_str_to_time(timestamp, utc = FALSE, tm = NULL, OUTLIST long tz_off, OUTLIST const char *rest)
    - const char *timestamp
    - gboolean utc
    - struct tm *tm
    - PROTOTYPE: $;$$
    -
    -MODULE = Purple::Util PACKAGE = Purple::Util::Date PREFIX = purple_date_
    -PROTOTYPES: ENABLE
    -
    -const char *
    -purple_date_format_full(tm)
    - const struct tm *tm
    -
    -const char *
    -purple_date_format_long(tm)
    - const struct tm *tm
    -
    -const char *
    -purple_date_format_short(tm)
    - const struct tm *tm
    -
    -MODULE = Purple::Util PACKAGE = Purple::Util::Markup PREFIX = purple_markup_
    -PROTOTYPES: ENABLE
    -
    -gboolean
    -purple_markup_extract_info_field(str, len, user_info, start_token, skip, end_token, check_value, no_value_token, display_name, is_link, link_prefix, format_cb)
    - const char *str
    - int len
    - Purple::NotifyUserInfo user_info
    - const char *start_token
    - int skip
    - const char *end_token
    - char check_value
    - const char *no_value_token
    - const char *display_name
    - gboolean is_link
    - const char *link_prefix
    - Purple::Util::InfoFieldFormatCallback format_cb
    -
    - # XXX: returning start/end to perl doesn't make a lot of sense...
    - # XXX: the actual tag data can be gotten with $start =~ s/$end//g;
    -void
    -purple_markup_find_tag(needle, haystack)
    - const char *needle
    - const char *haystack
    - PREINIT:
    - const char *start = NULL;
    - const char *end = NULL;
    - GData *attributes;
    - gboolean ret;
    - HV *hv = NULL;
    - PPCODE:
    - ret = purple_markup_find_tag(needle, haystack, &start, &end, &attributes);
    - if(!ret) XSRETURN_UNDEF;
    -
    - hv = newHV();
    - g_datalist_foreach(&attributes, (GDataForeachFunc) markup_find_tag_foreach, hv);
    - g_datalist_clear(&attributes);
    -
    - XPUSHs(sv_2mortal(newSVpv(start, 0)));
    - XPUSHs(sv_2mortal(newSVpv(end, 0)));
    - XPUSHs(sv_2mortal(newRV_noinc((SV *) hv)));
    -
    -gchar_own *
    -purple_markup_get_tag_name(tag)
    - const char *tag
    -
    -void
    -purple_markup_html_to_xhtml(html, OUTLIST gchar_own *dest_xhtml, OUTLIST gchar_own *dest_plain)
    - const char *html
    - PROTOTYPE: $
    -
    -gchar_own *
    -purple_markup_linkify(str)
    - const char *str
    -
    -gchar_own *
    -purple_markup_slice(str, x, y)
    - const char *str
    - guint x
    - guint y
    -
    -gchar_own *
    -purple_markup_strip_html(str)
    - const char *str
    -
    -gchar_own *
    -purple_markup_get_css_property(style, opt)
    - const gchar* style
    - const gchar* opt
    -
    -SV*
    -purple_markup_unescape_entity(text)
    - const char* text
    - PREINIT:
    - int length;
    - CODE:
    - {
    - const char *str = purple_markup_unescape_entity(text, &length);
    - if(length) {
    - RETVAL = newSVpv(str, length);
    - } else {
    - XSRETURN_UNDEF;
    - }
    - }
    - OUTPUT:
    - RETVAL
    -
    -
    -MODULE = Purple::Util PACKAGE = Purple::Util PREFIX = purple_util_
    -PROTOTYPES: ENABLE
    -
    -void
    -purple_util_set_user_dir(dir)
    - const char *dir
    -
    -gboolean
    -purple_util_write_data_to_file(filename, const char *data, size_t length(data))
    - const char *filename
    - PROTOTYPE: $$
    -
    -void
    -purple_util_set_current_song(title, artist, album)
    - const char *title
    - const char *artist
    - const char *album
    -
    -gchar_own*
    -purple_util_format_song_info(title, artist, album, unused)
    - const char* title
    - const char* artist
    - const char* album
    - gpointer unused
    -
    -Purple::XMLNode
    -purple_util_read_xml_from_file(filename, description)
    - const char* filename
    - const char* description
    -
    -gboolean
    -purple_util_write_data_to_file_absolute(filename_full, char *data, gssize length(data))
    - const char* filename_full
    - PROTOTYPE: $$
    --- a/libpurple/plugins/perl/common/Whiteboard.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,74 +0,0 @@
    -#include "module.h"
    -
    -MODULE = Purple::Whiteboard PACKAGE = Purple::Whiteboard PREFIX = purple_whiteboard_
    -PROTOTYPES: ENABLE
    -
    -void
    -purple_whiteboard_clear(wb)
    - Purple::Whiteboard wb
    -
    -Purple::Whiteboard
    -purple_whiteboard_new(account, who, state)
    - Purple::Account account
    - const char* who
    - int state
    -
    -void
    -purple_whiteboard_draw_line(wb, x1, y1, x2, y2, color, size)
    - Purple::Whiteboard wb
    - int x1
    - int y1
    - int x2
    - int y2
    - int color
    - int size
    -
    -void
    -purple_whiteboard_draw_point(wb, x, y, color, size)
    - Purple::Whiteboard wb
    - int x
    - int y
    - int color
    - int size
    -
    -Purple::Whiteboard
    -purple_whiteboard_get_session(account, who)
    - Purple::Account account
    - const char* who
    -
    -void
    -purple_whiteboard_send_brush(wb, size, color)
    - Purple::Whiteboard wb
    - int size
    - int color
    -
    -void
    -purple_whiteboard_send_clear(wb)
    - Purple::Whiteboard wb
    -
    -void
    -purple_whiteboard_set_brush(wb, size, color)
    - Purple::Whiteboard wb
    - int size
    - int color
    -
    -void
    -purple_whiteboard_set_dimensions(wb, width, height)
    - Purple::Whiteboard wb
    - int width
    - int height
    -
    -gboolean
    -purple_whiteboard_get_brush(wb, OUTLIST int size, OUTLIST int color)
    - Purple::Whiteboard wb
    - PROTOTYPE: $
    -
    -gboolean
    -purple_whiteboard_get_dimensions(wb, OUTLIST int width, OUTLIST int height)
    - Purple::Whiteboard wb
    - PROTOTYPE: $
    -
    -void
    -purple_whiteboard_start(wb)
    - Purple::Whiteboard wb
    -
    --- a/libpurple/plugins/perl/common/XMLNode.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,122 +0,0 @@
    -#include "module.h"
    -
    -MODULE = Purple::XMLNode PACKAGE = Purple::XMLNode PREFIX = purple_xmlnode_
    -PROTOTYPES: ENABLE
    -
    -Purple::XMLNode
    -purple_xmlnode_copy(src)
    - Purple::XMLNode src
    -
    -void
    -purple_xmlnode_free(node)
    - Purple::XMLNode node
    -
    -Purple::XMLNode
    -purple_xmlnode_from_str(const char *str, gssize length(str))
    - PROTOTYPE: $
    -
    -const char *
    -purple_xmlnode_get_name(node)
    - Purple::XMLNode node
    - CODE:
    - RETVAL = node->name;
    - OUTPUT:
    - RETVAL
    -
    -const char *
    -purple_xmlnode_get_attrib(node, attr)
    - Purple::XMLNode node
    - const char *attr
    -
    -Purple::XMLNode
    -purple_xmlnode_get_child(parent, name)
    - Purple::XMLNode parent
    - const char *name
    -PREINIT:
    - PurpleXmlNode *tmp;
    -CODE:
    - if (!name || *name == '\0') {
    - tmp = parent->child;
    - while (tmp && tmp->type != PURPLE_XMLNODE_TYPE_TAG)
    - tmp = tmp->next;
    - RETVAL = tmp;
    - } else
    - RETVAL = purple_xmlnode_get_child(parent, name);
    -OUTPUT:
    - RETVAL
    -
    -Purple::XMLNode
    -purple_xmlnode_get_child_with_namespace(parent, name, xmlns)
    - Purple::XMLNode parent
    - const char *name
    - const char *xmlns
    -
    -gchar_own *
    -purple_xmlnode_get_data(node)
    - Purple::XMLNode node
    -
    -Purple::XMLNode
    -purple_xmlnode_get_next(node)
    - Purple::XMLNode node
    -PREINIT:
    - PurpleXmlNode *tmp;
    -CODE:
    - tmp = node->next;
    - while (tmp && tmp->type != PURPLE_XMLNODE_TYPE_TAG)
    - tmp = tmp->next;
    - RETVAL = tmp;
    -OUTPUT:
    - RETVAL
    -
    -Purple::XMLNode
    -purple_xmlnode_get_next_twin(node)
    - Purple::XMLNode node
    -
    -void
    -purple_xmlnode_insert_child(parent, child)
    - Purple::XMLNode parent
    - Purple::XMLNode child
    -
    -void
    -purple_xmlnode_insert_data(node, data, size)
    - Purple::XMLNode node
    - const char *data
    - gssize size
    -
    -Purple::XMLNode
    -purple_xmlnode_new(class, name)
    - const char *name
    - C_ARGS:
    - name
    -
    -Purple::XMLNode
    -purple_xmlnode_new_child(parent, name)
    - Purple::XMLNode parent
    - const char *name
    -
    -void
    -purple_xmlnode_remove_attrib(node, attr)
    - Purple::XMLNode node
    - const char *attr
    -
    -void
    -purple_xmlnode_set_attrib(node, attr, value)
    - Purple::XMLNode node
    - const char *attr
    - const char *value
    -
    -gchar_own *
    -purple_xmlnode_to_formatted_str(node)
    - Purple::XMLNode node
    - CODE:
    - RETVAL = purple_xmlnode_to_formatted_str(node, NULL);
    - OUTPUT:
    - RETVAL
    -
    -gchar_own *
    -purple_xmlnode_to_str(node)
    - Purple::XMLNode node
    - CODE:
    - RETVAL = purple_xmlnode_to_str(node, NULL);
    - OUTPUT:
    - RETVAL
    --- a/libpurple/plugins/perl/common/Xfer.xs Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,179 +0,0 @@
    -#include "module.h"
    -
    -MODULE = Purple::Xfer PACKAGE = Purple::Xfer PREFIX = purple_xfer_
    -PROTOTYPES: ENABLE
    -
    -BOOT:
    -{
    - HV *type_stash = gv_stashpv("Purple::Xfer::Type", 1);
    - HV *status_stash = gv_stashpv("Purple::Xfer::Status", 1);
    -
    - static const constiv *civ, type_const_iv[] = {
    -#define const_iv(name) {#name, (IV)PURPLE_XFER_TYPE_##name}
    - const_iv(UNKNOWN),
    - const_iv(SEND),
    - const_iv(RECEIVE),
    - };
    - static const constiv status_const_iv[] = {
    -#undef const_iv
    -#define const_iv(name) {#name, (IV)PURPLE_XFER_STATUS_##name}
    - const_iv(UNKNOWN),
    - const_iv(NOT_STARTED),
    - const_iv(ACCEPTED),
    - const_iv(STARTED),
    - const_iv(DONE),
    - const_iv(CANCEL_LOCAL),
    - const_iv(CANCEL_REMOTE),
    - };
    -
    - for (civ = type_const_iv + sizeof(type_const_iv) / sizeof(type_const_iv[0]); civ-- > type_const_iv; )
    - newCONSTSUB(type_stash, (char *)civ->name, newSViv(civ->iv));
    -
    - for (civ = status_const_iv + sizeof(status_const_iv) / sizeof(status_const_iv[0]); civ-- > status_const_iv; )
    - newCONSTSUB(status_stash, (char *)civ->name, newSViv(civ->iv));
    -}
    -
    -Purple::Xfer
    -purple_xfer_new(class, account, type, who)
    - Purple::Account account
    - Purple::XferType type
    - const char *who
    - C_ARGS:
    - account, type, who
    -
    -void
    -purple_xfer_add(xfer)
    - Purple::Xfer xfer
    -
    -void
    -purple_xfer_cancel_local(xfer)
    - Purple::Xfer xfer
    -
    -void
    -purple_xfer_cancel_remote(xfer)
    - Purple::Xfer xfer
    -
    -void
    -purple_xfer_end(xfer)
    - Purple::Xfer xfer
    -
    -void
    -purple_xfer_error(type, account, who, msg)
    - Purple::XferType type
    - Purple::Account account
    - const char *who
    - const char *msg
    -
    -Purple::Account
    -purple_xfer_get_account(xfer)
    - Purple::Xfer xfer
    -
    -size_t
    -purple_xfer_get_bytes_remaining(xfer)
    - Purple::Xfer xfer
    -
    -size_t
    -purple_xfer_get_bytes_sent(xfer)
    - Purple::Xfer xfer
    -
    -const char *
    -purple_xfer_get_filename(xfer)
    - Purple::Xfer xfer
    -
    -const char *
    -purple_xfer_get_local_filename(xfer)
    - Purple::Xfer xfer
    -
    -unsigned int
    -purple_xfer_get_local_port(xfer)
    - Purple::Xfer xfer
    -
    -double
    -purple_xfer_get_progress(xfer)
    - Purple::Xfer xfer
    -
    -const char *
    -purple_xfer_get_remote_ip(xfer)
    - Purple::Xfer xfer
    -
    -unsigned int
    -purple_xfer_get_remote_port(xfer)
    - Purple::Xfer xfer
    -
    -size_t
    -purple_xfer_get_size(xfer)
    - Purple::Xfer xfer
    -
    -Purple::XferStatus
    -purple_xfer_get_status(xfer)
    - Purple::Xfer xfer
    -
    -Purple::XferType
    -purple_xfer_get_xfer_type(xfer)
    - Purple::Xfer xfer
    -
    -gboolean
    -purple_xfer_is_cancelled(xfer)
    - Purple::Xfer xfer
    -
    -gboolean
    -purple_xfer_is_completed(xfer)
    - Purple::Xfer xfer
    -
    -ssize_t
    -purple_xfer_read(xfer, buffer)
    - Purple::Xfer xfer
    - guchar **buffer
    -
    -void
    -purple_xfer_request(xfer)
    - Purple::Xfer xfer
    -
    -void
    -purple_xfer_request_accepted(xfer, filename)
    - Purple::Xfer xfer
    - const char *filename
    -
    -void
    -purple_xfer_request_denied(xfer)
    - Purple::Xfer xfer
    -
    -void
    -purple_xfer_set_completed(xfer, completed)
    - Purple::Xfer xfer
    - gboolean completed
    -
    -void
    -purple_xfer_set_filename(xfer, filename)
    - Purple::Xfer xfer
    - const char *filename
    -
    -void
    -purple_xfer_set_local_filename(xfer, filename)
    - Purple::Xfer xfer
    - const char *filename
    -
    -void
    -purple_xfer_set_message(xfer, message)
    - Purple::Xfer xfer
    - const char *message
    -
    -void
    -purple_xfer_set_size(xfer, size)
    - Purple::Xfer xfer
    - size_t size
    -
    -void
    -purple_xfer_update_progress(xfer)
    - Purple::Xfer xfer
    -
    -ssize_t
    -purple_xfer_write(xfer, buffer, size)
    - Purple::Xfer xfer
    - const guchar *buffer
    - size_t size
    -
    -MODULE = Purple::Xfer PACKAGE = Purple::Xfers PREFIX = purple_xfers_
    -PROTOTYPES: ENABLE
    -
    -
    --- a/libpurple/plugins/perl/common/fallback/const-c.inc Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,115 +0,0 @@
    -#define PERL_constant_NOTFOUND 1
    -#define PERL_constant_NOTDEF 2
    -#define PERL_constant_ISIV 3
    -#define PERL_constant_ISNO 4
    -#define PERL_constant_ISNV 5
    -#define PERL_constant_ISPV 6
    -#define PERL_constant_ISPVN 7
    -#define PERL_constant_ISSV 8
    -#define PERL_constant_ISUNDEF 9
    -#define PERL_constant_ISUV 10
    -#define PERL_constant_ISYES 11
    -
    -#ifndef NVTYPE
    -typedef double NV; /* 5.6 and later define NVTYPE, and typedef NV to it. */
    -#endif
    -#ifndef aTHX_
    -#define aTHX_ /* 5.6 or later define this for threading support. */
    -#endif
    -#ifndef pTHX_
    -#define pTHX_ /* 5.6 or later define this for threading support. */
    -#endif
    -
    -static int
    -constant (pTHX_ const char *name, STRLEN len, IV *iv_return) {
    - /* Initially switch on the length of the name. */
    - /* When generated this function returned values for the list of names given
    - in this section of perl code. Rather than manually editing these functions
    - to add or remove constants, which would result in this comment and section
    - of code becoming inaccurate, we recommend that you edit this section of
    - code, and use it to regenerate a new set of constant functions which you
    - then use to replace the originals.
    -
    - Regenerate these constant functions by feeding this entire source file to
    - perl -x
    -
    -#!/usr/bin/env perl -w
    -use ExtUtils::Constant qw (constant_types C_constant XS_constant);
    -
    -my $types = {map {($_, 1)} qw(IV)};
    -my @names = (qw(),
    - {name=>"PURPLE_DEBUG_ALL", type=>"IV", macro=>"1"},
    - {name=>"PURPLE_DEBUG_ERROR", type=>"IV", macro=>"1"},
    - {name=>"PURPLE_DEBUG_FATAL", type=>"IV", macro=>"1"},
    - {name=>"PURPLE_DEBUG_INFO", type=>"IV", macro=>"1"},
    - {name=>"PURPLE_DEBUG_MISC", type=>"IV", macro=>"1"},
    - {name=>"PURPLE_DEBUG_WARNING", type=>"IV", macro=>"1"});
    -
    -print constant_types(); # macro defs
    -foreach (C_constant ("Purple::DebugLevel", 'constant', 'IV', $types, undef, 3, @names) ) {
    - print $_, "\n"; # C constant subs
    -}
    -print "#### XS Section:\n";
    -print XS_constant ("Purple::DebugLevel", $types);
    -__END__
    - */
    -
    - switch (len) {
    - case 14:
    - if (memEQ(name, "PURPLE_DEBUG_ALL", 14)) {
    - *iv_return = PURPLE_DEBUG_ALL;
    - return PERL_constant_ISIV;
    - }
    - break;
    - case 15:
    - /* Names all of length 15. */
    - /* PURPLE_DEBUG_INFO PURPLE_DEBUG_MISC */
    - /* Offset 11 gives the best switch position. */
    - switch (name[11]) {
    - case 'I':
    - if (memEQ(name, "PURPLE_DEBUG_INFO", 15)) {
    - /* ^ */
    - *iv_return = PURPLE_DEBUG_INFO;
    - return PERL_constant_ISIV;
    - }
    - break;
    - case 'M':
    - if (memEQ(name, "PURPLE_DEBUG_MISC", 15)) {
    - /* ^ */
    - *iv_return = PURPLE_DEBUG_MISC;
    - return PERL_constant_ISIV;
    - }
    - break;
    - }
    - break;
    - case 16:
    - /* Names all of length 16. */
    - /* PURPLE_DEBUG_ERROR PURPLE_DEBUG_FATAL */
    - /* Offset 11 gives the best switch position. */
    - switch (name[11]) {
    - case 'E':
    - if (memEQ(name, "PURPLE_DEBUG_ERROR", 16)) {
    - /* ^ */
    - *iv_return = PURPLE_DEBUG_ERROR;
    - return PERL_constant_ISIV;
    - }
    - break;
    - case 'F':
    - if (memEQ(name, "PURPLE_DEBUG_FATAL", 16)) {
    - /* ^ */
    - *iv_return = PURPLE_DEBUG_FATAL;
    - return PERL_constant_ISIV;
    - }
    - break;
    - }
    - break;
    - case 18:
    - if (memEQ(name, "PURPLE_DEBUG_WARNING", 18)) {
    - *iv_return = PURPLE_DEBUG_WARNING;
    - return PERL_constant_ISIV;
    - }
    - break;
    - }
    - return PERL_constant_NOTFOUND;
    -}
    -
    --- a/libpurple/plugins/perl/common/fallback/const-xs.inc Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,88 +0,0 @@
    -void
    -constant(sv)
    - PREINIT:
    -#ifdef dXSTARG
    - dXSTARG; /* Faster if we have it. */
    -#else
    - dTARGET;
    -#endif
    - STRLEN len;
    - int type;
    - IV iv;
    - /* NV nv; Uncomment this if you need to return NVs */
    - /* const char *pv; Uncomment this if you need to return PVs */
    - INPUT:
    - SV * sv;
    - const char * s = SvPV(sv, len);
    - PPCODE:
    - /* Change this to constant(aTHX_ s, len, &iv, &nv);
    - if you need to return both NVs and IVs */
    - type = constant(aTHX_ s, len, &iv);
    - /* Return 1 or 2 items. First is error message, or undef if no error.
    - Second, if present, is found value */
    - switch (type) {
    - case PERL_constant_NOTFOUND:
    - sv = sv_2mortal(newSVpvf("%s is not a valid Purple::DebugLevel macro", s));
    - PUSHs(sv);
    - break;
    - case PERL_constant_NOTDEF:
    - sv = sv_2mortal(newSVpvf(
    - "Your vendor has not defined Purple::DebugLevel macro %s, used", s));
    - PUSHs(sv);
    - break;
    - case PERL_constant_ISIV:
    - EXTEND(SP, 1);
    - PUSHs(&PL_sv_undef);
    - PUSHi(iv);
    - break;
    - /* Uncomment this if you need to return NOs
    - case PERL_constant_ISNO:
    - EXTEND(SP, 1);
    - PUSHs(&PL_sv_undef);
    - PUSHs(&PL_sv_no);
    - break; */
    - /* Uncomment this if you need to return NVs
    - case PERL_constant_ISNV:
    - EXTEND(SP, 1);
    - PUSHs(&PL_sv_undef);
    - PUSHn(nv);
    - break; */
    - /* Uncomment this if you need to return PVs
    - case PERL_constant_ISPV:
    - EXTEND(SP, 1);
    - PUSHs(&PL_sv_undef);
    - PUSHp(pv, strlen(pv));
    - break; */
    - /* Uncomment this if you need to return PVNs
    - case PERL_constant_ISPVN:
    - EXTEND(SP, 1);
    - PUSHs(&PL_sv_undef);
    - PUSHp(pv, iv);
    - break; */
    - /* Uncomment this if you need to return SVs
    - case PERL_constant_ISSV:
    - EXTEND(SP, 1);
    - PUSHs(&PL_sv_undef);
    - PUSHs(sv);
    - break; */
    - /* Uncomment this if you need to return UNDEFs
    - case PERL_constant_ISUNDEF:
    - break; */
    - /* Uncomment this if you need to return UVs
    - case PERL_constant_ISUV:
    - EXTEND(SP, 1);
    - PUSHs(&PL_sv_undef);
    - PUSHu((UV)iv);
    - break; */
    - /* Uncomment this if you need to return YESs
    - case PERL_constant_ISYES:
    - EXTEND(SP, 1);
    - PUSHs(&PL_sv_undef);
    - PUSHs(&PL_sv_yes);
    - break; */
    - default:
    - sv = sv_2mortal(newSVpvf(
    - "Unexpected return type %d while processing Purple::DebugLevel macro %s, used",
    - type, s));
    - PUSHs(sv);
    - }
    --- a/libpurple/plugins/perl/common/module.h Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,310 +0,0 @@
    -/* Allow the Perl code to see deprecated functions, so we can continue to
    - * export them to Perl plugins. */
    -/* Re-enable this after 3.0.0 release.
    - #undef PURPLE_DISABLE_DEPRECATED
    - */
    -
    -typedef struct group *Purple__Group;
    -
    -#define group perl_group
    -
    -#include <glib.h>
    -#ifdef _WIN32
    -#undef pipe
    -#endif
    -
    -#define SILENT_NO_TAINT_SUPPORT 0
    -#define NO_TAINT_SUPPORT 0
    -
    -#include <EXTERN.h>
    -#include <perl.h>
    -#include <XSUB.h>
    -
    -#undef group
    -
    -#include "../perl-common.h"
    -
    -#include "accounts.h"
    -#include "accountopt.h"
    -#include "buddylist.h"
    -#include "buddyicon.h"
    -#include "certificate.h"
    -#include "cipher.h"
    -#include "ciphers/aescipher.h"
    -#include "ciphers/des3cipher.h"
    -#include "ciphers/descipher.h"
    -#include "ciphers/hmaccipher.h"
    -#include "ciphers/pbkdf2cipher.h"
    -#include "ciphers/rc4cipher.h"
    -#include "ciphers/md4hash.h"
    -#include "ciphers/md5hash.h"
    -#include "ciphers/sha1hash.h"
    -#include "ciphers/sha256hash.h"
    -#include "cmds.h"
    -#include "connection.h"
    -#include "conversations.h"
    -#include "core.h"
    -#include "debug.h"
    -#include "desktopitem.h"
    -#include "eventloop.h"
    -#include "xfer.h"
    -#ifdef PURPLE_GTKPERL
    -#include "gtkaccount.h"
    -#include "gtkblist.h"
    -#include "gtkconn.h"
    -#include "gtkconv.h"
    -#include "gtkutils.h"
    -#endif
    -#include "idle.h"
    -#include "network.h"
    -#include "notify.h"
    -#include "plugins.h"
    -#include "pluginpref.h"
    -#include "pounce.h"
    -#include "prefs.h"
    -#include "presence.h"
    -#include "protocol.h"
    -#include "proxy.h"
    -#include "request.h"
    -#include "roomlist.h"
    -#include "savedstatuses.h"
    -#include "server.h"
    -#include "signals.h"
    -#include "smiley.h"
    -#include "sound.h"
    -#include "sslconn.h"
    -#include "status.h"
    -#include "stringref.h"
    -/* Ewww. perl has it's own util.h which is in the include path :( */
    -#include "libpurple/util.h"
    -#include "whiteboard.h"
    -#include "xmlnode.h"
    -
    -#ifdef __COVERITY__
    -
    -/* avoid extra_comma false positives */
    -#undef SvPOK_only
    -#define SvPOK_only(sv) { \
    - SvFLAGS(sv) &= ~(SVf_OK | SVf_IVisUV | SVf_UTF8); \
    - SvFLAGS(sv) |= (SVf_POK | SVp_POK); \
    - }
    -
    -#endif /* __COVERITY__ */
    -
    -/* account.h */
    -typedef PurpleAccount * Purple__Account;
    -typedef PurpleAccountOption * Purple__Account__Option;
    -typedef PurpleAccountUserSplit * Purple__Account__UserSplit;
    -typedef PurpleAccountPrivacyType Purple__Account__PrivacyType;
    -
    -/* buddylist.h */
    -typedef PurpleBlistNode * Purple__BuddyList__Node;
    -typedef PurpleCountingNode * Purple__BuddyList__CountingNode;
    -typedef PurpleBuddyList * Purple__BuddyList;
    -typedef PurpleBuddy * Purple__BuddyList__Buddy;
    -typedef PurpleChat * Purple__BuddyList__Chat;
    -typedef PurpleContact * Purple__BuddyList__Contact;
    -typedef PurpleGroup * Purple__BuddyList__Group;
    -
    -/* buddyicon.h */
    -typedef PurpleBuddyIcon * Purple__Buddy__Icon;
    -
    -/* certificate.h */
    -typedef PurpleCertificate * Purple__Certificate;
    -typedef PurpleCertificatePool * Purple__Certificate__Pool;
    -typedef PurpleCertificateScheme * Purple__Certificate__Scheme;
    -typedef PurpleCertificateVerifier * Purple__Certificate__Verifier;
    -typedef PurpleCertificateVerificationRequest * Purple__Certificate__VerificationRequest;
    -typedef PurpleCertificateVerificationStatus Purple__Certificate__VerificationStatus;
    -
    -/* cipher.h */
    -typedef PurpleCipher * Purple__Cipher;
    -typedef PurpleHash * Purple__Hash;
    -typedef PurpleCipherBatchMode Purple__Cipher__BatchMode;
    -
    -/* cmds.h */
    -typedef PurpleCmdFlag Purple__Cmd__Flag;
    -typedef PurpleCmdId Purple__Cmd__Id;
    -typedef PurpleCmdPriority Purple__Cmd__Priority;
    -typedef PurpleCmdRet Purple__Cmd__Ret;
    -
    -/* connection.h */
    -typedef PurpleConnection * Purple__Connection;
    -typedef PurpleConnectionFlags Purple__ConnectionFlags;
    -typedef PurpleConnectionState Purple__ConnectionState;
    -
    -/* conversations.h */
    -typedef PurpleMessageFlags Purple__MessageFlags;
    -typedef PurpleConversation * Purple__Conversation;
    -typedef PurpleConversationUpdateType Purple__Conversation__UpdateType;
    -typedef PurpleIMConversation * Purple__IMConversation;
    -typedef PurpleIMTypingState Purple__IMTypingState;
    -typedef PurpleChatConversation * Purple__ChatConversation;
    -typedef PurpleChatUser * Purple__ChatUser;
    -typedef PurpleChatUserFlags Purple__ChatUser__Flags;
    -
    -/* core.h */
    -
    -typedef PurpleCore * Purple__Core;
    -
    -/* debug.h */
    -typedef PurpleDebugLevel Purple__DebugLevel;
    -
    -/* desktopitem.h */
    -typedef PurpleDesktopItem * Purple__DesktopItem;
    -typedef PurpleDesktopItemType Purple__DesktopItemType;
    -
    -/* eventloop.h */
    -typedef PurpleInputCondition * Purple__InputCondition;
    -
    -/* xfer.h */
    -typedef PurpleXfer * Purple__Xfer;
    -typedef PurpleXferType Purple__XferType;
    -typedef PurpleXferStatus Purple__XferStatus;
    -
    -
    -#ifdef PURPLE_GTKPERL
    -/* gtkblish.h */
    -typedef PurpleGtkBuddyList * Purple__GTK__BuddyList;
    -typedef PurpleStatusIconSize Purple__StatusIconSize;
    -
    -/* gtkutils.h */
    -typedef PurpleButtonOrientation Purple__ButtonOrientation;
    -typedef PurpleButtonStyle Purple__ButtonStyle;
    -#ifndef _WIN32
    -typedef PurpleBrowserPlace Purple__BrowserPlace;
    -#endif /* _WIN32 */
    -
    -/* gtkconv.h */
    -typedef PurpleUnseenState Purple__UnseenState;
    -typedef PurpleGtkConversation * Purple__GTK__Conversation;
    -typedef GdkPixbuf * Purple__GDK__Pixbuf;
    -typedef GtkWidget * Purple__GTK__Widget;
    -
    -/* gtkutils.h */
    -typedef GtkFileSelection * Purple__GTK__FileSelection;
    -typedef GtkSelectionData * Purple__GTK__SelectionData;
    -typedef GtkTextView * Purple__GTK__TextView;
    -
    -/* gtkconn.h */
    -#endif
    -
    -/* log.h */
    -typedef PurpleLog * Purple__Log;
    -typedef PurpleLogCommonLoggerData * Purple__LogCommonLoggerData;
    -typedef PurpleLogLogger * Purple__Log__Logger;
    -typedef PurpleLogReadFlags * Purple__Log__ReadFlags;
    -typedef PurpleLogSet * Purple__LogSet;
    -typedef PurpleLogType Purple__LogType;
    -
    -/* network.h */
    -typedef PurpleNetworkListenData * Purple__NetworkListenData;
    -typedef PurpleNetworkListenCallback Purple__NetworkListenCallback;
    -
    -/* notify.h */
    -typedef PurpleNotifyCloseCallback Purple__NotifyCloseCallback;
    -typedef PurpleNotifyMsgType Purple__NotifyMsgType;
    -typedef PurpleNotifySearchButtonType Purple__NotifySearchButtonType;
    -typedef PurpleNotifySearchResults * Purple__NotifySearchResults;
    -typedef PurpleNotifySearchColumn * Purple__NotifySearchColumn;
    -typedef PurpleNotifySearchButton * Purple__NotifySearchButton;
    -typedef PurpleNotifyType Purple__NotifyType;
    -typedef PurpleNotifyUserInfo * Purple__NotifyUserInfo;
    -typedef PurpleNotifyUserInfoEntry * Purple__NotifyUserInfoEntry;
    -
    -/* plugins.h */
    -typedef PurplePlugin * Purple__Plugin;
    -typedef PurplePluginAction * Purple__Plugin__Action;
    -typedef PurplePluginInfo * Purple__PluginInfo;
    -typedef PurplePluginLoaderInfo * Purple__PluginLoaderInfo;
    -typedef PurplePluginType Purple__PluginType;
    -typedef PurplePluginUiInfo * Purple__PluginUiInfo;
    -
    -/* pluginpref.h */
    -typedef PurplePluginPref * Purple__PluginPref;
    -typedef PurplePluginPrefFrame * Purple__PluginPref__Frame;
    -typedef PurplePluginPrefType Purple__PluginPrefType;
    -typedef PurpleStringFormatType Purple__String__Format__Type;
    -
    -/* pounce.h */
    -typedef PurplePounce * Purple__Pounce;
    -typedef PurplePounceEvent Purple__PounceEvent;
    -
    -/* prefs.h */
    -typedef PurplePrefType Purple__PrefType;
    -
    -/* presence.h */
    -typedef PurplePresence * Purple__Presence;
    -typedef PurpleAccountPresence * Purple__AccountPresence;
    -typedef PurpleBuddyPresence * Purple__BuddyPresence;
    -
    -/* proxy.h */
    -typedef PurpleProxyInfo * Purple__ProxyInfo;
    -typedef PurpleProxyType Purple__ProxyType;
    -
    -/* protocol.h */
    -typedef PurpleBuddyIconSpec * Purple__Buddy__Icon__Spec;
    -typedef PurpleIconScaleRules Purple__IconScaleRules;
    -typedef PurpleProtocol * Purple__PluginProtocolInfo;
    -typedef PurpleProtocolOptions Purple__ProtocolOptions;
    -
    -/* request.h */
    -typedef PurpleRequestField * Purple__Request__Field;
    -typedef PurpleRequestFields * Purple__Request__Fields;
    -typedef PurpleRequestFieldGroup * Purple__Request__Field__Group;
    -typedef PurpleRequestFieldType Purple__RequestFieldType;
    -typedef PurpleRequestType Purple__RequestType;
    -
    -/* roomlist.h */
    -typedef PurpleRoomlist * Purple__Roomlist;
    -typedef PurpleRoomlistField * Purple__Roomlist__Field;
    -typedef PurpleRoomlistFieldType Purple__RoomlistFieldType;
    -typedef PurpleRoomlistRoom * Purple__Roomlist__Room;
    -typedef PurpleRoomlistRoomType Purple__RoomlistRoomType;
    -
    -/* savedstatuses.h */
    -typedef PurpleSavedStatus * Purple__SavedStatus;
    -typedef PurpleSavedStatusSub * Purple__SavedStatus__Sub;
    -
    -/* smiley.h */
    -typedef PurpleSmiley * Purple__Smiley;
    -
    -/* sound.h */
    -typedef PurpleSoundEventID Purple__SoundEventID;
    -
    -/* sslconn.h */
    -typedef PurpleInputCondition * Purple__Input__Condition;
    -typedef PurpleSslConnection * Purple__Ssl__Connection;
    -typedef PurpleSslErrorType Purple__SslErrorType;
    -typedef PurpleSslOps * Purple__Ssl__Ops;
    -
    -/* status.h */
    -typedef PurpleStatus * Purple__Status;
    -typedef PurpleStatusAttribute * Purple__StatusAttr;
    -typedef PurpleStatusPrimitive Purple__StatusPrimitive;
    -typedef PurpleStatusType * Purple__StatusType;
    -
    -/* stringref.h */
    -typedef PurpleStringref * Purple__Stringref;
    -
    -/* util.h */
    -typedef PurpleInfoFieldFormatCallback Purple__Util__InfoFieldFormatCallback;
    -typedef PurpleMenuAction * Purple__Menu__Action;
    -
    -/* whiteboard.h */
    -typedef PurpleWhiteboard * Purple__Whiteboard;
    -
    -/* xmlnode.h */
    -typedef PurpleXmlNode * Purple__XMLNode;
    -typedef PurpleXmlNodeType XMLNode__Type;
    -
    -/* other */
    -typedef void * Purple__Handle;
    -
    -typedef gchar gchar_own;
    -
    -typedef struct _constiv {
    - const char *name;
    - IV iv;
    -} constiv;
    -
    --- a/libpurple/plugins/perl/common/typemap Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,210 +0,0 @@
    -TYPEMAP
    -guint T_IV
    -gint T_IV
    -gint64 T_IV
    -const gint * T_PTR
    -const guint * T_PTR
    -const guint8 * T_PTR
    -guint8 T_IV
    -guint8 * T_PTR
    -time_t T_IV
    -gboolean T_BOOL
    -gpointer T_PurpleObj
    -gconstpointer T_PTR
    -const gchar * T_PV
    -const char * T_PV
    -const char ** T_PTR
    -char ** T_PTR
    -gchar T_IV
    -gchar * T_PV
    -gchar_own * T_GCHAR_OWN
    -guchar T_IV
    -guchar * T_PV
    -guchar ** T_PTR
    -const guchar * T_PV
    -char * T_PV
    -int * T_PTR
    -long * T_PTR
    -size_t * T_PTR
    -GCallback T_PTR
    -va_list T_PTR
    -GString * T_PTR
    -GData * T_PTR
    -GData ** T_PTR
    -const unsigned char * T_PV
    -struct tm * T_PTR
    -const struct tm * T_PTR
    -gssize T_IV
    -const void * T_PTR
    -GValue * T_PTR
    -GType T_IV
    -
    -Purple::Account T_PurpleObj
    -Purple::Account::Option T_PurpleObj
    -Purple::Account::UserSplit T_PurpleObj
    -Purple::Account::PrivacyType T_IV
    -
    -Purple::Buddy::Icon T_PurpleObj
    -Purple::Buddy::Icon::Spec T_PurpleObj
    -Purple::BuddyList T_PurpleObj
    -Purple::BuddyList::Buddy T_PurpleObj
    -Purple::BuddyList::Chat T_PurpleObj
    -Purple::BuddyList::Contact T_PurpleObj
    -Purple::BuddyList::Group T_PurpleObj
    -Purple::BuddyList::Node T_PurpleObj
    -Purple::BuddyList::CountingNode T_PurpleObj
    -
    -Purple::Cipher T_PurpleObj
    -Purple::Hash T_PurpleObj
    -Purple::Cmd::Flag T_IV
    -Purple::Cmd::Id T_IV
    -Purple::Cmd::Priority T_IV
    -Purple::Cmd::Ret T_IV
    -Purple::Connection T_PurpleObj
    -Purple::Core T_PurpleObj
    -
    -Purple::Desktop::Item T_PurpleObj
    -Purple::DesktopItemType T_IV
    -
    -Purple::Handle T_PurpleObj
    -
    -Purple::IconScaleRules T_IV
    -
    -Purple::Log T_PurpleObj
    -Purple::LogType T_IV
    -Purple::Log::CommonLoggerData T_PurpleObj
    -Purple::Log::Logger T_PurpleObj
    -Purple::Log::ReadFlags T_PurpleObj
    -Purple::Log::Set T_PurpleObj
    -
    -Purple::Menu::Action T_PurpleObj
    -
    -Purple::NetworkListenData T_PurpleObj
    -Purple::NetworkListenCallback T_PTR
    -
    -Purple::NotifyCloseCallback T_PTR
    -Purple::NotifyMsgType T_IV
    -Purple::NotifySearchButtonType T_IV
    -Purple::NotifySearchResults T_PurpleObj
    -Purple::NotifySearchColumn T_PurpleObj
    -Purple::NotifySearchButton T_PurpleObj
    -Purple::NotifyType T_IV
    -Purple::NotifyUserInfo T_PurpleObj
    -Purple::NotifyUserInfoEntry T_PurpleObj
    -
    -Purple::Plugin T_PurpleObj
    -Purple::PluginType T_IV
    -Purple::PluginUiInfo T_PurpleObj
    -Purple::Plugin::Action T_PurpleObj
    -Purple::Plugin::Info T_PurpleObj
    -Purple::Plugin::Loader::Info T_PurpleObj
    -Purple::Plugin::Protocol::Info T_PurpleObj
    -Purple::PrefType T_IV
    -Purple::PluginPref T_PurpleObj
    -Purple::PluginPrefType T_IV
    -Purple::PluginPref::Frame T_PurpleObj
    -Purple::Pounce T_PurpleObj
    -Purple::PounceEvent T_IV
    -Purple::ProtocolOptions T_IV
    -Purple::ProxyInfo T_PurpleObj
    -Purple::ProxyType T_IV
    -
    -Purple::RequestFieldType T_IV
    -Purple::RequestType T_IV
    -Purple::Request::Field T_PurpleObj
    -Purple::Request::Fields T_PurpleObj
    -Purple::Request::Field::Group T_PurpleObj
    -
    -Purple::Roomlist T_PurpleObj
    -Purple::Roomlist::Room T_PurpleObj
    -Purple::Roomlist::Field T_PurpleObj
    -Purple::RoomlistFieldType T_IV
    -Purple::RoomlistRoomType T_IV
    -
    -Purple::SavedStatus T_PurpleObj
    -const Purple::SavedStatus T_PurpleObj
    -Purple::SavedStatus::Sub T_PurpleObj
    -const Purple::SavedStatus::Sub T_PurpleObj
    -Purple::SoundEventID T_IV
    -
    -Purple::Input::Condition T_PurpleObj
    -Purple::SslErrorType T_IV
    -Purple::Ssl::Connection T_PurpleObj
    -Purple::Ssl::Ops T_PurpleObj
    -
    -Purple::Presence T_PurpleObj
    -Purple::AccountPresence T_PurpleObj
    -Purple::BuddyPresence T_PurpleObj
    -Purple::Status T_PurpleObj
    -Purple::StatusAttr T_PurpleObj
    -Purple::StatusPrimitive T_IV
    -Purple::StatusType T_PurpleObj
    -const Purple::StatusType T_PurpleObj
    -
    -Purple::StoredImage T_PurpleObj
    -Purple::String::Format::Type T_IV
    -Purple::Stringref T_PurpleObj
    -Purple::Util::FetchUrlData T_PTR
    -Purple::Util::InfoFieldFormatCallback T_PTR
    -
    -Purple::Xfer T_PurpleObj
    -Purple::XferType T_IV
    -Purple::XferStatus T_IV
    -
    -Purple::XMLNode T_PurpleObj
    -XMLNode::Type T_IV
    -
    -/* enums */
    -
    -/* certificate.h */
    -Purple::Certificate T_PurpleObj
    -Purple::Certificate::Pool T_PurpleObj
    -Purple::Certificate::Scheme T_PurpleObj
    -Purple::Certificate::Verifier T_PurpleObj
    -Purple::Certificate::VerificationRequest T_PurpleObj
    -Purple::Certificate::VerificationStatus T_IV
    -
    -/* cipher.h */
    -Purple::Cipher::BatchMode T_IV
    -
    -/* blist.h */
    -
    -/* debug.h */
    -Purple::DebugLevel T_IV
    -
    -/* conversations.h */
    -Purple::Conversation T_PurpleObj
    -Purple::ChatConversation T_PurpleObj
    -Purple::ChatUser T_PurpleObj
    -Purple::IMConversation T_PurpleObj
    -Purple::ChatUser::Flags T_IV
    -Purple::Conversation::UpdateType T_IV
    -Purple::MessageFlags T_IV
    -Purple::IMTypingState T_IV
    -Purple::UnseenState T_IV
    -
    -/* connection.h */
    -Purple::ConnectionFlags T_IV
    -Purple::ConnectionState T_IV
    -
    -/* whiteboard.h */
    -Purple::Whiteboard T_PurpleObj
    -
    -INPUT
    -
    -T_PurpleObj
    - $var = purple_perl_ref_object($arg)
    -
    -OUTPUT
    -
    -T_PurpleObj
    - $arg = purple_perl_bless_object($var, \"$type\");
    -
    -T_GCHAR_OWN
    - /* used when we can directly own the returned string. */
    - /* we have to copy in the case when perl's malloc != gtk's malloc,
    - * so best copy all the time. */
    - sv_setpv ((SV*)$arg, $var);
    - SvUTF8_on ($arg);
    - g_free ($var);
    -
    --- a/libpurple/plugins/perl/libpurpleperl.c Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,18 +0,0 @@
    -#include <gmodule.h>
    -
    -#ifdef __SUNPRO_C
    -#pragma init (my_init)
    -void my_init(void);
    -
    -void my_init() {
    -#else
    -void __attribute__ ((constructor)) my_init(void);
    -
    -void __attribute__ ((constructor)) my_init() {
    -#endif
    -
    - /* Very evil hack...puts perl.so's symbols in the global table
    - * but does not create a circular dependancy because g_module_open
    - * will only open the library once. */
    - g_module_open("perl.so", 0);
    -}
    --- a/libpurple/plugins/perl/perl-common.c Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,620 +0,0 @@
    -#include "perl-common.h"
    -
    -#include "cipher.h"
    -#include "debug.h"
    -#include "savedstatuses.h"
    -
    -extern PerlInterpreter *my_perl;
    -
    -static GHashTable *object_stashes = NULL;
    -
    -void purple_perl_normalize_script_name(char *name)
    -{
    - char *c;
    -
    - c = strrchr(name, '.');
    -
    - if (c != NULL)
    - *c = '\0';
    -
    - for (c = name; *c != '\0'; c++) {
    - if (*c != '_' && !g_ascii_isalnum(*c))
    - *c = '_';
    - }
    -}
    -
    -static int
    -magic_free_object(pTHX_ SV *sv, MAGIC *mg)
    -{
    - sv_setiv(sv, 0);
    -
    - return 0;
    -}
    -
    -static MGVTBL vtbl_free_object =
    -{
    - 0, 0, 0, 0, magic_free_object, 0, 0
    -#if PERL_API_REVISION > 5 || (PERL_API_REVISION == 5 && PERL_API_VERSION >= 10)
    - , 0
    -#endif
    -};
    -
    -static SV *
    -create_sv_ptr(void *object)
    -{
    - SV *sv;
    -
    - PURPLE_STATIC_ASSERT(sizeof(IV) >= sizeof(void *),
    - sv_can_not_hold_a_pointer);
    -
    - sv = newSViv((IV)(gintptr)object);
    -
    - sv_magic(sv, NULL, '~', NULL, 0);
    -
    - SvMAGIC(sv)->mg_private = 0x1551; /* HF */
    - SvMAGIC(sv)->mg_virtual = &vtbl_free_object;
    -
    - return sv;
    -}
    -
    -SV *
    -newSVGChar(const char *str)
    -{
    - SV *sv;
    -
    - if (str == NULL)
    - return &PL_sv_undef;
    -
    - sv = newSVpv(str, 0);
    - SvUTF8_on(sv);
    -
    - return sv;
    -}
    -
    -SV *
    -purple_perl_bless_object(void *object, const char *stash_name)
    -{
    - HV *stash;
    - HV *hv;
    -
    - if (object == NULL)
    - return NULL;
    -
    - if (object_stashes == NULL) {
    - object_stashes = g_hash_table_new(g_direct_hash, g_direct_equal);
    - }
    -
    - stash = gv_stashpv(stash_name, 1);
    -
    - hv = newHV();
    - if (hv_store(hv, "_purple", 7, create_sv_ptr(object), 0) == NULL)
    - purple_debug_error("perl", "hv_store failed\n");
    -
    - return sv_bless(newRV_noinc((SV *)hv), stash);
    -}
    -
    -gboolean
    -purple_perl_is_ref_object(SV *o)
    -{
    - SV **sv;
    - HV *hv;
    -
    - hv = hvref(o);
    -
    - if (hv != NULL) {
    - sv = hv_fetch(hv, "_purple", 7, 0);
    -
    - if (sv != NULL)
    - return TRUE;
    - }
    -
    - return FALSE;
    -}
    -
    -void *
    -purple_perl_ref_object(SV *o)
    -{
    - SV **sv;
    - HV *hv;
    - void *p;
    -
    - if (o == NULL)
    - return NULL;
    -
    - hv = hvref(o);
    -
    - if (hv == NULL)
    - return NULL;
    -
    - sv = hv_fetch(hv, "_purple", 7, 0);
    -
    - if (sv == NULL)
    - croak("variable is damaged");
    -
    - p = GINT_TO_POINTER(SvIV(*sv));
    -
    - return p;
    -}
    -
    -/*
    - 2003/02/06: execute_perl modified by Mark Doliner <mark@kingant.net>
    - Pass parameters by pushing them onto the stack rather than
    - passing an array of strings. This way, perl scripts can
    - modify the parameters and we can get the changed values
    - and then shoot ourselves. I mean, uh, use them.
    -
    - 2001/06/14: execute_perl replaced by Martin Persson <mep@passagen.se>
    - previous use of perl_eval leaked memory, replaced with
    - a version that uses perl_call instead
    -
    - 30/11/2002: execute_perl modified by Eric Timme <timothy@voidnet.com>
    - args changed to char** so that we can have preparsed
    - arguments again, and many headaches ensued! This essentially
    - means we replaced one hacked method with a messier hacked
    - method out of perceived necessity. Formerly execute_perl
    - required a single char_ptr, and it would insert it into an
    - array of character pointers and NULL terminate the new array.
    - Now we have to pass in pre-terminated character pointer arrays
    - to accomodate functions that want to pass in multiple arguments.
    -
    - Previously arguments were preparsed because an argument list
    - was constructed in the form 'arg one','arg two' and was
    - executed via a call like &funcname(arglist) (see .59.x), so
    - the arglist was magically pre-parsed because of the method.
    - With Martin Persson's change to perl_call we now need to
    - use a null terminated list of character pointers for arguments
    - if we wish them to be parsed. Lacking a better way to allow
    - for both single arguments and many I created a NULL terminated
    - array in every function that called execute_perl and passed
    - that list into the function. In the former version a single
    - character pointer was passed in, and was placed into an array
    - of character pointers with two elements, with a NULL element
    - tacked onto the back, but this method no longer seemed prudent.
    -
    - Enhancements in the future might be to get rid of pre-declaring
    - the array sizes? I am not comfortable enough with this
    - subject to attempt it myself and hope it to stand the test
    - of time.
    -*/
    -int
    -execute_perl(const char *function, int argc, char **args)
    -{
    - int count = 0, i, ret_value = 1;
    - SV *sv_args[argc];
    - dSP;
    - PERL_SET_CONTEXT(my_perl);
    - /*
    - * Set up the perl environment, push arguments onto the
    - * perl stack, then call the given function
    - */
    - SPAGAIN;
    - ENTER;
    - SAVETMPS;
    - PUSHMARK(sp);
    -
    - for (i = 0; i < argc; i++) {
    - if (args[i]) {
    - sv_args[i] = sv_2mortal(newSVpv(args[i], 0));
    - XPUSHs(sv_args[i]);
    - } else
    - sv_args[i] = NULL;
    - }
    -
    - PUTBACK;
    - PERL_SET_CONTEXT(my_perl);
    - count = call_pv(function, G_EVAL | G_SCALAR);
    - SPAGAIN;
    -
    - /*
    - * Check for "die," make sure we have 1 argument, and set our
    - * return value.
    - */
    - if (SvTRUE(ERRSV)) {
    - purple_debug(PURPLE_DEBUG_ERROR, "perl",
    - "Perl function %s exited abnormally: %s\n",
    - function, SvPVutf8_nolen(ERRSV));
    - (void)POPs;
    - } else if (count != 1) {
    - /*
    - * This should NEVER happen. G_SCALAR ensures that we WILL
    - * have 1 parameter.
    - */
    - purple_debug(PURPLE_DEBUG_ERROR, "perl",
    - "Perl error from %s: expected 1 return value, "
    - "but got %d\n", function, count);
    - } else
    - ret_value = POPi;
    -
    - /* Check for changed arguments */
    - for (i = 0; i < argc; i++) {
    - if (args[i] && strcmp(args[i], SvPVX(sv_args[i]))) {
    - /*
    - * Shizzel. So the perl script changed one of the parameters,
    - * and we want this change to affect the original parameters.
    - * args[i] is just a temporary little list of pointers. We don't
    - * want to free args[i] here because the new parameter doesn't
    - * overwrite the data that args[i] points to. That is done by
    - * the function that called execute_perl. I'm not explaining this
    - * very well. See, it's aggregate... Oh, but if 2 perl scripts
    - * both modify the data, _that's_ a memleak. This is really kind
    - * of hackish. I should fix it. Look how long this comment is.
    - * Holy crap.
    - */
    - args[i] = g_strdup(SvPVutf8_nolen(sv_args[i]));
    - }
    - }
    -
    - PUTBACK;
    - FREETMPS;
    - LEAVE;
    -
    - return ret_value;
    -}
    -
    -#if 0
    -gboolean
    -purple_perl_value_from_sv(PurpleValue *value, SV *sv)
    -{
    - switch (purple_value_get_type(value))
    - {
    - case PURPLE_TYPE_CHAR:
    - if ((tmp = SvGChar(sv)) != NULL)
    - purple_value_set_char(value, tmp[0]);
    - else
    - return FALSE;
    - break;
    -
    - case PURPLE_TYPE_UCHAR:
    - if ((tmp = SvPV_nolen(sv)) != NULL)
    - purple_value_set_uchar(value, tmp[0]);
    - else
    - return FALSE;
    - break;
    -
    - case PURPLE_TYPE_BOOLEAN:
    - purple_value_set_boolean(value, SvTRUE(sv));
    - break;
    -
    - case PURPLE_TYPE_INT:
    - purple_value_set_int(value, SvIV(sv));
    - break;
    -
    - case PURPLE_TYPE_UINT:
    - purple_value_set_uint(value, SvIV(sv));
    - break;
    -
    - case PURPLE_TYPE_LONG:
    - purple_value_set_long(value, SvIV(sv));
    - break;
    -
    - case PURPLE_TYPE_ULONG:
    - purple_value_set_ulong(value, SvIV(sv));
    - break;
    -
    - case PURPLE_TYPE_INT64:
    - purple_value_set_int64(value, SvIV(sv));
    - break;
    -
    - case PURPLE_TYPE_UINT64:
    - purple_value_set_uint64(value, SvIV(sv));
    - break;
    -
    - case PURPLE_TYPE_STRING:
    - purple_value_set_string(value, SvGChar(sv));
    - break;
    -
    - case PURPLE_TYPE_POINTER:
    - purple_value_set_pointer(value, (void *)SvIV(sv));
    - break;
    -
    - case PURPLE_TYPE_BOXED:
    - if (!strcmp(purple_value_get_specific_type(value), "SV"))
    - purple_value_set_boxed(value, (sv == &PL_sv_undef ? NULL : sv));
    - else
    - purple_value_set_boxed(value, sv);
    - break;
    -
    - default:
    - return FALSE;
    - }
    -
    - return TRUE;
    -}
    -
    -SV *
    -purple_perl_sv_from_value(const PurpleValue *value, va_list list)
    -{
    - switch (purple_value_get_type(value))
    - {
    - case PURPLE_TYPE_BOOLEAN:
    - return newSViv(purple_value_get_boolean(value));
    - break;
    -
    - case PURPLE_TYPE_INT:
    - return newSViv(purple_value_get_int(value));
    - break;
    -
    - case PURPLE_TYPE_UINT:
    - return newSVuv(purple_value_get_uint(value));
    - break;
    -
    - case PURPLE_TYPE_LONG:
    - return newSViv(purple_value_get_long(value));
    - break;
    -
    - case PURPLE_TYPE_ULONG:
    - return newSVuv(purple_value_get_ulong(value));
    - break;
    -
    - case PURPLE_TYPE_INT64:
    - return newSViv(purple_value_get_int64(value));
    - break;
    -
    - case PURPLE_TYPE_UINT64:
    - return newSVuv(purple_value_get_int64(value));
    - break;
    -
    - case PURPLE_TYPE_STRING:
    - return newSVGChar(purple_value_get_string(value));
    - break;
    -
    - case PURPLE_TYPE_POINTER:
    - return newSViv((IV)purple_value_get_pointer(value));
    - break;
    -
    - case PURPLE_TYPE_BOXED:
    - if (!strcmp(purple_value_get_specific_type(value), "SV"))
    - {
    - SV *sv = (SV *)purple_perl_get_boxed(value);
    -
    - return (sv == NULL ? &PL_sv_undef : sv);
    - }
    -
    - /* Uh.. I dunno. Try this? */
    - return sv_2mortal(purple_perl_bless_object(
    - purple_perl_get_boxed(value),
    - purple_value_get_specific_type(value)));
    -
    - default:
    - return FALSE;
    - }
    -
    - return TRUE;
    -}
    -#endif
    -
    -void *
    -purple_perl_data_from_sv(GType type, SV *sv)
    -{
    - switch (type) {
    - case G_TYPE_BOOLEAN: return (void *)(gintptr)SvIV(sv);
    - case G_TYPE_INT: return (void *)(gintptr)SvIV(sv);
    - case G_TYPE_UINT: return (void *)(gintptr)SvUV(sv);
    - case G_TYPE_LONG: return (void *)(gintptr)SvIV(sv);
    - case G_TYPE_ULONG: return (void *)(gintptr)SvUV(sv);
    - case G_TYPE_INT64: return (void *)(gintptr)SvIV(sv);
    - case G_TYPE_UINT64: return (void *)(gintptr)SvUV(sv);
    - case G_TYPE_STRING: return g_strdup(SvPVutf8_nolen(sv));
    - case G_TYPE_POINTER: return (void *)(gintptr)SvIV(sv);
    - }
    -
    - return NULL;
    -}
    -
    -static SV *
    -purple_perl_sv_from_purple_type(GType type, void *arg)
    -{
    - const char *stash = "Purple"; /* ? */
    -
    - if (type == PURPLE_TYPE_ACCOUNT)
    - stash = "Purple::Account";
    - else if (type == PURPLE_TYPE_CONTACT)
    - stash = "Purple::BuddyList::Contact";
    - else if (type == PURPLE_TYPE_BUDDY)
    - stash = "Purple::BuddyList::Buddy";
    - else if (type == PURPLE_TYPE_GROUP)
    - stash = "Purple::BuddyList::Group";
    - else if (type == PURPLE_TYPE_CHAT)
    - stash = "Purple::BuddyList::Chat";
    - else if (type == PURPLE_TYPE_BUDDY_ICON)
    - stash = "Purple::Buddy::Icon";
    - else if (type == PURPLE_TYPE_CONNECTION)
    - stash = "Purple::Connection";
    - else if (type == PURPLE_TYPE_CONVERSATION)
    - stash = "Purple::Conversation";
    - else if (type == PURPLE_TYPE_PLUGIN)
    - stash = "Purple::Plugin";
    - else if (type == PURPLE_TYPE_BLIST_NODE)
    - stash = "Purple::BuddyList::Node";
    - else if (type == PURPLE_TYPE_CIPHER)
    - stash = "Purple::Cipher";
    - else if (type == PURPLE_TYPE_STATUS)
    - stash = "Purple::Status";
    - else if (type == PURPLE_TYPE_SAVEDSTATUS)
    - stash = "Purple::SavedStatus";
    - else if (type == PURPLE_TYPE_LOG)
    - stash = "Purple::Log";
    - else if (type == PURPLE_TYPE_XFER)
    - stash = "Purple::Xfer";
    - else if (type == PURPLE_TYPE_XMLNODE)
    - stash = "Purple::XMLNode";
    - else if (type == PURPLE_TYPE_NOTIFY_USER_INFO)
    - stash = "Purple::NotifyUserInfo";
    - else if (type == PURPLE_TYPE_CERTIFICATE_POOL)
    - stash = "Purple::Certificate::Pool";
    - else
    - stash = "Purple::Unknown";
    -
    - return sv_2mortal(purple_perl_bless_object(arg, stash));
    -}
    -
    -SV *
    -purple_perl_sv_from_vargs(GType type, va_list *args, void ***copy_arg)
    -{
    -#if 0
    - if (purple_value_is_outgoing(value)) {
    - switch (purple_value_get_type(value)) {
    - case PURPLE_TYPE_SUBTYPE:
    - if ((*copy_arg = va_arg(*args, void **)) == NULL)
    - return &PL_sv_undef;
    -
    - return purple_perl_sv_from_subtype(value, *(void **)*copy_arg);
    -
    - case PURPLE_TYPE_BOOLEAN:
    - if ((*copy_arg = (void *)va_arg(*args, gboolean *)) == NULL)
    - return &PL_sv_undef;
    -
    - return newSViv(*(gboolean *)*copy_arg);
    -
    - case PURPLE_TYPE_INT:
    - if ((*copy_arg = (void *)va_arg(*args, int *)) == NULL)
    - return &PL_sv_undef;
    -
    - return newSViv(*(int *)*copy_arg);
    -
    - case PURPLE_TYPE_UINT:
    - if ((*copy_arg = (void *)va_arg(*args, unsigned int *)) == NULL)
    - return &PL_sv_undef;
    -
    - return newSVuv(*(unsigned int *)*copy_arg);
    -
    - case PURPLE_TYPE_LONG:
    - if ((*copy_arg = (void *)va_arg(*args, long *)) == NULL)
    - return &PL_sv_undef;
    -
    - return newSViv(*(long *)*copy_arg);
    -
    - case PURPLE_TYPE_ULONG:
    - if ((*copy_arg = (void *)va_arg(*args,
    - unsigned long *)) == NULL)
    - return &PL_sv_undef;
    -
    - return newSVuv(*(unsigned long *)*copy_arg);
    -
    - case PURPLE_TYPE_INT64:
    - if ((*copy_arg = (void *)va_arg(*args, gint64 *)) == NULL)
    - return &PL_sv_undef;
    -
    - return newSViv(*(gint64 *)*copy_arg);
    -
    - case PURPLE_TYPE_UINT64:
    - if ((*copy_arg = (void *)va_arg(*args, guint64 *)) == NULL)
    - return &PL_sv_undef;
    -
    - return newSVuv(*(guint64 *)*copy_arg);
    -
    - case PURPLE_TYPE_STRING:
    - if ((*copy_arg = (void *)va_arg(*args, char **)) == NULL)
    - return &PL_sv_undef;
    -
    - return newSVGChar(*(char **)*copy_arg);
    -
    - case PURPLE_TYPE_POINTER:
    - if ((*copy_arg = va_arg(*args, void **)) == NULL)
    - return &PL_sv_undef;
    -
    - return newSViv((IV)*(void **)*copy_arg);
    -
    - case PURPLE_TYPE_BOXED:
    - /* Uh.. I dunno. Try this? */
    - if ((*copy_arg = va_arg(*args, void **)) == NULL)
    - return &PL_sv_undef;
    -
    - return sv_2mortal(purple_perl_bless_object(
    - *(void **)*copy_arg,
    - purple_value_get_specific_type(value)));
    -
    - default:
    - /* If this happens, things are going to get screwed up... */
    - return NULL;
    - }
    - } else {
    -#endif
    - switch (type) {
    - case G_TYPE_BOOLEAN:
    - *copy_arg = GINT_TO_POINTER( va_arg(*args, gboolean) );
    -
    - return newSViv((gboolean)GPOINTER_TO_INT(*copy_arg));
    -
    - case G_TYPE_INT:
    - *copy_arg = GINT_TO_POINTER( va_arg(*args, int) );
    -
    - return newSViv(GPOINTER_TO_INT(*copy_arg));
    -
    - case G_TYPE_UINT:
    - *copy_arg = GUINT_TO_POINTER(va_arg(*args, unsigned int));
    -
    - return newSVuv(GPOINTER_TO_UINT(*copy_arg));
    -
    - case G_TYPE_LONG:
    - *copy_arg = (void *)va_arg(*args, long);
    -
    - return newSViv((long)*copy_arg);
    -
    - case G_TYPE_ULONG:
    - *copy_arg = (void *)va_arg(*args, unsigned long);
    -
    - return newSVuv((unsigned long)*copy_arg);
    -
    - case G_TYPE_INT64:
    - /* XXX This yells and complains. */
    -#if 0
    - *copy_arg = (void *)va_arg(*args, gint64);
    -
    - return newSViv((gint64)*copy_arg);
    -#endif
    - break;
    -
    - case G_TYPE_UINT64:
    - /* XXX This also yells and complains. */
    -#if 0
    - *copy_arg = (void *)va_arg(*args, guint64);
    -
    - return newSVuv((guint64)*copy_arg);
    -#endif
    - break;
    -
    - case G_TYPE_STRING:
    - if ((*copy_arg = (void *)va_arg(*args, char *)) == NULL)
    - return &PL_sv_undef;
    -
    - return newSVGChar((char *)*copy_arg);
    -
    - case G_TYPE_POINTER:
    - if ((*copy_arg = (void *)va_arg(*args, void *)) == NULL)
    - return &PL_sv_undef;
    -
    - return newSViv((IV)(gintptr)*copy_arg);
    -
    - default:
    - if ((*copy_arg = va_arg(*args, void *)) == NULL)
    - return &PL_sv_undef;
    -
    - return purple_perl_sv_from_purple_type(type, *copy_arg);
    - }
    -
    - return NULL;
    -}
    -
    -SV *purple_perl_sv_from_fun(PurplePlugin *plugin, SV *callback)
    -{
    - SV *sv = NULL;
    -
    - if (SvTYPE(callback) == SVt_RV) {
    - SV *cbsv = SvRV(callback);
    -
    - if (SvTYPE(cbsv) == SVt_PVCV) {
    - sv = newSVsv(callback);
    - }
    - } else if (SvTYPE(callback) == SVt_PV) {
    - PurplePerlScript *gps;
    -
    - gps = (PurplePerlScript *)PURPLE_PLUGIN_LOADER_INFO(plugin);
    - sv = newSVpvf("%s::%s", gps->package, SvPV_nolen(callback));
    - } else {
    - purple_debug_warning("perl", "Callback not a valid type, only strings and coderefs allowed.\n");
    - }
    -
    - return sv;
    -}
    -
    --- a/libpurple/plugins/perl/perl-common.h Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,82 +0,0 @@
    -#ifndef _PURPLE_PERL_COMMON_H_
    -#define _PURPLE_PERL_COMMON_H_
    -
    -#include <glib.h>
    -#ifdef _WIN32
    -#undef pipe
    -#endif
    -
    -#define SILENT_NO_TAINT_SUPPORT 0
    -#define NO_TAINT_SUPPORT 0
    -
    -#include <EXTERN.h>
    -#include <perl.h>
    -#include <XSUB.h>
    -
    -/* XXX: perl defines it's own _ but I think it's safe to undef it */
    -#undef _
    -/* Dirty hack to prevent the win32 libc compat stuff from interfering with the Perl internal stuff */
    -#ifdef _WIN32
    -#define _WIN32DEP_H_
    -#endif
    -#include "internal.h"
    -#ifdef _WIN32
    -#undef _WIN32DEP_H_
    -#endif
    -#include "plugins.h"
    -
    -#define is_hvref(o) \
    - ((o) && SvROK(o) && SvRV(o) && (SvTYPE(SvRV(o)) == SVt_PVHV))
    -
    -#define hvref(o) \
    - (is_hvref(o) ? (HV *)SvRV(o) : NULL);
    -
    -#define PURPLE_PERL_BOOT_PROTO(x) \
    - void boot_Purple__##x(pTHX_ CV *cv);
    -
    -#define PURPLE_PERL_BOOT(x) \
    - purple_perl_callXS(boot_Purple__##x, cv, mark)
    -
    -#ifdef HAVE_NEW_SVUPGRADE
    -# define SvUPGRADE_common(a, b) SvUPGRADE(a, b)
    -#else
    -# define SvUPGRADE_common(a, b) if (!SvUPGRADE(a, b)) { croak("Cannot upgrade variable"); }
    -#endif
    -
    -typedef struct _PurplePerlInfoStrings PurplePerlInfoStrings;
    -
    -typedef struct
    -{
    - PurplePlugin *plugin;
    - PurplePerlInfoStrings *info_strings;
    - char *package;
    - char *load_sub;
    - char *unload_sub;
    - char *prefs_sub;
    -#ifdef PURPLE_GTKPERL
    - char *gtk_prefs_sub;
    -#endif
    - char *plugin_action_sub;
    -} PurplePerlScript;
    -
    -void purple_perl_normalize_script_name(char *name);
    -
    -SV *newSVGChar(const char *str);
    -
    -void purple_perl_callXS(void (*subaddr)(pTHX_ CV *cv), CV *cv, SV **mark);
    -void purple_perl_bless_plain(const char *stash, void *object);
    -SV *purple_perl_bless_object(void *object, const char *stash);
    -gboolean purple_perl_is_ref_object(SV *o);
    -void *purple_perl_ref_object(SV *o);
    -
    -int execute_perl(const char *function, int argc, char **args);
    -
    -#if 0
    -gboolean purple_perl_value_from_sv(PurpleValue *value, SV *sv);
    -SV *purple_perl_sv_from_value(const PurpleValue *value);
    -#endif
    -
    -void *purple_perl_data_from_sv(GType type, SV *sv);
    -SV *purple_perl_sv_from_vargs(GType type, va_list *args, void ***copy_arg);
    -SV *purple_perl_sv_from_fun(PurplePlugin *plugin, SV *callback);
    -#endif /* _PURPLE_PERL_COMMON_H_ */
    --- a/libpurple/plugins/perl/perl-handlers.c Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,967 +0,0 @@
    -#include "perl-common.h"
    -#include "perl-handlers.h"
    -
    -#include "debug.h"
    -#include "signals.h"
    -
    -typedef struct
    -{
    - SV *callback;
    - SV *data;
    -} PurplePerlAccountPasswordHandler;
    -
    -extern PerlInterpreter *my_perl;
    -static GSList *cmd_handlers = NULL;
    -static GSList *signal_handlers = NULL;
    -static GSList *timeout_handlers = NULL;
    -static GSList *pref_handlers = NULL;
    -
    -/* perl < 5.8.0 doesn't define PERL_MAGIC_ext */
    -#ifndef PERL_MAGIC_ext
    -#define PERL_MAGIC_ext '~'
    -#endif
    -
    -void
    -purple_perl_plugin_action_cb(PurplePluginAction *action)
    -{
    - SV **callback;
    - HV *hv = NULL;
    - gchar *hvname;
    - PurplePlugin *plugin;
    - PurplePerlScript *gps;
    - dSP;
    -
    - plugin = action->plugin;
    - gps = (PurplePerlScript *)plugin->info->extra_info;
    - hvname = g_strdup_printf("%s::plugin_actions", gps->package);
    - hv = get_hv(hvname, FALSE);
    - g_free(hvname);
    -
    - if (hv == NULL)
    - croak("No plugin_actions hash found in \"%s\" plugin.", purple_plugin_get_name(plugin));
    -
    - ENTER;
    - SAVETMPS;
    -
    - callback = hv_fetch(hv, action->label, strlen(action->label), 0);
    -
    - if (callback == NULL || *callback == NULL)
    - croak("No plugin_action function named \"%s\" in \"%s\" plugin.", action->label, purple_plugin_get_name(plugin));
    -
    - PUSHMARK(sp);
    - XPUSHs(purple_perl_bless_object(gps->plugin, "Purple::Plugin"));
    - PUTBACK;
    -
    - call_sv(*callback, G_EVAL | G_VOID | G_DISCARD);
    -
    - SPAGAIN;
    -
    - if (SvTRUE(ERRSV)) {
    - purple_debug_error("perl",
    - "Perl plugin action function exited abnormally: %s\n",
    - SvPVutf8_nolen(ERRSV));
    - }
    -
    - PUTBACK;
    - FREETMPS;
    - LEAVE;
    -}
    -
    -GList *
    -purple_perl_plugin_actions(PurplePlugin *plugin, gpointer context)
    -{
    - GList *l = NULL;
    - PurplePerlScript *gps;
    - int i = 0, count = 0;
    - dSP;
    -
    - gps = plugin->info->extra_info;
    -
    - ENTER;
    - SAVETMPS;
    -
    - PUSHMARK(SP);
    - XPUSHs(sv_2mortal(purple_perl_bless_object(plugin, "Purple::Plugin")));
    - /* XXX This *will* cease working correctly if context gets changed to
    - * ever be able to hold anything other than a PurpleConnection */
    - if (context != NULL)
    - XPUSHs(sv_2mortal(purple_perl_bless_object(context,
    - "Purple::Connection")));
    - else
    - XPUSHs(&PL_sv_undef);
    - PUTBACK;
    -
    - count = call_pv(gps->plugin_action_sub, G_EVAL | G_ARRAY);
    -
    - SPAGAIN;
    -
    - if (SvTRUE(ERRSV)) {
    - purple_debug_error("perl",
    - "Perl plugin actions lookup exited abnormally: %s\n",
    - SvPVutf8_nolen(ERRSV));
    - }
    -
    - if (count == 0)
    - croak("The plugin_actions sub didn't return anything.\n");
    -
    - for (i = 0; i < count; i++) {
    - SV *sv;
    - PurplePluginAction *act;
    -
    - sv = POPs;
    - act = purple_plugin_action_new(SvPVutf8_nolen(sv), purple_perl_plugin_action_cb);
    - l = g_list_prepend(l, act);
    - }
    -
    - PUTBACK;
    - FREETMPS;
    - LEAVE;
    -
    - return l;
    -}
    -
    -#ifdef PURPLE_GTKPERL
    -GtkWidget *
    -purple_perl_gtk_get_plugin_frame(PurplePlugin *plugin)
    -{
    - SV * sv;
    - int count;
    - MAGIC *mg;
    - GtkWidget *ret;
    - PurplePerlScript *gps;
    - dSP;
    -
    - gps = plugin->info->extra_info;
    -
    - ENTER;
    - SAVETMPS;
    -
    - count = call_pv(gps->gtk_prefs_sub, G_EVAL | G_SCALAR | G_NOARGS);
    - if (count != 1)
    - croak("call_pv: Did not return the correct number of values.\n");
    -
    - /* the frame was created in a perl sub and is returned */
    - SPAGAIN;
    -
    - if (SvTRUE(ERRSV)) {
    - purple_debug_error("perl",
    - "Perl gtk plugin frame init exited abnormally: %s\n",
    - SvPVutf8_nolen(ERRSV));
    - }
    -
    - /* We have a Gtk2::Frame on top of the stack */
    - sv = POPs;
    -
    - /* The magic field hides the pointer to the actual GtkWidget */
    - mg = mg_find(SvRV(sv), PERL_MAGIC_ext);
    - ret = (GtkWidget *)mg->mg_ptr;
    -
    - PUTBACK;
    - FREETMPS;
    - LEAVE;
    -
    - return ret;
    -}
    -#endif
    -
    -PurplePluginPrefFrame *
    -purple_perl_get_plugin_frame(PurplePlugin *plugin)
    -{
    - /* Sets up the Perl Stack for our call back into the script to run the
    - * plugin_pref... sub */
    - int count;
    - PurplePerlScript *gps;
    - PurplePluginPrefFrame *ret_frame;
    - dSP;
    -
    - gps = (PurplePerlScript *)plugin->info->extra_info;
    -
    - ENTER;
    - SAVETMPS;
    - /* Some perl magic to run perl_plugin_pref_frame_SV perl sub and
    - * return the frame */
    - PUSHMARK(SP);
    - PUTBACK;
    -
    - count = call_pv(gps->prefs_sub, G_EVAL | G_SCALAR | G_NOARGS);
    -
    - SPAGAIN;
    -
    - if (SvTRUE(ERRSV)) {
    - purple_debug_error("perl",
    - "Perl plugin prefs frame init exited abnormally: %s\n",
    - SvPVutf8_nolen(ERRSV));
    - }
    -
    - if (count != 1)
    - croak("call_pv: Did not return the correct number of values.\n");
    - /* the frame was created in a perl sub and is returned */
    - ret_frame = (PurplePluginPrefFrame *)purple_perl_ref_object(POPs);
    -
    - /* Tidy up the Perl stack */
    - PUTBACK;
    - FREETMPS;
    - LEAVE;
    -
    - return ret_frame;
    -}
    -
    -static gboolean
    -destroy_timeout_handler(PurplePerlTimeoutHandler *handler)
    -{
    - gboolean ret = FALSE;
    -
    - timeout_handlers = g_slist_remove(timeout_handlers, handler);
    -
    - if (handler->iotag > 0)
    - ret = purple_timeout_remove(handler->iotag);
    -
    - if (handler->callback != NULL)
    - SvREFCNT_dec(handler->callback);
    -
    - if (handler->data != NULL)
    - SvREFCNT_dec(handler->data);
    -
    - g_free(handler);
    -
    - return ret;
    -}
    -
    -static void
    -destroy_signal_handler(PurplePerlSignalHandler *handler)
    -{
    - signal_handlers = g_slist_remove(signal_handlers, handler);
    -
    - if (handler->callback != NULL)
    - SvREFCNT_dec(handler->callback);
    -
    - if (handler->data != NULL)
    - SvREFCNT_dec(handler->data);
    -
    - g_free(handler->signal);
    - g_free(handler);
    -}
    -
    -static gboolean
    -perl_timeout_cb(gpointer data)
    -{
    - PurplePerlTimeoutHandler *handler = data;
    - gboolean ret = FALSE;
    -
    - dSP;
    - ENTER;
    - SAVETMPS;
    - PUSHMARK(sp);
    - XPUSHs((SV *)handler->data);
    - PUTBACK;
    - call_sv(handler->callback, G_EVAL | G_SCALAR);
    - SPAGAIN;
    -
    - if (SvTRUE(ERRSV)) {
    - purple_debug_error("perl",
    - "Perl timeout function exited abnormally: %s\n",
    - SvPVutf8_nolen(ERRSV));
    - }
    -
    - ret = POPi;
    -
    - PUTBACK;
    - FREETMPS;
    - LEAVE;
    -
    - if (ret == FALSE)
    - destroy_timeout_handler(handler);
    -
    - return ret;
    -}
    -
    -typedef void *DATATYPE;
    -
    -static void *
    -perl_signal_cb(va_list args, void *data)
    -{
    - PurplePerlSignalHandler *handler = data;
    - void *ret_val = NULL;
    - int i;
    - int count;
    - int value_count;
    - GType ret_type, *value_types;
    - SV **sv_args;
    - DATATYPE **copy_args;
    -
    - dSP;
    - PERL_SET_CONTEXT(my_perl);
    - SPAGAIN;
    - ENTER;
    - SAVETMPS;
    - PUSHMARK(sp);
    -
    - purple_signal_get_types(handler->instance, handler->signal,
    - &ret_type, &value_count, &value_types);
    -
    - sv_args = g_new(SV *, value_count);
    - copy_args = g_new(void **, value_count);
    -
    - for (i = 0; i < value_count; i++) {
    - sv_args[i] = purple_perl_sv_from_vargs(value_types[i],
    -#ifdef VA_COPY_AS_ARRAY
    - (va_list*)args,
    -#else
    - (va_list*)&args,
    -#endif
    - &copy_args[i]);
    -
    - XPUSHs(sv_args[i]);
    - }
    -
    - XPUSHs((SV *)handler->data);
    -
    - PUTBACK;
    -
    - if (ret_type != G_TYPE_NONE) {
    - count = call_sv(handler->callback, G_EVAL | G_SCALAR);
    -
    - SPAGAIN;
    -
    - if (count != 1)
    - croak("Uh oh! call_sv returned %i != 1", i);
    - else
    - ret_val = purple_perl_data_from_sv(ret_type, POPs);
    - } else {
    - call_sv(handler->callback, G_EVAL | G_SCALAR);
    -
    - SPAGAIN;
    - }
    -
    - if (SvTRUE(ERRSV)) {
    - purple_debug_error("perl",
    - "Perl function exited abnormally: %s\n",
    - SvPVutf8_nolen(ERRSV));
    - }
    -
    -#if 0
    - /* See if any parameters changed. */
    - for (i = 0; i < value_count; i++) {
    - if (purple_value_is_outgoing(values[i])) {
    - switch (purple_value_get_type(values[i])) {
    - case PURPLE_TYPE_BOOLEAN:
    - *((gboolean *)copy_args[i]) = SvIV(sv_args[i]);
    - break;
    -
    - case PURPLE_TYPE_INT:
    - *((int *)copy_args[i]) = SvIV(sv_args[i]);
    - break;
    -
    - case PURPLE_TYPE_UINT:
    - *((unsigned int *)copy_args[i]) = SvUV(sv_args[i]);
    - break;
    -
    - case PURPLE_TYPE_LONG:
    - *((long *)copy_args[i]) = SvIV(sv_args[i]);
    - break;
    -
    - case PURPLE_TYPE_ULONG:
    - *((unsigned long *)copy_args[i]) = SvUV(sv_args[i]);
    - break;
    -
    - case PURPLE_TYPE_INT64:
    - *((gint64 *)copy_args[i]) = SvIV(sv_args[i]);
    - break;
    -
    - case PURPLE_TYPE_UINT64:
    - *((guint64 *)copy_args[i]) = SvUV(sv_args[i]);
    - break;
    -
    - case PURPLE_TYPE_STRING:
    - if (!*((char **)copy_args[i]) || !SvPVX(sv_args[i]) ||
    - strcmp(*((char **)copy_args[i]), SvPVX(sv_args[i]))) {
    - g_free(*((char **)copy_args[i]));
    - *((char **)copy_args[i]) =
    - g_strdup(SvPVutf8_nolen(sv_args[i]));
    - }
    - /* Clean up sv_args[i] - we're done with it */
    - sv_2mortal(sv_args[i]);
    - break;
    -
    - case PURPLE_TYPE_POINTER:
    - case PURPLE_TYPE_BOXED:
    - *((void **)copy_args[i]) = (void *)SvIV(sv_args[i]);
    - break;
    - case PURPLE_TYPE_SUBTYPE:
    - *((void **)copy_args[i]) = purple_perl_ref_object(sv_args[i]);
    - break;
    -
    - default:
    - break;
    - }
    -
    -
    -#if 0
    - *((void **)copy_args[i]) = purple_perl_data_from_sv(values[i],
    - sv_args[i]);
    -#endif
    - }
    - }
    -#endif
    -
    - PUTBACK;
    - FREETMPS;
    - LEAVE;
    -
    - g_free(sv_args);
    - g_free(copy_args);
    -
    - purple_debug_misc("perl", "ret_val = %p\n", ret_val);
    -
    - return ret_val;
    -}
    -
    -static PurplePerlSignalHandler *
    -find_signal_handler(PurplePlugin *plugin, void *instance, const char *signal)
    -{
    - PurplePerlSignalHandler *handler;
    - GSList *l;
    -
    - for (l = signal_handlers; l != NULL; l = l->next) {
    - handler = l->data;
    -
    - if (handler->plugin == plugin &&
    - handler->instance == instance &&
    - !strcmp(handler->signal, signal)) {
    - return handler;
    - }
    - }
    -
    - return NULL;
    -}
    -
    -guint
    -purple_perl_timeout_add(PurplePlugin *plugin, int seconds, SV *callback, SV *data)
    -{
    - PurplePerlTimeoutHandler *handler;
    -
    - if (plugin == NULL) {
    - croak("Invalid handle in adding perl timeout handler.\n");
    - return 0;
    - }
    -
    - handler = g_new0(PurplePerlTimeoutHandler, 1);
    -
    - handler->plugin = plugin;
    - handler->callback = (callback != NULL && callback != &PL_sv_undef
    - ? newSVsv(callback) : NULL);
    - handler->data = (data != NULL && data != &PL_sv_undef
    - ? newSVsv(data) : NULL);
    -
    - timeout_handlers = g_slist_append(timeout_handlers, handler);
    -
    - handler->iotag = purple_timeout_add_seconds(seconds, perl_timeout_cb, handler);
    -
    - return handler->iotag;
    -}
    -
    -gboolean
    -purple_perl_timeout_remove(guint handle)
    -{
    - PurplePerlTimeoutHandler *handler;
    - GSList *l, *l_next;
    -
    - for (l = timeout_handlers; l != NULL; l = l_next) {
    - handler = l->data;
    - l_next = l->next;
    -
    - if (handler->iotag == handle)
    - return destroy_timeout_handler(handler);
    - }
    -
    - purple_debug_info("perl", "No timeout handler found with handle %u.\n",
    - handle);
    - return FALSE;
    -}
    -
    -void
    -purple_perl_timeout_clear_for_plugin(PurplePlugin *plugin)
    -{
    - PurplePerlTimeoutHandler *handler;
    - GSList *l, *l_next;
    -
    - for (l = timeout_handlers; l != NULL; l = l_next) {
    - handler = l->data;
    - l_next = l->next;
    -
    - if (handler->plugin == plugin)
    - destroy_timeout_handler(handler);
    - }
    -}
    -
    -void
    -purple_perl_timeout_clear(void)
    -{
    - while (timeout_handlers != NULL)
    - destroy_timeout_handler(timeout_handlers->data);
    -}
    -
    -void
    -purple_perl_signal_connect(PurplePlugin *plugin, void *instance,
    - const char *signal, SV *callback, SV *data,
    - int priority)
    -{
    - PurplePerlSignalHandler *handler;
    -
    - handler = g_new0(PurplePerlSignalHandler, 1);
    - handler->plugin = plugin;
    - handler->instance = instance;
    - handler->signal = g_strdup(signal);
    - handler->callback = (callback != NULL &&
    - callback != &PL_sv_undef ? newSVsv(callback)
    - : NULL);
    - handler->data = (data != NULL &&
    - data != &PL_sv_undef ? newSVsv(data) : NULL);
    -
    - signal_handlers = g_slist_append(signal_handlers, handler);
    -
    - purple_signal_connect_priority_vargs(instance, signal, plugin,
    - PURPLE_CALLBACK(perl_signal_cb),
    - handler, priority);
    -}
    -
    -void
    -purple_perl_signal_disconnect(PurplePlugin *plugin, void *instance,
    - const char *signal)
    -{
    - PurplePerlSignalHandler *handler;
    -
    - handler = find_signal_handler(plugin, instance, signal);
    -
    - if (handler == NULL) {
    - croak("Invalid signal handler information in "
    - "disconnecting a perl signal handler.\n");
    - return;
    - }
    -
    - destroy_signal_handler(handler);
    -}
    -
    -void
    -purple_perl_signal_clear_for_plugin(PurplePlugin *plugin)
    -{
    - PurplePerlSignalHandler *handler;
    - GSList *l, *l_next;
    -
    - for (l = signal_handlers; l != NULL; l = l_next) {
    - l_next = l->next;
    - handler = l->data;
    -
    - if (handler->plugin == plugin)
    - destroy_signal_handler(handler);
    - }
    -}
    -
    -void
    -purple_perl_signal_clear(void)
    -{
    - while (signal_handlers != NULL)
    - destroy_signal_handler(signal_handlers->data);
    -}
    -
    -static PurpleCmdRet
    -perl_cmd_cb(PurpleConversation *conv, const gchar *command,
    - gchar **args, gchar **error, void *data)
    -{
    - int i = 0, count, ret_value = PURPLE_CMD_RET_OK;
    - SV *cmdSV, *tmpSV, *convSV;
    - PurplePerlCmdHandler *handler = data;
    -
    - dSP;
    - ENTER;
    - SAVETMPS;
    - PUSHMARK(SP);
    -
    - /* Push the conversation onto the perl stack */
    - convSV = sv_2mortal(purple_perl_bless_object(conv, "Purple::Conversation"));
    - XPUSHs(convSV);
    -
    - /* Push the command string onto the perl stack */
    - cmdSV = newSVpv(command, 0);
    - cmdSV = sv_2mortal(cmdSV);
    - XPUSHs(cmdSV);
    -
    - /* Push the data onto the perl stack */
    - XPUSHs((SV *)handler->data);
    -
    - /* Push any arguments we may have */
    - for (i = 0; args[i] != NULL; i++) {
    - /* XXX The mortality of these created SV's should prevent
    - * memory issues, if I read/understood everything correctly...
    - */
    - tmpSV = newSVpv(args[i], 0);
    - tmpSV = sv_2mortal(tmpSV);
    - XPUSHs(tmpSV);
    - }
    -
    - PUTBACK;
    - count = call_sv(handler->callback, G_EVAL | G_SCALAR);
    -
    - if (count != 1)
    - croak("call_sv: Did not return the correct number of values.\n");
    -
    - if (SvTRUE(ERRSV)) {
    - purple_debug_error("perl",
    - "Perl plugin command function exited abnormally: %s\n",
    - SvPVutf8_nolen(ERRSV));
    - }
    -
    - SPAGAIN;
    -
    - ret_value = POPi;
    -
    - PUTBACK;
    - FREETMPS;
    - LEAVE;
    -
    - return ret_value;
    -}
    -
    -PurpleCmdId
    -purple_perl_cmd_register(PurplePlugin *plugin, const gchar *command,
    - const gchar *args, PurpleCmdPriority priority,
    - PurpleCmdFlag flag, const gchar *protocol_id, SV *callback,
    - const gchar *helpstr, SV *data)
    -{
    - PurplePerlCmdHandler *handler;
    -
    - handler = g_new0(PurplePerlCmdHandler, 1);
    - handler->plugin = plugin;
    - handler->cmd = g_strdup(command);
    - handler->protocol_id = g_strdup(protocol_id);
    -
    - if (callback != NULL && callback != &PL_sv_undef)
    - handler->callback = newSVsv(callback);
    - else
    - handler->callback = NULL;
    -
    - if (data != NULL && data != &PL_sv_undef)
    - handler->data = newSVsv(data);
    - else
    - handler->data = NULL;
    -
    - cmd_handlers = g_slist_append(cmd_handlers, handler);
    -
    - handler->id = purple_cmd_register(command, args, priority, flag, protocol_id,
    - PURPLE_CMD_FUNC(perl_cmd_cb), helpstr,
    - handler);
    -
    - return handler->id;
    -}
    -
    -static void
    -destroy_cmd_handler(PurplePerlCmdHandler *handler)
    -{
    - purple_cmd_unregister(handler->id);
    - cmd_handlers = g_slist_remove(cmd_handlers, handler);
    -
    - if (handler->callback != NULL)
    - SvREFCNT_dec(handler->callback);
    -
    - if (handler->data != NULL)
    - SvREFCNT_dec(handler->data);
    -
    - g_free(handler->cmd);
    - g_free(handler->protocol_id);
    - g_free(handler);
    -}
    -
    -void
    -purple_perl_cmd_clear_for_plugin(PurplePlugin *plugin)
    -{
    - PurplePerlCmdHandler *handler;
    - GSList *l, *l_next;
    -
    - for (l = cmd_handlers; l != NULL; l = l_next) {
    - handler = l->data;
    - l_next = l->next;
    -
    - if (handler->plugin == plugin)
    - destroy_cmd_handler(handler);
    - }
    -}
    -
    -static PurplePerlCmdHandler *
    -find_cmd_handler(PurpleCmdId id)
    -{
    - PurplePerlCmdHandler *handler;
    - GSList *l;
    -
    - for (l = cmd_handlers; l != NULL; l = l->next) {
    - handler = (PurplePerlCmdHandler *)l->data;
    -
    - if (handler->id == id)
    - return handler;
    - }
    -
    - return NULL;
    -}
    -
    -void
    -purple_perl_cmd_unregister(PurpleCmdId id)
    -{
    - PurplePerlCmdHandler *handler;
    -
    - handler = find_cmd_handler(id);
    -
    - if (handler == NULL) {
    - croak("Invalid command id in removing a perl command handler.\n");
    - return;
    - }
    -
    - destroy_cmd_handler(handler);
    -}
    -
    -static void
    -perl_pref_cb(const char *name, PurplePrefType type, gconstpointer value,
    - gpointer data)
    -{
    - PurplePerlPrefsHandler *handler = data;
    -
    - dSP;
    - ENTER;
    - SAVETMPS;
    - PUSHMARK(sp);
    - XPUSHs(sv_2mortal(newSVpv(name, 0)));
    -
    - XPUSHs(sv_2mortal(newSViv(type)));
    -
    - switch(type) {
    - case PURPLE_PREF_INT:
    - XPUSHs(sv_2mortal(newSViv(GPOINTER_TO_INT(value))));
    - break;
    - case PURPLE_PREF_BOOLEAN:
    - XPUSHs((GPOINTER_TO_INT(value) == FALSE) ? &PL_sv_no : &PL_sv_yes);
    - break;
    - case PURPLE_PREF_STRING:
    - case PURPLE_PREF_PATH:
    - XPUSHs(sv_2mortal(newSVGChar(value)));
    - break;
    - case PURPLE_PREF_STRING_LIST:
    - case PURPLE_PREF_PATH_LIST:
    - {
    - AV* av = newAV();
    - const GList *l = value;
    -
    - /* Append stuff backward to preserve order */
    - while (l && l->next) l = l->next;
    - while (l) {
    - av_push(av, sv_2mortal(newSVGChar(l->data)));
    - l = l->prev;
    - }
    - XPUSHs(sv_2mortal(newRV_noinc((SV *) av)));
    - } break;
    - default:
    - case PURPLE_PREF_NONE:
    - XPUSHs(&PL_sv_undef);
    - break;
    - }
    -
    - XPUSHs((SV *)handler->data);
    - PUTBACK;
    - call_sv(handler->callback, G_EVAL | G_VOID | G_DISCARD);
    - SPAGAIN;
    -
    - if (SvTRUE(ERRSV)) {
    - purple_debug_error("perl",
    - "Perl prefs callback function exited abnormally: %s\n",
    - SvPVutf8_nolen(ERRSV));
    - }
    -
    - PUTBACK;
    - FREETMPS;
    - LEAVE;
    -}
    -
    -guint
    -purple_perl_prefs_connect_callback(PurplePlugin *plugin, const char *name,
    - SV *callback, SV *data)
    -{
    - PurplePerlPrefsHandler *handler;
    -
    - if (plugin == NULL) {
    - croak("Invalid handle in adding perl prefs handler.\n");
    - return 0;
    - }
    -
    - handler = g_new0(PurplePerlPrefsHandler, 1);
    -
    - handler->plugin = plugin;
    - handler->callback = (callback != NULL && callback != &PL_sv_undef
    - ? newSVsv(callback) : NULL);
    - handler->data = (data != NULL && data != &PL_sv_undef
    - ? newSVsv(data) : NULL);
    -
    - pref_handlers = g_slist_prepend(pref_handlers, handler);
    -
    - handler->iotag = purple_prefs_connect_callback(plugin, name, perl_pref_cb, handler);
    -
    - return handler->iotag;
    -}
    -
    -static void
    -destroy_prefs_handler(PurplePerlPrefsHandler *handler)
    -{
    - pref_handlers = g_slist_remove(pref_handlers, handler);
    -
    - if (handler->iotag > 0)
    - purple_prefs_disconnect_callback(handler->iotag);
    -
    - if (handler->callback != NULL)
    - SvREFCNT_dec(handler->callback);
    -
    - if (handler->data != NULL)
    - SvREFCNT_dec(handler->data);
    -
    - g_free(handler);
    -}
    -
    -void purple_perl_prefs_disconnect_callback(guint callback_id)
    -{
    - GSList *l, *l_next;
    - PurplePerlPrefsHandler *handler;
    -
    - for (l = pref_handlers; l != NULL; l = l_next) {
    - l_next = l->next;
    - handler = l->data;
    -
    - if (handler->iotag == callback_id) {
    - destroy_prefs_handler(handler);
    - return;
    - }
    - }
    -
    - purple_debug_info("perl", "No prefs handler found with handle %u.\n",
    - callback_id);
    -}
    -
    -void purple_perl_pref_cb_clear_for_plugin(PurplePlugin *plugin)
    -{
    - GSList *l, *l_next;
    - PurplePerlPrefsHandler *handler;
    -
    - for (l = pref_handlers; l != NULL; l = l_next) {
    - l_next = l->next;
    - handler = l->data;
    -
    - if (handler->plugin == plugin)
    - destroy_prefs_handler(handler);
    - }
    -}
    -
    -static void
    -perl_account_save_cb(PurpleAccount *account, GError *error, gpointer _handler)
    -{
    - PurplePerlAccountPasswordHandler *handler = _handler;
    - SV *accountSV, *errorSV;
    -
    - dSP;
    - ENTER;
    - SAVETMPS;
    - PUSHMARK(SP);
    -
    - accountSV = sv_2mortal(purple_perl_bless_object(account,
    - "Purple::Account"));
    - XPUSHs(accountSV);
    -
    - errorSV = sv_2mortal(purple_perl_bless_object(error, "GLib::Error"));
    - XPUSHs(errorSV);
    -
    - XPUSHs((SV *)handler->data);
    -
    - PUTBACK;
    - call_sv(handler->callback, G_EVAL | G_SCALAR);
    - SPAGAIN;
    -
    - if (SvTRUE(ERRSV)) {
    - purple_debug_error("perl", "Perl plugin command function "
    - "exited abnormally: %s\n", SvPVutf8_nolen(ERRSV));
    - }
    -
    - PUTBACK;
    - FREETMPS;
    - LEAVE;
    -
    - g_free(handler);
    -}
    -
    -static void
    -perl_account_read_cb(PurpleAccount *account, const gchar *password,
    - GError *error, gpointer _handler)
    -{
    - PurplePerlAccountPasswordHandler *handler = _handler;
    - SV *accountSV, *passwordSV, *errorSV;
    -
    - dSP;
    - ENTER;
    - SAVETMPS;
    - PUSHMARK(SP);
    -
    - accountSV = sv_2mortal(purple_perl_bless_object(account,
    - "Purple::Account"));
    - XPUSHs(accountSV);
    -
    - passwordSV = sv_2mortal(newSVpv(password, 0));
    - XPUSHs(passwordSV);
    -
    - errorSV = sv_2mortal(purple_perl_bless_object(error, "GLib::Error"));
    - XPUSHs(errorSV);
    -
    - XPUSHs((SV *)handler->data);
    -
    - PUTBACK;
    - call_sv(handler->callback, G_EVAL | G_SCALAR);
    - SPAGAIN;
    -
    - if (SvTRUE(ERRSV)) {
    - purple_debug_error("perl", "Perl plugin command function "
    - "exited abnormally: %s\n", SvPVutf8_nolen(ERRSV));
    - }
    -
    - PUTBACK;
    - FREETMPS;
    - LEAVE;
    -
    - g_free(handler);
    -}
    -
    -void
    -purple_perl_account_get_password(PurpleAccount *account, SV *func, SV *data)
    -{
    - PurplePerlAccountPasswordHandler *handler;
    -
    - if (func == &PL_sv_undef)
    - func = NULL;
    - if (data == &PL_sv_undef)
    - data = NULL;
    -
    - handler = g_new0(PurplePerlAccountPasswordHandler, 1);
    - handler->callback = (func != NULL ? newSVsv(func) : NULL);
    - handler->data = (data != NULL ? newSVsv(data) : NULL);
    -
    - purple_account_get_password(account, perl_account_read_cb, handler);
    -}
    -
    -void
    -purple_perl_account_set_password(PurpleAccount *account, const gchar *password,
    - SV *func, SV *data)
    -{
    - PurplePerlAccountPasswordHandler *handler;
    -
    - if (func == &PL_sv_undef)
    - func = NULL;
    - if (data == &PL_sv_undef)
    - data = NULL;
    -
    - handler = g_new0(PurplePerlAccountPasswordHandler, 1);
    - handler->callback = (func != NULL ? newSVsv(func) : NULL);
    - handler->data = (data != NULL ? newSVsv(data) : NULL);
    -
    - purple_account_set_password(account, password, perl_account_save_cb,
    - handler);
    -}
    --- a/libpurple/plugins/perl/perl-handlers.h Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,91 +0,0 @@
    -#ifndef _PURPLE_PERL_HANDLERS_H_
    -#define _PURPLE_PERL_HANDLERS_H_
    -
    -#include "cmds.h"
    -#include "plugins.h"
    -#include "prefs.h"
    -#include "pluginpref.h"
    -#ifdef PURPLE_GTKPERL
    -#include "gtkplugin.h"
    -#include "gtkutils.h"
    -#endif
    -
    -typedef struct
    -{
    - PurpleCmdId id;
    - SV *callback;
    - SV *data;
    - gchar *protocol_id;
    - gchar *cmd;
    - PurplePlugin *plugin;
    -} PurplePerlCmdHandler;
    -
    -typedef struct
    -{
    - SV *callback;
    - SV *data;
    - PurplePlugin *plugin;
    - guint iotag;
    -
    -} PurplePerlTimeoutHandler;
    -
    -typedef struct
    -{
    - gchar *signal;
    - SV *callback;
    - SV *data;
    - void *instance;
    - PurplePlugin *plugin;
    -
    -} PurplePerlSignalHandler;
    -
    -typedef struct
    -{
    - SV *callback;
    - SV *data;
    - PurplePlugin *plugin;
    - guint iotag;
    -
    -} PurplePerlPrefsHandler;
    -
    -void purple_perl_plugin_action_cb(PurplePluginAction * gpa);
    -GList *purple_perl_plugin_actions(PurplePlugin *plugin, gpointer context);
    -
    -PurplePluginPrefFrame *purple_perl_get_plugin_frame(PurplePlugin *plugin);
    -
    -#ifdef PURPLE_GTKPERL
    -GtkWidget *purple_perl_gtk_get_plugin_frame(PurplePlugin *plugin);
    -#endif
    -
    -guint purple_perl_timeout_add(PurplePlugin *plugin, int seconds, SV *callback,
    - SV *data);
    -gboolean purple_perl_timeout_remove(guint handle);
    -void purple_perl_timeout_clear_for_plugin(PurplePlugin *plugin);
    -void purple_perl_timeout_clear(void);
    -
    -void purple_perl_signal_connect(PurplePlugin *plugin, void *instance,
    - const char *signal, SV *callback,
    - SV *data, int priority);
    -void purple_perl_signal_disconnect(PurplePlugin *plugin, void *instance,
    - const char *signal);
    -void purple_perl_signal_clear_for_plugin(PurplePlugin *plugin);
    -void purple_perl_signal_clear(void);
    -
    -PurpleCmdId purple_perl_cmd_register(PurplePlugin *plugin, const gchar *cmd,
    - const gchar *args, PurpleCmdPriority priority,
    - PurpleCmdFlag flag, const gchar *protocol_id,
    - SV *callback, const gchar *helpstr, SV *data);
    -void purple_perl_cmd_unregister(PurpleCmdId id);
    -void purple_perl_cmd_clear_for_plugin(PurplePlugin *plugin);
    -
    -guint purple_perl_prefs_connect_callback(PurplePlugin *plugin, const char *name, SV *callback, SV *data);
    -void purple_perl_prefs_disconnect_callback(guint callback_id);
    -void purple_perl_pref_cb_clear_for_plugin(PurplePlugin *plugin);
    -
    -void
    -purple_perl_account_get_password(PurpleAccount *account, SV *func, SV *data);
    -void
    -purple_perl_account_set_password(PurpleAccount *account, const char *password,
    - SV *func, SV *data);
    -
    -#endif /* _PURPLE_PERL_HANDLERS_H_ */
    --- a/libpurple/plugins/perl/perl.c Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,726 +0,0 @@
    -/*
    - * purple
    - *
    - * Copyright (C) 2003 Christian Hammond <chipx86@gnupdate.org>
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program 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 General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
    - */
    -#ifdef HAVE_CONFIG_H
    -#include <config.h>
    -# ifdef HAVE_LIMITS_H
    -# include <limits.h>
    -# ifndef NAME_MAX
    -# define NAME_MAX _POSIX_NAME_MAX
    -# endif
    -# endif
    -#endif
    -
    -#ifdef DEBUG
    -# undef DEBUG
    -#endif
    -
    -#undef PACKAGE
    -
    -#define group perl_group
    -
    -#ifdef _WIN32
    -/* This took me an age to figure out.. without this __declspec(dllimport)
    - * will be ignored.
    - */
    -# define HASATTRIBUTE
    -#endif
    -
    -#include <EXTERN.h>
    -
    -#ifndef _SEM_SEMUN_UNDEFINED
    -# define HAS_UNION_SEMUN
    -#endif
    -
    -#define SILENT_NO_TAINT_SUPPORT 0
    -#define NO_TAINT_SUPPORT 0
    -
    -#include <perl.h>
    -#include <XSUB.h>
    -
    -#ifndef _WIN32
    -# include <sys/mman.h>
    -#endif
    -
    -#undef PACKAGE
    -
    -#ifndef _WIN32
    -# include <dirent.h>
    -#else
    - /* We're using perl's win32 port of this */
    -# define dirent direct
    -#endif
    -
    -#undef group
    -
    -/* perl module support */
    -#ifdef _WIN32
    -EXTERN_C void boot_Win32CORE (pTHX_ CV* cv);
    -#endif
    -
    -#ifdef OLD_PERL
    -extern void boot_DynaLoader _((CV * cv));
    -#else
    -extern void boot_DynaLoader _((pTHX_ CV * cv)); /* perl is so wacky */
    -#endif
    -
    -#undef _
    -#ifdef DEBUG
    -# undef DEBUG
    -#endif
    -#ifdef _WIN32
    -# undef pipe
    -#endif
    -
    -#ifdef _WIN32
    -#define _WIN32DEP_H_
    -#endif
    -#include "internal.h"
    -#include "debug.h"
    -#include "plugins.h"
    -#include "signals.h"
    -#include "version.h"
    -
    -#include "perl-common.h"
    -#include "perl-handlers.h"
    -
    -#include <gmodule.h>
    -
    -#define PERL_PLUGIN_ID "core-perl"
    -
    -PerlInterpreter *my_perl = NULL;
    -
    -struct _PurplePerlInfoStrings
    -{
    - char *name;
    - char *id;
    - char *homepage;
    - char *author;
    - char *summary;
    - char *description;
    - char *version;
    -};
    -
    -static PurplePluginUiInfo ui_info =
    -{
    - purple_perl_get_plugin_frame,
    - NULL,
    -
    - /* Padding */
    - NULL,
    - NULL,
    - NULL,
    - NULL
    -};
    -
    -#ifdef PURPLE_GTKPERL
    -static PurpleGtkPluginUiInfo gtk_ui_info =
    -{
    - purple_perl_gtk_get_plugin_frame,
    - 0 /* page_num (Reserved) */
    -};
    -#endif
    -
    -static void perl_infostrings_free(PurplePerlInfoStrings *info_strings)
    -{
    - if (info_strings == NULL)
    - return;
    -
    - g_free(info_strings->name);
    - g_free(info_strings->id);
    - g_free(info_strings->homepage);
    - g_free(info_strings->author);
    - g_free(info_strings->summary);
    - g_free(info_strings->description);
    - g_free(info_strings->version);
    - g_free(info_strings);
    -}
    -
    -static void
    -#ifdef OLD_PERL
    -xs_init()
    -#else
    -xs_init(pTHX)
    -#endif
    -{
    - char *file = __FILE__;
    - GList *search_paths = purple_plugins_get_search_paths();
    - dXSUB_SYS;
    -
    - /* This one allows dynamic loading of perl modules in perl scripts by
    - * the 'use perlmod;' construction */
    - newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
    -#ifdef _WIN32
    - newXS("Win32CORE::bootstrap", boot_Win32CORE, file);
    -#endif
    -
    - while (search_paths != NULL) {
    - gchar *uselib;
    - const gchar *search_path = search_paths->data;
    - search_paths = g_list_next(search_paths);
    -
    - uselib = g_strdup_printf("unshift @INC, q(%s%sperl);",
    - search_path, G_DIR_SEPARATOR_S);
    - eval_pv(uselib, TRUE);
    - g_free(uselib);
    - }
    -}
    -
    -static void
    -perl_init(void)
    -{
    - /* changed the name of the variable from load_file to perl_definitions
    - * since now it does much more than defining the load_file sub.
    - * Moreover, deplaced the initialisation to the xs_init function.
    - * (TheHobbit) */
    - char *perl_args[] = { "", "-e", "0", "-w" };
    - char perl_definitions[] =
    - {
    - /* We use to function one to load a file the other to execute
    - * the string obtained from the first and holding the file
    - * contents. This allows to have a really local $/ without
    - * introducing temp variables to hold the old value. Just a
    - * question of style:) */
    - "package Purple::PerlLoader;"
    - "use Symbol;"
    -
    - "sub load_file {"
    - "my $f_name=shift;"
    - "local $/=undef;"
    - "open FH,$f_name or return \"__FAILED__\";"
    - "$_=<FH>;"
    - "close FH;"
    - "return $_;"
    - "}"
    -
    - "sub destroy_package {"
    - "eval { $_[0]->UNLOAD() if $_[0]->can('UNLOAD'); };"
    - "Symbol::delete_package($_[0]);"
    - "}"
    -
    - "sub load_n_eval {"
    - "my ($f_name, $package) = @_;"
    - "destroy_package($package);"
    - "my $strin=load_file($f_name);"
    - "return 2 if($strin eq \"__FAILED__\");"
    - "my $eval = qq{package $package; $strin;};"
    -
    - "{"
    - " eval $eval;"
    - "}"
    -
    - "if($@) {"
    - /*" #something went wrong\n"*/
    - "die(\"Errors loading file $f_name: $@\");"
    - "}"
    -
    - "return 0;"
    - "}"
    - };
    -
    - my_perl = perl_alloc();
    - PERL_SET_CONTEXT(my_perl);
    - PL_perl_destruct_level = 1;
    - perl_construct(my_perl);
    -#ifdef DEBUG
    - perl_parse(my_perl, xs_init, 4, perl_args, NULL);
    -#else
    - perl_parse(my_perl, xs_init, 3, perl_args, NULL);
    -#endif
    -#ifdef HAVE_PERL_EVAL_PV
    - eval_pv(perl_definitions, TRUE);
    -#else
    - perl_eval_pv(perl_definitions, TRUE); /* deprecated */
    -#endif
    - perl_run(my_perl);
    -}
    -
    -static void
    -perl_end(void)
    -{
    - if (my_perl == NULL)
    - return;
    -
    - PL_perl_destruct_level = 1;
    - PERL_SET_CONTEXT(my_perl);
    - perl_eval_pv(
    - "foreach my $lib (@DynaLoader::dl_modules) {"
    - "if ($lib =~ /^Purple\\b/) {"
    - "$lib .= '::deinit();';"
    - "eval $lib;"
    - "}"
    - "}",
    - TRUE);
    -
    - PL_perl_destruct_level = 1;
    - PERL_SET_CONTEXT(my_perl);
    - perl_destruct(my_perl);
    - perl_free(my_perl);
    - my_perl = NULL;
    -}
    -
    -void
    -purple_perl_callXS(void (*subaddr)(pTHX_ CV *cv), CV *cv, SV **mark)
    -{
    - dSP;
    -
    - PUSHMARK(mark);
    - (*subaddr)(aTHX_ cv);
    -
    - PUTBACK;
    -}
    -
    -static gboolean
    -probe_perl_plugin(PurplePlugin *plugin)
    -{
    -
    - char *args[] = {"", plugin->path };
    - char **argv = args;
    - int argc = 2, ret;
    - PerlInterpreter *prober;
    - gboolean status = TRUE;
    - HV *plugin_info;
    -
    - PERL_SYS_INIT(&argc, &argv);
    -
    - /* XXX This would be much faster if we didn't create a new
    - * PerlInterpreter every time we probe a plugin */
    - prober = perl_alloc();
    -
    - PERL_SET_CONTEXT(prober);
    -
    - PL_perl_destruct_level = 1;
    - perl_construct(prober);
    -
    -/* Fix IO redirection to match where pidgin's is going.
    - * Without this, we lose stdout/stderr unless we redirect to a file */
    -#ifdef _WIN32
    -{
    - PerlIO* newprlIO = PerlIO_open("CONOUT$", "w");
    - if (newprlIO) {
    - int stdout_fd = PerlIO_fileno(PerlIO_stdout());
    - int stderr_fd = PerlIO_fileno(PerlIO_stderr());
    - PerlIO_close(PerlIO_stdout());
    - PerlIO_close(PerlIO_stderr());
    - PerlLIO_dup2(PerlIO_fileno(newprlIO), stdout_fd);
    - PerlLIO_dup2(PerlIO_fileno(newprlIO), stderr_fd);
    -
    - PerlIO_close(newprlIO);
    - }
    -}
    -#endif
    -
    - ret = perl_parse(prober, xs_init, argc, argv, NULL);
    -
    - if (ret != 0) {
    - const char * errmsg = "Unknown error";
    - if (SvTRUE(ERRSV))
    - errmsg = SvPVutf8_nolen(ERRSV);
    - purple_debug_error("perl", "Unable to parse plugin %s (%d:%s)\n",
    - plugin->path, ret, errmsg);
    - status = FALSE;
    - goto cleanup;
    - }
    -
    - ret = perl_run(prober);
    -
    - if (ret != 0) {
    - const char * errmsg = "Unknown error";
    - if (SvTRUE(ERRSV))
    - errmsg = SvPVutf8_nolen(ERRSV);
    - purple_debug_error("perl", "Unable to run perl interpreter on plugin %s (%d:%s)\n",
    - plugin->path, ret, errmsg);
    - status = FALSE;
    - goto cleanup;
    - }
    -
    - plugin_info = perl_get_hv("PLUGIN_INFO", FALSE);
    -
    - if (plugin_info == NULL)
    - status = FALSE;
    - else if (!hv_exists(plugin_info, "perl_api_version",
    - strlen("perl_api_version")) ||
    - !hv_exists(plugin_info, "name", strlen("name")) ||
    - !hv_exists(plugin_info, "load", strlen("load"))) {
    - /* Not a valid plugin. */
    -
    - status = FALSE;
    - } else {
    - SV **key;
    - int perl_api_ver;
    -
    - key = hv_fetch(plugin_info, "perl_api_version",
    - strlen("perl_api_version"), 0);
    -
    - perl_api_ver = SvIV(*key);
    -
    - if (perl_api_ver != 2)
    - status = FALSE;
    - else {
    - PurplePluginInfo *info;
    - PurplePerlScript *gps;
    - char *basename;
    -
    - info = g_new0(PurplePluginInfo, 1);
    - gps = g_new0(PurplePerlScript, 1);
    - gps->info_strings = g_new0(PurplePerlInfoStrings, 1);
    -
    - info->magic = PURPLE_PLUGIN_MAGIC;
    - info->major_version = PURPLE_MAJOR_VERSION;
    - info->minor_version = PURPLE_MINOR_VERSION;
    - info->type = PURPLE_PLUGIN_STANDARD;
    -
    - info->dependencies = g_list_append(info->dependencies,
    - PERL_PLUGIN_ID);
    -
    - gps->plugin = plugin;
    -
    - basename = g_path_get_basename(plugin->path);
    - purple_perl_normalize_script_name(basename);
    - gps->package = g_strdup_printf("Purple::Script::%s",
    - basename);
    - g_free(basename);
    -
    - /* We know this one exists. */
    - key = hv_fetch(plugin_info, "name", strlen("name"), 0);
    - info->name = gps->info_strings->name = g_strdup(SvPVutf8_nolen(*key));
    - /* Set id here in case we don't find one later. */
    - info->id = gps->info_strings->id = g_strdup(info->name);
    -
    -#ifdef PURPLE_GTKPERL
    - if ((key = hv_fetch(plugin_info, "GTK_UI",
    - strlen("GTK_UI"), 0)))
    - info->ui_requirement = PURPLE_GTK_PLUGIN_TYPE;
    -#endif
    -
    - if ((key = hv_fetch(plugin_info, "url",
    - strlen("url"), 0)))
    - info->homepage = gps->info_strings->homepage = g_strdup(SvPVutf8_nolen(*key));
    -
    - if ((key = hv_fetch(plugin_info, "author",
    - strlen("author"), 0)))
    - info->author = gps->info_strings->author = g_strdup(SvPVutf8_nolen(*key));
    -
    - if ((key = hv_fetch(plugin_info, "summary",
    - strlen("summary"), 0)))
    - info->summary = gps->info_strings->summary = g_strdup(SvPVutf8_nolen(*key));
    -
    - if ((key = hv_fetch(plugin_info, "description",
    - strlen("description"), 0)))
    - info->description = gps->info_strings->description = g_strdup(SvPVutf8_nolen(*key));
    -
    - if ((key = hv_fetch(plugin_info, "version",
    - strlen("version"), 0)))
    - info->version = gps->info_strings->version = g_strdup(SvPVutf8_nolen(*key));
    -
    - /* We know this one exists. */
    - key = hv_fetch(plugin_info, "load", strlen("load"), 0);
    - gps->load_sub = g_strdup_printf("%s::%s", gps->package,
    - SvPVutf8_nolen(*key));
    -
    - if ((key = hv_fetch(plugin_info, "unload",
    - strlen("unload"), 0)))
    - gps->unload_sub = g_strdup_printf("%s::%s",
    - gps->package,
    - SvPVutf8_nolen(*key));
    -
    - if ((key = hv_fetch(plugin_info, "id",
    - strlen("id"), 0))) {
    - g_free(gps->info_strings->id);
    - info->id = gps->info_strings->id = g_strdup_printf("perl-%s",
    - SvPVutf8_nolen(*key));
    - }
    -
    - /********************************************************/
    - /* Only one of the next two options should be present */
    - /* */
    - /* prefs_info - Uses non-GUI (read GTK) purple API calls */
    - /* and creates a PurplePluginPrefInfo type. */
    - /* */
    - /* gtk_prefs_info - Requires gtk2-perl be installed by */
    - /* the user and he must create a */
    - /* GtkWidget the user and he must */
    - /* create a GtkWidget representing the */
    - /* plugin preferences page. */
    - /********************************************************/
    - if ((key = hv_fetch(plugin_info, "prefs_info",
    - strlen("prefs_info"), 0))) {
    - /* key now is the name of the Perl sub that
    - * will create a frame for us */
    - gps->prefs_sub = g_strdup_printf("%s::%s",
    - gps->package,
    - SvPVutf8_nolen(*key));
    - info->prefs_info = &ui_info;
    - }
    -
    -#ifdef PURPLE_GTKPERL
    - if ((key = hv_fetch(plugin_info, "gtk_prefs_info",
    - strlen("gtk_prefs_info"), 0))) {
    - /* key now is the name of the Perl sub that
    - * will create a frame for us */
    - gps->gtk_prefs_sub = g_strdup_printf("%s::%s",
    - gps->package,
    - SvPVutf8_nolen(*key));
    - info->ui_info = &gtk_ui_info;
    - }
    -#endif
    -
    - if ((key = hv_fetch(plugin_info, "plugin_action_sub",
    - strlen("plugin_action_sub"), 0))) {
    - gps->plugin_action_sub = g_strdup_printf("%s::%s",
    - gps->package,
    - SvPVutf8_nolen(*key));
    - info->actions = purple_perl_plugin_actions;
    - }
    -
    - plugin->info = info;
    - info->extra_info = gps;
    -
    - status = purple_plugin_register(plugin);
    - }
    - }
    -
    - cleanup:
    - PL_perl_destruct_level = 1;
    - PERL_SET_CONTEXT(prober);
    - perl_destruct(prober);
    - perl_free(prober);
    - return status;
    -}
    -
    -static gboolean
    -load_perl_plugin(PurplePlugin *plugin)
    -{
    - PurplePerlScript *gps = (PurplePerlScript *)plugin->info->extra_info;
    - gboolean loaded = TRUE;
    - char *atmp[3] = { plugin->path, NULL, NULL };
    -
    - if (gps == NULL || gps->load_sub == NULL)
    - return FALSE;
    -
    - purple_debug(PURPLE_DEBUG_INFO, "perl", "Loading perl script\n");
    -
    - if (my_perl == NULL)
    - perl_init();
    -
    - plugin->handle = gps;
    -
    - atmp[1] = gps->package;
    -
    - PERL_SET_CONTEXT(my_perl);
    - execute_perl("Purple::PerlLoader::load_n_eval", 2, atmp);
    -
    - {
    - dSP;
    - PERL_SET_CONTEXT(my_perl);
    - SPAGAIN;
    - ENTER;
    - SAVETMPS;
    - PUSHMARK(sp);
    - XPUSHs(sv_2mortal(purple_perl_bless_object(plugin,
    - "Purple::Plugin")));
    - PUTBACK;
    -
    - perl_call_pv(gps->load_sub, G_EVAL | G_SCALAR);
    - SPAGAIN;
    -
    - if (SvTRUE(ERRSV)) {
    - purple_debug(PURPLE_DEBUG_ERROR, "perl",
    - "Perl function %s exited abnormally: %s\n",
    - gps->load_sub, SvPVutf8_nolen(ERRSV));
    - loaded = FALSE;
    - }
    -
    - PUTBACK;
    - FREETMPS;
    - LEAVE;
    - }
    -
    - return loaded;
    -}
    -
    -static void
    -destroy_package(const char *package)
    -{
    - dSP;
    - PERL_SET_CONTEXT(my_perl);
    - SPAGAIN;
    -
    - ENTER;
    - SAVETMPS;
    -
    - PUSHMARK(SP);
    - XPUSHs(sv_2mortal(newSVpv(package, 0)));
    - PUTBACK;
    -
    - perl_call_pv("Purple::PerlLoader::destroy_package",
    - G_VOID | G_EVAL | G_DISCARD);
    -
    - SPAGAIN;
    -
    - PUTBACK;
    - FREETMPS;
    - LEAVE;
    -}
    -
    -static gboolean
    -unload_perl_plugin(PurplePlugin *plugin)
    -{
    - PurplePerlScript *gps = (PurplePerlScript *)plugin->info->extra_info;
    -
    - if (gps == NULL)
    - return FALSE;
    -
    - purple_debug(PURPLE_DEBUG_INFO, "perl", "Unloading perl script\n");
    -
    - if (gps->unload_sub != NULL) {
    - dSP;
    - PERL_SET_CONTEXT(my_perl);
    - SPAGAIN;
    - ENTER;
    - SAVETMPS;
    - PUSHMARK(sp);
    - XPUSHs(sv_2mortal(purple_perl_bless_object(plugin,
    - "Purple::Plugin")));
    - PUTBACK;
    -
    - perl_call_pv(gps->unload_sub, G_EVAL | G_SCALAR);
    - SPAGAIN;
    -
    - if (SvTRUE(ERRSV)) {
    - purple_debug(PURPLE_DEBUG_ERROR, "perl",
    - "Perl function %s exited abnormally: %s\n",
    - gps->unload_sub, SvPVutf8_nolen(ERRSV));
    - }
    -
    - PUTBACK;
    - FREETMPS;
    - LEAVE;
    - }
    -
    - purple_perl_cmd_clear_for_plugin(plugin);
    - purple_perl_signal_clear_for_plugin(plugin);
    - purple_perl_timeout_clear_for_plugin(plugin);
    - purple_perl_pref_cb_clear_for_plugin(plugin);
    -
    - destroy_package(gps->package);
    -
    - return TRUE;
    -}
    -
    -static void
    -destroy_perl_plugin(PurplePlugin *plugin)
    -{
    - if (plugin->info != NULL) {
    - PurplePerlScript *gps;
    -
    - gps = (PurplePerlScript *)plugin->info->extra_info;
    - if (gps != NULL) {
    - perl_infostrings_free(gps->info_strings);
    - gps->info_strings = NULL;
    -
    - g_free(gps->package);
    - g_free(gps->load_sub);
    - g_free(gps->unload_sub);
    - g_free(gps->prefs_sub);
    -#ifdef PURPLE_GTKPERL
    - g_free(gps->gtk_prefs_sub);
    -#endif
    - g_free(gps->plugin_action_sub);
    - g_free(gps);
    - plugin->info->extra_info = NULL;
    - }
    -
    - g_free(plugin->info);
    - plugin->info = NULL;
    - }
    -}
    -
    -static PurplePluginLoaderInfo loader_info =
    -{
    - probe_perl_plugin, /**< probe */
    - load_perl_plugin, /**< load */
    - unload_perl_plugin, /**< unload */
    - destroy_perl_plugin, /**< destroy */
    -};
    -
    -static GPluginPluginInfo *
    -plugin_query(GError **error)
    -{
    - const gchar * const authors[] = {
    - "Christian Hammond <chipx86@gnupdate.org>",
    - NULL
    - };
    -
    - return gplugin_plugin_info_new(
    - "id", PERL_PLUGIN_ID,
    - "name", N_("Perl Plugin Loader"),
    - "version", DISPLAY_VERSION,
    - "category", N_("Loader"),
    - "summary", N_("Provides support for loading perl plugins."),
    - "description", N_("Provides support for loading perl plugins."),
    - "authors", authors,
    - "website", PURPLE_WEBSITE,
    - "abi-version", PURPLE_ABI_VERSION,
    - "internal", TRUE,
    - "load-on-query", TRUE,
    - NULL
    - );
    -}
    -
    -static gboolean
    -plugin_load(PurplePlugin *plugin, GError **error)
    -{
    - return TRUE;
    -}
    -
    -static gboolean
    -plugin_unload(PurplePlugin *plugin, GError **error)
    -{
    - perl_end();
    -
    - return TRUE;
    -}
    -
    -static void
    -init_plugin(PurplePlugin *plugin)
    -{
    - loader_info.exts = g_list_append(loader_info.exts, "pl");
    -}
    -
    -#ifdef __SUNPRO_C
    -#pragma init (my_init)
    -#else
    -void __attribute__ ((constructor)) my_init(void);
    -#endif
    -
    -void
    -my_init(void)
    -{
    - /* Mostly evil hack... puts perl.so's symbols in the global table but
    - * does not create a circular dependency because g_module_open will
    - * only open the library once. */
    - /* Do we need to keep track of the returned GModule here so that we
    - * can g_module_close it when this plugin gets unloaded?
    - * At the moment I don't think this plugin can ever get unloaded but
    - * in case that becomes possible this wants to get noted. */
    - g_module_open("perl.so", 0);
    -}
    -
    -PURPLE_PLUGIN_INIT(perl, plugin_query, plugin_load, plugin_unload);
    --- a/libpurple/plugins/perl/scripts/account.pl Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,155 +0,0 @@
    -$MODULE_NAME = "Account Functions Test";
    -
    -use Purple;
    -
    -# All the information Purple gets about our nifty plugin
    -%PLUGIN_INFO = (
    - perl_api_version => 2,
    - name => "Perl: $MODULE_NAME",
    - version => "0.1",
    - summary => "Test plugin for the Perl interpreter.",
    - description => "Implements a set of test proccedures to ensure all " .
    - "functions that work in the C API still work in the " .
    - "Perl plugin interface. As XSUBs are added, this " .
    - "*should* be updated to test the changes. " .
    - "Furthermore, this will function as the tutorial perl " .
    - "plugin.",
    - author => "John H. Kelm <johnhkelm\@gmail.com>",
    - url => "http://sourceforge.net/users/johnhkelm/",
    -
    - load => "plugin_load",
    - unload => "plugin_unload"
    -);
    -
    -
    - # These names must already exist
    - my $USERNAME = "johnhkelm2";
    -
    - # We will create these on load then destroy them on unload
    - my $TEST_NAME = "perlTestName";
    - my $PROTOCOL_ID = "aim";
    -
    -
    -sub plugin_init {
    - return %PLUGIN_INFO;
    -}
    -
    -sub set_password_cb
    -{
    - my $account = shift;
    - my $error = shift;
    - my $data = shift;
    -
    - if ($error) {
    - Purple::Debug::warning($MODULE_NAME, "Failed to set password " .
    - "for $account\n");
    - return;
    - }
    -
    - Purple::Debug::misc($MODULE_NAME, "Password for $account was set\n");
    -}
    -
    -sub get_password_cb
    -{
    - my $account = shift;
    - my $password = shift;
    - my $error = shift;
    - my $data = shift;
    -
    - if ($error) {
    - Purple::Debug::warning($MODULE_NAME, "Failed to get password for $account\n");
    - return;
    - }
    -
    - Purple::Debug::misc($MODULE_NAME, "Got password for $account\n");
    -
    - $account->set_password($password, \&set_password_cb);
    -}
    -
    -# This is the sub defined in %PLUGIN_INFO to be called when the plugin is loaded
    -# Note: The plugin has a reference to itself on top of the argument stack.
    -sub plugin_load {
    - my $plugin = shift;
    - print "#" x 80 . "\n\n";
    - Purple::Debug::info($MODULE_NAME, "plugin_load() - Testing $MODULE_NAME Started.");
    - print "\n\n";
    -
    -
    - #################################
    - # #
    - # Purple::Account::Option #
    - # #
    - #################################
    -
    - print "Testing: Purple::Account::Option::new()...\n";
    - $acc_opt = Purple::Account::Option->new(1, "TEXT", "pref_name");
    - $acc_opt2 = Purple::Account::Option->bool_new("TeXt", "MYprefName", 1);
    -
    - #################################
    - # #
    - # Purple::Account #
    - # #
    - #################################
    -
    -
    - print "Testing: Purple::Account::new()... ";
    - $account = Purple::Account->new($TEST_NAME, $PROTOCOL_ID);
    - if ($account) { print "ok.\n"; } else { print "fail.\n"; }
    -
    - print "Testing: Purple::Accounts::add()...";
    - Purple::Accounts::add($account);
    - print "pending find...\n";
    -
    - print "Testing: Purple::Accounts::find()...";
    - $account = Purple::Accounts::find($TEST_NAME, $PROTOCOL_ID);
    - if ($account) { print "ok.\n"; } else { print "fail.\n"; }
    -
    - print "Testing: Purple::Account::get_username()... ";
    - $user_name = $account->get_username();
    - if ($user_name) {
    - print "Success: $user_name.\n";
    - } else {
    - print "Failed!\n";
    - }
    -
    - print "Testing: Purple::Account::is_connected()... ";
    - if ($account->is_connected()) {
    - print " Connected.\n";
    - } else {
    - print " Disconnected.\n";
    - }
    -
    - print "Testing: Purple::Accounts::get_active_status()... ";
    - if ($account->get_active_status()) {
    - print "Okay.\n";
    - } else {
    - print "Failed!\n";
    - }
    -
    - $account = Purple::Accounts::find($USERNAME, $PROTOCOL_ID);
    - print "Testing: Purple::Accounts::connect()...pending...\n";
    -
    - $account->set_status("available", TRUE);
    - $account->connect();
    -
    - $account->get_password(\&get_password_cb);
    -
    - print "\n\n";
    - Purple::Debug::info($MODULE_NAME, "plugin_load() - Testing $MODULE_NAME Completed.\n");
    - print "\n\n" . "#" x 80 . "\n\n";
    -}
    -
    -sub plugin_unload {
    - my $plugin = shift;
    -
    - print "#" x 80 . "\n\n";
    - Purple::Debug::info($MODULE_NAME, "plugin_unload() - Testing $MODULE_NAME Started.\n");
    - print "\n\n";
    -
    - ######### TEST CODE HERE ##########
    -
    - print "\n\n";
    - Purple::Debug::info($MODULE_NAME, "plugin_unload() - Testing $MODULE_NAME Completed.\n");
    - print "\n\n" . "#" x 80 . "\n\n";
    -}
    -
    --- a/libpurple/plugins/perl/scripts/buddy_list.pl Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,107 +0,0 @@
    -$MODULE_NAME = "Buddy List Test";
    -
    -use Purple;
    -
    -# All the information Purple gets about our nifty plugin
    -%PLUGIN_INFO = (
    - perl_api_version => 2,
    - name => "Perl: $MODULE_NAME",
    - version => "0.1",
    - summary => "Test plugin for the Perl interpreter.",
    - description => "Implements a set of test proccedures to ensure all functions that work in the C API still work in the Perl plugin interface. As XSUBs are added, this *should* be updated to test the changes. Furthermore, this will function as the tutorial perl plugin.",
    - author => "John H. Kelm <johnhkelm\@gmail.com>",
    - url => "http://sourceforge.net/users/johnhkelm/",
    -
    - load => "plugin_load",
    - unload => "plugin_unload"
    -);
    -
    -
    - # These names must already exist
    - my $USERNAME = "johnhkelm2";
    -
    - # We will create these on load then destroy them on unload
    - my $TEST_GROUP = "UConn Buddies";
    - my $TEST_NAME = "johnhkelm";
    - my $TEST_ALIAS = "John Kelm";
    - my $PROTOCOL_ID = "aim";
    -
    -
    -sub plugin_init {
    - return %PLUGIN_INFO;
    -}
    -
    -
    -# This is the sub defined in %PLUGIN_INFO to be called when the plugin is loaded
    -# Note: The plugin has a reference to itself on top of the argument stack.
    -sub plugin_load {
    - my $plugin = shift;
    -
    - # This is how we get an account to use in the following tests. You should replace the username
    - # with an existing user
    - $account = Purple::Accounts::find($USERNAME, $PROTOCOL_ID);
    -
    - # Testing a find function: Note Purple::Find not Purple::Buddy:find!
    - # Furthermore, this should work the same for chats and groups
    - Purple::Debug::info($MODULE_NAME, "Testing: Purple::Find::buddy()...");
    - $buddy = Purple::Find::buddy($account, $TEST_NAME);
    - Purple::Debug::info("", ($buddy ? "ok." : "fail.") . "\n");
    -
    - # If you should need the handle for some reason, here is how you do it
    - Purple::Debug::info($MODULE_NAME, "Testing: Purple::BuddyList::get_handle()...");
    - $handle = Purple::BuddyList::get_handle();
    - Purple::Debug::info("", ($handle ? "ok." : "fail.") . "\n");
    -
    - # This gets the Purple::BuddyList and references it by $blist
    - Purple::Debug::info($MODULE_NAME, "Testing: Purple::get_blist()...");
    - $blist = Purple::get_blist();
    - Purple::Debug::info("", ($blist ? "ok." : "fail.") . "\n");
    -
    - # This is how you would add a buddy named $TEST_NAME" with the alias $TEST_ALIAS
    - Purple::Debug::info($MODULE_NAME, "Testing: Purple::BuddyList::Buddy::new...");
    - $buddy = Purple::BuddyList::Buddy::new($account, $TEST_NAME, $TEST_ALIAS);
    - Purple::Debug::info("", ($buddy ? "ok." : "fail.") . "\n");
    -
    - # Here we add the new buddy '$buddy' to the group $TEST_GROUP
    - # so first we must find the group
    - Purple::Debug::info($MODULE_NAME, "Testing: Purple::Find::group...");
    - $group = Purple::Find::group($TEST_GROUP);
    - Purple::Debug::info("", ($group ? "ok." : "fail.") . "\n");
    -
    - # To add the buddy we need to have the buddy, contact, group and node for insertion.
    - # For this example we can let contact be undef and set the insertion node as the group
    - Purple::Debug::info($MODULE_NAME, "Testing: Purple::BuddyList::add_buddy...\n");
    - Purple::BuddyList::add_buddy($buddy, undef, $group, $group);
    -
    - # The example that follows gives an indication of how an API call that returns a list is handled.
    - # In this case the buddies of the account found earlier are retrieved and put in an array '@buddy_array'
    - # Further down an accessor method is used, 'get_name()' -- see source for details on the full set of methods
    - Purple::Debug::info($MODULE_NAME, "Testing: Purple::Find::buddies...\n");
    - @buddy_array = Purple::Find::buddies($account, undef);
    - if (@buddy_array) {
    - Purple::Debug::info($MODULE_NAME, "Buddies in list (" . @buddy_array . "): \n");
    - foreach $bud (@buddy_array) {
    - Purple::Debug::info($MODULE_NAME, Purple::BuddyList::Buddy::get_name($bud) . "\n");
    - }
    - }
    -}
    -
    -sub plugin_unload {
    - my $plugin = shift;
    -
    - print "#" x 80 . "\n\n";
    - ######### TEST CODE HERE ##########
    -
    - print "Testing: Purple::Find::buddy()...";
    - $buddy = Purple::Find::buddy($account, $TEST_NAME . TEST);
    - if ($buddy) {
    - print "ok.\n";
    - print "Testing: Purple::BuddyList::remove_buddy()...";
    - Purple::BuddyList::remove_buddy($buddy);
    - if (Purple::Find::buddy($account, $TEST_NAME . TEST)) { print "fail.\n"; } else { print "ok.\n"; }
    - } else { print "fail.\n"; }
    -
    -
    - print "\n\n" . "#" x 80 . "\n\n";
    -}
    -
    --- a/libpurple/plugins/perl/scripts/conversation.pl Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,119 +0,0 @@
    -$MODULE_NAME = "Conversation Test";
    -
    -use Purple;
    -
    -# All the information Purple gets about our nifty plugin
    -%PLUGIN_INFO = (
    - perl_api_version => 2,
    - name => "Perl: $MODULE_NAME",
    - version => "0.1",
    - summary => "Test plugin for the Perl interpreter.",
    - description => "Implements a set of test proccedures to ensure all " .
    - "functions that work in the C API still work in the " .
    - "Perl plugin interface. As XSUBs are added, this " .
    - "*should* be updated to test the changes. " .
    - "Furthermore, this will function as the tutorial perl " .
    - "plugin.",
    - author => "John H. Kelm <johnhkelm\@gmail.com>",
    - url => "http://sourceforge.net/users/johnhkelm/",
    -
    - load => "plugin_load",
    - unload => "plugin_unload"
    -);
    -
    -
    - # These names must already exist
    - my $GROUP = "UIUC Buddies";
    - my $USERNAME = "johnhkelm2";
    -
    - # We will create these on load then destroy them on unload
    - my $TEST_GROUP = "UConn Buddies";
    - my $TEST_NAME = "johnhkelm";
    - my $TEST_ALIAS = "John Kelm";
    - my $PROTOCOL_ID = "aim";
    -
    -
    -sub plugin_init {
    - return %PLUGIN_INFO;
    -}
    -
    -
    -# This is the sub defined in %PLUGIN_INFO to be called when the plugin is loaded
    -# Note: The plugin has a reference to itself on top of the argument stack.
    -sub plugin_load {
    - my $plugin = shift;
    - print "#" x 80 . "\n\n";
    -
    - print "PERL: Finding account.\n";
    - $account = Purple::Accounts::find($USERNAME, $PROTOCOL_ID);
    -
    - ######### TEST CODE HERE ##########
    - # First we create two new conversations.
    - print "Testing Purple::Conversation::new()...";
    - $conv1 = Purple::Conversation->new(1, $account, "Test Conversation 1");
    - if ($conv1) { print "ok.\n"; } else { print "fail.\n"; }
    -
    - print "Testing Purple::Conversation::new()...";
    - $conv2 = Purple::Conversation->new(1, $account, "Test Conversation 2");
    - if ($conv2) { print "ok.\n"; } else { print "fail.\n"; }
    -
    - # Second we create a window to display the conversations in.
    - # Note that the package here is Purple::Conversation::Window
    - print "Testing Purple::Conversation::Window::new()...\n";
    - $win = Purple::Conversation::Window::new();
    -
    - # The third thing to do is to add the two conversations to the windows.
    - # The subroutine add_conversation() returns the number of conversations
    - # present in the window.
    - print "Testing Purple::Conversation::Window::add_conversation()...";
    - $conv_count = $conv1->add_conversation();
    - if ($conv_count) {
    - print "ok..." . $conv_count . " conversations...\n";
    - } else {
    - print "fail.\n";
    - }
    -
    - print "Testing Purple::Conversation::Window::add_conversation()...";
    - $conv_count = $win->add_conversation($conv2);
    - if ($conv_count) {
    - print "ok..." . $conv_count . " conversations...\n";
    - } else {
    - print "fail.\n";
    - }
    -
    - # Now the window is displayed to the user.
    - print "Testing Purple::Conversation::Window::show()...\n";
    - $win->show();
    -
    - # Use get_im_data() to get a handle for the conversation
    - print "Testing Purple::Conversation::get_im_data()...\n";
    - $im = $conv1->get_im_data();
    - if ($im) { print "ok.\n"; } else { print "fail.\n"; }
    -
    - # Here we send messages to the conversation
    - print "Testing Purple::Conversation::IM::send()...\n";
    - $im->send("Message Test.");
    -
    - print "Testing Purple::Conversation::IM::write()...\n";
    - $im->write("SENDER", "<b>Message</b> Test.", 0, 0);
    -
    - print "#" x 80 . "\n\n";
    -}
    -
    -sub plugin_unload {
    - my $plugin = shift;
    -
    - print "#" x 80 . "\n\n";
    - ######### TEST CODE HERE ##########
    -
    - print "Testing Purple::Conversation::Window::get_conversation_count()...\n";
    - $conv_count = $win->get_conversation_count();
    - print "...and it returned $conv_count.\n";
    - if ($conv_count > 0) {
    - print "Testing Purple::Conversation::Window::destroy()...\n";
    - $win->destroy();
    - }
    -
    - print "\n\n" . "#" x 80 . "\n\n";
    -}
    -
    --- a/libpurple/plugins/perl/scripts/count_down.pl Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,89 +0,0 @@
    -use Purple;
    -
    -%PLUGIN_INFO = (
    - perl_api_version => 2,
    - name => "Countdown Info Timer",
    - version => "0.1",
    - summary => "Makes a countdown in days from today.",
    - description => "Long description coming....",
    - author => "John H. Kelm <johnhkelm\@gmail.com>",
    - url => "https://pidgin.im",
    -
    - load => "plugin_load",
    - unload => "plugin_unload"
    -);
    -
    - $GLOBAL_TEST_VAR = "STUFF!";
    -
    -sub plugin_unload {
    - my $plugin = shift;
    -}
    -
    -sub plugin_init {
    - return %PLUGIN_INFO;
    -}
    -
    -
    -sub plugin_load {
    - my $plugin = shift;
    -
    - # Retrieve all the accounts
    - @accounts = Purple::Accounts::get_all();
    -
    - print "NUM OF ACCS: " . $accounts . "\n";
    - # Search each account's user info for our tag
    - foreach $acc (@accounts) {
    - print "IN ACCOUNTS\n";
    - $user_info = $acc->get_user_info();
    - print "USER INFO 1: " . $user_info . "\n";
    - # Find <countdown> and replace
    - $user_info =~ /countdown([0-9]+).([0-9]+).([0-9]+)/;
    - print "Found: " .$1 . " " . $2 . " " . $3 . "\n";
    - $days = count_days($1, $2, $3);
    - $user_info =~ s/countdown(\d\d\d\d).(\d\d).(\d\d)/$days/;
    - print "USER INFO 2: " . $user_info . "\n";
    - # $acc->set_user_info($user_info);
    -
    - }
    -
    - eval '
    - use Gtk2 \'-init\';
    - use Glib;
    - $window = Gtk2::Window->new(\'toplevel\');
    - $window->set_border_width(10);
    - $button = Gtk2::Button->new("Hello World");
    - $button->signal_connect(clicked => \&hello, $window);
    -
    - $window->add($button);
    - $button->show;
    - $window->show;
    - # Gtk2->main;
    -
    - 0;
    -
    - '; warn $@ if $@;
    -}
    -
    -sub hello {
    - my ($widget, $window) = @_;
    - print "Called from sub hello!\n ";
    - print "Test var: " . $GLOBAL_TEST_VAR . " \n";
    - @accounts = Purple::Accounts::get_all();
    - $acc = $accounts[0];
    - $user_info = $acc->get_user_info();
    - print "USER INFO from sub hello: " . $user_info . "\n";
    - $window->destroy;
    -}
    -
    -sub count_days {
    - ($year, $month, $day) = @_;
    -
    -
    - eval '
    - use Time::Local;
    - $future = timelocal(0,0,0,$day,$month-1,$year);
    - '; warn $@ if $@;
    - $today = time();
    - $days = int(($future - $today)/(60*60*24));
    - return $days;
    -}
    --- a/libpurple/plugins/perl/scripts/function_list.pl Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,69 +0,0 @@
    -$MODULE_NAME = "List all Purple:: (and Pidgin::) functions";
    -use Purple;
    -# Uncomment this to print the Pidgin:: functions as well.
    -#use Pidgin;
    -
    -# All the information Purple gets about our nifty plugin
    -%PLUGIN_INFO = (
    - perl_api_version => 2,
    - name => "Perl: $MODULE_NAME",
    - version => "0.1",
    - summary => "Print to standard output all the functions under the Purple:: (and Pidgin::) packages",
    - description => "Print to standard output all the functions under the Purple:: (and Pidgin::) packages",
    - author => "Etan Reisner <deryni\@gmail.com>",
    - url => "http://sourceforge.net/users/deryni9/",
    - id => "functionlist",
    -
    - load => "plugin_load",
    - unload => "plugin_unload"
    -);
    -
    -sub plugin_init {
    - return %PLUGIN_INFO;
    -}
    -
    -sub print_array {
    - my $array = shift;
    -
    - my @arr = sort @$array;
    - foreach $mod (@arr) {
    - my @sub;
    -
    - foreach $key (sort keys %{$mod}) {
    - if ($key =~ /::$/) {
    - push @sub, "$mod$key";
    - } else {
    - print "$mod$key\n";
    - }
    - }
    - print_array(\@sub);
    - }
    -}
    -
    -sub plugin_load {
    - my $plugin = shift;
    - my @purplearray;
    - my @pidginarray;
    -
    - foreach $key (sort keys %Purple::) {
    - if ($key =~ /::$/) {
    - push @purplearray, "Purple::$key";
    - } else {
    - print "Purple::$key\n";
    - }
    - }
    - print_array(\@purplearray);
    -
    - foreach $key (sort keys %Pidgin::) {
    - if ($key =~ /::$/) {
    - push @pidginarray, "Pidgin::$key";
    - } else {
    - print "Pidgin::$key\n";
    - }
    - }
    - print_array(\@pidginarray);
    -}
    -
    -sub plugin_unload {
    - my $plugin = shift;
    -}
    --- a/libpurple/plugins/perl/scripts/gtk_frame_test.pl Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,66 +0,0 @@
    -$MODULE_NAME = "GTK Frame Test";
    -
    -use Purple;
    -
    -%PLUGIN_INFO = (
    - perl_api_version => 2,
    - name => " Perl: $MODULE_NAME",
    - version => "0.1",
    - summary => "Test plugin for the Perl interpreter.",
    - description => "Implements a set of test proccedures to ensure all functions that work in the C API still work in the Perl plugin interface. As XSUBs are added, this *should* be updated to test the changes. Furthermore, this will function as the tutorial perl plugin.",
    - author => "John H. Kelm <johnhkelm\@gmail.com>",
    - url => "https://pidgin.im",
    -
    - GTK_UI => TRUE,
    - gtk_prefs_info => "foo",
    - load => "plugin_load",
    - unload => "plugin_unload",
    -);
    -
    -
    -sub plugin_init {
    - return %PLUGIN_INFO;
    -}
    -
    -sub button_cb {
    - my $widget = shift;
    - my $data = shift;
    - print "Clicked button with message: " . $data . "\n";
    -}
    -
    -sub foo {
    - eval '
    - use Glib;
    - use Gtk2 \'-init\';
    -
    - $frame = Gtk2::Frame->new(\'Gtk Test Frame\');
    - $button = Gtk2::Button->new(\'Print Message\');
    -
    - $frame->set_border_width(10);
    - $button->set_border_width(150);
    - $button->signal_connect("clicked" => \&button_cb, "Message Text");
    - $frame->add($button);
    -
    - $button->show();
    - $frame->show();
    - ';
    - return $frame;
    -}
    -
    -sub plugin_load {
    - my $plugin = shift;
    - print "#" x 80 . "\n";
    -
    -
    - ######### TEST CODE HERE ##########
    -
    - print "$MODULE_NAME: Loading...\n";
    -
    -
    - Purple::debug_info("plugin_load()", "Testing $MODULE_NAME Completed.");
    - print "#" x 80 . "\n\n";
    -}
    -
    -sub plugin_unload {
    -
    -}
    --- a/libpurple/plugins/perl/scripts/plugin_action.pl Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,58 +0,0 @@
    -$MODULE_NAME = "Plugin Action Test Plugin";
    -use Purple;
    -
    -sub plugin_init {
    - return %PLUGIN_INFO;
    -}
    -
    -sub plugin_load {
    - my $plugin = shift;
    -}
    -
    -sub plugin_unload {
    - my $plugin = shift;
    -}
    -
    -sub fun1 {
    - print "1\n";
    -}
    -
    -sub fun2 {
    - print "2\n";
    -}
    -
    -sub fun3 {
    - print "3\n";
    -}
    -
    -%plugin_actions = (
    - "Action 1" => \&fun1,
    - "Action 2" => \&fun2,
    - "Action 3" => \&fun3
    -# "Action 1" => sub { print "1\n"; },
    -# "Action 2" => sub { print "2\n"; },
    -# "Action 3" => sub { print "3\n"; }
    -);
    -
    -sub plugin_action_names {
    - foreach $key (keys %plugin_actions) {
    - push @array, $key;
    - }
    -
    - return @array;
    -}
    -
    -# All the information Purple gets about our nifty plugin
    -%PLUGIN_INFO = (
    - perl_api_version => 2,
    - name => "Perl: $MODULE_NAME",
    - version => "0.1",
    - summary => "Test plugin for the Perl interpreter.",
    - description => "Just a basic test plugin template.",
    - author => "Etan Reisner <deryni\@gmail.com>",
    - url => "http://sourceforge.net/users/deryni9/",
    -
    - load => "plugin_load",
    - unload => "plugin_unload",
    - plugin_action_sub => "plugin_action_names"
    -);
    --- a/libpurple/plugins/perl/scripts/plugin_pref.pl Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,103 +0,0 @@
    -$MODULE_NAME = "Prefs Functions Test";
    -use Purple;
    -# All the information Purple gets about our nifty plugin
    -%PLUGIN_INFO = (
    - perl_api_version => 2,
    - name => "Perl: $MODULE_NAME",
    - version => "0.1",
    - summary => "Test plugin for the Perl interpreter.",
    - description => "Implements a set of test proccedures to ensure all " .
    - "functions that work in the C API still work in the " .
    - "Perl plugin interface. As XSUBs are added, this " .
    - "*should* be updated to test the changes. " .
    - "Furthermore, this will function as the tutorial perl " .
    - "plugin.",
    - author => "John H. Kelm <johnhkelm\@gmail.com>",
    - url => "http://sourceforge.net/users/johnhkelm/",
    -
    - load => "plugin_load",
    - unload => "plugin_unload",
    - prefs_info => "foo"
    -);
    -
    - # These names must already exist
    - my $GROUP = "UIUC Buddies";
    - my $USERNAME = "johnhkelm2";
    -
    - # We will create these on load then destroy them on unload
    - my $TEST_GROUP = "perlTestGroup";
    - my $TEST_NAME = "perlTestName";
    - my $TEST_ALIAS = "perlTestAlias";
    - my $PROTOCOL_ID = "aim";
    -
    -sub foo {
    - $frame = Purple::PluginPref::Frame->new();
    -
    - $ppref = Purple::PluginPref->new_with_label("boolean");
    - $frame->add($ppref);
    -
    - $ppref = Purple::PluginPref->new_with_name_and_label(
    - "/plugins/core/perl_test/bool", "Boolean Preference");
    - $frame->add($ppref);
    -
    -
    - $ppref = Purple::PluginPref->new_with_name_and_label(
    - "/plugins/core/perl_test/choice", "Choice Preference");
    - $ppref->set_type(1);
    - $ppref->add_choice("ch0", "ch0-val");
    - $ppref->add_choice("ch1", "ch1-val");
    - $frame->add($ppref);
    -
    - $ppref = Purple::PluginPref->new_with_name_and_label(
    - "/plugins/core/perl_test/text", "Text Box Preference");
    - $ppref->set_max_length(16);
    - $frame->add($ppref);
    -
    - return $frame;
    -}
    -
    -sub pref_cb {
    - my ($pref, $type, $value, $data) = @_;
    -
    - print "pref changed: [$pref]($type)=$value data=$data\n";
    -}
    -
    -sub plugin_init {
    -
    - return %PLUGIN_INFO;
    -}
    -
    -# This is the sub defined in %PLUGIN_INFO to be called when the plugin is loaded
    -# Note: The plugin has a reference to itself on top of the argument stack.
    -sub plugin_load {
    - my $plugin = shift;
    - print "#" x 80 . "\n\n";
    -
    -
    - ######### TEST CODE HERE ##########
    -
    - Purple::Prefs::add_none("/plugins/core/perl_test");
    - Purple::Prefs::add_bool("/plugins/core/perl_test/bool", 1);
    - Purple::Prefs::add_string("/plugins/core/perl_test/choice", "ch1");
    - Purple::Prefs::add_string("/plugins/core/perl_test/text", "Foobar");
    -
    - Purple::Prefs::connect_callback($plugin, "/plugins/core/perl_test", \&pref_cb, "none");
    - Purple::Prefs::connect_callback($plugin, "/plugins/core/perl_test/bool", \&pref_cb, "bool");
    - Purple::Prefs::connect_callback($plugin, "/plugins/core/perl_test/choice", \&pref_cb, "choice");
    - Purple::Prefs::connect_callback($plugin, "/plugins/core/perl_test/text", \&pref_cb, "text");
    -
    - print "\n\n" . "#" x 80 . "\n\n";
    -}
    -
    -sub plugin_unload {
    - my $plugin = shift;
    -
    - print "#" x 80 . "\n\n";
    -
    -
    - ######### TEST CODE HERE ##########
    -
    -
    - print "\n\n" . "#" x 80 . "\n\n";
    -}
    -
    --- a/libpurple/plugins/perl/scripts/request.pl Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,109 +0,0 @@
    -$MODULE_NAME = "Request Functions Test";
    -
    -use Purple;
    -
    -# All the information Purple gets about our nifty plugin
    -%PLUGIN_INFO = (
    - perl_api_version => 2,
    - name => "Perl: $MODULE_NAME",
    - version => "0.1",
    - summary => "Test plugin for the Perl interpreter.",
    - description => "Implements a set of test proccedures to ensure all functions that work in the C API still work in the Perl plugin interface. As XSUBs are added, this *should* be updated to test the changes. Furthermore, this will function as the tutorial perl plugin.",
    - author => "John H. Kelm <johnhkelm\@gmail.com>",
    - url => "http://sourceforge.net/users/johnhkelm/",
    -
    - load => "plugin_load",
    - unload => "plugin_unload",
    - plugin_action_sub => "plugin_action_names"
    -);
    -
    -%plugin_actions = (
    - "Plugin Action Test Label" => \&plugin_action_test,
    -);
    -
    -sub plugin_action_names {
    - foreach $key (keys %plugin_actions) {
    - push @array, $key;
    - }
    -
    - return @array;
    -}
    -
    -sub plugin_init {
    - return %PLUGIN_INFO;
    -}
    -
    -sub ok_cb_test {
    - $fields = shift;
    -
    - Purple::Debug::info($MODULE_NAME, "plugin_action_cb_test: BEGIN\n");
    - Purple::Debug::info($MODULE_NAME, "ok_cb_test: BEGIN\n");
    - Purple::Debug::info($MODULE_NAME, "ok_cb_test: Button Click\n");
    - Purple::Debug::info($MODULE_NAME, "ok_cb_test: Field Type: $fields \n");
    - $account = Purple::Request::Fields::get_account($fields, "acct_test");
    - Purple::Debug::info($MODULE_NAME, "ok_cb_test: Username of selected account: " . Purple::Account::get_username($account) . "\n");
    - $int = Purple::Request::Fields::get_integer($fields, "int_test");
    - Purple::Debug::info($MODULE_NAME, "ok_cb_test: Integer Value: $int \n");
    - $choice = Purple::Request::Fields::get_choice($fields, "ch_test");
    - Purple::Debug::info($MODULE_NAME, "ok_cb_test: Choice Value: $choice \n");
    - Purple::Debug::info($MODULE_NAME, "ok_cb_test: END\n");
    -}
    -
    -sub cancel_cb_test {
    - Purple::Debug::info($MODULE_NAME, "cancel_cb_test: Button Click\n");
    -}
    -
    -sub plugin_action_test {
    - $plugin = shift;
    - Purple::Debug::info($MODULE_NAME, "plugin_action_cb_test: BEGIN\n");
    - plugin_request($plugin);
    - Purple::Debug::info($MODULE_NAME, "plugin_action_cb_test: END\n");
    -}
    -
    -sub plugin_load {
    - my $plugin = shift;
    - ######### TEST CODE HERE ##########
    -
    -
    -}
    -
    -sub plugin_request {
    - $group = Purple::Request::Field::Group::new("Group Name");
    - $field = Purple::Request::Field::account_new("acct_test", "Account Text", undef);
    - Purple::Request::Field::account_set_show_all($field, 0);
    - Purple::Request::Field::Group::add_field($group, $field);
    -
    - $field = Purple::Request::Field::int_new("int_test", "Integer Text", 33);
    - Purple::Request::Field::Group::add_field($group, $field);
    -
    - # Test field choice
    - $field = Purple::Request::Field::choice_new("ch_test", "Choice Text", 1);
    - Purple::Request::Field::choice_add($field, "Choice 0");
    - Purple::Request::Field::choice_add($field, "Choice 1");
    - Purple::Request::Field::choice_add($field, "Choice 2");
    -
    - Purple::Request::Field::Group::add_field($group, $field);
    -
    -
    - $request = Purple::Request::Fields::new();
    - Purple::Request::Fields::add_group($request, $group);
    -
    - Purple::Request::fields(
    - $plugin,
    - "Request Title!",
    - "Primary Title",
    - "Secondary Title",
    - $request,
    - "Ok Text", "ok_cb_test",
    - "Cancel Text", "cancel_cb_test");
    -}
    -
    -sub plugin_unload {
    - my $plugin = shift;
    - Purple::Debug::info($MODULE_NAME, "#" x 80 . "\n");
    - ######### TEST CODE HERE ##########
    -
    -
    - Purple::Debug::info($MODULE_NAME, "\n" . "#" x 80 . "\n");
    -}
    -
    --- a/libpurple/plugins/perl/scripts/signals-test.pl Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,88 +0,0 @@
    -$MODULE_NAME = "Signals Test Script in Perl";
    -
    -use Purple;
    -
    -%PLUGIN_INFO = (
    - perl_api_version => 2,
    - name => "Perl: $MODULE_NAME",
    - version => "0.1",
    - summary => "Signals Test plugin for the Perl interpreter.",
    - description => "Demonstrate the use of purple signals from " .
    - "a perl plugin.",
    - author => "Sadrul Habib Chowdhury <sadrul\@pidgin.im>",
    - url => "https://developer.pidgin.im/wiki/sadrul/",
    -
    - load => "plugin_load",
    - unload => "plugin_unload"
    -);
    -
    -# Accounts
    -sub account_connecting_cb
    -{
    - my $account = shift;
    - Purple::Debug::misc("signals test in perl", "account-connecting (" . $account->get_username() . ")\n");
    -}
    -
    -# Buddylist
    -sub buddy_signed_on
    -{
    - my $buddy = shift;
    - Purple::Debug::misc("signals test in perl", "buddy-signed-on (" . $buddy->get_name() . ")\n");
    -}
    -
    -# Connections
    -sub signed_on
    -{
    - my $conn = shift;
    - Purple::Debug::misc("signals test in perl", "signed-on (" . $conn->get_account()->get_username() . ")\n");
    -}
    -
    -# Conversations
    -sub conv_received_msg
    -{
    - my ($account, $sender, $message, $conv, $flags, $data) = @_;
    - Purple::Debug::misc("signals test in perl", "$data (" . $account->get_username() . ", $sender, $message, $flags)\n");
    -}
    -
    -sub timeout_cb
    -{
    - Purple::Debug::misc("signals test in perl", "timeout elapsed\n");
    -}
    -
    -sub plugin_load
    -{
    - my $plugin = shift;
    -
    - # Hook to the signals
    -
    - # Accounts
    - $act_handle = Purple::Accounts::get_handle();
    - Purple::Signal::connect($act_handle, "account-connecting", $plugin,
    - \&account_connecting_cb, 0);
    -
    - # Buddy List
    - $blist = Purple::BuddyList::get_handle();
    - Purple::Signal::connect($blist, "buddy-signed-on", $plugin,
    - \&buddy_signed_on, 0);
    -
    - # Connections
    - $conn = Purple::Connections::get_handle();
    - Purple::Signal::connect($conn, "signed-on", $plugin,
    - \&signed_on, 0);
    -
    - # Conversations
    - $conv = Purple::Conversations::get_handle();
    - Purple::Signal::connect($conv, "received-im-msg", $plugin,
    - \&conv_received_msg, "received im message");
    - Purple::Signal::connect($conv, "received-chat-msg", $plugin,
    - \&conv_received_msg, "received chat message");
    -
    -
    - Purple::timeout_add($plugin, 10, \&timeout_cb);
    -}
    -
    -sub plugin_unload
    -{
    - # Nothing to do here for this plugin.
    -}
    -
    --- a/libpurple/plugins/tcl/Makefile.am Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,23 +0,0 @@
    -plugindir = @PURPLE_PLUGINDIR@
    -
    -tcl_la_LDFLAGS = -module @PLUGIN_LDFLAGS@
    -
    -plugin_LTLIBRARIES = tcl.la
    -
    -tcl_la_SOURCES = tcl.c tcl_glib.c tcl_glib.h tcl_cmds.c tcl_signals.c tcl_purple.h \
    - tcl_ref.c tcl_cmd.c
    -
    -tcl_la_LIBADD = @PURPLE_LIBS@ $(GPLUGIN_LIBS) $(TCL_LIBS) $(TK_LIBS)
    -
    -EXTRA_DIST = signal-test.tcl Makefile.mingw
    -
    -AM_CPPFLAGS = \
    - -I$(top_srcdir) \
    - -I$(top_srcdir)/libpurple \
    - -I$(top_builddir)/libpurple \
    - $(DEBUG_CFLAGS) \
    - $(GLIB_CFLAGS) \
    - $(GPLUGIN_CFLAGS) \
    - $(PLUGIN_CFLAGS) \
    - $(TK_CFLAGS) \
    - $(TCL_CFLAGS)
    --- a/libpurple/plugins/tcl/Makefile.mingw Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,78 +0,0 @@
    -#
    -# Makefile.mingw
    -#
    -# Description: Makefile for tcl plugin loader plugin.
    -#
    -
    -PIDGIN_TREE_TOP := ../../..
    -include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
    -
    -TARGET = tcl
    -TCL_INC_DIR := $(TCL_LIB_TOP)/include
    -DEFINES += -DHAVE_TK -DUSE_TCL_STUBS -DUSE_TK_STUBS
    -
    -##
    -## INCLUDE PATHS
    -##
    -INCLUDE_PATHS += -I. \
    - -I$(PIDGIN_TREE_TOP) \
    - -I$(PURPLE_TOP) \
    - -I$(PURPLE_TOP)/win32 \
    - -I$(GTK_TOP)/include \
    - -I$(GTK_TOP)/include/glib-2.0 \
    - -I$(GTK_TOP)/lib/glib-2.0/include \
    - -I$(TCL_INC_DIR)
    -
    -LIB_PATHS += -L$(GTK_TOP)/lib \
    - -L$(PURPLE_TOP) \
    - -L$(TCL_LIB_TOP)/lib
    -
    -##
    -## SOURCES, OBJECTS
    -##
    -C_SRC = tcl.c \
    - tcl_cmd.c \
    - tcl_cmds.c \
    - tcl_glib.c \
    - tcl_ref.c \
    - tcl_signals.c
    -
    -OBJECTS = $(C_SRC:%.c=%.o)
    -
    -##
    -## LIBRARIES
    -##
    -LIBS = \
    - -lglib-2.0 \
    - -lgobject-2.0 \
    - -lws2_32 \
    - -lintl \
    - -lpurple \
    - -ltclstub85 \
    - -ltkstub85
    -
    -include $(PIDGIN_COMMON_RULES)
    -
    -##
    -## TARGET DEFINITIONS
    -##
    -.PHONY: all install clean
    -
    -all: $(TARGET).dll
    -
    -install: all $(PURPLE_INSTALL_PLUGINS_DIR)
    - cp $(TARGET).dll $(PURPLE_INSTALL_PLUGINS_DIR)
    -
    -$(OBJECTS): $(PURPLE_CONFIG_H)
    -
    -$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)
    - $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
    -
    -##
    -## CLEAN RULES
    -##
    -clean:
    - rm -rf $(OBJECTS)
    - rm -rf $(TARGET).dll
    -
    -include $(PIDGIN_COMMON_TARGETS)
    --- a/libpurple/plugins/tcl/signal-test.tcl Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,123 +0,0 @@
    -purple::signal connect [purple::account handle] account-away { account state message } {
    - purple::debug -info "tcl signal" "account-away [purple::account username $account] \"$state\" \"$message\""
    -}
    -
    -purple::signal connect [purple::account handle] account-connecting { account } {
    - purple::debug -info "tcl signal" "account-connecting [purple::account username $account]"
    -}
    -
    -purple::signal connect [purple::account handle] account-set-info { account info } {
    - purple::debug -info "tcl signal" "account-set-info [purple::account username $account] $info"
    -}
    -
    -purple::signal connect [purple::account handle] account-setting-info { account info } {
    - purple::debug -info "tcl signal" "account-set-info [purple::account username $account] $info"
    -}
    -
    -purple::signal connect [purple::buddy handle] buddy-away { buddy } {
    - purple::debug -info "tcl signal" "buddy-away [purple::account username [lindex $buddy 2]] [lindex $buddy 1]"
    -}
    -
    -purple::signal connect [purple::buddy handle] buddy-back { buddy } {
    - purple::debug -info "tcl signal" "buddy-back [purple::account username [lindex $buddy 2]] [lindex $buddy 1]"
    -}
    -
    -purple::signal connect [purple::buddy handle] buddy-idle { buddy } {
    - purple::debug -info "tcl signal" "buddy-idle [purple::account username [lindex $buddy 2]] [lindex $buddy 1]"
    -}
    -
    -purple::signal connect [purple::buddy handle] buddy-unidle { buddy } {
    - purple::debug -info "tcl signal" "buddy-unidle [purple::account username [lindex $buddy 2]] [lindex $buddy 1]"
    -}
    -
    -purple::signal connect [purple::buddy handle] buddy-signed-on { buddy } {
    - purple::debug -info "tcl signal" "buddy-signed-on [purple::account username [lindex $buddy 2]] [lindex $buddy 1]"
    -}
    -
    -purple::signal connect [purple::buddy handle] buddy-signed-off { buddy } {
    - purple::debug -info "tcl signal" "buddy-signed-off [purple::account username [lindex $buddy 2]] [lindex $buddy 1]"
    -}
    -
    -purple::signal connect [purple::core handle] quitting {} {
    - purple::debug -info "tcl signal" "quitting"
    -}
    -
    -purple::signal connect [purple::conversation handle] receiving-chat-msg { account who what id flags } {
    - purple::debug -info "tcl signal" "receiving-chat-msg [purple::account username $account] $id $flags $who \"$what\""
    - return 0
    -}
    -
    -purple::signal connect [purple::conversation handle] receiving-im-msg { account who what id flags } {
    - purple::debug -info "tcl signal" "receiving-im-msg [purple::account username $account] $id $flags $who \"$what\""
    - return 0
    -}
    -
    -purple::signal connect [purple::conversation handle] received-chat-msg { account who what id flags } {
    - purple::debug -info "tcl signal" "received-chat-msg [purple::account username $account] $id $flags $who \"$what\""
    -}
    -
    -purple::signal connect [purple::conversation handle] received-im-msg { account who what id flags } {
    - purple::debug -info "tcl signal" "received-im-msg [purple::account username $account] $id $flags $who \"$what\""
    -}
    -
    -purple::signal connect [purple::conversation handle] sending-chat-msg { account what id } {
    - purple::debug -info "tcl signal" "sending-chat-msg [purple::account username $account] $id \"$what\""
    - return 0
    -}
    -
    -purple::signal connect [purple::conversation handle] sending-im-msg { account who what } {
    - purple::debug -info "tcl signal" "sending-im-msg [purple::account username $account] $who \"$what\""
    - return 0
    -}
    -
    -purple::signal connect [purple::conversation handle] sent-chat-msg { account id what } {
    - purple::debug -info "tcl signal" "sent-chat-msg [purple::account username $account] $id \"$what\""
    -}
    -
    -purple::signal connect [purple::conversation handle] sent-im-msg { account who what } {
    - purple::debug -info "tcl signal" "sent-im-msg [purple::account username $account] $who \"$what\""
    -}
    -
    -purple::signal connect [purple::connection handle] signed-on { gc } {
    - purple::debug -info "tcl signal" "signed-on [purple::account username [purple::connection account $gc]]"
    -}
    -
    -purple::signal connect [purple::connection handle] signed-off { gc } {
    - purple::debug -info "tcl signal" "signed-off [purple::account username [purple::connection account $gc]]"
    -}
    -
    -purple::signal connect [purple::connection handle] signing-on { gc } {
    - purple::debug -info "tcl signal" "signing-on [purple::account username [purple::connection account $gc]]"
    -}
    -
    -if { 0 } {
    -purple::signal connect signing-off {
    - purple::debug -info "tcl signal" "signing-off [purple::account username [purple::connection account $event::gc]]"
    -}
    -
    -purple::signal connect update-idle {
    - purple::debug -info "tcl signal" "update-idle"
    -}
    -}
    -
    -purple::signal connect [purple::plugins handle] plugin-load args {
    - purple::debug -info "tcl signal" "plugin-load [list $args]"
    -}
    -
    -purple::signal connect [purple::plugins handle] plugin-unload args {
    - purple::debug -info "tcl signal" "plugin-unload [list $args]"
    -}
    -
    -purple::signal connect [purple::savedstatus handle] savedstatus-changed args {
    - purple::debug -info "tcl signal" "savedstatus-changed [list $args]"
    - purple::debug -info "tcl signal" "purple::savedstatus current = [purple::savedstatus current]"
    -}
    -
    -proc plugin_init { } {
    - list "Tcl Signal Test" \
    - "$purple::version" \
    - "Tests Tcl signal handlers" \
    - "Debugs a ridiculous amount of signal information." \
    - "Ethan Blanton <elb@pidgin.im>" \
    - "https://pidgin.im/"
    -}
    --- a/libpurple/plugins/tcl/tcl.c Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,503 +0,0 @@
    -/**
    - * @file tcl.c Purple Tcl plugin bindings
    - *
    - * purple
    - *
    - * Copyright (C) 2003 Ethan Blanton <eblanton@cs.purdue.edu>
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program 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 General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
    - */
    -
    -#include "config.h"
    -
    -#include <tcl.h>
    -
    -#ifdef HAVE_TK
    -#include <tk.h>
    -#endif
    -
    -#include <stdio.h>
    -#include <sys/types.h>
    -#include <unistd.h>
    -#include <string.h>
    -
    -#include "tcl_glib.h"
    -#include "tcl_purple.h"
    -
    -#include "internal.h"
    -#include "connection.h"
    -#include "plugins.h"
    -#include "signals.h"
    -#include "debug.h"
    -#include "util.h"
    -#include "version.h"
    -
    -struct tcl_plugin_data {
    - PurplePlugin *plugin;
    - Tcl_Interp *interp;
    -};
    -
    -typedef struct {
    - char *id;
    - char *name;
    - char *version;
    - char *summary;
    - char *description;
    - char *author;
    - char *homepage;
    -} tcl_plugin_info_strings;
    -
    -PurpleStringref *PurpleTclRefAccount;
    -PurpleStringref *PurpleTclRefConnection;
    -PurpleStringref *PurpleTclRefConversation;
    -PurpleStringref *PurpleTclRefPointer;
    -PurpleStringref *PurpleTclRefPlugin;
    -PurpleStringref *PurpleTclRefPresence;
    -PurpleStringref *PurpleTclRefStatus;
    -PurpleStringref *PurpleTclRefStatusAttr;
    -PurpleStringref *PurpleTclRefStatusType;
    -PurpleStringref *PurpleTclRefXfer;
    -PurpleStringref *PurpleTclRefHandle;
    -
    -static GHashTable *tcl_plugins = NULL;
    -
    -PurplePlugin *_tcl_plugin;
    -
    -static gboolean tcl_loaded = FALSE;
    -
    -static void tcl_plugin_info_strings_free(tcl_plugin_info_strings *strings)
    -{
    - if (strings == NULL)
    - return;
    -
    - g_free(strings->id);
    - g_free(strings->name);
    - g_free(strings->version);
    - g_free(strings->summary);
    - g_free(strings->description);
    - g_free(strings->author);
    - g_free(strings->homepage);
    - g_free(strings);
    -}
    -
    -PurplePlugin *tcl_interp_get_plugin(Tcl_Interp *interp)
    -{
    - struct tcl_plugin_data *data;
    -
    - if (tcl_plugins == NULL)
    - return NULL;
    -
    - data = g_hash_table_lookup(tcl_plugins, (gpointer)interp);
    - return data != NULL ? data->plugin : NULL;
    -}
    -
    -static int tcl_init_interp(Tcl_Interp *interp)
    -{
    - char *rcfile;
    - char init[] =
    - "namespace eval ::purple {\n"
    - " namespace export account buddy connection conversation\n"
    - " namespace export core debug notify prefs send_im\n"
    - " namespace export signal unload\n"
    - " namespace eval _callback { }\n"
    - "\n"
    - " proc conv_send { account who text } {\n"
    - " set gc [purple::account connection $account]\n"
    - " set convo [purple::conversation new $account $who]\n"
    - " set myalias [purple::account alias $account]\n"
    - "\n"
    - " if {![string length $myalias]} {\n"
    - " set myalias [purple::account username $account]\n"
    - " }\n"
    - "\n"
    - " purple::send_im $gc $who $text\n"
    - " purple::conversation write $convo send $myalias $text\n"
    - " }\n"
    - "}\n"
    - "\n"
    - "proc bgerror { message } {\n"
    - " global errorInfo\n"
    - " purple::notify -error \"Tcl Error\" \"Tcl Error: $message\" \"$errorInfo\"\n"
    - "}\n";
    -
    - if (Tcl_EvalEx(interp, init, -1, TCL_EVAL_GLOBAL) != TCL_OK) {
    - return 1;
    - }
    -
    - Tcl_SetVar(interp, "argc", "0", TCL_GLOBAL_ONLY);
    - Tcl_SetVar(interp, "argv0", "purple", TCL_GLOBAL_ONLY);
    - Tcl_SetVar(interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
    - rcfile = g_strdup_printf("%s" G_DIR_SEPARATOR_S "tclrc", purple_user_dir());
    - Tcl_SetVar(interp, "tcl_rcFileName", rcfile, TCL_GLOBAL_ONLY);
    - g_free(rcfile);
    -
    - Tcl_SetVar(interp, "::purple::version", VERSION, TCL_GLOBAL_ONLY);
    - Tcl_SetVar(interp, "::purple::user_dir", purple_user_dir(), TCL_GLOBAL_ONLY);
    -#ifdef HAVE_TK
    - Tcl_SetVar(interp, "::purple::tk_available", "1", TCL_GLOBAL_ONLY);
    -#else
    - Tcl_SetVar(interp, "::purple::tk_available", "0", TCL_GLOBAL_ONLY);
    -#endif /* HAVE_TK */
    -
    - Tcl_CreateObjCommand(interp, "::purple::account", tcl_cmd_account, (ClientData)NULL, NULL);
    - Tcl_CreateObjCommand(interp, "::purple::buddy", tcl_cmd_buddy, (ClientData)NULL, NULL);
    - Tcl_CreateObjCommand(interp, "::purple::cmd", tcl_cmd_cmd, (ClientData)NULL, NULL);
    - Tcl_CreateObjCommand(interp, "::purple::connection", tcl_cmd_connection, (ClientData)NULL, NULL);
    - Tcl_CreateObjCommand(interp, "::purple::conversation", tcl_cmd_conversation, (ClientData)NULL, NULL);
    - Tcl_CreateObjCommand(interp, "::purple::core", tcl_cmd_core, (ClientData)NULL, NULL);
    - Tcl_CreateObjCommand(interp, "::purple::debug", tcl_cmd_debug, (ClientData)NULL, NULL);
    - Tcl_CreateObjCommand(interp, "::purple::notify", tcl_cmd_notify, (ClientData)NULL, NULL);
    - Tcl_CreateObjCommand(interp, "::purple::plugins", tcl_cmd_plugins, (ClientData)NULL, NULL);
    - Tcl_CreateObjCommand(interp, "::purple::prefs", tcl_cmd_prefs, (ClientData)NULL, NULL);
    - Tcl_CreateObjCommand(interp, "::purple::presence", tcl_cmd_presence, (ClientData)NULL, NULL);
    - Tcl_CreateObjCommand(interp, "::purple::send_im", tcl_cmd_send_im, (ClientData)NULL, NULL);
    - Tcl_CreateObjCommand(interp, "::purple::savedstatus", tcl_cmd_savedstatus, (ClientData)NULL, NULL);
    - Tcl_CreateObjCommand(interp, "::purple::signal", tcl_cmd_signal, (ClientData)NULL, NULL);
    - Tcl_CreateObjCommand(interp, "::purple::status", tcl_cmd_status, (ClientData)NULL, NULL);
    - Tcl_CreateObjCommand(interp, "::purple::status_attr", tcl_cmd_status_attr, (ClientData)NULL, NULL);
    - Tcl_CreateObjCommand(interp, "::purple::status_type", tcl_cmd_status_type, (ClientData)NULL, NULL);
    - Tcl_CreateObjCommand(interp, "::purple::unload", tcl_cmd_unload, (ClientData)NULL, NULL);
    -
    - return 0;
    -}
    -
    -static Tcl_Interp *tcl_create_interp(void)
    -{
    - Tcl_Interp *interp;
    -
    - interp = Tcl_CreateInterp();
    - if (Tcl_Init(interp) == TCL_ERROR) {
    - Tcl_DeleteInterp(interp);
    - return NULL;
    - }
    -
    - if (tcl_init_interp(interp)) {
    - Tcl_DeleteInterp(interp);
    - return NULL;
    - }
    - Tcl_StaticPackage(interp, "purple", tcl_init_interp, NULL);
    -
    - return interp;
    -}
    -
    -static gboolean tcl_probe_plugin(PurplePlugin *plugin)
    -{
    - PurplePluginInfo *info;
    - Tcl_Interp *interp;
    - Tcl_Parse parse;
    - Tcl_Obj *result, **listitems;
    - char *buf;
    - const char *next;
    - int found = 0, err = 0, nelems;
    - gsize len;
    - gboolean status = FALSE;
    -
    - if (!g_file_get_contents(plugin->path, &buf, &len, NULL)) {
    - purple_debug(PURPLE_DEBUG_INFO, "tcl", "Error opening plugin %s\n",
    - plugin->path);
    - return FALSE;
    - }
    -
    - if ((interp = tcl_create_interp()) == NULL) {
    - return FALSE;
    - }
    -
    - next = buf;
    - do {
    - if (Tcl_ParseCommand(interp, next, len, 0, &parse) == TCL_ERROR) {
    - purple_debug(PURPLE_DEBUG_ERROR, "tcl", "parse error in %s: %s\n", plugin->path,
    - Tcl_GetString(Tcl_GetObjResult(interp)));
    - err = 1;
    - break;
    - }
    - if (parse.tokenPtr[0].type == TCL_TOKEN_SIMPLE_WORD
    - && !strncmp(parse.tokenPtr[0].start, "proc", parse.tokenPtr[0].size)) {
    - if (!strncmp(parse.tokenPtr[2].start, "plugin_init", parse.tokenPtr[2].size)) {
    - if (Tcl_EvalEx(interp, parse.commandStart, parse.commandSize, TCL_EVAL_GLOBAL) != TCL_OK) {
    - Tcl_FreeParse(&parse);
    - break;
    - }
    - found = 1;
    - /* We'll continue parsing the file, just in case */
    - }
    - }
    - len -= (parse.commandStart + parse.commandSize) - next;
    - next = parse.commandStart + parse.commandSize;
    - Tcl_FreeParse(&parse);
    - } while (len);
    -
    - if (found && !err) {
    - if (Tcl_EvalEx(interp, "plugin_init", -1, TCL_EVAL_GLOBAL) == TCL_OK) {
    - result = Tcl_GetObjResult(interp);
    - if (Tcl_ListObjGetElements(interp, result, &nelems, &listitems) == TCL_OK) {
    - if ((nelems == 6) || (nelems == 7)) {
    - tcl_plugin_info_strings *strings = g_new0(tcl_plugin_info_strings, 1);
    - info = g_new0(PurplePluginInfo, 1);
    - info->extra_info = strings;
    -
    - info->magic = PURPLE_PLUGIN_MAGIC;
    - info->major_version = PURPLE_MAJOR_VERSION;
    - info->minor_version = PURPLE_MINOR_VERSION;
    - info->type = PURPLE_PLUGIN_STANDARD;
    - info->dependencies = g_list_append(info->dependencies, "core-tcl");
    -
    - info->name = strings->name = g_strdup(Tcl_GetString(listitems[0]));
    - info->version = strings->version = g_strdup(Tcl_GetString(listitems[1]));
    - info->summary = strings->summary = g_strdup(Tcl_GetString(listitems[2]));
    - info->description = strings->description = g_strdup(Tcl_GetString(listitems[3]));
    - info->author = strings->author = g_strdup(Tcl_GetString(listitems[4]));
    - info->homepage = strings->homepage = g_strdup(Tcl_GetString(listitems[5]));
    -
    - if (nelems == 6)
    - info->id = strings->id = g_strdup_printf("tcl-%s", Tcl_GetString(listitems[0]));
    - else if (nelems == 7)
    - info->id = strings->id = g_strdup_printf("tcl-%s", Tcl_GetString(listitems[6]));
    -
    - plugin->info = info;
    -
    - if (purple_plugin_register(plugin))
    - status = TRUE;
    - }
    - }
    - }
    - }
    -
    - Tcl_DeleteInterp(interp);
    - g_free(buf);
    - return status;
    -}
    -
    -static gboolean tcl_load_plugin(PurplePlugin *plugin)
    -{
    - struct tcl_plugin_data *data;
    - Tcl_Interp *interp;
    - Tcl_Obj *result;
    -
    - plugin->extra = NULL;
    -
    - if ((interp = tcl_create_interp()) == NULL) {
    - purple_debug(PURPLE_DEBUG_ERROR, "tcl", "Could not initialize Tcl interpreter\n");
    - return FALSE;
    - }
    -
    - Tcl_SourceRCFile(interp);
    -
    - if (Tcl_EvalFile(interp, plugin->path) != TCL_OK) {
    - result = Tcl_GetObjResult(interp);
    - purple_debug(PURPLE_DEBUG_ERROR, "tcl",
    - "Error evaluating %s: %s\n", plugin->path,
    - Tcl_GetString(result));
    - Tcl_DeleteInterp(interp);
    - return FALSE;
    - }
    -
    - Tcl_Preserve((ClientData)interp);
    -
    - data = g_new0(struct tcl_plugin_data, 1);
    - data->plugin = plugin;
    - data->interp = interp;
    - plugin->extra = data;
    -
    - g_hash_table_insert(tcl_plugins, (gpointer)interp, (gpointer)data);
    -
    - return TRUE;
    -}
    -
    -static gboolean tcl_unload_plugin(PurplePlugin *plugin)
    -{
    - struct tcl_plugin_data *data;
    -
    - if (plugin == NULL)
    - return TRUE;
    -
    - data = plugin->extra;
    -
    - if (data != NULL) {
    - g_hash_table_remove(tcl_plugins, (gpointer)(data->interp));
    - purple_signals_disconnect_by_handle(data->interp);
    - tcl_cmd_cleanup(data->interp);
    - tcl_signal_cleanup(data->interp);
    - Tcl_Release((ClientData)data->interp);
    - Tcl_DeleteInterp(data->interp);
    - g_free(data);
    - }
    -
    - return TRUE;
    -}
    -
    -static void tcl_destroy_plugin(PurplePlugin *plugin)
    -{
    - if (plugin->info != NULL) {
    - tcl_plugin_info_strings *info_strings = plugin->info->extra_info;
    - tcl_plugin_info_strings_free(info_strings);
    - plugin->info->extra_info = NULL;
    - }
    -
    - return;
    -}
    -
    -static PurplePluginLoaderInfo tcl_loader_info =
    -{
    - tcl_probe_plugin,
    - tcl_load_plugin,
    - tcl_unload_plugin,
    - tcl_destroy_plugin,
    -};
    -
    -static GPluginPluginInfo *
    -tcl_query(GError **error)
    -{
    - const gchar * const authors[] = {
    - "Ethan Blanton <eblanton@cs.purdue.edu>",
    - NULL
    - };
    -
    - return gplugin_plugin_info_new(
    - "id", "core-tcl",
    - "name", N_("Tcl Plugin Loader"),
    - "version", DISPLAY_VERSION,
    - "category", N_("Loader"),
    - "summary", N_("Provides support for loading Tcl plugins"),
    - "description", N_("Provides support for loading Tcl plugins"),
    - "authors", authors,
    - "website", PURPLE_WEBSITE,
    - "abi-version", PURPLE_ABI_VERSION,
    - "internal", TRUE,
    - "load-on-query", TRUE,
    - NULL
    - );
    -}
    -
    -static gboolean tcl_load(PurplePlugin *plugin, GError **error)
    -{
    - if(!tcl_loaded)
    - return FALSE;
    - tcl_glib_init();
    - tcl_cmd_init();
    - tcl_signal_init();
    - purple_tcl_ref_init();
    -
    - PurpleTclRefAccount = purple_stringref_new("Account");
    - PurpleTclRefConnection = purple_stringref_new("Connection");
    - PurpleTclRefConversation = purple_stringref_new("Conversation");
    - PurpleTclRefPointer = purple_stringref_new("Pointer");
    - PurpleTclRefPlugin = purple_stringref_new("Plugin");
    - PurpleTclRefPresence = purple_stringref_new("Presence");
    - PurpleTclRefStatus = purple_stringref_new("Status");
    - PurpleTclRefStatusAttr = purple_stringref_new("StatusAttr");
    - PurpleTclRefStatusType = purple_stringref_new("StatusType");
    - PurpleTclRefXfer = purple_stringref_new("Xfer");
    - PurpleTclRefHandle = purple_stringref_new("Handle");
    -
    - tcl_plugins = g_hash_table_new(g_direct_hash, g_direct_equal);
    -
    -#ifdef HAVE_TK
    - Tcl_StaticPackage(NULL, "Tk", Tk_Init, Tk_SafeInit);
    -#endif /* HAVE_TK */
    -
    - return TRUE;
    -}
    -
    -static gboolean tcl_unload(PurplePlugin *plugin, GError **error)
    -{
    - g_hash_table_destroy(tcl_plugins);
    - tcl_plugins = NULL;
    -
    - purple_stringref_unref(PurpleTclRefAccount);
    - purple_stringref_unref(PurpleTclRefConnection);
    - purple_stringref_unref(PurpleTclRefConversation);
    - purple_stringref_unref(PurpleTclRefPointer);
    - purple_stringref_unref(PurpleTclRefPlugin);
    - purple_stringref_unref(PurpleTclRefPresence);
    - purple_stringref_unref(PurpleTclRefStatus);
    - purple_stringref_unref(PurpleTclRefStatusAttr);
    - purple_stringref_unref(PurpleTclRefStatusType);
    - purple_stringref_unref(PurpleTclRefXfer);
    -
    - return TRUE;
    -}
    -
    -#ifdef _WIN32
    -typedef Tcl_Interp* (__cdecl* LPFNTCLCREATEINTERP)(void);
    -typedef void (__cdecl* LPFNTKINIT)(Tcl_Interp*);
    -
    -LPFNTCLCREATEINTERP wtcl_CreateInterp = NULL;
    -LPFNTKINIT wtk_Init = NULL;
    -#undef Tcl_CreateInterp
    -#define Tcl_CreateInterp wtcl_CreateInterp
    -#undef Tk_Init
    -#define Tk_Init wtk_Init
    -
    -static gboolean tcl_win32_init() {
    - gboolean retval = FALSE;
    -
    - if(!(wtcl_CreateInterp = (LPFNTCLCREATEINTERP) wpurple_find_and_loadproc("tcl85.dll", "Tcl_CreateInterp"))) {
    - purple_debug(PURPLE_DEBUG_INFO, "tcl", "tcl_win32_init error loading Tcl_CreateInterp\n");
    - } else {
    - if(!(wtk_Init = (LPFNTKINIT) wpurple_find_and_loadproc("tk85.dll", "Tk_Init"))) {
    - HMODULE mod;
    - purple_debug(PURPLE_DEBUG_INFO, "tcl", "tcl_win32_init error loading Tk_Init\n");
    - if((mod = GetModuleHandle("tcl85.dll")))
    - FreeLibrary(mod);
    - } else {
    - retval = TRUE;
    - }
    - }
    -
    - return retval;
    -}
    -
    -#endif /* _WIN32 */
    -
    -static void tcl_init_plugin(PurplePlugin *plugin)
    -{
    -#ifdef USE_TCL_STUBS
    - Tcl_Interp *interp = NULL;
    -#endif
    - _tcl_plugin = plugin;
    -
    -#ifdef USE_TCL_STUBS
    -#ifdef _WIN32
    - if(!tcl_win32_init())
    - return;
    -#endif
    - if(!(interp = Tcl_CreateInterp()))
    - return;
    -
    - if(!Tcl_InitStubs(interp, TCL_VERSION, 0)) {
    - purple_debug(PURPLE_DEBUG_ERROR, "tcl", "Tcl_InitStubs: %s\n", interp->result);
    - return;
    - }
    -#endif
    -
    - Tcl_FindExecutable("purple");
    -
    -#if defined(USE_TK_STUBS) && defined(HAVE_TK)
    - Tk_Init(interp);
    -
    - if(!Tk_InitStubs(interp, TK_VERSION, 0)) {
    - purple_debug(PURPLE_DEBUG_ERROR, "tcl", "Error Tk_InitStubs: %s\n", interp->result);
    - Tcl_DeleteInterp(interp);
    - return;
    - }
    -#endif
    - tcl_loaded = TRUE;
    -#ifdef USE_TCL_STUBS
    - Tcl_DeleteInterp(interp);
    -#endif
    - tcl_loader_info.exts = g_list_append(tcl_loader_info.exts, "tcl");
    -}
    -
    -PURPLE_PLUGIN_INIT(tcl, tcl_query, tcl_load, tcl_unload);
    --- a/libpurple/plugins/tcl/tcl_cmd.c Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,189 +0,0 @@
    -/**
    - * @file tcl_cmd.c Purple Tcl cmd API
    - *
    - * purple
    - *
    - * Copyright (C) 2006 Etan Reisner <deryni@gmail.com>
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program 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 General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
    - */
    -#include <tcl.h>
    -
    -#include "tcl_purple.h"
    -
    -#include "internal.h"
    -#include "cmds.h"
    -#include "debug.h"
    -
    -static GList *tcl_cmd_callbacks;
    -
    -static PurpleCmdRet tcl_cmd_callback(PurpleConversation *conv, const gchar *cmd,
    - gchar **args, gchar **errors,
    - struct tcl_cmd_handler *handler);
    -static Tcl_Obj *new_cmd_cb_namespace(void);
    -
    -void tcl_cmd_init()
    -{
    - tcl_cmd_callbacks = NULL;
    -}
    -
    -void tcl_cmd_handler_free(struct tcl_cmd_handler *handler)
    -{
    - if (handler == NULL)
    - return;
    -
    - Tcl_DecrRefCount(handler->namespace);
    - g_free(handler);
    -}
    -
    -void tcl_cmd_cleanup(Tcl_Interp *interp)
    -{
    - GList *cur;
    - struct tcl_cmd_handler *handler;
    -
    - for (cur = tcl_cmd_callbacks; cur != NULL; cur = g_list_next(cur)) {
    - handler = cur->data;
    - if (handler->interp == interp) {
    - purple_cmd_unregister(handler->id);
    - tcl_cmd_handler_free(handler);
    - cur->data = NULL;
    - }
    - }
    - tcl_cmd_callbacks = g_list_remove_all(tcl_cmd_callbacks, NULL);
    -}
    -
    -PurpleCmdId tcl_cmd_register(struct tcl_cmd_handler *handler)
    -{
    - int id;
    - GString *proc;
    -
    - if ((id = purple_cmd_register(Tcl_GetString(handler->cmd),
    - handler->args, handler->priority,
    - handler->flags, handler->protocol_id,
    - PURPLE_CMD_FUNC(tcl_cmd_callback),
    - handler->helpstr, (void *)handler)) == 0)
    - return 0;
    -
    - handler->namespace = new_cmd_cb_namespace ();
    - Tcl_IncrRefCount(handler->namespace);
    - proc = g_string_new("");
    - g_string_append_printf(proc, "namespace eval %s { proc cb { conv cmd arglist } { %s } }",
    - Tcl_GetString(handler->namespace),
    - Tcl_GetString(handler->proc));
    - if (Tcl_Eval(handler->interp, proc->str) != TCL_OK) {
    - Tcl_DecrRefCount(handler->namespace);
    - g_string_free(proc, TRUE);
    - return 0;
    - }
    - g_string_free(proc, TRUE);
    -
    - tcl_cmd_callbacks = g_list_append(tcl_cmd_callbacks, (gpointer)handler);
    -
    - return id;
    -}
    -
    -void tcl_cmd_unregister(PurpleCmdId id, Tcl_Interp *interp)
    -{
    - GList *cur;
    - GString *cmd;
    - gboolean found = FALSE;
    - struct tcl_cmd_handler *handler;
    -
    - for (cur = tcl_cmd_callbacks; cur != NULL; cur = g_list_next(cur)) {
    - handler = cur->data;
    - if (handler->interp == interp && handler->id == id) {
    - purple_cmd_unregister(id);
    - cmd = g_string_sized_new(64);
    - g_string_printf(cmd, "namespace delete %s",
    - Tcl_GetString(handler->namespace));
    - Tcl_EvalEx(interp, cmd->str, -1, TCL_EVAL_GLOBAL);
    - tcl_cmd_handler_free(handler);
    - g_string_free(cmd, TRUE);
    - cur->data = NULL;
    - found = TRUE;
    - break;
    - }
    - }
    -
    - if (found)
    - tcl_cmd_callbacks = g_list_remove_all(tcl_cmd_callbacks, NULL);
    -}
    -
    -static PurpleCmdRet tcl_cmd_callback(PurpleConversation *conv, const gchar *cmd,
    - gchar **args, gchar **errors,
    - struct tcl_cmd_handler *handler)
    -{
    - int retval, i;
    - Tcl_Obj *command, *arg, *tclargs, *result;
    -
    - command = Tcl_NewListObj(0, NULL);
    - Tcl_IncrRefCount(command);
    -
    - /* The callback */
    - arg = Tcl_DuplicateObj(handler->namespace);
    - Tcl_AppendStringsToObj(arg, "::cb", NULL);
    - Tcl_ListObjAppendElement(handler->interp, command, arg);
    -
    - /* The conversation */
    - arg = purple_tcl_ref_new(PurpleTclRefConversation, conv);
    - Tcl_ListObjAppendElement(handler->interp, command, arg);
    -
    - /* The command */
    - arg = Tcl_NewStringObj(cmd, -1);
    - Tcl_ListObjAppendElement(handler->interp, command, arg);
    -
    - /* The args list */
    - tclargs = Tcl_NewListObj(0, NULL);
    - for (i = 0; i < handler->nargs; i++) {
    - arg = Tcl_NewStringObj(args[i], -1);
    -
    - Tcl_ListObjAppendElement(handler->interp, tclargs, arg);
    - }
    - Tcl_ListObjAppendElement(handler->interp, command, tclargs);
    -
    - if (Tcl_EvalObjEx(handler->interp, command, TCL_EVAL_GLOBAL) != TCL_OK) {
    - gchar *errorstr;
    -
    - errorstr = g_strdup_printf("error evaluating callback: %s\n",
    - Tcl_GetString(Tcl_GetObjResult(handler->interp)));
    - purple_debug(PURPLE_DEBUG_ERROR, "tcl", "%s", errorstr);
    - *errors = errorstr;
    - retval = PURPLE_CMD_RET_FAILED;
    - } else {
    - result = Tcl_GetObjResult(handler->interp);
    - if (Tcl_GetIntFromObj(handler->interp, result,
    - &retval) != TCL_OK) {
    - gchar *errorstr;
    -
    - errorstr = g_strdup_printf("Error retreiving procedure result: %s\n",
    - Tcl_GetString(Tcl_GetObjResult(handler->interp)));
    - purple_debug(PURPLE_DEBUG_ERROR, "tcl", "%s", errorstr);
    - *errors = errorstr;
    - retval = PURPLE_CMD_RET_FAILED;
    - }
    - }
    -
    - return retval;
    -}
    -
    -static Tcl_Obj *new_cmd_cb_namespace()
    -{
    - char name[32];
    - static int cbnum;
    -
    - g_snprintf(name, sizeof(name), "::purple::_cmd_callback::cb_%d",
    - cbnum++);
    - return Tcl_NewStringObj(name, -1);
    -}
    --- a/libpurple/plugins/tcl/tcl_cmds.c Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,1769 +0,0 @@
    -/**
    - * @file tcl_cmds.c Commands for the Purple Tcl plugin bindings
    - *
    - * purple
    - *
    - * Copyright (C) 2003 Ethan Blanton <eblanton@cs.purdue.edu>
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program 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 General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
    - */
    -
    -#include <tcl.h>
    -
    -#include "internal.h"
    -#include "conversation.h"
    -#include "connection.h"
    -#include "eventloop.h"
    -#include "account.h"
    -#include "server.h"
    -#include "notify.h"
    -#include "buddylist.h"
    -#include "savedstatuses.h"
    -#include "debug.h"
    -#include "prefs.h"
    -#include "presence.h"
    -#include "core.h"
    -
    -#include "tcl_purple.h"
    -
    -static PurpleAccount *tcl_validate_account(Tcl_Obj *obj, Tcl_Interp *interp);
    -static PurpleConversation *tcl_validate_conversation(Tcl_Obj *obj, Tcl_Interp *interp);
    -static PurpleConnection *tcl_validate_gc(Tcl_Obj *obj, Tcl_Interp *interp);
    -
    -static PurpleAccount *tcl_validate_account(Tcl_Obj *obj, Tcl_Interp *interp)
    -{
    - PurpleAccount *account;
    - GList *cur;
    -
    - account = purple_tcl_ref_get(interp, obj, PurpleTclRefAccount);
    -
    - if (account == NULL)
    - return NULL;
    -
    - for (cur = purple_accounts_get_all(); cur != NULL; cur = g_list_next(cur)) {
    - if (account == cur->data)
    - return account;
    - }
    - if (interp != NULL)
    - Tcl_SetObjResult(interp, Tcl_NewStringObj("invalid account", -1));
    - return NULL;
    -}
    -
    -static PurpleConversation *tcl_validate_conversation(Tcl_Obj *obj, Tcl_Interp *interp)
    -{
    - PurpleConversation *convo;
    - GList *cur;
    -
    - convo = purple_tcl_ref_get(interp, obj, PurpleTclRefConversation);
    -
    - if (convo == NULL)
    - return NULL;
    -
    - for (cur = purple_conversations_get_all(); cur != NULL; cur = g_list_next(cur)) {
    - if (convo == cur->data)
    - return convo;
    - }
    - if (interp != NULL)
    - Tcl_SetObjResult(interp, Tcl_NewStringObj("invalid conversation", -1));
    - return NULL;
    -}
    -
    -static PurpleConnection *tcl_validate_gc(Tcl_Obj *obj, Tcl_Interp *interp)
    -{
    - PurpleConnection *gc;
    - GList *cur;
    -
    - gc = purple_tcl_ref_get(interp, obj, PurpleTclRefConnection);
    -
    - if (gc == NULL)
    - return NULL;
    -
    - for (cur = purple_connections_get_all(); cur != NULL; cur = g_list_next(cur)) {
    - if (gc == cur->data)
    - return gc;
    - }
    - return NULL;
    -}
    -
    -int tcl_cmd_account(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
    -{
    - Tcl_Obj *result, *list, *elem;
    - const char *cmds[] = { "alias", "connect", "connection", "disconnect",
    - "enabled", "find", "handle", "isconnected",
    - "list", "presence", "protocol", "status",
    - "status_type", "status_types", "username",
    - NULL };
    - enum { CMD_ACCOUNT_ALIAS,
    - CMD_ACCOUNT_CONNECT, CMD_ACCOUNT_CONNECTION,
    - CMD_ACCOUNT_DISCONNECT, CMD_ACCOUNT_ENABLED, CMD_ACCOUNT_FIND,
    - CMD_ACCOUNT_HANDLE, CMD_ACCOUNT_ISCONNECTED, CMD_ACCOUNT_LIST,
    - CMD_ACCOUNT_PRESENCE, CMD_ACCOUNT_PROTOCOL, CMD_ACCOUNT_STATUS,
    - CMD_ACCOUNT_STATUS_TYPE, CMD_ACCOUNT_STATUS_TYPES,
    - CMD_ACCOUNT_USERNAME } cmd;
    - const char *listopts[] = { "-all", "-online", NULL };
    - enum { CMD_ACCOUNTLIST_ALL, CMD_ACCOUNTLIST_ONLINE } listopt;
    - const char *alias;
    - GList *cur;
    - PurpleAccount *account;
    - PurpleStatus *status;
    - PurpleStatusType *status_type;
    - GValue *value;
    - char *attr_id;
    - int error;
    - int b, i;
    -
    - if (objc < 2) {
    - Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
    - return TCL_ERROR;
    - }
    -
    - if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
    - return error;
    -
    - switch (cmd) {
    - case CMD_ACCOUNT_ALIAS:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "account");
    - return TCL_ERROR;
    - }
    - if ((account = tcl_validate_account(objv[2], interp)) == NULL)
    - return TCL_ERROR;
    - alias = purple_account_get_private_alias(account);
    - Tcl_SetObjResult(interp, Tcl_NewStringObj(alias ? (char *)alias : "", -1));
    - break;
    - case CMD_ACCOUNT_CONNECT:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "account");
    - return TCL_ERROR;
    - }
    - if ((account = tcl_validate_account(objv[2], interp)) == NULL)
    - return TCL_ERROR;
    - if (!purple_account_is_connected(account))
    - purple_account_connect(account);
    - Tcl_SetObjResult(interp,
    - purple_tcl_ref_new(PurpleTclRefConnection,
    - purple_account_get_connection(account)));
    - break;
    - case CMD_ACCOUNT_CONNECTION:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "account");
    - return TCL_ERROR;
    - }
    -
    - if ((account = tcl_validate_account(objv[2], interp)) == NULL)
    - return TCL_ERROR;
    - Tcl_SetObjResult(interp,
    - purple_tcl_ref_new(PurpleTclRefConnection,
    - purple_account_get_connection(account)));
    - break;
    - case CMD_ACCOUNT_DISCONNECT:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "account");
    - return TCL_ERROR;
    - }
    - if ((account = tcl_validate_account(objv[2], interp)) == NULL)
    - return TCL_ERROR;
    - purple_account_disconnect(account);
    - break;
    - case CMD_ACCOUNT_ENABLED:
    - if (objc != 3 && objc != 4) {
    - Tcl_WrongNumArgs(interp, 2, objv, "account ?enabled?");
    - return TCL_ERROR;
    - }
    - if ((account = tcl_validate_account(objv[2], interp)) == NULL)
    - return TCL_ERROR;
    - if (objc == 3) {
    - Tcl_SetObjResult(interp,
    - Tcl_NewBooleanObj(
    - purple_account_get_enabled(account,
    - purple_core_get_ui())));
    - } else {
    - if ((error = Tcl_GetBooleanFromObj(interp, objv[3], &b)) != TCL_OK)
    - return TCL_ERROR;
    - purple_account_set_enabled(account, purple_core_get_ui(), b);
    - }
    - break;
    - case CMD_ACCOUNT_FIND:
    - if (objc != 4) {
    - Tcl_WrongNumArgs(interp, 2, objv, "username protocol");
    - return TCL_ERROR;
    - }
    - account = purple_accounts_find(Tcl_GetString(objv[2]),
    - Tcl_GetString(objv[3]));
    - Tcl_SetObjResult(interp,
    - purple_tcl_ref_new(PurpleTclRefAccount, account));
    - break;
    - case CMD_ACCOUNT_HANDLE:
    - if (objc != 2) {
    - Tcl_WrongNumArgs(interp, 2, objv, "");
    - return TCL_ERROR;
    - }
    - Tcl_SetObjResult(interp,
    - purple_tcl_ref_new(PurpleTclRefHandle,
    - purple_accounts_get_handle()));
    - break;
    - case CMD_ACCOUNT_ISCONNECTED:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "account");
    - return TCL_ERROR;
    - }
    - if ((account = tcl_validate_account(objv[2], interp)) == NULL)
    - return TCL_ERROR;
    - Tcl_SetObjResult(interp,
    - Tcl_NewBooleanObj(
    - purple_account_is_connected(account)));
    - break;
    - case CMD_ACCOUNT_LIST:
    - listopt = CMD_ACCOUNTLIST_ALL;
    - if (objc > 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "?option?");
    - return TCL_ERROR;
    - }
    - if (objc == 3) {
    - if ((error = Tcl_GetIndexFromObj(interp, objv[2], listopts, "option", 0, (int *)&listopt)) != TCL_OK)
    - return error;
    - }
    - list = Tcl_NewListObj(0, NULL);
    - for (cur = purple_accounts_get_all(); cur != NULL; cur = g_list_next(cur)) {
    - account = cur->data;
    - if (listopt == CMD_ACCOUNTLIST_ONLINE && !purple_account_is_connected(account))
    - continue;
    - elem = purple_tcl_ref_new(PurpleTclRefAccount, account);
    - Tcl_ListObjAppendElement(interp, list, elem);
    - }
    - Tcl_SetObjResult(interp, list);
    - break;
    - case CMD_ACCOUNT_PRESENCE:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "account");
    - return TCL_ERROR;
    - }
    - if ((account = tcl_validate_account(objv[2], interp)) == NULL)
    - return TCL_ERROR;
    - Tcl_SetObjResult(interp, purple_tcl_ref_new(PurpleTclRefPresence,
    - purple_account_get_presence(account)));
    - break;
    - case CMD_ACCOUNT_PROTOCOL:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "account");
    - return TCL_ERROR;
    - }
    - if ((account = tcl_validate_account(objv[2], interp)) == NULL)
    - return TCL_ERROR;
    - Tcl_SetObjResult(interp, Tcl_NewStringObj((char *)purple_account_get_protocol_id(account), -1));
    - break;
    - case CMD_ACCOUNT_STATUS:
    - if (objc < 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "account ?status_id name value ...?");
    - return TCL_ERROR;
    - }
    - if ((account = tcl_validate_account(objv[2], interp)) == NULL)
    - return TCL_ERROR;
    - if (objc == 3) {
    - Tcl_SetObjResult(interp,
    - purple_tcl_ref_new(PurpleTclRefStatus,
    - purple_account_get_active_status(account)));
    - } else {
    - GList *l = NULL;
    - if (objc % 2) {
    - Tcl_SetObjResult(interp, Tcl_NewStringObj("name without value setting status", -1));
    - return TCL_ERROR;
    - }
    - status = purple_account_get_status(account, Tcl_GetString(objv[3]));
    - if (status == NULL) {
    - Tcl_SetObjResult(interp, Tcl_NewStringObj("invalid status for account", -1));
    - return TCL_ERROR;
    - }
    - for (i = 4; i < objc; i += 2) {
    - attr_id = Tcl_GetString(objv[i]);
    - value = purple_status_get_attr_value(status, attr_id);
    - if (value == NULL) {
    - Tcl_SetObjResult(interp, Tcl_NewStringObj("invalid attribute for account", -1));
    - return TCL_ERROR;
    - }
    - switch (G_VALUE_TYPE(value)) {
    - case G_TYPE_BOOLEAN:
    - error = Tcl_GetBooleanFromObj(interp, objv[i + 1], &b);
    - if (error != TCL_OK)
    - return error;
    - l = g_list_append(l, attr_id);
    - l = g_list_append(l, GINT_TO_POINTER(b));
    - break;
    - case G_TYPE_INT:
    - error = Tcl_GetIntFromObj(interp, objv[i + 1], &b);
    - if (error != TCL_OK)
    - return error;
    - l = g_list_append(l, attr_id);
    - l = g_list_append(l, GINT_TO_POINTER(b));
    - break;
    - case G_TYPE_STRING:
    - l = g_list_append(l, attr_id);
    - l = g_list_append(l, Tcl_GetString(objv[i + 1]));
    - break;
    - default:
    - Tcl_SetObjResult(interp, Tcl_NewStringObj("unknown GValue type", -1));
    - return TCL_ERROR;
    - }
    - }
    - purple_account_set_status_list(account, Tcl_GetString(objv[3]), TRUE, l);
    - g_list_free(l);
    - }
    - break;
    - case CMD_ACCOUNT_STATUS_TYPE:
    - if (objc != 4 && objc != 5) {
    - Tcl_WrongNumArgs(interp, 2, objv, "account ?statustype? ?-primitive primitive?");
    - return TCL_ERROR;
    - }
    - if ((account = tcl_validate_account(objv[2], interp)) == NULL)
    - return TCL_ERROR;
    - if (objc == 4) {
    - status_type = purple_account_get_status_type(account,
    - Tcl_GetString(objv[3]));
    - } else {
    - PurpleStatusPrimitive primitive;
    - if (strcmp(Tcl_GetString(objv[3]), "-primitive")) {
    - result = Tcl_NewStringObj("bad option \"", -1);
    - Tcl_AppendObjToObj(result, objv[3]);
    - Tcl_AppendToObj(result, "\": should be -primitive", -1);
    - Tcl_SetObjResult(interp,result);
    - return TCL_ERROR;
    - }
    - primitive = purple_primitive_get_type_from_id(Tcl_GetString(objv[4]));
    - status_type = purple_account_get_status_type_with_primitive(account,
    - primitive);
    - }
    - if (status_type == NULL) {
    - Tcl_SetObjResult(interp, Tcl_NewStringObj("status type not found", -1));
    - return TCL_ERROR;
    - }
    - Tcl_SetObjResult(interp,
    - purple_tcl_ref_new(PurpleTclRefStatusType,
    - status_type));
    - break;
    - case CMD_ACCOUNT_STATUS_TYPES:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "account");
    - return TCL_ERROR;
    - }
    - if ((account = tcl_validate_account(objv[2], interp)) == NULL)
    - return TCL_ERROR;
    - list = Tcl_NewListObj(0, NULL);
    - for (cur = purple_account_get_status_types(account); cur != NULL;
    - cur = g_list_next(cur)) {
    - Tcl_ListObjAppendElement(interp, list,
    - purple_tcl_ref_new(PurpleTclRefStatusType,
    - cur->data));
    - }
    - Tcl_SetObjResult(interp, list);
    - break;
    - case CMD_ACCOUNT_USERNAME:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "account");
    - return TCL_ERROR;
    - }
    - if ((account = tcl_validate_account(objv[2], interp)) == NULL)
    - return TCL_ERROR;
    - Tcl_SetObjResult(interp,
    - Tcl_NewStringObj((char *)purple_account_get_username(account), -1));
    - break;
    - }
    -
    - return TCL_OK;
    -}
    -
    -static PurpleBlistNode *tcl_list_to_buddy(Tcl_Interp *interp, int count, Tcl_Obj **elems)
    -{
    - PurpleBlistNode *node = NULL;
    - PurpleAccount *account;
    - char *name;
    - char *type;
    -
    - if (count < 3) {
    - Tcl_SetObjResult(interp,
    - Tcl_NewStringObj("list too short", -1));
    - return NULL;
    - }
    -
    - type = Tcl_GetString(elems[0]);
    - name = Tcl_GetString(elems[1]);
    - if ((account = tcl_validate_account(elems[2], interp)) == NULL)
    - return NULL;
    -
    - if (!strcmp(type, "buddy")) {
    - node = PURPLE_BLIST_NODE(purple_blist_find_buddy(account, name));
    - } else if (!strcmp(type, "group")) {
    - node = PURPLE_BLIST_NODE(purple_blist_find_chat(account, name));
    - }
    -
    - return node;
    -}
    -
    -int tcl_cmd_buddy(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
    -{
    - Tcl_Obj *list, *tclgroup, *tclgrouplist, *tclcontact, *tclcontactlist, *tclbud, **elems, *result;
    - const char *cmds[] = { "alias", "handle", "info", "list", NULL };
    - enum { CMD_BUDDY_ALIAS, CMD_BUDDY_HANDLE, CMD_BUDDY_INFO, CMD_BUDDY_LIST } cmd;
    - PurpleBlistNode *node, *gnode, *bnode;
    - PurpleAccount *account;
    - PurpleBuddy *bud;
    - PurpleChat *cnode;
    - int error, all = 0, count;
    -
    - if (objc < 2) {
    - Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
    - return TCL_ERROR;
    - }
    - if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
    - return error;
    -
    - switch (cmd) {
    - case CMD_BUDDY_ALIAS:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "buddy");
    - return TCL_ERROR;
    - }
    - if ((error = Tcl_ListObjGetElements(interp, objv[2], &count, &elems)) != TCL_OK)
    - return error;
    - if ((node = tcl_list_to_buddy(interp, count, elems)) == NULL)
    - return TCL_ERROR;
    - if (PURPLE_IS_CHAT(node))
    - Tcl_SetObjResult(interp,
    - Tcl_NewStringObj(purple_chat_get_name(PURPLE_CHAT(node)), -1));
    - else if (PURPLE_IS_BUDDY(node))
    - Tcl_SetObjResult(interp,
    - Tcl_NewStringObj((char *)purple_buddy_get_alias(PURPLE_BUDDY(node)), -1));
    - return TCL_OK;
    - break;
    - case CMD_BUDDY_HANDLE:
    - if (objc != 2) {
    - Tcl_WrongNumArgs(interp, 2, objv, "");
    - return TCL_ERROR;
    - }
    - Tcl_SetObjResult(interp,
    - purple_tcl_ref_new(PurpleTclRefHandle,
    - purple_blist_get_handle()));
    - break;
    - case CMD_BUDDY_INFO:
    - if (objc != 3 && objc != 4) {
    - Tcl_WrongNumArgs(interp, 2, objv, "( buddy | account username )");
    - return TCL_ERROR;
    - }
    - if (objc == 3) {
    - if ((error = Tcl_ListObjGetElements(interp, objv[2], &count, &elems)) != TCL_OK)
    - return error;
    - if (count < 3) {
    - Tcl_SetObjResult(interp,
    - Tcl_NewStringObj("buddy too short", -1));
    - return TCL_ERROR;
    - }
    - if (strcmp("buddy", Tcl_GetString(elems[0]))) {
    - Tcl_SetObjResult(interp,
    - Tcl_NewStringObj("invalid buddy", -1));
    - return TCL_ERROR;
    - }
    - if ((account = tcl_validate_account(elems[2], interp)) == NULL)
    - return TCL_ERROR;
    - purple_serv_get_info(purple_account_get_connection(account), Tcl_GetString(elems[1]));
    - } else {
    - if ((account = tcl_validate_account(objv[2], interp)) == NULL)
    - return TCL_ERROR;
    - purple_serv_get_info(purple_account_get_connection(account), Tcl_GetString(objv[3]));
    - }
    - break;
    - case CMD_BUDDY_LIST:
    - if (objc == 3) {
    - if (!strcmp("-all", Tcl_GetString(objv[2]))) {
    - all = 1;
    - } else {
    - result = Tcl_NewStringObj("",-1);
    - Tcl_AppendStringsToObj(result, "unknown option: ", Tcl_GetString(objv[2]), NULL);
    - Tcl_SetObjResult(interp,result);
    - return TCL_ERROR;
    - }
    - }
    - list = Tcl_NewListObj(0, NULL);
    - for (gnode = purple_blist_get_root(); gnode != NULL; gnode = purple_blist_node_get_sibling_next(gnode)) {
    - tclgroup = Tcl_NewListObj(0, NULL);
    - Tcl_ListObjAppendElement(interp, tclgroup, Tcl_NewStringObj("group", -1));
    - Tcl_ListObjAppendElement(interp, tclgroup,
    - Tcl_NewStringObj(purple_group_get_name(PURPLE_GROUP(gnode)), -1));
    - tclgrouplist = Tcl_NewListObj(0, NULL);
    - for (node = purple_blist_node_get_first_child(gnode); node != NULL; node = purple_blist_node_get_sibling_next(node)) {
    - PurpleAccount *account;
    -
    - if (PURPLE_IS_CONTACT(node)) {
    - tclcontact = Tcl_NewListObj(0, NULL);
    - Tcl_IncrRefCount(tclcontact);
    - Tcl_ListObjAppendElement(interp, tclcontact, Tcl_NewStringObj("contact", -1));
    - tclcontactlist = Tcl_NewListObj(0, NULL);
    - Tcl_IncrRefCount(tclcontactlist);
    - count = 0;
    - for (bnode = purple_blist_node_get_first_child(node); bnode != NULL; bnode = purple_blist_node_get_sibling_next(bnode)) {
    - if (!PURPLE_IS_BUDDY(bnode))
    - continue;
    - bud = PURPLE_BUDDY(bnode);
    - account = purple_buddy_get_account(bud);
    - if (!all && !purple_account_is_connected(account))
    - continue;
    - count++;
    - tclbud = Tcl_NewListObj(0, NULL);
    - Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewStringObj("buddy", -1));
    - Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewStringObj(purple_buddy_get_name(bud), -1));
    - Tcl_ListObjAppendElement(interp, tclbud, purple_tcl_ref_new(PurpleTclRefAccount, account));
    - Tcl_ListObjAppendElement(interp, tclcontactlist, tclbud);
    - }
    - if (count) {
    - Tcl_ListObjAppendElement(interp, tclcontact, tclcontactlist);
    - Tcl_ListObjAppendElement(interp, tclgrouplist, tclcontact);
    - }
    - Tcl_DecrRefCount(tclcontact);
    - Tcl_DecrRefCount(tclcontactlist);
    - } else if (PURPLE_IS_CHAT(node)) {
    - cnode = PURPLE_CHAT(node);
    - account = purple_chat_get_account(cnode);
    - if (!all && !purple_account_is_connected(account))
    - continue;
    - tclbud = Tcl_NewListObj(0, NULL);
    - Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewStringObj("chat", -1));
    - Tcl_ListObjAppendElement(interp, tclbud, Tcl_NewStringObj(purple_chat_get_name(cnode), -1));
    - Tcl_ListObjAppendElement(interp, tclbud, purple_tcl_ref_new(PurpleTclRefAccount, account));
    - Tcl_ListObjAppendElement(interp, tclgrouplist, tclbud);
    - } else {
    - purple_debug(PURPLE_DEBUG_WARNING, "tcl", "Unexpected buddy type %s", G_OBJECT_TYPE_NAME(node));
    - continue;
    - }
    - }
    - Tcl_ListObjAppendElement(interp, tclgroup, tclgrouplist);
    - Tcl_ListObjAppendElement(interp, list, tclgroup);
    - }
    - Tcl_SetObjResult(interp, list);
    - break;
    - }
    -
    - return TCL_OK;
    -}
    -
    -int tcl_cmd_cmd(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
    -{
    - const char *cmds[] = { "do", "help", "list", "register", "unregister", NULL };
    - enum { CMD_CMD_DO, CMD_CMD_HELP, CMD_CMD_LIST, CMD_CMD_REGISTER, CMD_CMD_UNREGISTER } cmd;
    - struct tcl_cmd_handler *handler;
    - Tcl_Obj *list, *elem;
    - PurpleConversation *convo;
    - PurpleCmdId id;
    - PurpleCmdStatus status;
    - int error;
    - GList *l, *cur;
    - gchar *escaped, *errstr = NULL;
    -
    - if (objc < 2) {
    - Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
    - return TCL_ERROR;
    - }
    -
    - if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
    - return error;
    -
    - switch (cmd) {
    - case CMD_CMD_DO:
    - if (objc != 4) {
    - Tcl_WrongNumArgs(interp, 2, objv, "conversation command");
    - return TCL_ERROR;
    - }
    - if ((convo = tcl_validate_conversation(objv[2], interp)) == NULL)
    - return TCL_ERROR;
    - escaped = g_markup_escape_text(Tcl_GetString(objv[3]), -1);
    - status = purple_cmd_do_command(convo, Tcl_GetString(objv[3]),
    - escaped, &errstr);
    - g_free(escaped);
    - Tcl_SetObjResult(interp,
    - Tcl_NewStringObj(errstr ? (char *)errstr : "", -1));
    - g_free(errstr);
    - if (status != PURPLE_CMD_STATUS_OK) {
    - return TCL_ERROR;
    - }
    - break;
    - case CMD_CMD_HELP:
    - if (objc != 4) {
    - Tcl_WrongNumArgs(interp, 2, objv, "conversation name");
    - return TCL_ERROR;
    - }
    - if ((convo = tcl_validate_conversation(objv[2], interp)) == NULL)
    - return TCL_ERROR;
    - l = cur = purple_cmd_help(convo, Tcl_GetString(objv[3]));
    - list = Tcl_NewListObj(0, NULL);
    - while (cur != NULL) {
    - elem = Tcl_NewStringObj((char *)cur->data, -1);
    - Tcl_ListObjAppendElement(interp, list, elem);
    - cur = g_list_next(cur);
    - }
    - g_list_free(l);
    - Tcl_SetObjResult(interp, list);
    - break;
    - case CMD_CMD_LIST:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "conversation");
    - return TCL_ERROR;
    - }
    - if ((convo = tcl_validate_conversation(objv[2], interp)) == NULL)
    - return TCL_ERROR;
    - l = cur = purple_cmd_list(convo);
    - list = Tcl_NewListObj(0, NULL);
    - while (cur != NULL) {
    - elem = Tcl_NewStringObj((char *)cur->data, -1);
    - Tcl_ListObjAppendElement(interp, list, elem);
    - cur = g_list_next(cur);
    - }
    - g_list_free(l);
    - Tcl_SetObjResult(interp, list);
    - break;
    - case CMD_CMD_REGISTER:
    - if (objc != 9) {
    - Tcl_WrongNumArgs(interp, 2, objv, "cmd arglist priority flags protocol_id proc helpstr");
    - return TCL_ERROR;
    - }
    - handler = g_new0(struct tcl_cmd_handler, 1);
    - handler->cmd = objv[2];
    - handler->args = Tcl_GetString(objv[3]);
    - handler->nargs = strlen(handler->args);
    - if ((error = Tcl_GetIntFromObj(interp, objv[4],
    - &handler->priority)) != TCL_OK) {
    - g_free(handler);
    - return error;
    - }
    - if ((error = Tcl_GetIntFromObj(interp, objv[5],
    - &handler->flags)) != TCL_OK) {
    - g_free(handler);
    - return error;
    - }
    - handler->protocol_id = Tcl_GetString(objv[6]);
    - handler->proc = objv[7];
    - handler->helpstr = Tcl_GetString(objv[8]);
    - handler->interp = interp;
    - if ((id = tcl_cmd_register(handler)) == 0) {
    - tcl_cmd_handler_free(handler);
    - Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
    - } else {
    - handler->id = id;
    - Tcl_SetObjResult(interp, Tcl_NewIntObj(id));
    - }
    - break;
    - case CMD_CMD_UNREGISTER:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "id");
    - return TCL_ERROR;
    - }
    - if ((error = Tcl_GetIntFromObj(interp, objv[2],
    - (int *)&id)) != TCL_OK)
    - return error;
    - tcl_cmd_unregister(id, interp);
    - break;
    - }
    -
    - return TCL_OK;
    -}
    -
    -int tcl_cmd_connection(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
    -{
    - Tcl_Obj *list, *elem;
    - const char *cmds[] = { "account", "displayname", "handle", "list", "state", NULL };
    - enum { CMD_CONN_ACCOUNT, CMD_CONN_DISPLAYNAME, CMD_CONN_HANDLE,
    - CMD_CONN_LIST, CMD_CONN_STATE } cmd;
    - int error;
    - GList *cur;
    - PurpleConnection *gc;
    -
    - if (objc < 2) {
    - Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
    - return TCL_ERROR;
    - }
    -
    - if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
    - return error;
    -
    - switch (cmd) {
    - case CMD_CONN_ACCOUNT:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "gc");
    - return TCL_ERROR;
    - }
    - if ((gc = tcl_validate_gc(objv[2], interp)) == NULL)
    - return TCL_ERROR;
    - Tcl_SetObjResult(interp,
    - purple_tcl_ref_new(PurpleTclRefAccount,
    - purple_connection_get_account(gc)));
    - break;
    - case CMD_CONN_DISPLAYNAME:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "gc");
    - return TCL_ERROR;
    - }
    - if ((gc = tcl_validate_gc(objv[2], interp)) == NULL)
    - return TCL_ERROR;
    - Tcl_SetObjResult(interp,
    - Tcl_NewStringObj(purple_connection_get_display_name(gc), -1));
    - break;
    - case CMD_CONN_HANDLE:
    - if (objc != 2) {
    - Tcl_WrongNumArgs(interp, 2, objv, "");
    - return TCL_ERROR;
    - }
    - Tcl_SetObjResult(interp, purple_tcl_ref_new(PurpleTclRefHandle,
    - purple_connections_get_handle()));
    - break;
    - case CMD_CONN_LIST:
    - if (objc != 2) {
    - Tcl_WrongNumArgs(interp, 2, objv, "");
    - return TCL_ERROR;
    - }
    - list = Tcl_NewListObj(0, NULL);
    - for (cur = purple_connections_get_all(); cur != NULL; cur = g_list_next(cur)) {
    - elem = purple_tcl_ref_new(PurpleTclRefConnection, cur->data);
    - Tcl_ListObjAppendElement(interp, list, elem);
    - }
    - Tcl_SetObjResult(interp, list);
    - break;
    - case CMD_CONN_STATE:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "gc");
    - return TCL_ERROR;
    - }
    - if ((gc = tcl_validate_gc(objv[2], interp)) == NULL)
    - return TCL_ERROR;
    - switch (purple_connection_get_state(gc)) {
    - case PURPLE_CONNECTION_DISCONNECTED:
    - Tcl_SetObjResult(interp, Tcl_NewStringObj("disconnected", -1));
    - break;
    - case PURPLE_CONNECTION_CONNECTED:
    - Tcl_SetObjResult(interp, Tcl_NewStringObj("connected", -1));
    - break;
    - case PURPLE_CONNECTION_CONNECTING:
    - Tcl_SetObjResult(interp, Tcl_NewStringObj("connecting", -1));
    - break;
    - }
    - break;
    - }
    -
    - return TCL_OK;
    -}
    -
    -int tcl_cmd_conversation(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
    -{
    - Tcl_Obj *list, *elem;
    - const char *cmds[] = { "find", "handle", "list", "new", "write", "name", "title", "send", NULL };
    - enum { CMD_CONV_FIND, CMD_CONV_HANDLE, CMD_CONV_LIST, CMD_CONV_NEW, CMD_CONV_WRITE , CMD_CONV_NAME, CMD_CONV_TITLE, CMD_CONV_SEND } cmd;
    - const char *styles[] = { "send", "recv", "system", NULL };
    - enum { CMD_CONV_WRITE_SEND, CMD_CONV_WRITE_RECV, CMD_CONV_WRITE_SYSTEM } style;
    - const char *newopts[] = { "-chat", "-im" };
    - enum { CMD_CONV_NEW_CHAT, CMD_CONV_NEW_IM } newopt;
    - PurpleConversation *convo;
    - PurpleAccount *account;
    - PurpleMessage *pmsg;
    - gboolean is_chat = FALSE;
    - GList *cur;
    - char *opt, *from, *what;
    - int error, argsused;
    -
    - if (objc < 2) {
    - Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
    - return TCL_ERROR;
    - }
    -
    - if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
    - return error;
    -
    - switch (cmd) {
    - case CMD_CONV_FIND:
    - if (objc != 4) {
    - Tcl_WrongNumArgs(interp, 2, objv, "account name");
    - return TCL_ERROR;
    - }
    - account = NULL;
    - if ((account = tcl_validate_account(objv[2], interp)) == NULL)
    - return TCL_ERROR;
    - convo = purple_conversations_find_with_account(Tcl_GetString(objv[3]),
    - account);
    - Tcl_SetObjResult(interp, purple_tcl_ref_new(PurpleTclRefConversation, convo));
    - break;
    - case CMD_CONV_HANDLE:
    - if (objc != 2) {
    - Tcl_WrongNumArgs(interp, 2, objv, "");
    - return TCL_ERROR;
    - }
    - Tcl_SetObjResult(interp,
    - purple_tcl_ref_new(PurpleTclRefHandle,
    - purple_conversations_get_handle()));
    - break;
    - case CMD_CONV_LIST:
    - list = Tcl_NewListObj(0, NULL);
    - for (cur = purple_conversations_get_all(); cur != NULL; cur = g_list_next(cur)) {
    - elem = purple_tcl_ref_new(PurpleTclRefConversation, cur->data);
    - Tcl_ListObjAppendElement(interp, list, elem);
    - }
    - Tcl_SetObjResult(interp, list);
    - break;
    - case CMD_CONV_NEW:
    - if (objc < 4) {
    - Tcl_WrongNumArgs(interp, 2, objv, "?options? account name");
    - return TCL_ERROR;
    - }
    - argsused = 2;
    - is_chat = FALSE;
    - while (argsused < objc) {
    - opt = Tcl_GetString(objv[argsused]);
    - if (*opt == '-') {
    - if ((error = Tcl_GetIndexFromObj(interp, objv[argsused], newopts,
    - "option", 0, (int *)&newopt)) != TCL_OK)
    - return error;
    - argsused++;
    - switch (newopt) {
    - case CMD_CONV_NEW_CHAT:
    - is_chat = TRUE;
    - break;
    - case CMD_CONV_NEW_IM:
    - is_chat = FALSE;
    - break;
    - }
    - } else {
    - break;
    - }
    - }
    - if (objc - argsused != 2) {
    - Tcl_WrongNumArgs(interp, 2, objv, "?options? account name");
    - return TCL_ERROR;
    - }
    - if ((account = tcl_validate_account(objv[argsused++], interp)) == NULL)
    - return TCL_ERROR;
    - if (is_chat)
    - convo = PURPLE_CONVERSATION(purple_chat_conversation_new(account, Tcl_GetString(objv[argsused])));
    - else
    - convo = PURPLE_CONVERSATION(purple_im_conversation_new(account, Tcl_GetString(objv[argsused])));
    - Tcl_SetObjResult(interp, purple_tcl_ref_new(PurpleTclRefConversation, convo));
    - break;
    - case CMD_CONV_WRITE:
    - if (objc != 6) {
    - Tcl_WrongNumArgs(interp, 2, objv, "conversation style from what");
    - return TCL_ERROR;
    - }
    - if ((convo = tcl_validate_conversation(objv[2], interp)) == NULL)
    - return TCL_ERROR;
    - if ((error = Tcl_GetIndexFromObj(interp, objv[3], styles, "style", 0, (int *)&style)) != TCL_OK)
    - return error;
    - from = Tcl_GetString(objv[4]);
    - what = Tcl_GetString(objv[5]);
    -
    - switch (style) {
    - case CMD_CONV_WRITE_SEND:
    - pmsg = purple_message_new_outgoing(from, what, 0);
    - break;
    - case CMD_CONV_WRITE_RECV:
    - pmsg = purple_message_new_incoming(from, what, 0, 0);
    - break;
    - case CMD_CONV_WRITE_SYSTEM:
    - default:
    - pmsg = purple_message_new_system(what, 0);
    - break;
    - }
    - purple_conversation_write_message(convo, pmsg);
    - break;
    - case CMD_CONV_NAME:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "conversation");
    - return TCL_ERROR;
    - }
    -
    - if ((convo = tcl_validate_conversation(objv[2], interp)) == NULL)
    - return TCL_ERROR;
    - Tcl_SetObjResult(interp,
    - Tcl_NewStringObj((char *)purple_conversation_get_name(convo), -1));
    - break;
    - case CMD_CONV_TITLE:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "conversation");
    - return TCL_ERROR;
    - }
    -
    - if ((convo = tcl_validate_conversation(objv[2], interp)) == NULL)
    - return TCL_ERROR;
    - Tcl_SetObjResult(interp,
    - Tcl_NewStringObj((char *)purple_conversation_get_title(convo), -1));
    - break;
    - case CMD_CONV_SEND:
    - if (objc != 4) {
    - Tcl_WrongNumArgs(interp, 2, objv, "conversation message");
    - return TCL_ERROR;
    - }
    - if ((convo = tcl_validate_conversation(objv[2], interp)) == NULL)
    - return TCL_ERROR;
    - what = Tcl_GetString(objv[3]);
    - purple_conversation_send(convo, what);
    - break;
    - }
    -
    - return TCL_OK;
    -}
    -
    -int tcl_cmd_core(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
    -{
    - const char *cmds[] = { "handle", "quit", NULL };
    - enum { CMD_CORE_HANDLE, CMD_CORE_QUIT } cmd;
    - int error;
    -
    - if (objc < 2) {
    - Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
    - return TCL_ERROR;
    - }
    -
    - if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
    - return error;
    -
    - switch (cmd) {
    - case CMD_CORE_HANDLE:
    - if (objc != 2) {
    - Tcl_WrongNumArgs(interp, 2, objv, "");
    - return TCL_ERROR;
    - }
    - Tcl_SetObjResult(interp,
    - purple_tcl_ref_new(PurpleTclRefHandle,
    - purple_get_core()));
    - break;
    - case CMD_CORE_QUIT:
    - if (objc != 2) {
    - Tcl_WrongNumArgs(interp, 2, objv, "");
    - return TCL_ERROR;
    - }
    - purple_core_quit();
    - break;
    - }
    -
    - return TCL_OK;
    -}
    -
    -int tcl_cmd_debug(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
    -{
    - char *category, *message;
    - int lev;
    - const char *levels[] = { "-misc", "-info", "-warning", "-error", NULL };
    - PurpleDebugLevel levelind[] = { PURPLE_DEBUG_MISC, PURPLE_DEBUG_INFO, PURPLE_DEBUG_WARNING, PURPLE_DEBUG_ERROR };
    - int error;
    -
    - if (objc != 4) {
    - Tcl_WrongNumArgs(interp, 1, objv, "level category message");
    - return TCL_ERROR;
    - }
    -
    - error = Tcl_GetIndexFromObj(interp, objv[1], levels, "debug level", 0, &lev);
    - if (error != TCL_OK)
    - return error;
    -
    - category = Tcl_GetString(objv[2]);
    - message = Tcl_GetString(objv[3]);
    -
    - purple_debug(levelind[lev], category, "%s\n", message);
    -
    - return TCL_OK;
    -}
    -
    -int tcl_cmd_notify(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
    -{
    - int error, type;
    - const char *opts[] = { "-error", "-warning", "-info", NULL };
    - PurpleNotifyMsgType optind[] = { PURPLE_NOTIFY_MSG_ERROR, PURPLE_NOTIFY_MSG_WARNING, PURPLE_NOTIFY_MSG_INFO };
    - char *title, *msg1, *msg2;
    -
    - if (objc < 4 || objc > 5) {
    - Tcl_WrongNumArgs(interp, 1, objv, "?type? title primary secondary");
    - return TCL_ERROR;
    - }
    -
    - if (objc == 4) {
    - type = 1; /* Default to warning */
    - title = Tcl_GetString(objv[1]);
    - msg1 = Tcl_GetString(objv[2]);
    - msg2 = Tcl_GetString(objv[3]);
    - } else {
    - error = Tcl_GetIndexFromObj(interp, objv[1], opts, "message type", 0, &type);
    - if (error != TCL_OK)
    - return error;
    - title = Tcl_GetString(objv[2]);
    - msg1 = Tcl_GetString(objv[3]);
    - msg2 = Tcl_GetString(objv[4]);
    - }
    -
    - purple_notify_message(_tcl_plugin, optind[type], title, msg1, msg2, NULL, NULL, NULL);
    -
    - return TCL_OK;
    -}
    -
    -int tcl_cmd_plugins(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
    -{
    - const char *cmds[] = { "handle", NULL };
    - enum { CMD_PLUGINS_HANDLE } cmd;
    - int error;
    -
    - if (objc < 2) {
    - Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
    - return TCL_ERROR;
    - }
    -
    - if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
    - return error;
    -
    - switch (cmd) {
    - case CMD_PLUGINS_HANDLE:
    - if (objc != 2) {
    - Tcl_WrongNumArgs(interp, 2, objv, "");
    - return TCL_ERROR;
    - }
    - Tcl_SetObjResult(interp,
    - purple_tcl_ref_new(PurpleTclRefHandle,
    - purple_plugins_get_handle()));
    - break;
    - }
    -
    - return TCL_OK;
    -}
    -
    -int tcl_cmd_prefs(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
    -{
    - Tcl_Obj *list, *elem, **elems;
    - const char *cmds[] = { "get", "set", "type", NULL };
    - enum { CMD_PREFS_GET, CMD_PREFS_SET, CMD_PREFS_TYPE } cmd;
    - /* char *types[] = { "none", "boolean", "int", "string", "stringlist", NULL }; */
    - /* enum { TCL_PREFS_NONE, TCL_PREFS_BOOL, TCL_PREFS_INT, TCL_PREFS_STRING, TCL_PREFS_STRINGLIST } type; */
    - PurplePrefType preftype;
    - GList *cur;
    - int error, intval, nelem, i;
    -
    - if (objc < 2) {
    - Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
    - return TCL_ERROR;
    - }
    -
    - if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
    - return error;
    -
    - switch (cmd) {
    - case CMD_PREFS_GET:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 1, objv, "path");
    - return TCL_ERROR;
    - }
    - preftype = purple_prefs_get_pref_type(Tcl_GetString(objv[2]));
    - switch (preftype) {
    - case PURPLE_PREF_NONE:
    - Tcl_SetObjResult(interp,
    - Tcl_NewStringObj("pref type none", -1));
    - return TCL_ERROR;
    - break;
    - case PURPLE_PREF_BOOLEAN:
    - Tcl_SetObjResult(interp,
    - Tcl_NewBooleanObj(
    - purple_prefs_get_bool(Tcl_GetString(objv[2]))));
    - break;
    - case PURPLE_PREF_INT:
    - Tcl_SetObjResult(interp, Tcl_NewIntObj(purple_prefs_get_int(Tcl_GetString(objv[2]))));
    - break;
    - case PURPLE_PREF_STRING:
    - Tcl_SetObjResult(interp,
    - Tcl_NewStringObj((char *)purple_prefs_get_string(Tcl_GetString(objv[2])), -1));
    - break;
    - case PURPLE_PREF_STRING_LIST:
    - cur = purple_prefs_get_string_list(Tcl_GetString(objv[2]));
    - list = Tcl_NewListObj(0, NULL);
    - while (cur != NULL) {
    - elem = Tcl_NewStringObj((char *)cur->data, -1);
    - Tcl_ListObjAppendElement(interp, list, elem);
    - cur = g_list_next(cur);
    - }
    - Tcl_SetObjResult(interp, list);
    - break;
    - default:
    - purple_debug(PURPLE_DEBUG_ERROR, "tcl", "tcl does not know about pref type %d\n", preftype);
    - Tcl_SetObjResult(interp,
    - Tcl_NewStringObj("unknown pref type", -1));
    - return TCL_ERROR;
    - }
    - break;
    - case CMD_PREFS_SET:
    - if (objc != 4) {
    - Tcl_WrongNumArgs(interp, 1, objv, "path value");
    - return TCL_ERROR;
    - }
    - preftype = purple_prefs_get_pref_type(Tcl_GetString(objv[2]));
    - switch (preftype) {
    - case PURPLE_PREF_NONE:
    - Tcl_SetObjResult(interp,
    - Tcl_NewStringObj("bad path or pref type none", -1));
    - return TCL_ERROR;
    - break;
    - case PURPLE_PREF_BOOLEAN:
    - if ((error = Tcl_GetBooleanFromObj(interp, objv[3], &intval)) != TCL_OK)
    - return error;
    - purple_prefs_set_bool(Tcl_GetString(objv[2]), intval);
    - break;
    - case PURPLE_PREF_INT:
    - if ((error = Tcl_GetIntFromObj(interp, objv[3], &intval)) != TCL_OK)
    - return error;
    - purple_prefs_set_int(Tcl_GetString(objv[2]), intval);
    - break;
    - case PURPLE_PREF_STRING:
    - purple_prefs_set_string(Tcl_GetString(objv[2]), Tcl_GetString(objv[3]));
    - break;
    - case PURPLE_PREF_STRING_LIST:
    - if ((error = Tcl_ListObjGetElements(interp, objv[3], &nelem, &elems)) != TCL_OK)
    - return error;
    - cur = NULL;
    - for (i = 0; i < nelem; i++) {
    - cur = g_list_append(cur, (gpointer)Tcl_GetString(elems[i]));
    - }
    - purple_prefs_set_string_list(Tcl_GetString(objv[2]), cur);
    - g_list_free(cur);
    - break;
    - default:
    - purple_debug(PURPLE_DEBUG_ERROR, "tcl", "tcl does not know about pref type %d\n", preftype);
    - return TCL_ERROR;
    - }
    - break;
    - case CMD_PREFS_TYPE:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 1, objv, "path");
    - return TCL_ERROR;
    - }
    - preftype = purple_prefs_get_pref_type(Tcl_GetString(objv[2]));
    - switch (preftype) {
    - case PURPLE_PREF_NONE:
    - Tcl_SetObjResult(interp, Tcl_NewStringObj("none", -1));
    - break;
    - case PURPLE_PREF_BOOLEAN:
    - Tcl_SetObjResult(interp, Tcl_NewStringObj("boolean", -1));
    - break;
    - case PURPLE_PREF_INT:
    - Tcl_SetObjResult(interp, Tcl_NewStringObj("int", -1));
    - break;
    - case PURPLE_PREF_STRING:
    - Tcl_SetObjResult(interp, Tcl_NewStringObj("string", -1));
    - break;
    - case PURPLE_PREF_STRING_LIST:
    - Tcl_SetObjResult(interp, Tcl_NewStringObj("stringlist", -1));
    - break;
    - default:
    - purple_debug(PURPLE_DEBUG_ERROR, "tcl", "tcl does not know about pref type %d\n", preftype);
    - Tcl_SetObjResult(interp, Tcl_NewStringObj("unknown", -1));
    - }
    - break;
    - }
    -
    - return TCL_OK;
    -}
    -
    -int tcl_cmd_presence(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
    -{
    - const char *cmds[] = { "account", "active_status", "available",
    - "idle", "type", "login", "online", "status",
    - "statuses", NULL };
    - enum { CMD_PRESENCE_ACCOUNT, CMD_PRESENCE_ACTIVE_STATUS,
    - CMD_PRESENCE_AVAILABLE, CMD_PRESENCE_IDLE, CMD_PRESENCE_TYPE,
    - CMD_PRESENCE_LOGIN, CMD_PRESENCE_ONLINE,
    - CMD_PRESENCE_STATUS, CMD_PRESENCE_STATUSES } cmd;
    - Tcl_Obj *result;
    - Tcl_Obj *list, *elem;
    - PurplePresence *presence;
    - GList *cur;
    - int error, idle, idle_time, login_time;
    -
    - if (objc < 2) {
    - Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
    - return TCL_ERROR;
    - }
    -
    - if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
    - return error;
    -
    - switch (cmd) {
    - case CMD_PRESENCE_ACCOUNT:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "presence");
    - return TCL_ERROR;
    - }
    - if ((presence = purple_tcl_ref_get(interp, objv[2], PurpleTclRefPresence)) == NULL)
    - return TCL_ERROR;
    - Tcl_SetObjResult(interp, purple_tcl_ref_new(PurpleTclRefAccount,
    - purple_account_presence_get_account(PURPLE_ACCOUNT_PRESENCE(presence))));
    - break;
    - case CMD_PRESENCE_ACTIVE_STATUS:
    - if (objc != 3 && objc != 4 && objc != 5) {
    - Tcl_WrongNumArgs(interp, 2, objv, "presence [?status_id? | ?-primitive primitive?]");
    - return TCL_ERROR;
    - }
    - if ((presence = purple_tcl_ref_get(interp, objv[2], PurpleTclRefPresence)) == NULL)
    - return TCL_ERROR;
    - if (objc == 3) {
    - Tcl_SetObjResult(interp,
    - purple_tcl_ref_new(PurpleTclRefStatus,
    - purple_presence_get_active_status(presence)));
    - } else if (objc == 4) {
    - Tcl_SetObjResult(interp,
    - Tcl_NewBooleanObj(
    - purple_presence_is_status_active(presence,
    - Tcl_GetString(objv[3]))));
    - } else {
    - PurpleStatusPrimitive primitive;
    - if (strcmp(Tcl_GetString(objv[3]), "-primitive")) {
    - result = Tcl_NewStringObj("bad option \"", -1);
    - Tcl_AppendObjToObj(result, objv[3]);
    - Tcl_AppendToObj(result,
    - "\": should be -primitive", -1);
    - Tcl_SetObjResult(interp,result);
    - return TCL_ERROR;
    - }
    - primitive = purple_primitive_get_type_from_id(Tcl_GetString(objv[4]));
    - if (primitive == PURPLE_STATUS_UNSET) {
    - result = Tcl_NewStringObj("invalid primitive ", -1);
    - Tcl_AppendObjToObj(result, objv[4]);
    - Tcl_SetObjResult(interp,result);
    - return TCL_ERROR;
    - }
    - Tcl_SetObjResult(interp,
    - Tcl_NewBooleanObj(
    - purple_presence_is_status_primitive_active(presence, primitive)));
    - break;
    - }
    - break;
    - case CMD_PRESENCE_AVAILABLE:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "presence");
    - return TCL_ERROR;
    - }
    - if ((presence = purple_tcl_ref_get(interp, objv[2], PurpleTclRefPresence)) == NULL)
    - return TCL_ERROR;
    - Tcl_SetObjResult(interp,
    - Tcl_NewBooleanObj(purple_presence_is_available(presence)));
    - break;
    - case CMD_PRESENCE_TYPE:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "presence");
    - return TCL_ERROR;
    - }
    - if ((presence = purple_tcl_ref_get(interp, objv[2], PurpleTclRefPresence)) == NULL)
    - return TCL_ERROR;
    - if (PURPLE_IS_ACCOUNT_PRESENCE(presence))
    - Tcl_SetObjResult(interp, Tcl_NewStringObj("account", -1));
    - else if (PURPLE_IS_BUDDY_PRESENCE(presence))
    - Tcl_SetObjResult(interp, Tcl_NewStringObj("buddy", -1));
    - break;
    - case CMD_PRESENCE_IDLE:
    - if (objc < 3 || objc > 5) {
    - Tcl_WrongNumArgs(interp, 2, objv, "presence ?idle? ?time?");
    - return TCL_ERROR;
    - }
    - if ((presence = purple_tcl_ref_get(interp, objv[2], PurpleTclRefPresence)) == NULL)
    - return TCL_ERROR;
    - if (objc == 3) {
    - if (purple_presence_is_idle(presence)) {
    - idle_time = purple_presence_get_idle_time (presence);
    - Tcl_SetObjResult(interp, Tcl_NewIntObj(idle_time));
    - } else {
    - result = Tcl_NewListObj(0, NULL);
    - Tcl_SetObjResult(interp, result);
    - }
    - break;
    - }
    - if ((error = Tcl_GetBooleanFromObj(interp, objv[3], &idle)) != TCL_OK)
    - return TCL_ERROR;
    - if (objc == 4) {
    - purple_presence_set_idle(presence, idle, time(NULL));
    - } else if (objc == 5) {
    - if ((error = Tcl_GetIntFromObj(interp,
    - objv[4],
    - &idle_time)) != TCL_OK)
    - return TCL_ERROR;
    - purple_presence_set_idle(presence, idle, idle_time);
    - }
    - break;
    - case CMD_PRESENCE_LOGIN:
    - if (objc != 3 && objc != 4) {
    - Tcl_WrongNumArgs(interp, 2, objv, "presence ?time?");
    - return TCL_ERROR;
    - }
    - if ((presence = purple_tcl_ref_get(interp, objv[2], PurpleTclRefPresence)) == NULL)
    - return TCL_ERROR;
    - if (objc == 3) {
    - Tcl_SetObjResult(interp, Tcl_NewIntObj(purple_presence_get_login_time(presence)));
    - } else {
    - if ((error == Tcl_GetIntFromObj(interp,
    - objv[3],
    - &login_time)) != TCL_OK)
    - return TCL_ERROR;
    - purple_presence_set_login_time(presence, login_time);
    - }
    - break;
    - case CMD_PRESENCE_ONLINE:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "presence");
    - return TCL_ERROR;
    - }
    - if ((presence = purple_tcl_ref_get(interp, objv[2], PurpleTclRefPresence)) == NULL)
    - return TCL_ERROR;
    - Tcl_SetObjResult(interp,
    - Tcl_NewBooleanObj(
    - purple_presence_is_online(presence)));
    - break;
    - case CMD_PRESENCE_STATUS:
    - if (objc != 4) {
    - Tcl_WrongNumArgs(interp, 2, objv, "presence status_id");
    - return TCL_ERROR;
    - }
    - if ((presence = purple_tcl_ref_get(interp, objv[2], PurpleTclRefPresence)) == NULL)
    - return TCL_ERROR;
    - Tcl_SetObjResult(interp,
    - purple_tcl_ref_new(PurpleTclRefStatus,
    - purple_presence_get_status(presence,
    - Tcl_GetString(objv[3]))));
    - break;
    - case CMD_PRESENCE_STATUSES:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "presence");
    - return TCL_ERROR;
    - }
    - if ((presence = purple_tcl_ref_get(interp, objv[2], PurpleTclRefPresence)) == NULL)
    - return TCL_ERROR;
    - list = Tcl_NewListObj(0, NULL);
    - for (cur = purple_presence_get_statuses(presence); cur != NULL;
    - cur = g_list_next(cur)) {
    - elem = purple_tcl_ref_new(PurpleTclRefStatus, cur->data);
    - Tcl_ListObjAppendElement(interp, list, elem);
    - }
    - Tcl_SetObjResult(interp, list);
    - break;
    - }
    -
    - return TCL_OK;
    -}
    -
    -int tcl_cmd_savedstatus(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
    -{
    - Tcl_Obj *result;
    - const char *cmds[] = { "current", "handle", NULL };
    - enum { CMD_SAVEDSTATUS_CURRENT, CMD_SAVEDSTATUS_HANDLE } cmd;
    - int error;
    - PurpleSavedStatus *saved_status;
    -
    - if (objc < 2) {
    - Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
    - return TCL_ERROR;
    - }
    -
    - if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
    - return error;
    -
    - switch (cmd) {
    - case CMD_SAVEDSTATUS_CURRENT:
    - if (objc != 2) {
    - Tcl_WrongNumArgs(interp, 2, objv, "");
    - return TCL_ERROR;
    - }
    - if ((saved_status = purple_savedstatus_get_current()) == NULL)
    - return TCL_ERROR;
    - result = Tcl_NewListObj(0, NULL);
    - Tcl_ListObjAppendElement(interp, result, Tcl_NewStringObj(purple_savedstatus_get_title(saved_status), -1));
    - Tcl_ListObjAppendElement(interp, result, Tcl_NewIntObj(purple_savedstatus_get_primitive_type(saved_status)));
    - Tcl_ListObjAppendElement(interp, result, Tcl_NewStringObj(purple_savedstatus_get_message(saved_status), -1));
    - Tcl_SetObjResult(interp,result);
    - break;
    - case CMD_SAVEDSTATUS_HANDLE:
    - if (objc != 2) {
    - Tcl_WrongNumArgs(interp, 2, objv, "");
    - return TCL_ERROR;
    - }
    - Tcl_SetObjResult(interp,
    - purple_tcl_ref_new(PurpleTclRefHandle,
    - purple_savedstatuses_get_handle()));
    - break;
    - }
    -
    - return TCL_OK;
    -}
    -
    -int tcl_cmd_send_im(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
    -{
    - PurpleConnection *gc;
    - char *who, *text;
    -
    - if (objc != 4) {
    - Tcl_WrongNumArgs(interp, 1, objv, "gc who text");
    - return TCL_ERROR;
    - }
    -
    - if ((gc = tcl_validate_gc(objv[1], interp)) == NULL)
    - return TCL_ERROR;
    -
    - who = Tcl_GetString(objv[2]);
    - text = Tcl_GetString(objv[3]);
    -
    - purple_serv_send_im(gc, purple_message_new_outgoing(who, text, 0));
    -
    - return TCL_OK;
    -}
    -
    -int tcl_cmd_signal(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
    -{
    - const char *cmds[] = { "connect", "disconnect", NULL };
    - enum { CMD_SIGNAL_CONNECT, CMD_SIGNAL_DISCONNECT } cmd;
    - struct tcl_signal_handler *handler;
    - void *instance;
    - int error;
    -
    - if (objc < 2) {
    - Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
    - return TCL_ERROR;
    - }
    -
    - if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
    - return error;
    -
    - switch (cmd) {
    - case CMD_SIGNAL_CONNECT:
    - if (objc != 6) {
    - Tcl_WrongNumArgs(interp, 2, objv, "instance signal args proc");
    - return TCL_ERROR;
    - }
    - handler = g_new0(struct tcl_signal_handler, 1);
    - if ((handler->instance = purple_tcl_ref_get(interp, objv[2],PurpleTclRefHandle)) == NULL) {
    - g_free(handler);
    - return error;
    - }
    - handler->signal = objv[3];
    - Tcl_IncrRefCount(handler->signal);
    - handler->args = objv[4];
    - handler->proc = objv[5];
    - handler->interp = interp;
    - if (!tcl_signal_connect(handler)) {
    - tcl_signal_handler_free(handler);
    - Tcl_SetObjResult(interp, Tcl_NewIntObj(1));
    - } else {
    - Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
    - }
    - break;
    - case CMD_SIGNAL_DISCONNECT:
    - if (objc != 4) {
    - Tcl_WrongNumArgs(interp, 2, objv, "instance signal");
    - return TCL_ERROR;
    - }
    - if ((instance = purple_tcl_ref_get(interp, objv[2],PurpleTclRefHandle)) == NULL)
    - return error;
    - tcl_signal_disconnect(instance, Tcl_GetString(objv[3]), interp);
    - break;
    - }
    -
    - return TCL_OK;
    -}
    -
    -int tcl_cmd_status(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
    -{
    - const char *cmds[] = { "attr", "type", NULL };
    - enum { CMD_STATUS_ATTRIBUTE, CMD_STATUS_TYPE } cmd;
    - PurpleStatus *status;
    - PurpleStatusType *status_type;
    - int error;
    -# if (0)
    -/* #if !(defined PURPLE_DISABLE_DEPRECATED) */
    - PurpleValue *value;
    - const char *attr;
    - int v;
    -#endif
    -
    - if (objc < 2) {
    - Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
    - return TCL_ERROR;
    - }
    -
    - if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
    - return error;
    -
    - switch (cmd) {
    - case CMD_STATUS_ATTRIBUTE:
    -# if (0)
    -/* #if !(defined PURPLE_DISABLE_DEPRECATED) */
    - if (objc != 4 && objc != 5) {
    - Tcl_WrongNumArgs(interp, 2, objv, "status attr_id ?value?");
    - return TCL_ERROR;
    - }
    - if ((status = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatus)) == NULL)
    - return TCL_ERROR;
    - attr = Tcl_GetString(objv[3]);
    - value = purple_status_get_attr_value(status, attr);
    - if (value == NULL) {
    - Tcl_SetObjResult(interp,
    - Tcl_NewStringObj("no such attribute", -1));
    - return TCL_ERROR;
    - }
    - switch (purple_value_get_type(value)) {
    - case PURPLE_TYPE_BOOLEAN:
    - if (objc == 4) {
    - Tcl_SetObjResult(interp,
    - Tcl_NewBooleanObj(purple_value_get_boolean(value)));
    - } else {
    - if ((error = Tcl_GetBooleanFromObj(interp, objv[4], &v)) != TCL_OK)
    - return error;
    - purple_status_set_attr_boolean(status, attr, v);
    - }
    - break;
    - case PURPLE_TYPE_INT:
    - if (objc == 4) {
    - Tcl_SetObjResult(interp, Tcl_NewIntObj(purple_value_get_int(value)));
    - } else {
    - if ((error = Tcl_GetIntFromObj(interp, objv[4], &v)) != TCL_OK)
    - return error;
    - purple_status_set_attr_int(status, attr, v );
    - }
    - break;
    - case PURPLE_TYPE_STRING:
    - if (objc == 4)
    - Tcl_SetObjResult(interp,
    - Tcl_NewStringObj(purple_value_get_string(value), -1));
    - else
    - purple_status_set_attr_string(status, attr, Tcl_GetString(objv[4]));
    - break;
    - default:
    - Tcl_SetObjResult(interp,
    - Tcl_NewStringObj("attribute has unknown type", -1));
    - return TCL_ERROR;
    - }
    -#endif
    - break;
    - case CMD_STATUS_TYPE:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "status");
    - return TCL_ERROR;
    - }
    - if ((status = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatus)) == NULL)
    - return TCL_ERROR;
    - status_type = purple_status_get_status_type(status);
    - Tcl_SetObjResult(interp, purple_tcl_ref_new(PurpleTclRefStatusType,
    - status_type));
    - break;
    - }
    -
    - return TCL_OK;
    -}
    -
    -int tcl_cmd_status_attr(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
    -{
    - const char *cmds[] = { "id", "name", NULL };
    - enum { CMD_STATUS_ATTRIBUTE_ID, CMD_STATUS_ATTRIBUTE_NAME } cmd;
    - PurpleStatusAttribute *attr;
    - int error;
    -
    - if (objc < 2) {
    - Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
    - return TCL_ERROR;
    - }
    -
    - if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
    - return error;
    -
    - switch (cmd) {
    - case CMD_STATUS_ATTRIBUTE_ID:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "attr");
    - return TCL_ERROR;
    - }
    - if ((attr = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusAttr)) == NULL)
    - return TCL_ERROR;
    - Tcl_SetObjResult(interp,
    - Tcl_NewStringObj(purple_status_attribute_get_id(attr), -1));
    - break;
    - case CMD_STATUS_ATTRIBUTE_NAME:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "attr");
    - return TCL_ERROR;
    - }
    - if ((attr = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusAttr)) == NULL)
    - return TCL_ERROR;
    - Tcl_SetObjResult(interp,
    - Tcl_NewStringObj(purple_status_attribute_get_name(attr), -1));
    - break;
    - }
    -
    - return TCL_OK;
    -}
    -
    -int tcl_cmd_status_type(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
    -{
    - const char *cmds[] = { "attr", "attrs", "available", "exclusive", "id",
    - "independent", "name",
    - "primitive", "saveable", "user_settable",
    - NULL };
    - enum { CMD_STATUS_TYPE_ATTR, CMD_STATUS_TYPE_ATTRS,
    - CMD_STATUS_TYPE_AVAILABLE, CMD_STATUS_TYPE_EXCLUSIVE,
    - CMD_STATUS_TYPE_ID, CMD_STATUS_TYPE_INDEPENDENT,
    - CMD_STATUS_TYPE_NAME,
    - CMD_STATUS_TYPE_PRIMITIVE, CMD_STATUS_TYPE_SAVEABLE,
    - CMD_STATUS_TYPE_USER_SETTABLE } cmd;
    - PurpleStatusType *status_type;
    - Tcl_Obj *list, *elem;
    - GList *cur;
    - int error;
    -
    - if (objc < 2) {
    - Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
    - return TCL_ERROR;
    - }
    -
    - if ((error = Tcl_GetIndexFromObj(interp, objv[1], cmds, "subcommand", 0, (int *)&cmd)) != TCL_OK)
    - return error;
    -
    - switch (cmd) {
    - case CMD_STATUS_TYPE_AVAILABLE:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "statustype");
    - return TCL_ERROR;
    - }
    - if ((status_type = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusType)) == NULL)
    - return TCL_ERROR;
    - Tcl_SetObjResult(interp,
    - Tcl_NewBooleanObj(purple_status_type_is_available(status_type)));
    - break;
    - case CMD_STATUS_TYPE_ATTR:
    - if (objc != 4) {
    - Tcl_WrongNumArgs(interp, 2, objv, "statustype attr");
    - return TCL_ERROR;
    - }
    - if ((status_type = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusType)) == NULL)
    - return TCL_ERROR;
    - Tcl_SetObjResult(interp,
    - purple_tcl_ref_new(PurpleTclRefStatusAttr,
    - purple_status_type_get_attr(status_type,
    - Tcl_GetStringFromObj(objv[3], NULL))));
    - break;
    - case CMD_STATUS_TYPE_ATTRS:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "statustype");
    - return TCL_ERROR;
    - }
    - if ((status_type = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusType)) == NULL)
    - return TCL_ERROR;
    - list = Tcl_NewListObj(0, NULL);
    - for (cur = purple_status_type_get_attrs(status_type);
    - cur != NULL; cur = g_list_next(cur)) {
    - elem = purple_tcl_ref_new(PurpleTclRefStatusAttr, cur->data);
    - Tcl_ListObjAppendElement(interp, list, elem);
    - }
    - Tcl_SetObjResult(interp, list);
    - break;
    - case CMD_STATUS_TYPE_EXCLUSIVE:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "statustype");
    - return TCL_ERROR;
    - }
    - if ((status_type = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusType)) == NULL)
    - return TCL_ERROR;
    - Tcl_SetObjResult(interp,
    - Tcl_NewBooleanObj(purple_status_type_is_exclusive(status_type)));
    - break;
    - case CMD_STATUS_TYPE_ID:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "statustype");
    - return TCL_ERROR;
    - }
    - if ((status_type = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusType)) == NULL)
    - return TCL_ERROR;
    - Tcl_SetObjResult(interp,
    - Tcl_NewStringObj(purple_status_type_get_id(status_type), -1));
    - break;
    - case CMD_STATUS_TYPE_INDEPENDENT:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "statustype");
    - return TCL_ERROR;
    - }
    - if ((status_type = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusType)) == NULL)
    - return TCL_ERROR;
    - Tcl_SetObjResult(interp,
    - Tcl_NewBooleanObj(purple_status_type_is_independent(status_type)));
    - break;
    - case CMD_STATUS_TYPE_NAME:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "statustype");
    - return TCL_ERROR;
    - }
    - if ((status_type = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusType)) == NULL)
    - return TCL_ERROR;
    - Tcl_SetObjResult(interp,
    - Tcl_NewStringObj(purple_status_type_get_name(status_type), -1));
    - break;
    - case CMD_STATUS_TYPE_PRIMITIVE:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "statustype");
    - return TCL_ERROR;
    - }
    - if ((status_type = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusType)) == NULL)
    - return TCL_ERROR;
    - Tcl_SetObjResult(interp,
    - Tcl_NewStringObj(purple_primitive_get_id_from_type
    - (purple_status_type_get_primitive(status_type)), -1));
    - break;
    - case CMD_STATUS_TYPE_SAVEABLE:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "statustype");
    - return TCL_ERROR;
    - }
    - if ((status_type = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusType)) == NULL)
    - return TCL_ERROR;
    - Tcl_SetObjResult(interp,
    - Tcl_NewBooleanObj(
    - purple_status_type_is_saveable(status_type)));
    - break;
    - case CMD_STATUS_TYPE_USER_SETTABLE:
    - if (objc != 3) {
    - Tcl_WrongNumArgs(interp, 2, objv, "statustype");
    - return TCL_ERROR;
    - }
    - if ((status_type = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusType)) == NULL)
    - return TCL_ERROR;
    - Tcl_SetObjResult(interp,
    - Tcl_NewBooleanObj(
    - purple_status_type_is_user_settable(status_type)));
    - break;
    - }
    -
    - return TCL_OK;
    -}
    -
    -static gboolean unload_self(gpointer data)
    -{
    - PurplePlugin *plugin = data;
    - purple_plugin_unload(plugin);
    - return FALSE;
    -}
    -
    -int tcl_cmd_unload(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
    -{
    - PurplePlugin *plugin;
    - if (objc != 1) {
    - Tcl_WrongNumArgs(interp, 1, objv, "");
    - return TCL_ERROR;
    - }
    -
    - if ((plugin = tcl_interp_get_plugin(interp)) == NULL) {
    - /* This isn't exactly OK, but heh. What do you do? */
    - return TCL_OK;
    - }
    - /* We can't unload immediately, but we can unload at the first
    - * known safe opportunity. */
    - purple_timeout_add(0, unload_self, (gpointer)plugin);
    -
    - return TCL_OK;
    -}
    --- a/libpurple/plugins/tcl/tcl_glib.c Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,259 +0,0 @@
    -/*
    - * Tcl/Glib glue
    - *
    - * Copyright (C) 2003, 2004, 2006 Ethan Blanton <eblanton@cs.purdue.edu>
    - *
    - * This file is dual-licensed under the two sets of terms below. You may
    - * use, redistribute, or modify it pursuant to either the set of conditions
    - * under "TERMS 1" or "TERMS 2", at your discretion. The DISCLAIMER
    - * applies to both sets of terms.
    - *
    - * TERMS 1
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
    - *
    - * TERMS 2
    - *
    - * Redistribution and use in source and binary forms, with or without
    - * modification, are permitted provided that the following conditions
    - * are met:
    - *
    - * 1. Redistributions of source code must contain the above copyright
    - * notice and this comment block in their entirety.
    - *
    - * 2. Redistributions in binary form must reproduce the above copyright
    - * notice and the text of this comment block in their entirety in
    - * the documentation and/or other materials provided with the
    - * distribution.
    - *
    - * DISCLAIMER
    - *
    - * This program 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 General Public License for more details.
    - */
    -
    -/*
    - * NOTES
    - *
    - * This file was developed for the Purple project. It inserts the Tcl
    - * event loop into the glib2 event loop for the purposes of providing
    - * Tcl bindings in a glib2 (e.g. Gtk2) program. To use it, simply
    - * link it into your executable, include tcl_glib.h, and call the
    - * function tcl_glib_init() before creating or using any Tcl
    - * interpreters. Then go ahead and use Tcl, Tk, whatever to your
    - * heart's content.
    - *
    - * BUGS
    - *
    - * tcl_wait_for_event seems to have a bug that makes vwait not work so
    - * well... I'm not sure why, yet, but I haven't put much time into
    - * it. Hopefully I will figure it out soon. In the meantime, this
    - * means that Tk's bgerror function (which is called when there is an
    - * error in a callback function) causes some Bad Mojo -- you should
    - * override it with a function that does not use Tk
    - */
    -
    -#include <tcl.h>
    -#include <glib.h>
    -#include <string.h>
    -
    -#include "tcl_glib.h"
    -
    -#ifndef CONST86
    -# define CONST86
    -#endif
    -
    -struct tcl_file_handler {
    - int source;
    - int fd;
    - int mask;
    - int pending;
    - Tcl_FileProc *proc;
    - ClientData data;
    -};
    -
    -struct tcl_file_event {
    - Tcl_Event header;
    - int fd;
    -};
    -
    -static guint tcl_timer;
    -static gboolean tcl_timer_pending;
    -static GHashTable *tcl_file_handlers;
    -
    -static void tcl_set_timer(CONST86 Tcl_Time *timePtr);
    -static int tcl_wait_for_event(CONST86 Tcl_Time *timePtr);
    -static void tcl_create_file_handler(int fd, int mask, Tcl_FileProc *proc, ClientData data);
    -static void tcl_delete_file_handler(int fd);
    -
    -static gboolean tcl_kick(gpointer data);
    -static gboolean tcl_file_callback(GIOChannel *source, GIOCondition condition, gpointer data);
    -static int tcl_file_event_callback(Tcl_Event *event, int flags);
    -
    -#undef Tcl_InitNotifier
    -
    -ClientData Tcl_InitNotifier()
    -{
    - return NULL;
    -}
    -
    -void tcl_glib_init ()
    -{
    - Tcl_NotifierProcs notifier;
    -
    - memset(&notifier, 0, sizeof(notifier));
    -
    - notifier.createFileHandlerProc = tcl_create_file_handler;
    - notifier.deleteFileHandlerProc = tcl_delete_file_handler;
    - notifier.setTimerProc = tcl_set_timer;
    - notifier.waitForEventProc = tcl_wait_for_event;
    -
    - Tcl_SetNotifier(&notifier);
    - Tcl_SetServiceMode(TCL_SERVICE_ALL);
    -
    - tcl_timer_pending = FALSE;
    - tcl_file_handlers = g_hash_table_new(g_direct_hash, g_direct_equal);
    -}
    -
    -static void tcl_set_timer(CONST86 Tcl_Time *timePtr)
    -{
    - guint interval;
    -
    - if (tcl_timer_pending)
    - g_source_remove(tcl_timer);
    -
    - if (timePtr == NULL) {
    - tcl_timer_pending = FALSE;
    - return;
    - }
    -
    - interval = timePtr->sec * 1000 + (timePtr->usec ? timePtr->usec / 1000 : 0);
    - tcl_timer = g_timeout_add(interval, tcl_kick, NULL);
    - tcl_timer_pending = TRUE;
    -}
    -
    -static int tcl_wait_for_event(CONST86 Tcl_Time *timePtr)
    -{
    - if (!timePtr || (timePtr->sec == 0 && timePtr->usec == 0)) {
    - g_main_context_iteration(NULL, FALSE);
    - return 1;
    - } else {
    - tcl_set_timer(timePtr);
    - }
    -
    - g_main_context_iteration(NULL, TRUE);
    -
    - return 1;
    -}
    -
    -static void tcl_create_file_handler(int fd, int mask, Tcl_FileProc *proc, ClientData data)
    -{
    - struct tcl_file_handler *tfh = g_new0(struct tcl_file_handler, 1);
    - GIOChannel *channel;
    - GIOCondition cond = 0;
    -
    - if (g_hash_table_lookup(tcl_file_handlers, GINT_TO_POINTER(fd)))
    - tcl_delete_file_handler(fd);
    -
    - if (mask & TCL_READABLE)
    - cond |= G_IO_IN;
    - if (mask & TCL_WRITABLE)
    - cond |= G_IO_OUT;
    - if (mask & TCL_EXCEPTION)
    - cond |= G_IO_ERR|G_IO_HUP|G_IO_NVAL;
    -
    - tfh->fd = fd;
    - tfh->mask = mask;
    - tfh->proc = proc;
    - tfh->data = data;
    -
    - channel = g_io_channel_unix_new(fd);
    - tfh->source = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond, tcl_file_callback, tfh, g_free);
    - g_io_channel_unref(channel);
    -
    - g_hash_table_insert(tcl_file_handlers, GINT_TO_POINTER(fd), tfh);
    -
    - Tcl_ServiceAll();
    -}
    -
    -static void tcl_delete_file_handler(int fd)
    -{
    - struct tcl_file_handler *tfh = g_hash_table_lookup(tcl_file_handlers, GINT_TO_POINTER(fd));
    -
    - if (tfh == NULL)
    - return;
    -
    - g_source_remove(tfh->source);
    - g_hash_table_remove(tcl_file_handlers, GINT_TO_POINTER(fd));
    -
    - Tcl_ServiceAll();
    -}
    -
    -static gboolean tcl_kick(gpointer data)
    -{
    - tcl_timer_pending = FALSE;
    -
    - Tcl_ServiceAll();
    -
    - return FALSE;
    -}
    -
    -static gboolean tcl_file_callback(GIOChannel *source, GIOCondition condition, gpointer data)
    -{
    - struct tcl_file_handler *tfh = data;
    - struct tcl_file_event *fev;
    - int mask = 0;
    -
    - if (condition & G_IO_IN)
    - mask |= TCL_READABLE;
    - if (condition & G_IO_OUT)
    - mask |= TCL_WRITABLE;
    - if (condition & (G_IO_ERR|G_IO_HUP|G_IO_NVAL))
    - mask |= TCL_EXCEPTION;
    -
    - if (!(tfh->mask & (mask & ~tfh->pending)))
    - return TRUE;
    -
    - tfh->pending |= mask;
    - /* ckalloc returns memory "suitably aligned for any use" */
    - fev = (gpointer)ckalloc(sizeof(struct tcl_file_event));
    - memset(fev, 0, sizeof(struct tcl_file_event));
    - fev->header.proc = tcl_file_event_callback;
    - fev->fd = tfh->fd;
    - Tcl_QueueEvent((Tcl_Event *)fev, TCL_QUEUE_TAIL);
    -
    - Tcl_ServiceAll();
    -
    - return TRUE;
    -}
    -
    -int tcl_file_event_callback(Tcl_Event *event, int flags)
    -{
    - struct tcl_file_handler *tfh;
    - struct tcl_file_event *fev = (struct tcl_file_event *)event;
    - int mask;
    -
    - if (!(flags & TCL_FILE_EVENTS)) {
    - return 0;
    - }
    -
    - tfh = g_hash_table_lookup(tcl_file_handlers, GINT_TO_POINTER(fev->fd));
    - if (tfh == NULL)
    - return 1;
    -
    - mask = tfh->mask & tfh->pending;
    - if (mask)
    - (*tfh->proc)(tfh->data, mask);
    - tfh->pending = 0;
    -
    - return 1;
    -}
    --- a/libpurple/plugins/tcl/tcl_glib.h Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,29 +0,0 @@
    -/*
    - * Tcl/Glib glue
    - *
    - * Copyright (C) 2003 Ethan Blanton <eblanton@cs.purdue.edu>
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program 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 General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
    - */
    -
    -#ifndef _PURPLE_TCL_GLIB_H_
    -#define _PURPLE_TCL_GLIB_H_
    -
    -#include <tcl.h>
    -#include <glib.h>
    -
    -void tcl_glib_init(void);
    -
    -#endif /* _PURPLE_TCL_GLIB_H_ */
    --- a/libpurple/plugins/tcl/tcl_purple.h Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,118 +0,0 @@
    -/**
    - * @file tcl_purple.h Purple Tcl definitions
    - *
    - * purple
    - *
    - * Copyright (C) 2003 Ethan Blanton <eblanton@cs.purdue.edu>
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program 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 General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
    - */
    -
    -#ifndef _PURPLE_TCL_PURPLE_H_
    -#define _PURPLE_TCL_PURPLE_H_
    -
    -#include <tcl.h>
    -
    -#include "internal.h"
    -#include "cmds.h"
    -#include "plugins.h"
    -#include "stringref.h"
    -
    -struct tcl_signal_handler {
    - Tcl_Obj *signal;
    - Tcl_Interp *interp;
    -
    - void *instance;
    - Tcl_Obj *namespace;
    - /* These following two are temporary during setup */
    - Tcl_Obj *args;
    - Tcl_Obj *proc;
    -
    - GType returntype;
    - int nargs;
    - GType *argtypes;
    -};
    -
    -struct tcl_cmd_handler {
    - PurpleCmdId id;
    - Tcl_Obj *cmd;
    - Tcl_Interp *interp;
    -
    - Tcl_Obj *namespace;
    - /* These are temporary during setup */
    - const char *args;
    - int priority;
    - int flags;
    - const char *protocol_id;
    - Tcl_Obj *proc;
    - const char *helpstr;
    -
    - int nargs;
    -};
    -
    -extern PurplePlugin *_tcl_plugin;
    -
    -/* Capitalized this way because these are "types" */
    -extern PurpleStringref *PurpleTclRefAccount;
    -extern PurpleStringref *PurpleTclRefConnection;
    -extern PurpleStringref *PurpleTclRefConversation;
    -extern PurpleStringref *PurpleTclRefPointer;
    -extern PurpleStringref *PurpleTclRefPlugin;
    -extern PurpleStringref *PurpleTclRefPresence;
    -extern PurpleStringref *PurpleTclRefStatus;
    -extern PurpleStringref *PurpleTclRefStatusAttr;
    -extern PurpleStringref *PurpleTclRefStatusType;
    -extern PurpleStringref *PurpleTclRefXfer;
    -extern PurpleStringref *PurpleTclRefHandle;
    -
    -PurplePlugin *tcl_interp_get_plugin(Tcl_Interp *interp);
    -
    -void tcl_signal_init(void);
    -void tcl_signal_handler_free(struct tcl_signal_handler *handler);
    -void tcl_signal_cleanup(Tcl_Interp *interp);
    -gboolean tcl_signal_connect(struct tcl_signal_handler *handler);
    -void tcl_signal_disconnect(void *instance, const char *signal, Tcl_Interp *interp);
    -
    -void tcl_cmd_init(void);
    -void tcl_cmd_handler_free(struct tcl_cmd_handler *handler);
    -void tcl_cmd_cleanup(Tcl_Interp *interp);
    -PurpleCmdId tcl_cmd_register(struct tcl_cmd_handler *handler);
    -void tcl_cmd_unregister(PurpleCmdId id, Tcl_Interp *interp);
    -
    -void purple_tcl_ref_init(void);
    -void *purple_tcl_ref_get(Tcl_Interp *interp, Tcl_Obj *obj, PurpleStringref *type);
    -Tcl_Obj *purple_tcl_ref_new(PurpleStringref *type, void *value);
    -
    -Tcl_ObjCmdProc tcl_cmd_account;
    -Tcl_ObjCmdProc tcl_cmd_signal_connect;
    -Tcl_ObjCmdProc tcl_cmd_buddy;
    -Tcl_ObjCmdProc tcl_cmd_cmd;
    -Tcl_ObjCmdProc tcl_cmd_connection;
    -Tcl_ObjCmdProc tcl_cmd_conversation;
    -Tcl_ObjCmdProc tcl_cmd_core;
    -Tcl_ObjCmdProc tcl_cmd_debug;
    -Tcl_ObjCmdProc tcl_cmd_notify;
    -Tcl_ObjCmdProc tcl_cmd_plugins;
    -Tcl_ObjCmdProc tcl_cmd_prefs;
    -Tcl_ObjCmdProc tcl_cmd_presence;
    -Tcl_ObjCmdProc tcl_cmd_savedstatus;
    -Tcl_ObjCmdProc tcl_cmd_send_im;
    -Tcl_ObjCmdProc tcl_cmd_signal;
    -Tcl_ObjCmdProc tcl_cmd_status;
    -Tcl_ObjCmdProc tcl_cmd_status_attr;
    -Tcl_ObjCmdProc tcl_cmd_status_type;
    -Tcl_ObjCmdProc tcl_cmd_unload;
    -
    -#endif /* _PURPLE_TCL_PURPLE_H_ */
    --- a/libpurple/plugins/tcl/tcl_ref.c Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,156 +0,0 @@
    -/**
    - * @file tcl_ref.c Purple Tcl typed references API
    - *
    - * purple
    - *
    - * Copyright (C) 2006 Ethan Blanton <eblanton@cs.purdue.edu>
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program 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 General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
    - */
    -
    -#include <tcl.h>
    -#include <glib.h>
    -
    -#include "tcl_purple.h"
    -#include "stringref.h"
    -
    -/* Instead of all that internal representation mumbo jumbo, use these
    - * macros to access the internal representation of a PurpleTclRef */
    -#define OBJ_REF_TYPE(obj) (obj->internalRep.twoPtrValue.ptr1)
    -#define OBJ_REF_VALUE(obj) (obj->internalRep.twoPtrValue.ptr2)
    -
    -static Tcl_FreeInternalRepProc purple_tcl_ref_free;
    -static Tcl_DupInternalRepProc purple_tcl_ref_dup;
    -static Tcl_UpdateStringProc purple_tcl_ref_update;
    -static Tcl_SetFromAnyProc purple_tcl_ref_set;
    -
    -static Tcl_ObjType purple_tcl_ref = {
    - "PurpleTclRef",
    - purple_tcl_ref_free,
    - purple_tcl_ref_dup,
    - purple_tcl_ref_update,
    - purple_tcl_ref_set
    -};
    -
    -void purple_tcl_ref_init()
    -{
    - Tcl_RegisterObjType(&purple_tcl_ref);
    -}
    -
    -void *purple_tcl_ref_get(Tcl_Interp *interp, Tcl_Obj *obj, PurpleStringref *type)
    -{
    - if (obj->typePtr != &purple_tcl_ref) {
    - if (Tcl_ConvertToType(interp, obj, &purple_tcl_ref) != TCL_OK)
    - return NULL;
    - }
    - if (strcmp(purple_stringref_value(OBJ_REF_TYPE(obj)),
    - purple_stringref_value(type))) {
    - if (interp) {
    - Tcl_Obj *error = Tcl_NewStringObj("Bad Purple reference type: expected ", -1);
    - Tcl_AppendToObj(error, purple_stringref_value(type), -1);
    - Tcl_AppendToObj(error, " but got ", -1);
    - Tcl_AppendToObj(error, purple_stringref_value(OBJ_REF_TYPE(obj)), -1);
    - Tcl_SetObjResult(interp, error);
    - }
    - return NULL;
    - }
    - return OBJ_REF_VALUE(obj);
    -}
    -
    -Tcl_Obj *purple_tcl_ref_new(PurpleStringref *type, void *value)
    -{
    - Tcl_Obj *obj = Tcl_NewObj();
    - obj->typePtr = &purple_tcl_ref;
    - OBJ_REF_TYPE(obj) = purple_stringref_ref(type);
    - OBJ_REF_VALUE(obj) = value;
    - Tcl_InvalidateStringRep(obj);
    - return obj;
    -}
    -
    -static void purple_tcl_ref_free(Tcl_Obj *obj)
    -{
    - purple_stringref_unref(OBJ_REF_TYPE(obj));
    -}
    -
    -static void purple_tcl_ref_dup(Tcl_Obj *obj1, Tcl_Obj *obj2)
    -{
    - OBJ_REF_TYPE(obj2) = purple_stringref_ref(OBJ_REF_TYPE(obj1));
    - OBJ_REF_VALUE(obj2) = OBJ_REF_VALUE(obj1);
    -}
    -
    -static void purple_tcl_ref_update(Tcl_Obj *obj)
    -{
    - size_t len;
    - /* This is ugly on memory, but we pretty much have to either
    - * do this or guesstimate lengths or introduce a varargs
    - * function in here ... ugh. */
    - char *bytes = g_strdup_printf("purple-%s:%p",
    - purple_stringref_value(OBJ_REF_TYPE(obj)),
    - OBJ_REF_VALUE(obj));
    -
    - obj->length = strlen(bytes);
    - len = obj->length + 1;
    - obj->bytes = ckalloc(len);
    - g_strlcpy(obj->bytes, bytes, len);
    - g_free(bytes);
    -}
    -
    -/* This isn't as memory-efficient as setting could be, because we
    - * essentially have to synthesize the Stringref here, where we would
    - * really rather dup it. Oh, well. */
    -static int purple_tcl_ref_set(Tcl_Interp *interp, Tcl_Obj *obj)
    -{
    - char *bytes = Tcl_GetStringFromObj(obj, NULL);
    - char *ptr;
    - PurpleStringref *type;
    - void *value;
    - static const char prefix[] = "purple-";
    - static const gsize prefixlen = sizeof(prefix) - 1;
    -
    - if (strlen(bytes) < prefixlen
    - || strncmp(bytes, prefix, prefixlen)
    - || (ptr = strchr(bytes, ':')) == NULL
    - || (gsize)(ptr - bytes) == prefixlen)
    - goto badobject;
    -
    - /* Bad Ethan */
    - *ptr = '\0';
    - type = purple_stringref_new(bytes + prefixlen);
    - *ptr = ':';
    - ptr++;
    -
    - if (sscanf(ptr, "%p", &value) == 0) {
    - purple_stringref_unref(type);
    - goto badobject;
    - }
    -
    - /* At this point we know we have a good object; free the old and
    - * install our internal representation. */
    - if (obj->typePtr != NULL && obj->typePtr->freeIntRepProc != NULL)
    - obj->typePtr->freeIntRepProc(obj);
    -
    - obj->typePtr = &purple_tcl_ref;
    - OBJ_REF_TYPE(obj) = type;
    - OBJ_REF_VALUE(obj) = value;
    -
    - return TCL_OK;
    -
    -badobject:
    - if (interp) {
    - Tcl_SetObjResult(interp,
    - Tcl_NewStringObj("invalid PurpleTclRef representation", -1));
    - }
    - return TCL_ERROR;
    -}
    --- a/libpurple/plugins/tcl/tcl_signals.c Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,404 +0,0 @@
    -/**
    - * @file tcl_signals.c Purple Tcl signal API
    - *
    - * purple
    - *
    - * Copyright (C) 2003 Ethan Blanton <eblanton@cs.purdue.edu>
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program 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 General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
    - */
    -#include <tcl.h>
    -#include <stdarg.h>
    -
    -#include "tcl_purple.h"
    -
    -#include "internal.h"
    -#include "connection.h"
    -#include "conversation.h"
    -#include "signals.h"
    -#include "debug.h"
    -#include "core.h"
    -
    -static GList *tcl_callbacks;
    -
    -static void *tcl_signal_callback(va_list args, struct tcl_signal_handler *handler);
    -static Tcl_Obj *new_cb_namespace (void);
    -
    -void tcl_signal_init()
    -{
    - tcl_callbacks = NULL;
    -}
    -
    -void tcl_signal_handler_free(struct tcl_signal_handler *handler)
    -{
    - if (handler == NULL)
    - return;
    -
    - Tcl_DecrRefCount(handler->signal);
    - if (handler->namespace)
    - {
    - Tcl_DecrRefCount(handler->namespace);
    - }
    - g_free(handler);
    -}
    -
    -void tcl_signal_cleanup(Tcl_Interp *interp)
    -{
    - GList *cur;
    - struct tcl_signal_handler *handler;
    -
    - for (cur = tcl_callbacks; cur != NULL; cur = g_list_next(cur)) {
    - handler = cur->data;
    - if (handler->interp == interp) {
    - tcl_signal_handler_free(handler);
    - cur->data = NULL;
    - }
    - }
    - tcl_callbacks = g_list_remove_all(tcl_callbacks, NULL);
    -}
    -
    -gboolean tcl_signal_connect(struct tcl_signal_handler *handler)
    -{
    - GString *proc;
    -
    - purple_signal_get_types(handler->instance,
    - Tcl_GetString(handler->signal),
    - &handler->returntype, &handler->nargs,
    - &handler->argtypes);
    -
    - tcl_signal_disconnect(handler->interp, Tcl_GetString(handler->signal),
    - handler->interp);
    -
    - if (!purple_signal_connect_vargs(handler->instance,
    - Tcl_GetString(handler->signal),
    - (void *)handler->interp,
    - PURPLE_CALLBACK(tcl_signal_callback),
    - (void *)handler))
    - return FALSE;
    -
    - handler->namespace = new_cb_namespace ();
    - Tcl_IncrRefCount(handler->namespace);
    - proc = g_string_new("");
    - g_string_append_printf(proc, "namespace eval %s { proc cb { %s } { %s } }",
    - Tcl_GetString(handler->namespace),
    - Tcl_GetString(handler->args),
    - Tcl_GetString(handler->proc));
    - if (Tcl_Eval(handler->interp, proc->str) != TCL_OK) {
    - Tcl_DecrRefCount(handler->namespace);
    - g_string_free(proc, TRUE);
    - return FALSE;
    - }
    - g_string_free(proc, TRUE);
    -
    - tcl_callbacks = g_list_append(tcl_callbacks, (gpointer)handler);
    -
    - return TRUE;
    -}
    -
    -void tcl_signal_disconnect(void *instance, const char *signal, Tcl_Interp *interp)
    -{
    - GList *cur;
    - struct tcl_signal_handler *handler;
    - gboolean found = FALSE;
    - GString *cmd;
    -
    - for (cur = tcl_callbacks; cur != NULL; cur = g_list_next(cur)) {
    - handler = cur->data;
    - if (handler->interp == interp && handler->instance == instance
    - && !strcmp(signal, Tcl_GetString(handler->signal))) {
    - purple_signal_disconnect(instance, signal, handler->interp,
    - PURPLE_CALLBACK(tcl_signal_callback));
    - cmd = g_string_sized_new(64);
    - g_string_printf(cmd, "namespace delete %s",
    - Tcl_GetString(handler->namespace));
    - Tcl_EvalEx(interp, cmd->str, -1, TCL_EVAL_GLOBAL);
    - tcl_signal_handler_free(handler);
    - g_string_free(cmd, TRUE);
    - cur->data = NULL;
    - found = TRUE;
    - break;
    - }
    - }
    - if (found)
    - tcl_callbacks = g_list_remove_all(tcl_callbacks, NULL);
    -}
    -
    -static PurpleStringref *ref_purple_type(GType type)
    -{
    - if (type == PURPLE_TYPE_ACCOUNT)
    - return PurpleTclRefAccount;
    - else if (type == PURPLE_TYPE_CONNECTION)
    - return PurpleTclRefConnection;
    - else if (type == PURPLE_TYPE_CONVERSATION)
    - return PurpleTclRefConversation;
    - else if (type == PURPLE_TYPE_PLUGIN)
    - return PurpleTclRefPlugin;
    - else if (type == PURPLE_TYPE_STATUS)
    - return PurpleTclRefStatus;
    - else if (type == PURPLE_TYPE_XFER)
    - return PurpleTclRefXfer;
    - else
    - return NULL;
    -}
    -
    -static void *tcl_signal_callback(va_list args, struct tcl_signal_handler *handler)
    -{
    - GString *name, *val;
    - PurpleBlistNode *node;
    - int i;
    - void *retval = NULL;
    - Tcl_Obj *cmd, *arg, *result;
    - void **vals; /* Used for inout parameters */
    - char ***strs;
    -
    - vals = g_new0(void *, handler->nargs);
    - strs = g_new0(char **, handler->nargs);
    - name = g_string_sized_new(32);
    - val = g_string_sized_new(32);
    -
    - cmd = Tcl_NewListObj(0, NULL);
    - Tcl_IncrRefCount(cmd);
    -
    - arg = Tcl_DuplicateObj(handler->namespace);
    - Tcl_AppendStringsToObj(arg, "::cb", NULL);
    - Tcl_ListObjAppendElement(handler->interp, cmd, arg);
    -
    - for (i = 0; i < handler->nargs; i++) {
    -#if 0
    - if (purple_value_is_outgoing(handler->argtypes[i]))
    - g_string_printf(name, "%s::arg%d",
    - Tcl_GetString(handler->namespace), i);
    -#endif
    - switch(handler->argtypes[i]) {
    - case G_TYPE_POINTER:
    -#if 0
    - case G_TYPE_OBJECT:
    - case G_TYPE_BOXED:
    - /* These are all "pointer" types to us */
    - if (purple_value_is_outgoing(handler->argtypes[i]))
    - purple_debug_error("tcl", "pointer types do not currently support outgoing arguments\n");
    -#endif
    - arg = purple_tcl_ref_new(PurpleTclRefPointer, va_arg(args, void *));
    - break;
    - case G_TYPE_BOOLEAN:
    -#if 0
    - if (purple_value_is_outgoing(handler->argtypes[i])) {
    - vals[i] = va_arg(args, gboolean *);
    - Tcl_LinkVar(handler->interp, name->str,
    - (char *)&vals[i], TCL_LINK_BOOLEAN);
    - arg = Tcl_NewStringObj(name->str, -1);
    - } else
    -#endif
    - arg = Tcl_NewBooleanObj(va_arg(args, gboolean));
    - break;
    - case G_TYPE_CHAR:
    - case G_TYPE_UCHAR:
    - case G_TYPE_INT:
    - case G_TYPE_UINT:
    - case G_TYPE_LONG:
    - case G_TYPE_ULONG:
    - /* I should really cast these individually to
    - * preserve as much information as possible ...
    - * but heh */
    -#if 0
    - if (purple_value_is_outgoing(handler->argtypes[i])) {
    - vals[i] = va_arg(args, int *);
    - Tcl_LinkVar(handler->interp, name->str,
    - vals[i], TCL_LINK_INT);
    - arg = Tcl_NewStringObj(name->str, -1);
    - } else
    -#endif
    - arg = Tcl_NewIntObj(va_arg(args, int));
    - break;
    - case G_TYPE_INT64:
    - case G_TYPE_UINT64:
    - /* Tcl < 8.4 doesn't have wide ints, so we have ugly
    - * ifdefs in here */
    -#if 0
    - if (purple_value_is_outgoing(handler->argtypes[i])) {
    - vals[i] = (void *)va_arg(args, gint64 *);
    - #if (TCL_MAJOR_VERSION >= 8 && TCL_MINOR_VERSION >= 4)
    - Tcl_LinkVar(handler->interp, name->str,
    - vals[i], TCL_LINK_WIDE_INT);
    - #else
    - /* This is going to cause weirdness at best,
    - * but what do you want ... we're losing
    - * precision */
    - Tcl_LinkVar(handler->interp, name->str,
    - vals[i], TCL_LINK_INT);
    - #endif /* Tcl >= 8.4 */
    - arg = Tcl_NewStringObj(name->str, -1);
    - } else {
    -#endif
    - #if (TCL_MAJOR_VERSION >= 8 && TCL_MINOR_VERSION >= 4)
    - arg = Tcl_NewWideIntObj(va_arg(args, gint64));
    - #else
    - arg = Tcl_NewIntObj((int)va_arg(args, int));
    - #endif /* Tcl >= 8.4 */
    - break;
    - case G_TYPE_STRING:
    -#if 0
    - if (purple_value_is_outgoing(handler->argtypes[i])) {
    - strs[i] = va_arg(args, char **);
    - if (strs[i] == NULL || *strs[i] == NULL) {
    - vals[i] = ckalloc(1);
    - *(char *)vals[i] = '\0';
    - } else {
    - size_t len = strlen(*strs[i]) + 1;
    - vals[i] = ckalloc(len);
    - g_strlcpy(vals[i], *strs[i], len);
    - }
    - Tcl_LinkVar(handler->interp, name->str,
    - (char *)&vals[i], TCL_LINK_STRING);
    - arg = Tcl_NewStringObj(name->str, -1);
    - } else
    -#endif
    - arg = Tcl_NewStringObj(va_arg(args, char *), -1);
    - break;
    - default:
    - if (handler->argtypes[i] == PURPLE_TYPE_ACCOUNT ||
    - handler->argtypes[i] == PURPLE_TYPE_CONNECTION ||
    - handler->argtypes[i] == PURPLE_TYPE_CONVERSATION ||
    - handler->argtypes[i] == PURPLE_TYPE_STATUS ||
    - handler->argtypes[i] == PURPLE_TYPE_PLUGIN ||
    - handler->argtypes[i] == PURPLE_TYPE_XFER )
    - {
    -#if 0
    - if (purple_value_is_outgoing(handler->argtypes[i]))
    - purple_debug_error("tcl", "pointer subtypes do not currently support outgoing arguments\n");
    -#endif
    - arg = purple_tcl_ref_new(ref_purple_type(handler->argtypes[i]), va_arg(args, void *));
    - }
    - else
    - if (handler->argtypes[i] == PURPLE_TYPE_CONTACT ||
    - handler->argtypes[i] == PURPLE_TYPE_BUDDY ||
    - handler->argtypes[i] == PURPLE_TYPE_GROUP ||
    - handler->argtypes[i] == PURPLE_TYPE_CHAT )
    - {
    - /* We're going to switch again for code-deduping */
    -#if 0
    - if (purple_value_is_outgoing(handler->argtypes[i]))
    - node = *va_arg(args, PurpleBlistNode **);
    - else
    -#endif
    - node = va_arg(args, PurpleBlistNode *);
    -
    - if (PURPLE_IS_GROUP(node)) {
    - arg = Tcl_NewListObj(0, NULL);
    - Tcl_ListObjAppendElement(handler->interp, arg,
    - Tcl_NewStringObj("group", -1));
    - Tcl_ListObjAppendElement(handler->interp, arg,
    - Tcl_NewStringObj(purple_group_get_name(PURPLE_GROUP(node)), -1));
    - } else if (PURPLE_IS_CONTACT(node)) {
    - /* g_string_printf(val, "contact {%s}", Contact Name? ); */
    - arg = Tcl_NewStringObj("contact", -1);
    - } else if (PURPLE_IS_BUDDY(node)) {
    - arg = Tcl_NewListObj(0, NULL);
    - Tcl_ListObjAppendElement(handler->interp, arg,
    - Tcl_NewStringObj("buddy", -1));
    - Tcl_ListObjAppendElement(handler->interp, arg,
    - Tcl_NewStringObj(purple_buddy_get_name(PURPLE_BUDDY(node)), -1));
    - Tcl_ListObjAppendElement(handler->interp, arg,
    - purple_tcl_ref_new(PurpleTclRefAccount,
    - purple_buddy_get_account(PURPLE_BUDDY(node))));
    - } else if (PURPLE_IS_CHAT(node)) {
    - arg = Tcl_NewListObj(0, NULL);
    - Tcl_ListObjAppendElement(handler->interp, arg,
    - Tcl_NewStringObj("chat", -1));
    - Tcl_ListObjAppendElement(handler->interp, arg,
    - Tcl_NewStringObj(purple_chat_get_name(PURPLE_CHAT(node)), -1));
    - Tcl_ListObjAppendElement(handler->interp, arg,
    - purple_tcl_ref_new(PurpleTclRefAccount,
    - purple_chat_get_account(PURPLE_CHAT(node))));
    - }
    - }
    - else if (G_TYPE_IS_ENUM(handler->argtypes[i]))
    - {
    - arg = Tcl_NewIntObj(va_arg(args, int));
    - }
    - else
    - {
    - /* What? I guess just pass the word ... */
    - /* treat this as a pointer, but complain first */
    - purple_debug(PURPLE_DEBUG_ERROR, "tcl", "unknown type %s\n",
    - g_type_name(handler->argtypes[i]));
    - }
    - }
    - Tcl_ListObjAppendElement(handler->interp, cmd, arg);
    - }
    -
    - /* Call the friggin' procedure already */
    - if (Tcl_EvalObjEx(handler->interp, cmd, TCL_EVAL_GLOBAL) != TCL_OK) {
    - purple_debug(PURPLE_DEBUG_ERROR, "tcl", "error evaluating callback: %s\n",
    - Tcl_GetString(Tcl_GetObjResult(handler->interp)));
    - } else {
    - result = Tcl_GetObjResult(handler->interp);
    - /* handle return values -- strings and words only */
    - if (handler->returntype) {
    - if (handler->returntype == G_TYPE_STRING) {
    - retval = (void *)g_strdup(Tcl_GetString(result));
    - } else {
    - if (Tcl_GetIntFromObj(handler->interp, result, (int *)&retval) != TCL_OK) {
    - purple_debug(PURPLE_DEBUG_ERROR, "tcl", "Error retrieving procedure result: %s\n",
    - Tcl_GetString(Tcl_GetObjResult(handler->interp)));
    - retval = NULL;
    - }
    - }
    - }
    - }
    -
    - /* And finally clean up */
    - for (i = 0; i < handler->nargs; i++) {
    - g_string_printf(name, "%s::arg%d",
    - Tcl_GetString(handler->namespace), i);
    -#if 0
    - if (purple_value_is_outgoing(handler->argtypes[i])
    - && purple_value_get_type(handler->argtypes[i]) != G_TYPE_SUBTYPE)
    - Tcl_UnlinkVar(handler->interp, name->str);
    - /* We basically only have to deal with strings on the
    - * way out */
    - switch (handler->argtypes[i]) {
    - case G_TYPE_STRING:
    - if (purple_value_is_outgoing(handler->argtypes[i])) {
    - if (vals[i] != NULL && *(char **)vals[i] != NULL) {
    - g_free(*strs[i]);
    - *strs[i] = g_strdup(vals[i]);
    - }
    - ckfree(vals[i]);
    - }
    - break;
    - default:
    - /* nothing */
    - ;
    - }
    -#endif
    - }
    -
    - g_string_free(name, TRUE);
    - g_string_free(val, TRUE);
    - g_free(vals);
    - g_free(strs);
    -
    - return retval;
    -}
    -
    -static Tcl_Obj *new_cb_namespace ()
    -{
    - static int cbnum;
    - char name[32];
    -
    - g_snprintf (name, sizeof(name), "::purple::_callback::cb_%d", cbnum++);
    - return Tcl_NewStringObj (name, -1);
    -}
    --- a/libpurple/plugins/test.pl Tue Mar 08 21:09:10 2016 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,42 +0,0 @@
    -use Purple;
    -
    -%PLUGIN_INFO = (
    - perl_api_version => 2,
    - name => 'Test Perl Plugin',
    - version => '1.0',
    - summary => 'Provides as a test base for the perl plugin.',
    - description => 'Provides as a test base for the perl plugin.',
    - author => 'Etan Reisner <deryni\@pidgin.im>',
    - url => 'https://pidgin.im',
    -
    - load => "plugin_load"
    -);
    -
    -sub plugin_init {
    - return %PLUGIN_INFO;
    -}
    -
    -sub account_status_cb {
    - my ($account, $old, $new, $data) = @_;
    -
    - Purple::Debug::info("perl test plugin", "In account_status_cb\n");
    -
    - Purple::Debug::info("perl test plugin", "Account " .
    - $account->get_username() . " changed status.\n");
    - Purple::Debug::info("perl test plugin", $data . "\n");
    -}
    -
    -sub plugin_load {
    - my $plugin = shift;
    -
    - Purple::Debug::info("perl test plugin", "plugin_load\n");
    -
    - Purple::Debug::info("perl test plugin", "Listing accounts.\n");
    - foreach $account (Purple::Accounts::get_all()) {
    - Purple::Debug::info("perl test plugin", $account->get_username() . "\n");
    - }
    -
    - Purple::Signal::connect(Purple::Accounts::get_handle(),
    - "account-status-changed", $plugin,
    - \&account_status_cb, "test");
    -}