URL Shortening Service - How to not use any? All shortening services available are spammed!

Okay - I’ve found out that I set wrong restrictions on my goo.gl service I think - however I would really love to know which file the code for the shortening is found nevertheless. On the list I got from t-online - also goo.gl and bit.ly domains will be classified as spam.
Optimizemember allows your own url instead - so I would really prefer that and I’m pretty sure as soon as I know inside which file(s) the shortening code stuff is to be found - I can just use the code from Optimizemember instead.

Oh yeah - just for reference - I cannot use any of the following shortening services!!!
So really need to use custom own URL instead.

T-Online blocks all of the URL services found on this website:
http://www.surbl.org/tld

Below are the top 10 of abused redirectors (to our knowledge):

1. bit.ly
2. bit.do
3. ow.ly
4. goo.gl
5. x.co
6. rebrand.ly
7. tinyurl.com
8. t.co
9. is.gd
10. ht.ly

1 Like

Okay - finally found it. The code is located inside utils-urls.inc.php - found inside: s2Member/includes/classes/

As Optimizemember is publishing this file under GNU - I feel so free to copy in a) the relevant section:

			/**
			* Shortens a long URL, based on optimizeMember configuration.
			*
			* @package optimizeMember\Utilities
			* @since 111002
			*
			* @param str $url A full/long URL to be shortened.
			* @param str $api_sp Optional. A specific URL shortening API to use. Defaults to that which is configured in the optimizeMember Dashboard. Normally `tiny_url`, by default.
			* @param bool $try_backups Defaults to true. If a failure occurs with the first API, we'll try others until we have success.
			* @return str|bool The shortened URL on success, else false on failure.
			*/
			public static function shorten($url = FALSE, $api_sp = FALSE, $try_backups = TRUE)
				{
					$url = /* Force strings, else false. */ ($url && is_string($url)) ? $url : false;
					$api_sp = ($api_sp && is_string($api_sp)) ? strtolower($api_sp) : false;
					/**/
					$default_url_shortener = $GLOBALS["WS_PLUGIN__"]["optimizemember"]["o"]["default_url_shortener"];
					if ($default_url_shortener === "none"){
						return false;
					}
					$default_custom_str_url_shortener = $GLOBALS["WS_PLUGIN__"]["optimizemember"]["o"]["default_custom_str_url_shortener"];
					/**/
					$apis = /* The shortening APIs currently pre-integrated in this release of optimizeMember. */ array("tiny_url", "goo_gl");
					/**/
					if($url && ($api = /* If specific, use it. Otherwise, use the default shortening API. */ ($api_sp) ? $api_sp : $default_url_shortener))
						{
							if(!$api_sp && ($custom_url = trim(apply_filters("ws_plugin__optimizemember_url_shorten", false, get_defined_vars()))) && stripos($custom_url, "http") === 0)
								return /* Using whatever other shortener API you prefer, over the ones available by default with optimizeMember. */ ($shorter_url = $custom_url);
							/**/
							else if(!$api_sp && stripos($default_custom_str_url_shortener, "http") === 0 && ($custom_url = trim(c_ws_plugin__optimizemember_utils_urls::remote(str_ireplace(array("%%s2_long_url%%", "%%s2_long_url_md5%%"), array(rawurlencode($url), urlencode(md5($url))), $default_custom_str_url_shortener)))) && stripos($custom_url, "http") === 0)
								return /* Using whatever other shortener API that a site owner prefers, over the ones available by default with optimizeMember. */ ($shorter_url = $custom_url);
							/**/
							else if($api === "tiny_url" && ($tiny_url = trim(c_ws_plugin__optimizemember_utils_urls::remote("http://tinyurl.com/api-create.php?url=".rawurlencode($url)))) && stripos($tiny_url, "http") === 0)
								return /* The default tinyURL API: <http://tinyurl.com/api-create.php?url=http://www.example.com/>. */ ($shorter_url = $tiny_url);
							/**/
							else if($api === "goo_gl" && ($goo_gl = json_decode(trim(c_ws_plugin__optimizemember_utils_urls::remote("https://www.googleapis.com/urlshortener/v1/url".((($goo_gl_key = apply_filters("ws_plugin__optimizemember_url_shorten_api_goo_gl_key", false))) ? "?key=".urlencode($goo_gl_key) : ""), json_encode(array("longUrl" => $url)), array("headers" => array("Content-Type" => "application/json")))), true)) && !empty($goo_gl["id"]) && is_string($goo_gl_url = $goo_gl["id"]) && stripos($goo_gl_url, "http") === 0)
								return /* Google API: <http://code.google.com/apis/urlshortener/v1/getting_started.html>. */ ($shorter_url = $goo_gl_url);
							/**/
							else if /* Try backups? This way we can still shorten the URL with a backup. */($try_backups && count($apis) > 1)
								/**/
								foreach /* Try other backup APIs now. */(array_diff($apis, array($api)) as $backup)
									if(($backup = c_ws_plugin__optimizemember_utils_urls::shorten($url, $backup, false)))
										return /* Success, we can return now. */ ($shorter_url = $backup);
						}
					return /* Default return value. */ false;
				}
			/**

and b) - find the full file to download here - would be great if someone can adapt this code to s2member- I’ll give it a try right now. and post the result in the next reply.
find it here (sorry not possible to upload here in the forum - remove the .txt that I just added for security reasons):
https://openmtbmap.org/wp-content/uploads/utils-urls.inc.php.txt

Adapted code below - however this will not work - as I need to find out also where to add the “none” setting in the s2member User Interface. Can someone give me a pointer there?

				/**
				* Shortens a long URL, based on s2Member configuration.
				*
				* @package s2Member\Utilities
				* @since 111002
				*
				* @param str $url A full/long URL to be shortened.
				* @param str $api_sp Optional. A specific URL shortening API to use. Defaults to that which is configured in the s2Member Dashboard. Normally `tiny_url`, by default.
				* @param bool $try_backups Defaults to true. If a failure occurs with the first API, we'll try others until we have success.
				* @return str|bool The shortened URL on success, else false on failure.
				*/
				public static function shorten($url = FALSE, $api_sp = FALSE, $try_backups = TRUE)
					{
						$url = /* Force strings, else false. */ ($url && is_string($url)) ? $url : false;
						$api_sp = ($api_sp && is_string($api_sp)) ? strtolower($api_sp) : false;
						/**/
						$default_url_shortener = $GLOBALS['WS_PLUGIN__']['s2Member']['o']['default_url_shortener'];
						if ($default_url_shortener === 'none'){
							return false;
						}
						$default_custom_str_url_shortener = $GLOBALS['WS_PLUGIN__']['s2Member']['o']['default_custom_str_url_shortener'];
						/**/
						$apis = /* The shortening APIs currently pre-integrated in this release of s2Member. */ array('tiny_url', 'goo_gl');
						/**/
						if($url && ($api = /* If specific, use it. Otherwise, use the default shortening API. */ ($api_sp) ? $api_sp : $default_url_shortener))
							{
								if(!$api_sp && ($custom_url = trim(apply_filters('ws_plugin__s2Member_url_shorten', false, get_defined_vars()))) && stripos($custom_url, 'http') === 0)
									return /* Using whatever other shortener API you prefer, over the ones available by default with s2Member. */ ($shorter_url = $custom_url);
								/**/
								else if(!$api_sp && stripos($default_custom_str_url_shortener, 'http') === 0 && ($custom_url = trim(c_ws_plugin__s2Member_utils_urls::remote(str_ireplace(array('%%s2_long_url%%', '%%s2_long_url_md5%%'), array(rawurlencode($url), urlencode(md5($url))), $default_custom_str_url_shortener)))) && stripos($custom_url, 'http') === 0)
									return /* Using whatever other shortener API that a site owner prefers, over the ones available by default with s2Member. */ ($shorter_url = $custom_url);
								/**/
								else if($api === 'tiny_url' && ($tiny_url = trim(c_ws_plugin__s2Member_utils_urls::remote('http://tinyurl.com/api-create.php?url='.rawurlencode($url)))) && stripos($tiny_url, 'http') === 0)
									return /* The default tinyURL API: <http://tinyurl.com/api-create.php?url=http://www.example.com/>. */ ($shorter_url = $tiny_url);
								/**/
								else if($api === 'goo_gl' && ($goo_gl = json_decode(trim(c_ws_plugin__s2Member_utils_urls::remote('https://www.googleapis.com/urlshortener/v1/url'.((($goo_gl_key = apply_filters('ws_plugin__s2Member_url_shorten_api_goo_gl_key', false))) ? '?key='.urlencode($goo_gl_key) : ''), json_encode(array('longUrl' => $url)), array('headers' => array('Content-Type' => 'application/json')))), true)) && !empty($goo_gl['id']) && is_string($goo_gl_url = $goo_gl['id']) && stripos($goo_gl_url, 'http') === 0)
									return /* Google API: <http://code.google.com/apis/urlshortener/v1/getting_started.html>. */ ($shorter_url = $goo_gl_url);
								/**/
								else if /* Try backups? This way we can still shorten the URL with a backup. */($try_backups && count($apis) > 1)
									/**/
									foreach /* Try other backup APIs now. */(array_diff($apis, array($api)) as $backup)
										if(($backup = c_ws_plugin__s2Member_utils_urls::shorten($url, $backup, false)))
											return /* Success, we can return now. */ ($shorter_url = $backup);
							}
						return /* Default return value. */ false;
					}
				/**

Cool.

I made a note of this to make it possible in a coming release, to not use a shortening service. I wasn’t aware that it’d be such a problem.

For the options page, look here: s2member/src/includes/menu-pages/gen-ops.inc.php

:slight_smile:

2 Likes

Thanks a lot - with t-online it’s actually even worse than ending up in spam folder - the emails are bounced so never arrive.

With your above info I can fix it for my site in the time till the update (must have been somehow blind not to find it).

echo '<option value="none"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["default_url_shortener"] === "none") ? ' selected="selected"' : '').'>none (prevents spam classification, risk: broken links)</option>'."\n";

while adding:

					if ($default_url_shortener === 'none'){
					return false;
					}

in line 264 of utils-urls.inc.php - hope I’m not missing something here - Optimizemember code is really different from s2member in section (most of it is identical - but here they clearly changed quite a bit or did not update when s2member updated this section). If this is not working I will copy over the full section as inserted 3 posts above.

Edit: This is working. I have to run some more tests however - The first link produced by s2member was 4 lines long - while optimizemember manages to create links that are only 2 lines long (and seem to work very well too) - not sure if where this link is created. Maybe it can be simplified by a bit - or the 4 line long link was an exception?

1 Like

S2member Register link not shortened:
/?s2member_register=ZGVmNTAyMDBkNGViZjg3ODE2NDIyNTgxZTY5YzAyYmYyYjU2MzZjNDRiMTE3ZjU2NjMwYTUyZDIyMjFmODY1NDlhZjg2N2IwNWU4MzQ5YjAxNDUxZTg5MzRkNDQwZTA0YTQxZjc4ODY4ZjFhZDcyZDUzZjk5OTMwMTY5YWY2MTY0NGQ1NTkxZTg2NGM1MmRlNDc5ZjFjYjNmNTY5ZDUyMWM4MGE0MTkxZjUzMjc1Y2JjY2I1YWU5ZTc2ODJjNmEwZGUyNjQwYzM5Zjg0N2YzYWZjZWM2ZWY2NTYwODVjMzBiMGZiN2M4ZDVlZWFhYjcyOGYwYjQ3ZWJkYmU4MzJlZDZiMWQzOTQ4ZWI3OWFiYTE4YzU2YzJlNDFhZWJmNjVlYmVjMDFmMjE4Njg2ZTA2MjFkYTlmY2NmOWYxZGEzNGVhOGUyNDVlNjBjMzkxYTFlNTVkMGNlZWMyMjQwMTk2NzAzZjMzNTliZWE5NjBhYzBkNWNmMjdhNDE0NTZiYWMwYjQzODNmMGE5Y2M5NmU3MTE3MjRiYjQ5YzBlN2Q5Yzg5ZDFkZTUwZGViZjgwMWIyOGRjYTJmNDAzMmUxYmY2NDk5MjIxNDUzODc4Njg5ZDYyNzg5ZTMzMg

Optimizemember register Link not shortened:

/?optimizemember_register=fnhlOjA3MDlmYjczNmU3NDVkMTI4MGRmNDc2YjQ5Mzg0OTA2fMHBmsGrqaK2hpaFl5rEmsujsoPJp6eWsrKvmZmYsbfKmsbEqrqciaOjl67Apb67rKW8nqlwemDWfXdvtZmtsKSPXlRqtYpjjnNte45qe1uEg55jZmuAdol5kYWFzWJScLugsIG5vrW8nrShcqW-jdZ8emN2b2JxeVNSWGRqzHmZvn1p0l15XHx6fmqxc3x8iGCRiGuqYlJwwGNnjXSOfn5piWV7aXw

okay - there must be some code difference - the length is always the same - would be great if you can tell me where this is defined - then I could share/use the code from optimizemember (I guess it’s GNU too). The Optimizemember link really is okay for any email provider I guess - while with s2member over twice as long link - maybe there could be problems (not sure - but well I guess there once was a reason for the shortening of links).

Looking at the code a bit now, I see that you could have used the filter ws_plugin__s2member_before_register_link_gen in a hack to set the $shrink' variable to FALSE, and s2 wouldn’t shorten the URL. See: c_ws_plugin__s2member_register_access::register_link_gen in s2member\src\includes\classes\register-access.inc.php

public static function register_link_gen($subscr_gateway = '', $subscr_id = '', $custom = '', $item_number = '', $shrink = TRUE)
{
	foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
	do_action('ws_plugin__s2member_before_register_link_gen', get_defined_vars());
	unset($__refs, $__v);

	if($subscr_gateway && is_string($subscr_gateway) && $subscr_id && is_string($subscr_id) && $custom && is_string($custom) && $item_number && (is_string($item_number) || is_numeric($item_number)))
	{
		$register = c_ws_plugin__s2member_utils_encryption::encrypt('subscr_gateway_subscr_id_custom_item_number_time:.:|:.:'.$subscr_gateway.':.:|:.:'.$subscr_id.':.:|:.:'.$custom.':.:|:.:'.$item_number.':.:|:.:'.strtotime('now'));

		$register_link = home_url('/?s2member_register='.urlencode($register)); // Generate long URL/link.

		if($shrink && ($shorter_url = c_ws_plugin__s2member_utils_urls::shorten($register_link)))
			$register_link = $shorter_url.'#'.$_SERVER['HTTP_HOST'];
	}
	return apply_filters('ws_plugin__s2member_register_link_gen', ((!empty($register_link)) ? $register_link : FALSE), get_defined_vars());
}

s2Member has been improved with the years, and Jason made it more secure whenever possible. The length of that link may be one example of that. That’s why Jason always used a URL shortener instead of compromising this.

My preferred choice, if I were in your position, since you’re already hacking s2, I’d use my own URL shortener. https://yourls.org/#API

After setting $shrink to false with the above filter, then I’d use the filter ws_plugin__s2member_register_link_gen to shorten $register_link with my own shortener (e.g. YOURLS).

Funny enough, hacking this was my first customization when I started using s2Member, just before starting to give support… The old hack doesn’t work with the current version, though. https://www.primothemes.com/forums/viewtopic.php%3Ff=4&t=1636.html

s2Member used to allow a custom shortening service before. Not sure when or why Jason removed it. I’ll look into it and probably bring it back, including the option to not shorten.

:slight_smile:

2 Likes

Thanks - will have a look at your answer in more detail.

And yes - Yourls sounds great. That would really be the best solution considering all the problems present with public shortening services (and 99 USD a month for custom domains with bitly which is way too much for such a service).

I do not see a high security risk at all if the link is only as short as optimizemember creates it - no one uses s2member for a site with thousands of new users a day - and if someone really tries to attack the server with various combinations to find a valid registration link amd is not blocked - some other server security settings are wrong (because that would need a couple million hits at least)

1 Like

Have you ever considered Pretty Links? It is a free plugin and it allows you to have a link that starts with the URL of your site so it looks even better.

I don’t know how to implement it - but it really has to be from your own domain - anything else ends up in too many spam folders. BTW - the goo.gl service did not work for some time, and now is fully switched off.

Pretty Links is a free plugin for WP. Once installed, you create a new Pretty Link by entering the destination URL you want to shorten, and then it will provide you the “root” part of your domain and then you add whatever you want to call it. So for example the (fake) url could start as:

//yourdomain(dot)com/promotion/video/registrationform/2019/

but end up as http:// yourdomain(dot)com/ register2019

And the source does not even have to be on your own domain, so you can even create a Pretty Link with your domain in it, yet, it could link to an affiliate page.

Yes - but how do I integrate it into s2member? I don’t think that will be easy.

I’ve never used Pretty Links, but have heard about it. I tend to redirect affiliate referrals before things get to PHP to save CPU (e.g., NGINX or Apache conf files), but it’s just a plugin. Install it and use it. Am I wrong @Cassel?

You’re right for inbuilt wordpress functions, but not for anything related to s2member. You would need to set up s2member to recognize it and use it especially for those links

Hi Felix.

I updated s2’s URL Shortening with some changes:

  • Removed Goo.gl, since it’s no longer available.
  • Added the option to not shorten the URL.
  • Added a field for other shortening services over GET.

The last one makes it possible to integrate with YOURLS. Just install YOURLS in a dir (e.g. /r), get your token from YOURLS Admin > Tools > secret signature token, and use it in the API URL like this:

https://yoursite.com/r/yourls-api.php?signature=yourtoken&action=shorturl&format=simple&url=%%s2_long_url%%

YOURLS is included in cPanel’s Softaculous or Fantastico, which makes it easier to install.

You may be interested in this YOURLS plugin to generate a random string ID, instead of the incremental number ID. https://github.com/YOURLS/random-keywords

After setting it up, you can test this from the signup link generator here: WP Admin > s2Member > PayPal Buttons > Member Registration Access Links. Just enter a random value in the subscr ID and click “Generate Access Link”. It will output something like this: https://yoursite.com/r/0s1q4

I look forward to your feedback. :slight_smile:

2 Likes

Thanks a lot for this Change - and sorry for not thanking/replying earlier. I was very busy with other problems the last weeks.

So what did I do:

  • following several tutorials how to install yourls I went crazy! And actually several times managed to get the firewall of my server to block me. Not sure what went wrong here - Easiest is not to install yourls with own domain - but just install an instance of yourls for each website - and follow this guide:
    http://www.hardeepasrani.com/2017/06/installing-yourls-on-nginx/

Actually I realised that it it intended this way anyhow.

Just one thing missing - before opening the /admin/ website to run the yourls installer - I did a
sudo chown -R www-data:www-data /var/www/MYWEBSITE.COM/go
because you likely have the wrong user still.

Watch out in the config to change the following line correctly (if installed to go subdirectory):
define( ‘YOURLS_SITE’, ‘https://MYDOMAIN.ORG/go’ );

I of course also created a new user for MariaDB database to be used your yourls (one for each website!).

then Copied in the Random Keyword plugin - and activated it from the Yourls Plugin section. Copied the secret key to the above API URL - and it seems everything is working fine - at least the test worked okay.

If I don’t report back here again - it means it is working and it would be great to include this patch into the next s2member version.

I guess you could run yourls also using your website database user - but I guess using a separate database is more secure? Or would you recommend using the same database and user so in case you need to move your server - less things to go wrong?

1 Like