2013-05-09 09:11:17 +00:00
< ? php
/**
* Name : pump . io Post Connector
* Description : Post to pump . io
* Version : 0.1
* Author : Michael Vogel < http :// pirati . ca / profile / heluecht >
*/
require ( 'addon/pumpio/oauth/http.php' );
require ( 'addon/pumpio/oauth/oauth_client.php' );
2013-05-09 12:36:50 +00:00
define ( 'PUMPIO_DEFAULT_POLL_INTERVAL' , 5 ); // given in minutes
2013-05-09 09:11:17 +00:00
function pumpio_install () {
register_hook ( 'post_local' , 'addon/pumpio/pumpio.php' , 'pumpio_post_local' );
register_hook ( 'notifier_normal' , 'addon/pumpio/pumpio.php' , 'pumpio_send' );
register_hook ( 'jot_networks' , 'addon/pumpio/pumpio.php' , 'pumpio_jot_nets' );
register_hook ( 'connector_settings' , 'addon/pumpio/pumpio.php' , 'pumpio_settings' );
register_hook ( 'connector_settings_post' , 'addon/pumpio/pumpio.php' , 'pumpio_settings_post' );
2013-05-09 12:36:50 +00:00
register_hook ( 'cron' , 'addon/pumpio/pumpio.php' , 'pumpio_cron' );
2013-05-09 09:11:17 +00:00
}
function pumpio_uninstall () {
unregister_hook ( 'post_local' , 'addon/pumpio/pumpio.php' , 'pumpio_post_local' );
unregister_hook ( 'notifier_normal' , 'addon/pumpio/pumpio.php' , 'pumpio_send' );
unregister_hook ( 'jot_networks' , 'addon/pumpio/pumpio.php' , 'pumpio_jot_nets' );
unregister_hook ( 'connector_settings' , 'addon/pumpio/pumpio.php' , 'pumpio_settings' );
unregister_hook ( 'connector_settings_post' , 'addon/pumpio/pumpio.php' , 'pumpio_settings_post' );
2013-05-09 12:36:50 +00:00
unregister_hook ( 'cron' , 'addon/pumpio/pumpio.php' , 'pumpio_cron' );
2013-05-09 09:11:17 +00:00
}
function pumpio_module () {}
function pumpio_content ( & $a ) {
if ( ! local_user ()) {
notice ( t ( 'Permission denied.' ) . EOL );
return '' ;
}
if ( isset ( $a -> argv [ 1 ]))
switch ( $a -> argv [ 1 ]) {
case " connect " :
$o = pumpio_connect ( $a );
break ;
default :
$o = print_r ( $a -> argv , true );
break ;
}
else
$o = pumpio_connect ( $a );
return $o ;
}
2013-05-09 12:36:50 +00:00
function pumpio_registerclient ( $a , $host ) {
2013-05-09 09:11:17 +00:00
$url = " https:// " . $host . " /api/client/register " ;
$params = array ();
2013-05-09 12:36:50 +00:00
$application_name = get_config ( 'pumpio' , 'application_name' );
if ( $application_name == " " )
$application_name = $a -> get_hostname ();
2013-05-09 09:11:17 +00:00
$params [ " type " ] = " client_associate " ;
2013-05-16 20:58:48 +00:00
$params [ " contacts " ] = $a -> config [ 'admin_email' ];
2013-05-09 09:11:17 +00:00
$params [ " application_type " ] = " native " ;
2013-05-09 12:36:50 +00:00
$params [ " application_name " ] = $application_name ;
2013-05-15 20:22:16 +00:00
$params [ " logo_url " ] = $a -> get_baseurl () . " /images/friendica-256.png " ;
$params [ " redirect_uris " ] = $a -> get_baseurl () . " /pumpio/connect " ;
2013-05-09 09:11:17 +00:00
$ch = curl_init ( $url );
curl_setopt ( $ch , CURLOPT_HEADER , false );
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
curl_setopt ( $ch , CURLOPT_POST , 1 );
curl_setopt ( $ch , CURLOPT_POSTFIELDS , $params );
curl_setopt ( $ch , CURLOPT_USERAGENT , " Friendica " );
$s = curl_exec ( $ch );
$curl_info = curl_getinfo ( $ch );
if ( $curl_info [ " http_code " ] == " 200 " ) {
$values = json_decode ( $s );
return ( $values );
$pumpio = array ();
$pumpio [ " client_id " ] = $values -> client_id ;
$pumpio [ " client_secret " ] = $values -> client_secret ;
print_r ( $values );
}
return ( false );
}
function pumpio_connect ( $a ) {
// Start a session. This is necessary to hold on to a few keys the callback script will also need
session_start ();
// Define the needed keys
$consumer_key = get_pconfig ( local_user (), 'pumpio' , 'consumer_key' );
$consumer_secret = get_pconfig ( local_user (), 'pumpio' , 'consumer_secret' );
$hostname = get_pconfig ( local_user (), 'pumpio' , 'host' );
if ((( $consumer_key == " " ) OR ( $consumer_secret == " " )) AND ( $hostname != " " )) {
2013-05-09 12:36:50 +00:00
$clientdata = pumpio_registerclient ( $a , $hostname );
2013-05-09 09:11:17 +00:00
set_pconfig ( local_user (), 'pumpio' , 'consumer_key' , $clientdata -> client_id );
set_pconfig ( local_user (), 'pumpio' , 'consumer_secret' , $clientdata -> client_secret );
$consumer_key = get_pconfig ( local_user (), 'pumpio' , 'consumer_key' );
$consumer_secret = get_pconfig ( local_user (), 'pumpio' , 'consumer_secret' );
}
if (( $consumer_key == " " ) OR ( $consumer_secret == " " ))
return ;
// The callback URL is the script that gets called after the user authenticates with pumpio
$callback_url = $a -> get_baseurl () . " /pumpio/connect " ;
// Let's begin. First we need a Request Token. The request token is required to send the user
// to pumpio's login page.
// Create a new instance of the TumblrOAuth library. For this step, all we need to give the library is our
// Consumer Key and Consumer Secret
$client = new oauth_client_class ;
$client -> debug = 1 ;
$client -> server = '' ;
$client -> oauth_version = '1.0a' ;
$client -> request_token_url = 'https://' . $hostname . '/oauth/request_token' ;
$client -> dialog_url = 'https://' . $hostname . '/oauth/authorize' ;
$client -> access_token_url = 'https://' . $hostname . '/oauth/access_token' ;
$client -> url_parameters = false ;
$client -> authorization_header = true ;
$client -> redirect_uri = $callback_url ;
$client -> client_id = $consumer_key ;
$client -> client_secret = $consumer_secret ;
if (( $success = $client -> Initialize ())) {
if (( $success = $client -> Process ())) {
if ( strlen ( $client -> access_token )) {
set_pconfig ( local_user (), " pumpio " , " oauth_token " , $client -> access_token );
set_pconfig ( local_user (), " pumpio " , " oauth_token_secret " , $client -> access_token_secret );
}
}
$success = $client -> Finalize ( $success );
}
if ( $client -> exit )
$o = 'Could not connect to pumpio. Refresh the page or try again later.' ;
if ( $success ) {
$o .= t ( " You are now authenticated to pumpio. " );
$o .= '<br /><a href="' . $a -> get_baseurl () . '/settings/connectors">' . t ( " return to the connector page " ) . '</a>' ;
}
return ( $o );
}
function pumpio_jot_nets ( & $a , & $b ) {
if ( ! local_user ())
return ;
$pumpio_post = get_pconfig ( local_user (), 'pumpio' , 'post' );
if ( intval ( $pumpio_post ) == 1 ) {
$pumpio_defpost = get_pconfig ( local_user (), 'pumpio' , 'post_by_default' );
$selected = (( intval ( $pumpio_defpost ) == 1 ) ? ' checked="checked" ' : '' );
$b .= '<div class="profile-jot-net"><input type="checkbox" name="pumpio_enable"' . $selected . ' value="1" /> '
. t ( 'Post to pumpio' ) . '</div>' ;
}
}
function pumpio_settings ( & $a , & $s ) {
if ( ! local_user ())
return ;
/* Add our stylesheet to the page so we can make our settings look nice */
$a -> page [ 'htmlhead' ] .= '<link rel="stylesheet" type="text/css" href="' . $a -> get_baseurl () . '/addon/pumpio/pumpio.css' . '" media="all" />' . " \r \n " ;
/* Get the current state of our config variables */
$enabled = get_pconfig ( local_user (), 'pumpio' , 'post' );
$checked = (( $enabled ) ? ' checked="checked" ' : '' );
$def_enabled = get_pconfig ( local_user (), 'pumpio' , 'post_by_default' );
$def_checked = (( $def_enabled ) ? ' checked="checked" ' : '' );
2013-05-09 12:36:50 +00:00
$public_enabled = get_pconfig ( local_user (), 'pumpio' , 'public' );
$public_checked = (( $public_enabled ) ? ' checked="checked" ' : '' );
2013-05-09 13:08:08 +00:00
$mirror_enabled = get_pconfig ( local_user (), 'pumpio' , 'mirror' );
$mirror_checked = (( $mirror_enabled ) ? ' checked="checked" ' : '' );
2013-05-09 09:11:17 +00:00
$servername = get_pconfig ( local_user (), " pumpio " , " host " );
$username = get_pconfig ( local_user (), " pumpio " , " user " );
/* Add some HTML to the existing form */
$s .= '<div class="settings-block">' ;
$s .= '<h3>' . t ( 'Pump.io Post Settings' ) . '</h3>' ;
$s .= '<div id="pumpio-servername-wrapper">' ;
2013-05-09 12:36:50 +00:00
$s .= '<label id="pumpio-servername-label" for="pumpio-servername">' . t ( 'pump.io servername (without "http://" or "https://" )' ) . '</label>' ;
2013-05-09 09:11:17 +00:00
$s .= '<input id="pumpio-servername" type="text" name="pumpio_host" value="' . $servername . '" />' ;
$s .= '</div><div class="clear"></div>' ;
$s .= '<div id="pumpio-username-wrapper">' ;
2013-05-16 21:27:21 +00:00
$s .= '<label id="pumpio-username-label" for="pumpio-username">' . t ( 'pump.io username (without the servername)' ) . '</label>' ;
2013-05-09 09:11:17 +00:00
$s .= '<input id="pumpio-username" type="text" name="pumpio_user" value="' . $username . '" />' ;
$s .= '</div><div class="clear"></div>' ;
if (( $username != '' ) AND ( $servername != '' )) {
$s .= '<div id="pumpio-authenticate-wrapper">' ;
$s .= '<a href="' . $a -> get_baseurl () . '/pumpio/connect">' . t ( " (Re-)Authenticate your pump.io connection " ) . '</a>' ;
$s .= '</div><div class="clear"></div>' ;
$s .= '<div id="pumpio-enable-wrapper">' ;
$s .= '<label id="pumpio-enable-label" for="pumpio-checkbox">' . t ( 'Enable pump.io Post Plugin' ) . '</label>' ;
$s .= '<input id="pumpio-checkbox" type="checkbox" name="pumpio" value="1" ' . $checked . '/>' ;
$s .= '</div><div class="clear"></div>' ;
$s .= '<div id="pumpio-bydefault-wrapper">' ;
$s .= '<label id="pumpio-bydefault-label" for="pumpio-bydefault">' . t ( 'Post to pump.io by default' ) . '</label>' ;
$s .= '<input id="pumpio-bydefault" type="checkbox" name="pumpio_bydefault" value="1" ' . $def_checked . '/>' ;
$s .= '</div><div class="clear"></div>' ;
2013-05-09 12:36:50 +00:00
$s .= '<div id="pumpio-public-wrapper">' ;
$s .= '<label id="pumpio-public-label" for="pumpio-public">' . t ( 'Should posts be public?' ) . '</label>' ;
$s .= '<input id="pumpio-public" type="checkbox" name="pumpio_public" value="1" ' . $public_checked . '/>' ;
$s .= '</div><div class="clear"></div>' ;
2013-05-09 13:08:08 +00:00
$s .= '<div id="pumpio-mirror-wrapper">' ;
$s .= '<label id="pumpio-mirror-label" for="pumpio-mirror">' . t ( 'Mirror all public posts' ) . '</label>' ;
$s .= '<input id="pumpio-mirror" type="checkbox" name="pumpio_mirror" value="1" ' . $mirror_checked . '/>' ;
$s .= '</div><div class="clear"></div>' ;
2013-05-09 09:11:17 +00:00
$oauth_token = get_pconfig ( local_user (), " pumpio " , " oauth_token " );
$oauth_token_secret = get_pconfig ( local_user (), " pumpio " , " oauth_token_secret " );
$s .= '<div id="pumpio-password-wrapper">' ;
if (( $oauth_token == " " ) OR ( $oauth_token_secret == " " ))
$s .= t ( " You are not authenticated to pumpio " );
$s .= '</div><div class="clear"></div>' ;
}
/* provide a submit button */
$s .= '<div class="settings-submit-wrapper" ><input type="submit" id="pumpio-submit" name="pumpio-submit" class="settings-submit" value="' . t ( 'Submit' ) . '" /></div></div>' ;
}
function pumpio_settings_post ( & $a , & $b ) {
if ( x ( $_POST , 'pumpio-submit' )) {
2013-05-16 21:27:21 +00:00
// filtering the username if it is filled wrong
$user = $_POST [ 'pumpio_user' ];
if ( strstr ( $user , " @ " )) {
$pos = strpos ( $user , " @ " );
if ( $pos > 0 )
$user = substr ( $user , 0 , $pos );
}
// Filtering the hostname if someone is entering it with "http"
$host = $_POST [ 'pumpio_host' ];
$host = trim ( $host );
$host = str_replace ( array ( " https:// " , " http:// " ), array ( " " , " " ), $host );
2013-05-09 09:11:17 +00:00
set_pconfig ( local_user (), 'pumpio' , 'post' , intval ( $_POST [ 'pumpio' ]));
2013-05-16 21:27:21 +00:00
set_pconfig ( local_user (), 'pumpio' , 'host' , $host );
set_pconfig ( local_user (), 'pumpio' , 'user' , $user );
2013-05-09 12:36:50 +00:00
set_pconfig ( local_user (), 'pumpio' , 'public' , $_POST [ 'pumpio_public' ]);
2013-05-09 13:08:08 +00:00
set_pconfig ( local_user (), 'pumpio' , 'mirror' , $_POST [ 'pumpio_mirror' ]);
2013-05-09 09:11:17 +00:00
set_pconfig ( local_user (), 'pumpio' , 'post_by_default' , intval ( $_POST [ 'pumpio_bydefault' ]));
}
}
function pumpio_post_local ( & $a , & $b ) {
// This can probably be changed to allow editing by pointing to a different API endpoint
if ( $b [ 'edit' ])
return ;
if (( ! local_user ()) || ( local_user () != $b [ 'uid' ]))
return ;
if ( $b [ 'private' ] || $b [ 'parent' ])
return ;
$pumpio_post = intval ( get_pconfig ( local_user (), 'pumpio' , 'post' ));
$pumpio_enable = (( $pumpio_post && x ( $_REQUEST , 'pumpio_enable' )) ? intval ( $_REQUEST [ 'pumpio_enable' ]) : 0 );
if ( $_REQUEST [ 'api_source' ] && intval ( get_pconfig ( local_user (), 'pumpio' , 'post_by_default' )))
$pumpio_enable = 1 ;
if ( ! $pumpio_enable )
return ;
if ( strlen ( $b [ 'postopts' ]))
$b [ 'postopts' ] .= ',' ;
$b [ 'postopts' ] .= 'pumpio' ;
}
function pumpio_send ( & $a , & $b ) {
if ( $b [ 'deleted' ] || $b [ 'private' ] || ( $b [ 'created' ] !== $b [ 'edited' ]))
return ;
if ( ! strstr ( $b [ 'postopts' ], 'pumpio' ))
return ;
if ( $b [ 'parent' ] != $b [ 'id' ])
return ;
2013-05-09 12:36:50 +00:00
// if post comes from pump.io don't send it back
if ( $b [ 'app' ] == " pump.io " )
return ;
2013-05-09 09:11:17 +00:00
$oauth_token = get_pconfig ( $b [ 'uid' ], " pumpio " , " oauth_token " );
$oauth_token_secret = get_pconfig ( $b [ 'uid' ], " pumpio " , " oauth_token_secret " );
$consumer_key = get_pconfig ( $b [ 'uid' ], " pumpio " , " consumer_key " );
$consumer_secret = get_pconfig ( $b [ 'uid' ], " pumpio " , " consumer_secret " );
$host = get_pconfig ( $b [ 'uid' ], " pumpio " , " host " );
$user = get_pconfig ( $b [ 'uid' ], " pumpio " , " user " );
2013-05-09 12:36:50 +00:00
$public = get_pconfig ( $b [ 'uid' ], " pumpio " , " public " );
2013-05-09 09:11:17 +00:00
if ( $oauth_token && $oauth_token_secret ) {
require_once ( 'include/bbcode.php' );
$title = trim ( $b [ 'title' ]);
if ( $title != '' )
$title = " <h4> " . $title . " </h4> " ;
2013-05-15 20:22:16 +00:00
$params = array ();
2013-05-09 09:11:17 +00:00
2013-05-15 20:22:16 +00:00
$params [ " verb " ] = " post " ;
$params [ " object " ] = array (
2013-05-09 09:11:17 +00:00
'objectType' => " note " ,
'content' => $title . bbcode ( $b [ 'body' ], false , false ));
2013-05-09 12:36:50 +00:00
if ( $public )
2013-05-15 20:22:16 +00:00
$params [ " to " ] = array ( Array (
2013-05-09 12:36:50 +00:00
" objectType " => " collection " ,
" id " => " http://activityschema.org/collection/public " ));
2013-05-09 09:11:17 +00:00
$client = new oauth_client_class ;
$client -> oauth_version = '1.0a' ;
$client -> url_parameters = false ;
$client -> authorization_header = true ;
$client -> access_token = $oauth_token ;
$client -> access_token_secret = $oauth_token_secret ;
$client -> client_id = $consumer_key ;
$client -> client_secret = $consumer_secret ;
$success = $client -> CallAPI (
'https://' . $host . '/api/user/' . $user . '/feed' ,
'POST' , $params , array ( 'FailOnAccessError' => true , 'RequestContentType' => 'application/json' ), $user );
if ( $success )
logger ( 'pumpio_send: success' );
else
logger ( 'pumpio_send: general error: ' . print_r ( $user , true ));
}
}
2013-05-09 12:36:50 +00:00
function pumpio_cron ( $a , $b ) {
$last = get_config ( 'pumpio' , 'last_poll' );
$poll_interval = intval ( get_config ( 'pumpio' , 'poll_interval' ));
if ( ! $poll_interval )
$poll_interval = PUMPIO_DEFAULT_POLL_INTERVAL ;
2013-05-16 20:58:48 +00:00
if ( $last ) {
$next = $last + ( $poll_interval * 60 );
if ( $next > time ()) {
logger ( 'pumpio: poll intervall not reached' );
return ;
}
}
2013-05-09 12:36:50 +00:00
logger ( 'pumpio: cron_start' );
2013-05-09 13:08:08 +00:00
$r = q ( " SELECT * FROM `pconfig` WHERE `cat` = 'pumpio' AND `k` = 'mirror' AND `v` = '1' ORDER BY RAND() " );
2013-05-09 12:36:50 +00:00
if ( count ( $r )) {
foreach ( $r as $rr ) {
logger ( 'pumpio: fetching for user ' . $rr [ 'uid' ]);
pumpio_fetchtimeline ( $a , $rr [ 'uid' ]);
}
}
logger ( 'pumpio: cron_end' );
set_config ( 'pumpio' , 'last_poll' , time ());
}
function pumpio_fetchtimeline ( $a , $uid ) {
2013-05-15 20:22:16 +00:00
$ckey = get_pconfig ( $uid , 'pumpio' , 'consumer_key' );
$csecret = get_pconfig ( $uid , 'pumpio' , 'consumer_secret' );
$otoken = get_pconfig ( $uid , 'pumpio' , 'oauth_token' );
$osecret = get_pconfig ( $uid , 'pumpio' , 'oauth_token_secret' );
2013-05-09 13:08:08 +00:00
$lastdate = get_pconfig ( $uid , 'pumpio' , 'lastdate' );
2013-05-09 12:36:50 +00:00
$hostname = get_pconfig ( $uid , 'pumpio' , 'host' );
$username = get_pconfig ( $uid , " pumpio " , " user " );
$application_name = get_config ( 'pumpio' , 'application_name' );
if ( $application_name == " " )
$application_name = $a -> get_hostname ();
2013-05-16 20:58:48 +00:00
$first_time = ( $lastdate == " " );
2013-05-09 12:36:50 +00:00
$client = new oauth_client_class ;
$client -> oauth_version = '1.0a' ;
$client -> authorization_header = true ;
$client -> url_parameters = false ;
$client -> client_id = $ckey ;
2013-05-15 20:22:16 +00:00
$client -> client_secret = $csecret ;
2013-05-09 12:36:50 +00:00
$client -> access_token = $otoken ;
$client -> access_token_secret = $osecret ;
2013-05-15 20:22:16 +00:00
$url = 'https://' . $hostname . '/api/user/' . $username . '/feed/major' ;
logger ( 'pumpio: fetching for user ' . $uid . ' ' . $url . ' C:' . $client -> client_id . ' CS:' . $client -> client_secret . ' T:' . $client -> access_token . ' TS:' . $client -> access_token_secret );
$success = $client -> CallAPI ( $url , 'GET' , array (), array ( 'FailOnAccessError' => true ), $user );
if ( ! $success ) {
logger ( 'pumpio: error fetching posts for user ' . $uid . " " . print_r ( $user , true ));
return ;
}
2013-05-09 12:36:50 +00:00
2013-05-09 13:08:08 +00:00
$posts = array_reverse ( $user -> items );
$initiallastdate = $lastdate ;
2013-05-16 20:58:48 +00:00
$lastdate = '' ;
2013-05-09 12:36:50 +00:00
if ( count ( $posts )) {
foreach ( $posts as $post ) {
2013-05-16 20:58:48 +00:00
if ( $post -> generator -> published <= $initiallastdate )
2013-05-09 12:36:50 +00:00
continue ;
2013-05-16 20:58:48 +00:00
if ( $lastdate < $post -> generator -> published )
$lastdate = $post -> generator -> published ;
2013-05-09 13:08:08 +00:00
2013-05-16 20:58:48 +00:00
if ( $first_time )
continue ;
2013-05-09 13:08:08 +00:00
2013-05-16 21:36:05 +00:00
$receiptians = array ();
if ( @ is_array ( $post -> cc ))
$receiptians = array_merge ( $receiptians , $post -> cc );
if ( @ is_array ( $post -> to ))
$receiptians = array_merge ( $receiptians , $post -> to );
$public = false ;
foreach ( $receiptians AS $receiver )
if ( is_string ( $receiver -> objectType ))
if ( $receiver -> id == " http://activityschema.org/collection/public " )
$public = true ;
if ( $public AND ! strstr ( $post -> generator -> displayName , $application_name )) {
2013-05-09 12:36:50 +00:00
require_once ( 'include/html2bbcode.php' );
$_SESSION [ " authenticated " ] = true ;
$_SESSION [ " uid " ] = $uid ;
$_REQUEST [ " type " ] = " wall " ;
$_REQUEST [ " api_source " ] = true ;
$_REQUEST [ " profile_uid " ] = $uid ;
$_REQUEST [ " source " ] = " pump.io " ;
2013-05-16 20:58:48 +00:00
if ( $post -> object -> displayName != " " )
$_REQUEST [ " title " ] = html2bbcode ( $post -> object -> displayName );
2013-05-09 12:36:50 +00:00
$_REQUEST [ " body " ] = html2bbcode ( $post -> object -> content );
2013-05-16 20:58:48 +00:00
if ( $post -> object -> fullImage -> url != " " )
$_REQUEST [ " body " ] = " [url= " . $post -> object -> fullImage -> url . " ][img] " . $post -> object -> image -> url . " [/img][/url] \n " . $_REQUEST [ " body " ];
2013-05-09 12:36:50 +00:00
logger ( 'pumpio: posting for user ' . $uid );
require_once ( 'mod/item.php' );
2013-05-16 20:58:48 +00:00
//print_r($_REQUEST);
2013-05-09 12:36:50 +00:00
item_post ( $a );
2013-05-16 20:58:48 +00:00
logger ( 'pumpio: posting done - user ' . $uid );
2013-05-09 12:36:50 +00:00
}
}
}
2013-05-16 20:58:48 +00:00
//$lastdate = '2013-05-16T20:22:12Z';
2013-05-09 13:08:08 +00:00
if ( $lastdate != 0 )
set_pconfig ( $uid , 'pumpio' , 'lastdate' , $lastdate );
2013-05-09 12:36:50 +00:00
}