Version 4.3.0

This commit is contained in:
Neo committed 2025-12-19 05:47:12 -08:00
1 parent 96997ddd8e
commit fe1acf984a
1349 files changed
+116159 -67711

No files matched your search

@@ -158,6 +158,10 @@ class _Vbulletin5 extends \IPS\convert\Software
$where = array( $this->db->in( 'nodeid', $clubs ) );
return parent::countRows( $table, $where, $recache );
break;
case 'userchangelog':
return $this->db->select( 'count(changeid)', 'userchangelog', array( $this->db->in( 'fieldname', array_keys( static::$changeLogTypes ) ) ) )->first();
break;
default:
return parent::countRows( $table, $where, $recache );
@@ -464,8 +468,14 @@ class _Vbulletin5 extends \IPS\convert\Software
/* Content Counts */
\IPS\Task::queue( 'core', 'RecountMemberContent', array( 'app' => $this->app->app_id ), 4, array( 'app' ) );
/* Clubs */
\IPS\Task::queue( 'convert', 'RecountClubMembers', array( 'app' => $this->app->app_id ), 2, array( 'app' ) );
/* First Post Data */
\IPS\Task::queue( 'convert', 'RebuildConversationFirstIds', array( 'app' => $this->app->app_id ), 2, array( 'app' ) );
/* Attachments */
\IPS\Task::queue( 'core', 'RebuildAttachmentThumbnails', array( 'app' => $this->app->app_id ), 1, array( 'app' ) );
return array( "f_search_index_rebuild", "f_clear_caches", "f_rebuild_pms", "f_signatures_rebuild" );
}
@@ -488,6 +498,77 @@ class _Vbulletin5 extends \IPS\convert\Software
/* Remove video tags and allow our parser to handle the embeds it supports */
$post = preg_replace( "#\[video=[a-z]+;[a-z0-9_]+\](.*?)\[\/video\]#i", '$1', $post );
/* IMG2 BBcode */
$matches = array();
preg_match_all( "/\[IMG2=JSON](.+?)\[\/IMG2\]/i", $post, $matches );
if ( count( $matches ) )
{
foreach( $matches[0] as $k => $v )
{
try
{
/* Make sure the JSON value exists */
if( !isset( $matches[1][ $k ] ) )
{
throw new \DomainException;
}
$decoded = json_decode( $matches[1][ $k ], TRUE );
/* Make sure the JSON is valid and contains src */
if( !isset( $decoded['src'] ) OR empty( $decoded['src'] ) )
{
throw new \DomainException;
}
$post = str_replace( $v, "[img]{$decoded['src']}[/img]", $post );
}
catch( \DomainException $e )
{
continue;
}
}
}
/* Mentions */
$matches = array();
preg_match_all( '#\[user(=\"?(\d+)\"?)?\](.+?)\[\/user\]#i', $post, $matches ); // this purposefully matches more than the default vB mention.
if ( count( $matches ) )
{
if ( isset( $matches[1] ) )
{
$mentions = array();
foreach( $matches[1] AS $k => $v )
{
if ( isset( $matches[3][$k] ) )
{
$name = trim( $matches[3][ $k ], '@' );
$mentions[ $name ] = $v;
}
}
$maps = array();
$urls = array();
$cardUrls = array();
foreach( new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'core_members', array( \IPS\Db::i()->in( 'name', array_keys( $mentions ) ) ) ), 'IPS\Member' ) AS $member )
{
$maps[ $member->name ] = $member->member_id;
$urls[ $member->name ] = $member->url();
$cardUrls[ $member->name ] = $member->url()->setQueryString( 'do', 'hovercard' );
}
foreach( $mentions AS $member_name => $member_id )
{
$maps[ $member_name ] = preg_quote( $maps[ $member_name ], '#' );
$memberNameEscaped = preg_quote( $member_name, '#' );
$post = preg_replace( "#\[user(=\"?(\d+)\"?)?\]@?{$memberNameEscaped}\[\/user\]#i", "<a contenteditable=\"false\" rel=\"\" href=\"{$urls[ $member_name ]}\" data-mentionid=\"{$maps[ $member_name ]}\" data-ipshover-target=\"{$cardUrls[ $member_name ]}\" data-ipshover=\"\">@{$member_name}</a>", $post );
}
}
}
return $post;
}
@@ -822,7 +903,7 @@ class _Vbulletin5 extends \IPS\convert\Software
/**
* @brief Member history type map
*/
protected $changeLogTypes = array( 'username' => 'display_name', 'email' => 'email_change', 'usergroupid' => 'member_group_id', 'membergroupids' => 'mgroup_others' );
protected static $changeLogTypes = array( 'username' => 'display_name', 'email' => 'email_change', 'usergroupid' => 'member_group_id', 'membergroupids' => 'mgroup_others' );
/**
* Convert member history
@@ -832,53 +913,18 @@ class _Vbulletin5 extends \IPS\convert\Software
public function convertMemberHistory()
{
$libraryClass = $this->getLibrary();
$libraryClass::setKey( 'changeid' );
$fixGroups = function( $string )
foreach( $this->fetch( 'userchangelog', 'changeid', array( $this->db->in( 'fieldname', array_keys( static::$changeLogTypes ) ) ) ) AS $change )
{
$groups = explode( ',', $string );
$newGroups = array();
array_walk( $groups, function( &$item, $key ) use ( &$newGroups )
{
try
{
$item = $this->app->getLink( $item, 'core_groups' );
$newGroups[] = $item;
}
catch( \OutOfRangeException $e ){}
});
return implode( ',', $newGroups );
};
foreach( $this->fetch( 'userchangelog', 'changeid' ) AS $change )
{
if( !in_array( $change['fieldname'], array_keys( $this->changeLogTypes ) ) )
{
$libraryClass->setLastKeyValue( $change['changeid'] );
continue;
}
/* Any processing we need to do */
switch( $this->changeLogTypes[ $change['fieldname'] ] )
{
case 'member_group_id':
case 'mgroup_others':
$change['oldvalue'] = $fixGroups( $change['oldvalue'] );
$change['newvalue'] = $fixGroups( $change['newvalue'] );
break;
}
$libraryClass->convertMemberHistory( array(
'log_id' => $change['changeid'],
'log_member' => $change['userid'],
'log_by' => $change['adminid'],
'log_type' => $this->changeLogTypes[ $change['fieldname'] ],
'log_type' => static::$changeLogTypes[ $change['fieldname'] ],
'log_data' => array( 'old' => $change['oldvalue'], 'new' => $change['newvalue'] ),
'log_date' => $change['change_time'],
'log_ip_address' => long2ip( $change['ipaddress'] )
'log_ip_address' => long2ip( (int) $change['ipaddress'] )
)
);
@@ -1221,7 +1267,7 @@ class _Vbulletin5 extends \IPS\convert\Software
$libraryClass->convertMemberHistory( array(
'log_id' => 'w' . $warn['nodeid'],
'log_member' => $warn['infracteduserid'],
'log_by' => $warn['userid'],
'log_by' => $warn['actionuserid'],
'log_type' => 'warning',
'log_data' => array( 'wid' => $warnId ),
'log_date' => $warn['actiondateline']
@@ -1344,18 +1390,19 @@ class _Vbulletin5 extends \IPS\convert\Software
'map_user_active' => 1,
'map_user_banned' => 0,
'map_has_unread' => 0,
'map_is_starter' => ( $pm['userid'] == $pm['userid'] ) ? 1 : 0,
'map_is_starter' => 1,
);
foreach( $this->db->select( '*', 'node', array( "parentid=?", $pm['nodeid'] ) ) AS $post )
/* All other maps */
foreach( $this->db->select( '*', 'sentto', array( "nodeid=? AND userid!=?", $pm['nodeid'], $pm['userid'] ) ) AS $map )
{
$maps[ $post['userid'] ] = array(
'map_user_id' => $post['userid'],
$maps[ $map['userid'] ] = array(
'map_user_id' => $map['userid'],
'map_topic_id' => $pm['nodeid'],
'map_user_active' => 1,
'map_user_active' => !$map['deleted'],
'map_user_banned' => 0,
'map_has_unread' => 0,
'map_is_starter' => ( $post['userid'] == $pm['userid'] ) ? 1 : 0,
'map_has_unread' => !$map['msgread'],
'map_is_starter' => 0
);
}
@@ -1880,4 +1927,42 @@ class _Vbulletin5 extends \IPS\convert\Software
return NULL;
}
/**
* Process a login
*
* @param \IPS\Member $member The member
* @param string $password Password from form
* @return bool
*/
public static function login( $member, $password )
{
/* If no algorithm is defined, use the legacy handler */
if ( \strpos( $member->misc, 'blowfish' ) === FALSE and \strpos( $member->misc, 'legacy' ) === FALSE )
{
return \IPS\convert\Software\Core\Vbulletin::login( $member, $password );
}
/* Which do we need to use? */
$algo = explode( ':', $member->misc );
switch( $algo[ 0 ] )
{
case 'blowfish':
/* vBulletin uses PasswordHash, however they md5 once the password prior to checking */
$md5_once_password = md5( $password );
require_once \IPS\ROOT_PATH . "/applications/convert/sources/Login/PasswordHash.php";
$ph = new \PasswordHash( $algo[ 1 ], FALSE );
return $ph->CheckPassword( $md5_once_password, $member->conv_password );
break;
case 'legacy':
/* Legacy Passwords are stored in a format of HASH SALT so we need to explode on the space. */
$token = explode( ' ', $member->conv_password );
$member->conv_password = $token[0];
$member->conv_password_extra = $token[1];
return \IPS\convert\Software\Core\Vbulletin::login( $member, $password );
break;
}
}
}