' .
'' .
'',
esc_attr( $padding ),
esc_url( $embed_url ),
esc_attr( $title ),
esc_attr( $allow ),
(int) $width
);
}
/**
* Render player from a share/embed URL or bare share code.
*
* @param string $url Dadan URL.
* @param int $width Width.
* @param int $height Height (0 = 16:9 from width).
* @param string $title Optional title.
* @return string
*/
public static function render_from_url( $url, $width = 640, $height = 0, $title = '' ) {
$embed_url = Dadan_Url::to_embed_url( $url );
if ( ! $embed_url ) {
return '';
}
$width = Dadan_Url::sanitize_dimension( $width, 640 );
if ( $height <= 0 ) {
$height = (int) round( $width * 9 / 16 );
} else {
$height = Dadan_Url::sanitize_dimension( $height, (int) round( $width * 9 / 16 ) );
}
return self::build_player_html( $embed_url, $width, $height, $title );
}
/**
* KSES allowlist for build_player_html() output (PC-1).
*
* @return array>
*/
public static function kses_player() {
return array(
'div' => array(
'class' => true,
'style' => true,
),
'iframe' => array(
'src' => true,
'title' => true,
'style' => true,
'allow' => true,
'allowfullscreen' => true,
'loading' => true,
'referrerpolicy' => true,
),
);
}
/**
* Allow only https://…/video/embed.html?…&link={code} on Dadan hosts.
*
* @param string $url Candidate embed src.
* @return string|null Sanitized URL or null.
*/
public static function sanitize_embed_src( $url ) {
$url = trim( (string) $url );
if ( '' === $url ) {
return null;
}
$parts = wp_parse_url( $url );
if ( ! is_array( $parts ) || empty( $parts['scheme'] ) || empty( $parts['host'] ) || empty( $parts['path'] ) ) {
return null;
}
if ( 'https' !== strtolower( $parts['scheme'] ) ) {
return null;
}
$host = strtolower( $parts['host'] );
$allowed_hosts = array( 'app.dadan.io', 'dadan.io', 'www.dadan.io', 'app.dadan.video', 'dadan.video', 'www.dadan.video' );
if ( ! in_array( $host, $allowed_hosts, true ) ) {
return null;
}
$path = isset( $parts['path'] ) ? $parts['path'] : '';
// Production player.
if ( preg_match( '#^/video/embed\.html$#i', $path ) ) {
$query = array();
if ( ! empty( $parts['query'] ) ) {
parse_str( $parts['query'], $query );
}
// DADAN-06: reject non-string link (e.g. ?link[]=) — avoids PHP 8 TypeError.
$link = isset( $query['link'] ) && is_string( $query['link'] ) ? $query['link'] : '';
if ( '' === $link || ! preg_match( '/^[A-Za-z0-9_-]{1,64}$/', $link ) ) {
return null;
}
$params = Dadan_Url::EMBED_DEFAULT_PARAMS;
$params['link'] = $link;
return rtrim( DADAN_API_BASE, '/' ) . '/video/embed.html?' . http_build_query( $params, '', '&', PHP_QUERY_RFC3986 );
}
// Legacy /embed/{id} → rewrite to production embed.html.
if ( preg_match( '#^/embed/([A-Za-z0-9_-]+)/?$#', $path, $m ) ) {
$params = Dadan_Url::EMBED_DEFAULT_PARAMS;
$params['link'] = $m[1];
return rtrim( DADAN_API_BASE, '/' ) . '/video/embed.html?' . http_build_query( $params, '', '&', PHP_QUERY_RFC3986 );
}
return null;
}
}