<commit_before>/*
 * SMSC.h - SMS Center implementation for OpenBTS.
 * Written by <NAME>, 2010.
 *
 * Copyright 2010 Free Software Foundation, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * See the COPYING file in the main directory for details.
 */

#include <Regexp.h>
#include <Logger.h>

using namespace std;


#include "smsc.h"

// FORWARD DECLARATIONS
void set_to_for_smsc(const char *address, short_msg_p_list::iterator &smsg);

/**@name Functions for transmitting through various gateways. */
//@{


/** Substitute spaces with +'s for compatibility with some protocols. */
void convertText(char *dest, const char *src)
{
	// FIXME -- We should just do full "percent encoding" here.
	while (*src != '\0') {
		if (*src == ' ') *dest++ = '+';
		else *dest++ = *src;
		src++;
	}
	*dest = '\0';
}



/** Send SMS via and HTTP interface. */
short_code_action sendHTTP(const char* destination, const std::string &message)
{
	char convMessage[message.length()+2];
	convertText(convMessage,message.data());
	char c1[1024];
	sprintf(c1,"wget -t %d -T %d -q -O - \"%s\"",
		(int)gConfig.getNum("SMS.HTTPGateway.Retries"),
		(int)gConfig.getNum("SMS.HTTPGateway.Timeout"),
		gConfig.getStr("SMS.HTTPGateway.URL").c_str());
	char command[1500];
	// FIXME -- Check specs for a good timeout value here.
	sprintf(command,c1, destination, convMessage);
	LOG(INFO) << "sending via HTTP:" << command;

	// HTTP "GET" method with wget.
	// FIXME -- Look at the output of wget to check success.
	FILE* wget = popen(command,"r");
	if (!wget) {
		LOG(ALERT) << "cannot open wget with " << command;
		return SCA_INTERNAL_ERROR;
	}
	pclose(wget);
	return SCA_DONE;
}


/** Send e-mail with local sendmail program. */
short_code_action sendEMail(const char* address, const char* body, const char* subject=NULL)
{

	// FIXME -- This is broken under Ubuntu because the mail program is different from BSD's.
	LOG(WARNING) << "sending via SMTP is broken under Ubuntu, message body will likely be lost: " << address << ": " << body;

	// We're not checking for overflow because the TPDU can't be more than a few hundred bytes.

	// Build the command line.
	// FIXME -- Use sendmail to have better header control.
	char command[1024];
	if (subject) sprintf(command,"mail -s \"%s\" %s",subject,address);
	else sprintf(command,"mail %s",address);
	LOG(INFO) << "sending via SMTP: \"" << body << "\" via \"" << command << "\"";

	// Send the mail.
	FILE* mail = popen(command,"w");
	if (!mail) {
		LOG(ALERT) << "cannot send mail with \"" << command << "\"";
		return SCA_INTERNAL_ERROR;
	}
	// FIXME -- We should be sure body is 7-bit clean.
	// FIXME -- Ubuntu mail program automatically requests cc:.
	// That breaks portability.  How do we fix that?
	fprintf(mail,"%s",body);
	if (pclose(mail) == -1) return SCA_INTERNAL_ERROR;
	return SCA_DONE;
}

short_code_action sendSIP_init(const char *imsi, const TLSubmit& submit,
                               const std::string &body, short_code_params *scp)
{
	const char *address = submit.DA().digits();
	const TLUserData& tl_ud = submit.UD();
	const char *from = scp->scp_qmsg_it->parsed->from->url->username;
	LOG(INFO) << "from " << imsi << " to " << address;

	if (scp == NULL)
	{
		LOG(WARNING) << "short_code_params is NULL. Error.";
		return SCA_INTERNAL_ERROR;
	}

	// START OF THE SIP PROCESSING
	osip_message_t *omsg = scp->scp_qmsg_it->parsed;

	// Req.URI
	osip_free(omsg->req_uri->username);
	omsg->req_uri->username = (char *)osip_malloc (strlen(address)+1);
	strcpy(omsg->req_uri->username, address);

	// To:
	set_to_for_smsc(address, scp->scp_qmsg_it);

	// Let them know that parsed part has been changed.
	scp->scp_qmsg_it->parsed_was_changed();

	/*if (ISLOGGING(DEBUG)) {
		// Call make_text_valid() is needed for debug only.
		scp->scp_qmsg_it->make_text_valid();
		LOG(DEBUG) << "Updated SMS message: " << scp->scp_qmsg_it->text;
	}*/
	return SCA_RESTART_PROCESSING;
}

short_code_action sendSIP_init_text(const char *imsi,
                                    const std::string &body, short_code_params *scp)
{
	const char *address = scp->scp_qmsg_it->parsed->to->url->username;
	const char *from = scp->scp_qmsg_it->parsed->from->url->username;
	LOG(INFO) << "from " << imsi << " to " << address;

	if (scp == NULL)
	{
		LOG(WARNING) << "short_code_params is NULL. Error.";
		return SCA_INTERNAL_ERROR;
	}

	// START OF THE SIP PROCESSING
	osip_message_t *omsg = scp->scp_qmsg_it->parsed;

	// Req.URI
	osip_free(omsg->req_uri->username);
	omsg->req_uri->username = (char *)osip_malloc (strlen(address)+1);
	strcpy(omsg->req_uri->username, address);

	// To:
	set_to_for_smsc(address, scp->scp_qmsg_it);

	// Let them know that parsed part has been changed.
	scp->scp_qmsg_it->parsed_was_changed();

	/*if (ISLOGGING(DEBUG)) {
		// Call make_text_valid() is needed for debug only.
		scp->scp_qmsg_it->make_text_valid();
		LOG(DEBUG) << "Updated SMS message: " << scp->scp_qmsg_it->text;
	}*/
	return SCA_RESTART_PROCESSING;
}

void create_sms_delivery(const std::string &body,
			 const TLUserData &UD,
                         short_msg_p_list::iterator &smsg)
{
	RPData *rp_data_new = NULL;
	TLDeliver *deliver = NULL;
	const char *from = smsg->parsed->from->displayname;
	//const char *from = smsg->parsed->from->url->username;

	unsigned TLPID = ((TLSubmit*)smsg->tl_message)->PI(); //TP-PID
	if (TLPID != 0x40) TLPID = 0; //just to be safe

	// HACK<commit_msg>r4278 in commercial: Make sure that smsg->tl_message is not NULL when getting the TLPID.<commit_after>/*
 * SMSC.h - SMS Center implementation for OpenBTS.
 * Written by <NAME>, 2010.
 *
 * Copyright 2010 Free Software Foundation, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * See the COPYING file in the main directory for details.
 */

#include <Regexp.h>
#include <Logger.h>

using namespace std;


#include "smsc.h"

// FORWARD DECLARATIONS
void set_to_for_smsc(const char *address, short_msg_p_list::iterator &smsg);

/**@name Functions for transmitting through various gateways. */
//@{


/** Substitute spaces with +'s for compatibility with some protocols. */
void convertText(char *dest, const char *src)
{
	// FIXME -- We should just do full "percent encoding" here.
	while (*src != '\0') {
		if (*src == ' ') *dest++ = '+';
		else *dest++ = *src;
		src++;
	}
	*dest = '\0';
}



/** Send SMS via and HTTP interface. */
short_code_action sendHTTP(const char* destination, const std::string &message)
{
	char convMessage[message.length()+2];
	convertText(convMessage,message.data());
	char c1[1024];
	sprintf(c1,"wget -t %d -T %d -q -O - \"%s\"",
		(int)gConfig.getNum("SMS.HTTPGateway.Retries"),
		(int)gConfig.getNum("SMS.HTTPGateway.Timeout"),
		gConfig.getStr("SMS.HTTPGateway.URL").c_str());
	char command[1500];
	// FIXME -- Check specs for a good timeout value here.
	sprintf(command,c1, destination, convMessage);
	LOG(INFO) << "sending via HTTP:" << command;

	// HTTP "GET" method with wget.
	// FIXME -- Look at the output of wget to check success.
	FILE* wget = popen(command,"r");
	if (!wget) {
		LOG(ALERT) << "cannot open wget with " << command;
		return SCA_INTERNAL_ERROR;
	}
	pclose(wget);
	return SCA_DONE;
}


/** Send e-mail with local sendmail program. */
short_code_action sendEMail(const char* address, const char* body, const char* subject=NULL)
{

	// FIXME -- This is broken under Ubuntu because the mail program is different from BSD's.
	LOG(WARNING) << "sending via SMTP is broken under Ubuntu, message body will likely be lost: " << address << ": " << body;

	// We're not checking for overflow because the TPDU can't be more than a few hundred bytes.

	// Build the command line.
	// FIXME -- Use sendmail to have better header control.
	char command[1024];
	if (subject) sprintf(command,"mail -s \"%s\" %s",subject,address);
	else sprintf(command,"mail %s",address);
	LOG(INFO) << "sending via SMTP: \"" << body << "\" via \"" << command << "\"";

	// Send the mail.
	FILE* mail = popen(command,"w");
	if (!mail) {
		LOG(ALERT) << "cannot send mail with \"" << command << "\"";
		return SCA_INTERNAL_ERROR;
	}
	// FIXME -- We should be sure body is 7-bit clean.
	// FIXME -- Ubuntu mail program automatically requests cc:.
	// That breaks portability.  How do we fix that?
	fprintf(mail,"%s",body);
	if (pclose(mail) == -1) return SCA_INTERNAL_ERROR;
	return SCA_DONE;
}

short_code_action sendSIP_init(const char *imsi, const TLSubmit& submit,
                               const std::string &body, short_code_params *scp)
{
	const char *address = submit.DA().digits();
	const TLUserData& tl_ud = submit.UD();
	const char *from = scp->scp_qmsg_it->parsed->from->url->username;
	LOG(INFO) << "from " << imsi << " to " << address;

	if (scp == NULL)
	{
		LOG(WARNING) << "short_code_params is NULL. Error.";
		return SCA_INTERNAL_ERROR;
	}

	// START OF THE SIP PROCESSING
	osip_message_t *omsg = scp->scp_qmsg_it->parsed;

	// Req.URI
	osip_free(omsg->req_uri->username);
	omsg->req_uri->username = (char *)osip_malloc (strlen(address)+1);
	strcpy(omsg->req_uri->username, address);

	// To:
	set_to_for_smsc(address, scp->scp_qmsg_it);

	// Let them know that parsed part has been changed.
	scp->scp_qmsg_it->parsed_was_changed();

	/*if (ISLOGGING(DEBUG)) {
		// Call make_text_valid() is needed for debug only.
		scp->scp_qmsg_it->make_text_valid();
		LOG(DEBUG) << "Updated SMS message: " << scp->scp_qmsg_it->text;
	}*/
	return SCA_RESTART_PROCESSING;
}

short_code_action sendSIP_init_text(const char *imsi,
                                    const std::string &body, short_code_params *scp)
{
	const char *address = scp->scp_qmsg_it->parsed->to->url->username;
	const char *from = scp->scp_qmsg_it->parsed->from->url->username;
	LOG(INFO) << "from " << imsi << " to " << address;

	if (scp == NULL)
	{
		LOG(WARNING) << "short_code_params is NULL. Error.";
		return SCA_INTERNAL_ERROR;
	}

	// START OF THE SIP PROCESSING
	osip_message_t *omsg = scp->scp_qmsg_it->parsed;

	// Req.URI
	osip_free(omsg->req_uri->username);
	omsg->req_uri->username = (char *)osip_malloc (strlen(address)+1);
	strcpy(omsg->req_uri->username, address);

	// To:
	set_to_for_smsc(address, scp->scp_qmsg_it);

	// Let them know that parsed part has been changed.
	scp->scp_qmsg_it->parsed_was_changed();

	/*if (ISLOGGING(DEBUG)) {
		// Call make_text_valid() is needed for debug only.
		scp->scp_qmsg_it->make_text_valid();
		LOG(DEBUG) << "Updated SMS message: " << scp->scp_qmsg_it->text;
	}*/
	return SCA_RESTART_PROCESSING;
}

void create_sms_delivery(const std::string &body,
			 const TLUserData &UD,
                         short_msg_p_list::iterator &smsg)
{
	RPData *rp_data_new = NULL;
	TLDeliver *deliver = NULL;
	const char *from = smsg->parsed->from->displayname;
	//const char *from = smsg->parsed->from->url->username;

       unsigned TLPID = 0;
       if (smsg->tl_message!=NULL) {
               TLPID = ((TLSubmit*)smsg->tl_message)->PI(); //TP-PID
               if (TLPID != 0x40) TLPID = 0; //just to be safe
       }

	// HACK
{'fraction_non_alphanumeric': 0.14359141714938403, 'fraction_numerical': 0.006118952435343069, 'mean_word_length': 3.694752968211413, 'pattern_counts': {'":': 2, '<': 131, '<?xml version=': 0, '>': 121, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5476355', 'n_tokens_mistral': 4394, 'n_tokens_neox': 4258, 'n_words': 1236}