<commit_before>/* copyright 2013 <NAME> and contributors (see LICENSE for licensing information) */

#define _GNU_SOURCE

#include <time.h>
#include <glib.h>
#include <errno.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/wait.h>

#include "dbus.h"
#include "x.h"
#include "notification.h"
#include "dunst.h"
#include "utils.h"
#include "settings.h"
#include "rules.h"
#include "menu.h"

int next_notification_id = 1;

        /*
         * print a human readable representation
         * of the given notification to stdout.
         */
void notification_print(notification * n)
{
        printf("{\n");
        printf("\tappname: '%s'\n", n->appname);
        printf("\tsummary: '%s'\n", n->summary);
        printf("\tbody: '%s'\n", n->body);
        printf("\ticon: '%s'\n", n->icon);
        printf("\tcategory: %s\n", n->category);
        printf("\turgency: %d\n", n->urgency);
        printf("\tformatted: '%s'\n", n->msg);
        printf("\tfg: %s\n", n->color_strings[ColFG]);
        printf("\tbg: %s\n", n->color_strings[ColBG]);
        printf("\tid: %d\n", n->id);
        if (n->urls) {
                printf("\turls\n");
                printf("\t{\n");
                printf("%s\n", n->urls);
                printf("\t}\n");
        }

        if (n->actions) {
                printf("\tactions:\n");
                printf("\t{\n");
                for (int i = 0; i < n->actions->count; i += 2) {
                        printf("\t\t [%s,%s]\n", n->actions->actions[i],
                               n->actions->actions[i + 1]);
                }
                printf("actions_dmenu: %s\n", n->actions->dmenu_str);
                printf("\t]\n");
        }
        printf("\tscript: %s\n", n->script);
        printf("}\n");
}

        /*
         * Run the script associated with the
         * given notification.
         */
void notification_run_script(notification * n)
{
        if (!n->script || strlen(n->script) < 1)
                return;

        char *appname = n->appname ? n->appname : "";
        char *summary = n->summary ? n->summary : "";
        char *body = n->body ? n->body : "";
        char *icon = n->icon ? n->icon : "";

        char *urgency;
        switch (n->urgency) {
        case LOW:
                urgency = "LOW";
                break;
        case NORM:
                urgency = "NORMAL";
                break;
        case CRIT:
                urgency = "CRITICAL";
                break;
        default:
                urgency = "NORMAL";
                break;
        }

        int pid1 = fork();

        if (pid1) {
                int status;
                waitpid(pid1, &status, 0);
        } else {
                int pid2 = fork();
                if (pid2) {
                        exit(0);
                } else {
                        int ret = execlp(n->script, n->script,
                                         appname,
                                         summary,
                                         body,
                                         icon,
                                         urgency,
                                         (char *)NULL);
                        if (ret != 0) {
                                PERR("Unable to run script", errno);
                                exit(EXIT_FAILURE);
                        }
                }
        }
}

        /*
         * Helper function to compare to given
         * notifications.
         */
int notification_cmp(const void *va, const void *vb)
{
        notification *a = (notification *) va;
        notification *b = (notification *) vb;

        if (!settings.sort)
                return 1;

        if (a->urgency != b->urgency) {
                return b->urgency - a->urgency;
        } else {
                return a->id - b->id;
        }
}

        /*
         * Wrapper for notification_cmp to match glib's
         * compare functions signature.
         */
int notification_cmp_data(const void *va, const void *vb, void *data)
{
        return notification_cmp(va, vb);
}

        /*
         * Free the memory used by the given notification.
         */
void notification_free(notification * n)
{
        if (n == NULL)
                return;
        free(n->appname);
        free(n->summary);
        free(n->body);
        free(n->icon);
        free(n->msg);
        free(n->dbus_client);

        if (n->actions) {
                g_strfreev(n->actions->actions);
                free(n->actions->dmenu_str);
        }

        if (n->raw_icon) {
            if (n->raw_icon->data)
                free(n->raw_icon->data);
            free(n->raw_icon);
        }

        free(n);
}

        /*
         * Strip any markup from text
         */<commit_msg>fix memleaks<commit_after>/* copyright 2013 <NAME> and contributors (see LICENSE for licensing information) */

#define _GNU_SOURCE

#include <time.h>
#include <glib.h>
#include <errno.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/wait.h>

#include "dbus.h"
#include "x.h"
#include "notification.h"
#include "dunst.h"
#include "utils.h"
#include "settings.h"
#include "rules.h"
#include "menu.h"

int next_notification_id = 1;

        /*
         * print a human readable representation
         * of the given notification to stdout.
         */
void notification_print(notification * n)
{
        printf("{\n");
        printf("\tappname: '%s'\n", n->appname);
        printf("\tsummary: '%s'\n", n->summary);
        printf("\tbody: '%s'\n", n->body);
        printf("\ticon: '%s'\n", n->icon);
        printf("\tcategory: %s\n", n->category);
        printf("\turgency: %d\n", n->urgency);
        printf("\tformatted: '%s'\n", n->msg);
        printf("\tfg: %s\n", n->color_strings[ColFG]);
        printf("\tbg: %s\n", n->color_strings[ColBG]);
        printf("\tid: %d\n", n->id);
        if (n->urls) {
                printf("\turls\n");
                printf("\t{\n");
                printf("%s\n", n->urls);
                printf("\t}\n");
        }

        if (n->actions) {
                printf("\tactions:\n");
                printf("\t{\n");
                for (int i = 0; i < n->actions->count; i += 2) {
                        printf("\t\t [%s,%s]\n", n->actions->actions[i],
                               n->actions->actions[i + 1]);
                }
                printf("actions_dmenu: %s\n", n->actions->dmenu_str);
                printf("\t]\n");
        }
        printf("\tscript: %s\n", n->script);
        printf("}\n");
}

        /*
         * Run the script associated with the
         * given notification.
         */
void notification_run_script(notification * n)
{
        if (!n->script || strlen(n->script) < 1)
                return;

        char *appname = n->appname ? n->appname : "";
        char *summary = n->summary ? n->summary : "";
        char *body = n->body ? n->body : "";
        char *icon = n->icon ? n->icon : "";

        char *urgency;
        switch (n->urgency) {
        case LOW:
                urgency = "LOW";
                break;
        case NORM:
                urgency = "NORMAL";
                break;
        case CRIT:
                urgency = "CRITICAL";
                break;
        default:
                urgency = "NORMAL";
                break;
        }

        int pid1 = fork();

        if (pid1) {
                int status;
                waitpid(pid1, &status, 0);
        } else {
                int pid2 = fork();
                if (pid2) {
                        exit(0);
                } else {
                        int ret = execlp(n->script, n->script,
                                         appname,
                                         summary,
                                         body,
                                         icon,
                                         urgency,
                                         (char *)NULL);
                        if (ret != 0) {
                                PERR("Unable to run script", errno);
                                exit(EXIT_FAILURE);
                        }
                }
        }
}

        /*
         * Helper function to compare to given
         * notifications.
         */
int notification_cmp(const void *va, const void *vb)
{
        notification *a = (notification *) va;
        notification *b = (notification *) vb;

        if (!settings.sort)
                return 1;

        if (a->urgency != b->urgency) {
                return b->urgency - a->urgency;
        } else {
                return a->id - b->id;
        }
}

        /*
         * Wrapper for notification_cmp to match glib's
         * compare functions signature.
         */
int notification_cmp_data(const void *va, const void *vb, void *data)
{
        return notification_cmp(va, vb);
}

        /*
         * Free the memory used by the given notification.
         */
void notification_free(notification * n)
{
        if (n == NULL)
                return;
        free(n->appname);
        free(n->summary);
        free(n->body);
        free(n->icon);
        free(n->msg);
        free(n->dbus_client);

        if (n->category && *n->category != '\0')
                g_free(n->category);

        if (n->text_to_render)
                g_free(n->text_to_render);

        if (n->urls)
                g_free(n->urls);

        if (n->actions) {
                g_strfreev(n->actions->actions);
                free(n->actions->dmenu_str);
        }

        if (n->raw_icon) {
            if (n->raw_icon->data)
                free(n->raw_icon->data);
            free(n->raw_icon);
        }

        free(n);
}

        /*
         * Strip any markup from text
         */
{'fraction_non_alphanumeric': 0.1481971888368303, 'fraction_numerical': 0.003768588307190874, 'mean_word_length': 1.210490769923458, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 142, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 24, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7410934', 'n_tokens_mistral': 2912, 'n_tokens_neox': 2763, 'n_words': 632}