diff options
Diffstat (limited to 'crates/shirabe/src/util')
| -rw-r--r-- | crates/shirabe/src/util/auth_helper.rs | 7 | ||||
| -rw-r--r-- | crates/shirabe/src/util/composer_mirror.rs | 13 | ||||
| -rw-r--r-- | crates/shirabe/src/util/config_validator.rs | 17 | ||||
| -rw-r--r-- | crates/shirabe/src/util/filesystem.rs | 40 | ||||
| -rw-r--r-- | crates/shirabe/src/util/forgejo_url.rs | 5 | ||||
| -rw-r--r-- | crates/shirabe/src/util/git.rs | 84 | ||||
| -rw-r--r-- | crates/shirabe/src/util/github.rs | 17 | ||||
| -rw-r--r-- | crates/shirabe/src/util/gitlab.rs | 5 | ||||
| -rw-r--r-- | crates/shirabe/src/util/hg.rs | 9 | ||||
| -rw-r--r-- | crates/shirabe/src/util/http/curl_downloader.rs | 15 | ||||
| -rw-r--r-- | crates/shirabe/src/util/http/response.rs | 7 | ||||
| -rw-r--r-- | crates/shirabe/src/util/http_downloader.rs | 16 | ||||
| -rw-r--r-- | crates/shirabe/src/util/perforce.rs | 7 | ||||
| -rw-r--r-- | crates/shirabe/src/util/platform.rs | 27 | ||||
| -rw-r--r-- | crates/shirabe/src/util/process_executor.rs | 48 | ||||
| -rw-r--r-- | crates/shirabe/src/util/remote_filesystem.rs | 25 | ||||
| -rw-r--r-- | crates/shirabe/src/util/svn.rs | 7 | ||||
| -rw-r--r-- | crates/shirabe/src/util/url.rs | 42 |
18 files changed, 222 insertions, 169 deletions
diff --git a/crates/shirabe/src/util/auth_helper.rs b/crates/shirabe/src/util/auth_helper.rs index 7d47f088..8d35d817 100644 --- a/crates/shirabe/src/util/auth_helper.rs +++ b/crates/shirabe/src/util/auth_helper.rs @@ -9,11 +9,10 @@ use crate::util::Bitbucket; use crate::util::GitHub; use crate::util::GitLab; use indexmap::IndexMap; -use shirabe_pcre::Preg; use shirabe_php_shim::{ PhpMixed, RuntimeException, base64_encode, explode, in_array_loose, in_array_strict, is_array, - is_string, json_decode_assoc, parse_url, php_regex, str_replace, strpos, strtolower, substr, - trim, + is_string, json_decode_assoc, parse_url, php_regex, preg_match2, str_replace, strpos, + strtolower, substr, trim, }; #[derive(Debug)] @@ -537,7 +536,7 @@ impl AuthHelper { } } else if origin == "github.com" && password == "x-oauth-basic" { // only add the access_token if it is actually a github API URL - if Preg::is_match(php_regex!(r"{^https?://api\.github\.com/}"), url) { + if preg_match2(php_regex!(r"{^https?://api\.github\.com/}"), url, 0).is_some() { headers.push(PhpMixed::String(format!( "Authorization: token {}", username, diff --git a/crates/shirabe/src/util/composer_mirror.rs b/crates/shirabe/src/util/composer_mirror.rs index f7bc179f..78f38782 100644 --- a/crates/shirabe/src/util/composer_mirror.rs +++ b/crates/shirabe/src/util/composer_mirror.rs @@ -1,7 +1,6 @@ //! ref: composer/src/Composer/Util/ComposerMirror.php -use shirabe_pcre::Preg; -use shirabe_php_shim::{hash, php_regex}; +use shirabe_php_shim::{hash, php_regex, preg_match2, preg_replace}; pub struct ComposerMirror; @@ -15,7 +14,7 @@ impl ComposerMirror { pretty_version: Option<&str>, ) -> String { let reference = reference.map(|r| { - if Preg::is_match(php_regex!(r"{^([a-f0-9]*|%reference%)$}"), r) { + if preg_match2(php_regex!(r"{^([a-f0-9]*|%reference%)$}"), r, 0).is_some() { r.to_string() } else { hash("md5", r) @@ -53,20 +52,22 @@ impl ComposerMirror { url: &str, r#type: Option<&str>, ) -> String { - let normalized_url = if let Some(gh_matches) = Preg::match3( + let normalized_url = if let Some(gh_matches) = preg_match2( php_regex!( r"#^(?:(?:https?|git)://github\.com/|git@github\.com:)([^/]+)/(.+?)(?:\.git)?$#" ), url, + 0, ) { format!( "gh-{}/{}", gh_matches.get(1).unwrap_or_default(), gh_matches.get(2).unwrap_or_default(), ) - } else if let Some(bb_matches) = Preg::match3( + } else if let Some(bb_matches) = preg_match2( php_regex!(r"#^https://bitbucket\.org/([^/]+)/(.+?)(?:\.git)?/?$#"), url, + 0, ) { format!( "bb-{}/{}", @@ -74,7 +75,7 @@ impl ComposerMirror { bb_matches.get(2).unwrap_or_default(), ) } else { - Preg::replace(php_regex!(r"{[^a-z0-9_.-]}i"), "-", url.trim_matches('/')) + preg_replace(php_regex!(r"{[^a-z0-9_.-]}i"), "-", url.trim_matches('/')) }; ["%package%", "%normalizedUrl%", "%type%"] diff --git a/crates/shirabe/src/util/config_validator.rs b/crates/shirabe/src/util/config_validator.rs index adf2aea2..52560caa 100644 --- a/crates/shirabe/src/util/config_validator.rs +++ b/crates/shirabe/src/util/config_validator.rs @@ -9,9 +9,8 @@ use crate::package::loader::LoaderInterface; use crate::package::loader::ValidatingArrayLoader; use indexmap::IndexMap; use serde::de::Error as _; -use shirabe_pcre::Preg; use shirabe_php_shim::Catch as _; -use shirabe_php_shim::{PhpMixed, php_regex}; +use shirabe_php_shim::{PhpMixed, php_regex, preg_match2, preg_replace}; use shirabe_spdx_licenses::SpdxLicenses; #[derive(Debug)] @@ -118,13 +117,17 @@ impl ConfigValidator { for license in &licenses { let spdx_license = license_validator.get_license_by_identifier(license); if spdx_license.is_some_and(|l| l.is_deprecated_license_id) { - if Preg::is_match(php_regex!(r"{^[AL]?GPL-[123](\.[01])?\+$}i"), license) { + if preg_match2(php_regex!(r"{^[AL]?GPL-[123](\.[01])?\+$}i"), license, 0) + .is_some() + { warnings.push(format!( "License \"{}\" is a deprecated SPDX license identifier, use \"{}-or-later\" instead", license, license.replace('+', "") )); - } else if Preg::is_match(php_regex!(r"{^[AL]?GPL-[123](\.[01])?$}i"), license) { + } else if preg_match2(php_regex!(r"{^[AL]?GPL-[123](\.[01])?$}i"), license, 0) + .is_some() + { warnings.push(format!( "License \"{}\" is a deprecated SPDX license identifier, use \"{}-only\" or \"{}-or-later\" instead", license, license, license @@ -145,9 +148,9 @@ impl ConfigValidator { if let Some(PhpMixed::String(name)) = manifest.get("name") && !name.is_empty() - && Preg::is_match(php_regex!(r"{[A-Z]}"), name) + && preg_match2(php_regex!(r"{[A-Z]}"), name, 0).is_some() { - let suggest_name = Preg::replace( + let suggest_name = preg_replace( php_regex!(r"{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}"), r"\1\3-\2\4", name, @@ -222,7 +225,7 @@ impl ConfigValidator { packages.extend(require_dev); for (package, version) in &packages { if let PhpMixed::String(version_str) = version - && Preg::is_match(php_regex!(r"{#}"), version_str) + && preg_match2(php_regex!(r"{#}"), version_str, 0).is_some() { warnings.push(format!( "The package \"{}\" is pointing to a commit-ref, this is bad practice and can cause unforeseen issues.", diff --git a/crates/shirabe/src/util/filesystem.rs b/crates/shirabe/src/util/filesystem.rs index 2ef51ba1..b79beeae 100644 --- a/crates/shirabe/src/util/filesystem.rs +++ b/crates/shirabe/src/util/filesystem.rs @@ -3,14 +3,14 @@ use crate::util::Platform; use crate::util::ProcessExecutor; use crate::util::Silencer; -use shirabe_pcre::Preg; use shirabe_php_shim::{ - ErrorException, LogicException, PhpMixed, RuntimeException, array_pop, basename, chdir, - clearstatcache, clearstatcache2, copy, dirname, explode, fclose, feof, file_exists, + ErrorException, LogicException, PhpMixed, PregMatches, RuntimeException, array_pop, basename, + chdir, clearstatcache, clearstatcache2, copy, dirname, explode, fclose, feof, file_exists, file_get_contents, file_put_contents, fileatime, filemtime, filesize, fopen, fread, function_exists, fwrite, implode, is_dir, is_file, is_link, is_readable, lstat, mkdir, - php_regex, rename, rmdir, rtrim, str_repeat, str_replace, strlen, strpos, strtoupper, strtr, - substr, substr_count, symlink, touch, unlink, usleep, var_export, + php_regex, preg_match2, preg_replace, preg_replace_callback, rename, rmdir, rtrim, str_repeat, + str_replace, strlen, strpos, strtoupper, strtr, substr, substr_count, symlink, touch, unlink, + usleep, var_export, }; use shirabe_symfony_filesystem::exception::IOException; use shirabe_symfony_finder::Finder; @@ -246,7 +246,7 @@ impl Filesystem { return Ok(Some(true)); } - if Preg::is_match3(php_regex!("{^(?:[a-z]:)?[/\\\\]+$}i"), directory).is_some() { + if preg_match2(php_regex!("{^(?:[a-z]:)?[/\\\\]+$}i"), directory, 0).is_some() { return Err(RuntimeException::new(format!("Aborting an attempted deletion of {}, this was probably not intended, if it is a real use case please report it.", directory)) .into()); } @@ -578,7 +578,7 @@ impl Filesystem { let mut common_path = to.clone(); while strpos(&format!("{}/", from), &format!("{}/", common_path)) != Some(0) && "/" != common_path - && Preg::is_match3(php_regex!("{^[A-Z]:/?$}i"), &common_path).is_none() + && preg_match2(php_regex!("{^[A-Z]:/?$}i"), &common_path, 0).is_none() { common_path = strtr(&dirname(&common_path), "\\", "/"); } @@ -635,7 +635,7 @@ impl Filesystem { let mut common_path = to.clone(); while strpos(&format!("{}/", from), &format!("{}/", common_path)) != Some(0) && "/" != common_path - && Preg::is_match3(php_regex!("{^[A-Z]:/?$}i"), &common_path).is_none() + && preg_match2(php_regex!("{^[A-Z]:/?$}i"), &common_path, 0).is_none() && "." != common_path { common_path = strtr(&dirname(&common_path), "\\", "/"); @@ -735,9 +735,10 @@ impl Filesystem { } // extract a prefix being a protocol://, protocol:, protocol://drive: or simply drive: - if let Some(prefix_match) = Preg::is_match3( + if let Some(prefix_match) = preg_match2( php_regex!("{^( [0-9a-z]{2,}+: (?: // (?: [a-z]: )? )? | [a-z]: )}ix"), &path, + 0, ) { prefix = prefix_match.get(1).unwrap_or_default().to_string(); path = substr(&path, strlen(&prefix), None); @@ -760,14 +761,15 @@ impl Filesystem { } // ensure c: is normalized to C: - prefix = Preg::replace_callback( + prefix = preg_replace_callback( php_regex!("{(^|://)[a-z]:$}i"), - |m: &shirabe_pcre::PregMatches| -> String { + |m: &PregMatches| -> anyhow::Result<String> { let s = m.get(0).unwrap_or_default().to_string(); - strtoupper(&s) + Ok(strtoupper(&s)) }, &prefix, - ); + ) + .expect("the replacement callback cannot fail"); format!("{}{}{}", prefix, absolute, implode("/", &parts)) } @@ -777,7 +779,7 @@ impl Filesystem { /// And other possible unforeseen disasters, see https://github.com/composer/composer/pull/9422 pub fn trim_trailing_slash(path: &str) -> String { let mut path = path.to_string(); - if Preg::is_match3(php_regex!("{^[/\\\\]+$}"), &path).is_none() { + if preg_match2(php_regex!("{^[/\\\\]+$}"), &path, 0).is_none() { path = rtrim(&path, Some("/\\")); } @@ -789,18 +791,20 @@ impl Filesystem { // on windows, \\foo indicates network paths so we exclude those from local paths, however it is unsafe // on linux as file:////foo (which would be a network path \\foo on windows) will resolve to /foo which could be a local path if Platform::is_windows() { - return Preg::is_match3( + return preg_match2( php_regex!( "{^(file://(?!//)|/(?!/)|/?[a-z]:[\\\\/]|\\.\\.[\\\\/]|[a-z0-9_.-]+[\\\\/])}i" ), path, + 0, ) .is_some(); } - Preg::is_match3( + preg_match2( php_regex!("{^(file://|/|/?[a-z]:[\\\\/]|\\.\\.[\\\\/]|[a-z0-9_.-]+[\\\\/])}i"), path, + 0, ) .is_some() } @@ -808,14 +812,14 @@ impl Filesystem { pub fn get_platform_path(path: &str) -> String { let mut path = path.to_string(); if Platform::is_windows() { - path = Preg::replace( + path = preg_replace( php_regex!("{^(?:file:///([a-z]):?/)}i"), "file://$1:/", &path, ); } - Preg::replace(php_regex!("{^file://}i"), "", &path) + preg_replace(php_regex!("{^file://}i"), "", &path) } /// Cross-platform safe version of is_readable() diff --git a/crates/shirabe/src/util/forgejo_url.rs b/crates/shirabe/src/util/forgejo_url.rs index 9ae1cbee..abb39d88 100644 --- a/crates/shirabe/src/util/forgejo_url.rs +++ b/crates/shirabe/src/util/forgejo_url.rs @@ -1,7 +1,6 @@ //! ref: composer/src/Composer/Util/ForgejoUrl.php -use shirabe_pcre::Preg; -use shirabe_php_shim::InvalidArgumentException; +use shirabe_php_shim::{InvalidArgumentException, preg_match2}; #[derive(Debug)] pub struct ForgejoUrl { @@ -37,7 +36,7 @@ impl ForgejoUrl { pub fn try_from(repo_url: Option<&str>) -> Option<Self> { let repo_url = repo_url?; - let matches = Preg::match3(Self::URL_REGEX, repo_url)?; + let matches = preg_match2(Self::URL_REGEX, repo_url, 0)?; let m: Vec<String> = (0..5) .map(|i| matches.get(i).unwrap_or_default().to_string()) diff --git a/crates/shirabe/src/util/git.rs b/crates/shirabe/src/util/git.rs index e14ff05f..31771e6c 100644 --- a/crates/shirabe/src/util/git.rs +++ b/crates/shirabe/src/util/git.rs @@ -14,12 +14,11 @@ use crate::util::ProcessExecutor; use crate::util::Url; use crate::util::{AuthHelper, StoreAuth}; use indexmap::IndexMap; -use shirabe_pcre::{Preg, PregMatches}; use shirabe_php_shim::{ - AnyThrowable, CmpOp, InvalidArgumentException, PHP_EOL, PhpMixed, RuntimeException, array_map, - clearstatcache, explode, implode, in_array_loose, in_array_strict, is_dir, php_regex, - preg_quote, rawurldecode, rawurlencode, str_replace_array, strlen, strpos, substr, trim, - version_compare, + AnyThrowable, CmpOp, InvalidArgumentException, PHP_EOL, PhpMixed, PregMatches, + RuntimeException, array_map, clearstatcache, explode, implode, in_array_loose, in_array_strict, + is_dir, php_regex, preg_match2, preg_quote, preg_replace, rawurldecode, rawurlencode, + str_replace_array, strlen, strpos, substr, trim, version_compare, }; use std::sync::Mutex; @@ -110,7 +109,7 @@ impl Git { map.insert("%url%".to_string(), url.to_string()); map.insert( "%sanitizedUrl%".to_string(), - Preg::replace(php_regex!(r"{://([^@]+?):(.+?)@}"), "://", url), + preg_replace(php_regex!(r"{://([^@]+?):(.+?)@}"), "://", url), ); array_map( @@ -210,7 +209,7 @@ impl Git { status }; - if Preg::is_match(php_regex!(r"{^ssh://[^@]+@[^:]+:[^0-9]+}"), url) { + if preg_match2(php_regex!(r"{^ssh://[^@]+@[^:]+:[^0-9]+}"), url, 0).is_some() { return Err(InvalidArgumentException::new(format!( "The source URL {} is invalid, ssh URLs should have a port number after \":\".\nUse ssh://git@example.com:22/path or just git@example.com:path if you do not want to provide a password or custom port.", url @@ -226,9 +225,10 @@ impl Git { &mut output, cwd, )?; - if let Some(m) = Preg::is_match3( + if let Some(m) = preg_match2( php_regex!(r"{^(?:composer|origin)\s+https?://(.+):(.+)@([^/]+)}im"), &output, + 0, ) { let m3 = m.get(3).unwrap_or_default().to_string(); if !self.io.has_authentication(&m3) { @@ -244,12 +244,13 @@ impl Git { let protocols = self.config.borrow_mut().get("github-protocols"); // public github, autoswitch protocols // @phpstan-ignore composerPcre.maybeUnsafeStrictGroups - if let Some(m) = Preg::is_match3( + if let Some(m) = preg_match2( format!( "{{^(?:https?|git)://{}/(.*)}}", Self::get_github_domains_regex(&self.config.borrow()) ), url, + 0, ) { let mut messages: Vec<String> = vec![]; let protocols_list: Vec<String> = match &protocols { @@ -280,7 +281,7 @@ impl Git { messages.push(format!( "- {}\n{}", proto_url, - Preg::replace(r"#^#m", " ", self.process.borrow().get_error_output()) + preg_replace(r"#^#m", " ", self.process.borrow().get_error_output()) )); if initial_clone && let Some(ref orig) = orig_cwd { @@ -311,19 +312,22 @@ impl Git { .collect(), _ => vec![], }; - let bypass_ssh_for_github = Preg::is_match( + let bypass_ssh_for_github = preg_match2( format!( "{{^git@{}:(.+?)\\.git$}}i", Self::get_github_domains_regex(&self.config.borrow()) ), url, - ) && !in_array_strict( - "ssh".to_string(), - &protocols_list - .iter() - .map(|s| PhpMixed::String(s.clone())) - .collect::<Vec<_>>(), - ); + 0, + ) + .is_some() + && !in_array_strict( + "ssh".to_string(), + &protocols_list + .iter() + .map(|s| PhpMixed::String(s.clone())) + .collect::<Vec<_>>(), + ); let mut auth: Option<IndexMap<String, Option<String>>> = None; let mut credentials: Vec<String> = vec![]; @@ -338,20 +342,22 @@ impl Git { let mut error_msg = self.process.borrow().get_error_output().to_string(); // private github repository without ssh key access, try https with auth // @phpstan-ignore composerPcre.maybeUnsafeStrictGroups - let github_matched = Preg::is_match3( + let github_matched = preg_match2( format!( "{{^git@{}:(.+?)\\.git$}}i", Self::get_github_domains_regex(&self.config.borrow()) ), url, + 0, ) .or_else(|| { - Preg::is_match3( + preg_match2( format!( "{{^https?://{}/(.*?)(?:\\.git)?$}}i", Self::get_github_domains_regex(&self.config.borrow()) ), url, + 0, ) }); if let Some(m) = github_matched { @@ -404,12 +410,18 @@ impl Git { credentials = vec![rawurlencode(&username), rawurlencode(&password)]; error_msg = self.process.borrow().get_error_output().to_string(); } - } else if let Some(m) = Preg::is_match3( + } else if let Some(m) = preg_match2( php_regex!(r"{^(https?)://(bitbucket\.org)/(.*?)(?:\.git)?$}i"), url, + 0, ) - .or_else(|| Preg::is_match3(php_regex!(r"{^(git)@(bitbucket\.org):(.+?\.git)$}i"), url)) - { + .or_else(|| { + preg_match2( + php_regex!(r"{^(git)@(bitbucket\.org):(.+?\.git)$}i"), + url, + 0, + ) + }) { // bitbucket either through oauth or app password, with fallback to ssh. let mut bitbucket_util = Bitbucket::new( self.io.clone(), @@ -546,20 +558,22 @@ impl Git { } error_msg = self.process.borrow().get_error_output().to_string(); - } else if let Some(m) = Preg::is_match3( + } else if let Some(m) = preg_match2( format!( "{{^(git)@{}:(.+?\\.git)$}}i", Self::get_gitlab_domains_regex(&self.config.borrow()) ), url, + 0, ) .or_else(|| { - Preg::is_match3( + preg_match2( format!( "{{^(https?)://{}/(.*)}}i", Self::get_gitlab_domains_regex(&self.config.borrow()) ), url, + 0, ) }) { let mut m1 = m.get(1).unwrap_or_default().to_string(); @@ -914,10 +928,10 @@ impl Git { pretty_version: Option<&str>, ) -> anyhow::Result<bool> { if self.check_ref_is_in_mirror(dir, r#ref)? { - if Preg::is_match(php_regex!(r"{^[a-f0-9]{40}$}"), r#ref) + if preg_match2(php_regex!(r"{^[a-f0-9]{40}$}"), r#ref, 0).is_some() && let Some(pretty_version) = pretty_version { - let branch = Preg::replace( + let branch = preg_replace( php_regex!(r"{(?:^dev-|(?:\.x)?-dev$)}i"), "", pretty_version, @@ -948,15 +962,19 @@ impl Git { // this can occur if a git tag gets created *after* the reference is already put into the cache, as the ref check above will then not sync the new tags // see https://github.com/composer/composer/discussions/11002 if branches.is_some() - && !Preg::is_match( + && preg_match2( format!(r"{{^[\s*]*v?{}$}}m", preg_quote(&branch, None)), branches.as_deref().unwrap_or(""), + 0, ) + .is_none() && tags.is_some() - && !Preg::is_match( + && preg_match2( format!(r"{{^[\s*]*{}$}}m", preg_quote(&branch, None)), tags.as_deref().unwrap_or(""), + 0, ) + .is_none() { self.sync_mirror(url, dir)?; } @@ -1042,7 +1060,7 @@ impl Git { } // Filter out "commit <hash>" lines for older git versions - Preg::replace(php_regex!(r"{^commit [a-f0-9]{40}\n?}m"), "", output) + preg_replace(php_regex!(r"{^commit [a-f0-9]{40}\n?}m"), "", output) } fn check_ref_is_in_mirror(&mut self, dir: &str, r#ref: &str) -> anyhow::Result<bool> { @@ -1081,7 +1099,7 @@ impl Git { } fn get_authentication_failure<'u>(&self, url: &'u str) -> Option<PregMatches<'u>> { - let m = Preg::is_match3(php_regex!(r"{^(https?://)([^/]+)(.*)$}i"), url)?; + let m = preg_match2(php_regex!(r"{^(https?://)([^/]+)(.*)$}i"), url, 0)?; let auth_failures = [ "fatal: Authentication failed", @@ -1164,7 +1182,7 @@ impl Git { .split_lines(output_mixed.as_string().unwrap_or("")); for line in lines { if let Some(matches) = - Preg::is_match3(php_regex!(r"{^\s*HEAD branch:\s(.+)\s*$}m"), &line) + preg_match2(php_regex!(r"{^\s*HEAD branch:\s(.+)\s*$}m"), &line, 0) { return Ok(Some(matches.get(1).unwrap_or_default().to_string())); } @@ -1285,7 +1303,7 @@ impl Git { ); if exit_code == 0 && let Some(matches) = - Preg::is_match3(php_regex!(r"/^git version (\d+(?:\.\d+)+)/m"), &output) + preg_match2(php_regex!(r"/^git version (\d+(?:\.\d+)+)/m"), &output, 0) { *version = Some(matches.get(1).map(str::to_string)); } diff --git a/crates/shirabe/src/util/github.rs b/crates/shirabe/src/util/github.rs index 570a33bb..9d73ae84 100644 --- a/crates/shirabe/src/util/github.rs +++ b/crates/shirabe/src/util/github.rs @@ -8,9 +8,10 @@ use crate::io::io_interface; use crate::util::HttpDownloader; use crate::util::ProcessExecutor; use indexmap::IndexMap; -use shirabe_pcre::Preg; use shirabe_php_shim::Catch as _; -use shirabe_php_shim::{PhpMixed, date_local, in_array_loose, php_regex, stripos, strtolower}; +use shirabe_php_shim::{ + PhpMixed, date_local, in_array_loose, php_regex, preg_match2, stripos, strtolower, +}; #[derive(Debug)] pub struct GitHub { @@ -325,7 +326,7 @@ impl GitHub { if stripos(header, "x-github-sso: required").is_none() { continue; } - if let Some(caps) = Preg::match3(php_regex!(r"{\burl=(?P<url>[^\s;]+)}"), header) { + if let Some(caps) = preg_match2(php_regex!(r"{\burl=(?P<url>[^\s;]+)}"), header, 0) { return caps.name("url").map(str::to_string); } } @@ -335,7 +336,13 @@ impl GitHub { pub fn is_rate_limited(&self, headers: &[String]) -> bool { for header in headers { - if Preg::is_match(php_regex!(r"{^x-ratelimit-remaining: *0$}i"), header.trim()) { + if preg_match2( + php_regex!(r"{^x-ratelimit-remaining: *0$}i"), + header.trim(), + 0, + ) + .is_some() + { return true; } } @@ -345,7 +352,7 @@ impl GitHub { pub fn requires_sso(&self, headers: &[String]) -> bool { for header in headers { - if Preg::is_match(php_regex!(r"{^x-github-sso: required}i"), header.trim()) { + if preg_match2(php_regex!(r"{^x-github-sso: required}i"), header.trim(), 0).is_some() { return true; } } diff --git a/crates/shirabe/src/util/gitlab.rs b/crates/shirabe/src/util/gitlab.rs index 52707b5b..c101b1f9 100644 --- a/crates/shirabe/src/util/gitlab.rs +++ b/crates/shirabe/src/util/gitlab.rs @@ -9,11 +9,10 @@ use crate::io::io_interface; use crate::util::HttpDownloader; use crate::util::ProcessExecutor; use indexmap::IndexMap; -use shirabe_pcre::Preg; use shirabe_php_shim::Catch as _; use shirabe_php_shim::{ PhpMixed, RuntimeException, http_build_query, in_array_strict, json_decode_assoc, php_regex, - time, + preg_replace, time, }; #[derive(Debug)] @@ -54,7 +53,7 @@ impl GitLab { pub fn authorize_oauth(&mut self, origin_url: &str) -> bool { // before composer 1.9, origin URLs had no port number in them - let bc_origin_url = Preg::replace(php_regex!("{:\\d+}"), "", origin_url); + let bc_origin_url = preg_replace(php_regex!("{:\\d+}"), "", origin_url); let gitlab_domains = self.config.borrow_mut().get("gitlab-domains"); if !in_array_strict(origin_url.to_string(), gitlab_domains.values()) diff --git a/crates/shirabe/src/util/hg.rs b/crates/shirabe/src/util/hg.rs index f95f15d5..00fee240 100644 --- a/crates/shirabe/src/util/hg.rs +++ b/crates/shirabe/src/util/hg.rs @@ -5,8 +5,7 @@ use crate::io::IOInterface; use crate::io::IOInterfaceImmutable; use crate::util::ProcessExecutor; use crate::util::Url; -use shirabe_pcre::Preg; -use shirabe_php_shim::{php_regex, rawurlencode}; +use shirabe_php_shim::{php_regex, preg_match2, rawurlencode}; use std::sync::OnceLock; static VERSION: OnceLock<Option<String>> = OnceLock::new(); @@ -56,11 +55,12 @@ impl Hg { } // Try with the authentication information available - let matched = Preg::is_match3( + let matched = preg_match2( php_regex!( r"{^(?P<proto>ssh|https?)://(?:(?P<user>[^:@]+)(?::(?P<pass>[^:@]+))?@)?(?P<host>[^/]+)(?P<path>/.*)?}mi" ), &url, + 0, ); if let Some(matches) = matched @@ -151,9 +151,10 @@ impl Hg { &mut output, None, ) == 0 - && let Some(matches) = Preg::is_match3( + && let Some(matches) = preg_match2( php_regex!(r"/^.+? (\d+(?:\.\d+)+)(?:\+.*?)?\)?\r?\n/"), &output, + 0, ) { return matches.get(1).map(str::to_string); diff --git a/crates/shirabe/src/util/http/curl_downloader.rs b/crates/shirabe/src/util/http/curl_downloader.rs index 6140bb08..91165015 100644 --- a/crates/shirabe/src/util/http/curl_downloader.rs +++ b/crates/shirabe/src/util/http/curl_downloader.rs @@ -31,10 +31,9 @@ use crate::util::http::ProxyManager; use crate::util::http::Response; use crate::util::{AuthHelper, PromptAuthResult, StoreAuth}; use indexmap::IndexMap; -use shirabe_pcre::Preg; use shirabe_php_shim::{ - PhpMixed, in_array_loose, in_array_strict, parse_url, php_regex, preg_quote, rename, strpos, - substr, unlink_silent, + PhpMixed, in_array_loose, in_array_strict, parse_url, php_regex, preg_match2, preg_quote, + preg_replace, rename, strpos, substr, unlink_silent, }; use std::sync::atomic::{AtomicBool, Ordering}; @@ -147,7 +146,7 @@ impl CurlDownloader { // check URL can be accessed (i.e. is not insecure), but allow insecure Packagist calls to // $hashed providers as file integrity is verified with sha256 - if !Preg::is_match(php_regex!(r"{^http://(repo\.)?packagist\.org/p/}"), url) + if preg_match2(php_regex!(r"{^http://(repo\.)?packagist\.org/p/}"), url, 0).is_none() || (strpos(url, "$").is_none() && strpos(url, "%24").is_none()) { self.config.borrow_mut().prohibit_url_by_config( @@ -653,7 +652,7 @@ impl CurlDownloader { // Absolute path; e.g. /foo let url_host = parse_url(url).and_then(|parsed| parsed.host); let url_host_str = url_host.as_deref().unwrap_or(""); - target_url = Preg::replace( + target_url = preg_replace( format!( r"{{^(.+(?://|@){}(?::\d+)?)(?:[/\?].*)?$}}", preg_quote(url_host_str, None) @@ -663,7 +662,7 @@ impl CurlDownloader { ); } else { // Relative path; e.g. foo - target_url = Preg::replace( + target_url = preg_replace( php_regex!(r"{^(.+/)[^/?]*(?:\?.*)?$}"), &format!("\\1{}", location_header), url, @@ -747,13 +746,15 @@ impl CurlDownloader { && substr(url, -4, None) == ".zip" && (location_header.is_none() || substr(location_header.as_deref().unwrap_or(""), -4, None) != ".zip") - && Preg::is_match( + && preg_match2( php_regex!(r"{^text/html\b}i"), &response .inner .get_header("content-type") .unwrap_or_default(), + 0, ) + .is_some() { needs_auth_retry = Some("Bitbucket requires authentication and it was not provided"); } diff --git a/crates/shirabe/src/util/http/response.rs b/crates/shirabe/src/util/http/response.rs index bd117a24..ed5c5214 100644 --- a/crates/shirabe/src/util/http/response.rs +++ b/crates/shirabe/src/util/http/response.rs @@ -1,8 +1,7 @@ //! ref: composer/src/Composer/Util/Http/Response.php use crate::json::JsonFile; -use shirabe_pcre::Preg; -use shirabe_php_shim::{PhpMixed, php_regex, preg_quote}; +use shirabe_php_shim::{PhpMixed, php_regex, preg_match2, preg_quote}; #[derive(Debug)] pub struct Response { @@ -29,7 +28,7 @@ impl Response { pub fn get_status_message(&self) -> Option<String> { let mut value = None; for header in &self.headers { - if Preg::is_match(php_regex!(r"{^HTTP/\S+ \d+}i"), header) { + if preg_match2(php_regex!(r"{^HTTP/\S+ \d+}i"), header, 0).is_some() { // In case of redirects, headers contain the headers of all responses // so we can not return directly and need to keep iterating value = Some(header.clone()); @@ -65,7 +64,7 @@ impl Response { let mut value = None; let pattern = format!("{{^{}:\\s*(.+?)\\s*$}}i", preg_quote(name, None)); for header in headers { - if let Some(matches) = Preg::match3(&pattern, header) + if let Some(matches) = preg_match2(&pattern, header, 0) && let Some(s) = matches.get(1) { value = Some(s.to_string()); diff --git a/crates/shirabe/src/util/http_downloader.rs b/crates/shirabe/src/util/http_downloader.rs index 151b2646..8210a5c4 100644 --- a/crates/shirabe/src/util/http_downloader.rs +++ b/crates/shirabe/src/util/http_downloader.rs @@ -16,12 +16,11 @@ use crate::util::http::CurlDownloader; use crate::util::http::Response; use crate::util::sync_executor; use indexmap::IndexMap; -use shirabe_pcre::Preg; use shirabe_php_shim::Catch as _; use shirabe_php_shim::{ InvalidArgumentException, LogicException, PhpMixed, array_replace_recursive, extension_loaded, - file_get_contents, function_exists, implode, is_numeric, php_regex, rawurldecode, - stream_context_create, stripos, strpos, substr, ucfirst, + file_get_contents, function_exists, implode, is_numeric, php_regex, preg_match2, preg_replace, + rawurldecode, stream_context_create, stripos, strpos, substr, ucfirst, }; use shirabe_semver::constraint::SimpleConstraint; @@ -240,8 +239,11 @@ impl HttpDownloader { let origin = Url::get_origin(&self.config.borrow(), url); // capture username/password from URL if there is one - if let Some(m) = Preg::is_match3(php_regex!(r"{^https?://([^:/]+):([^@/]+)@([^/]+)}i"), url) - { + if let Some(m) = preg_match2( + php_regex!(r"{^https?://([^:/]+):([^@/]+)@([^/]+)}i"), + url, + 0, + ) { self.io.borrow_mut().set_authentication( origin.clone(), rawurldecode(m.get(1).unwrap_or_default().to_string().as_str()), @@ -355,7 +357,7 @@ impl HttpDownloader { ) -> anyhow::Result<()> { let clean_message = |msg: &str| -> anyhow::Result<String> { if !io.is_decorated() { - return Ok(Preg::replace("{\x1b\\[[;\\d]*m}u", "", msg)); + return Ok(preg_replace("{\x1b\\[[;\\d]*m}u", "", msg)); } Ok(msg.to_string()) @@ -487,7 +489,7 @@ impl HttpDownloader { return false; } - if !Preg::is_match(php_regex!(r"{^https?://}i"), url) { + if preg_match2(php_regex!(r"{^https?://}i"), url, 0).is_none() { return false; } diff --git a/crates/shirabe/src/util/perforce.rs b/crates/shirabe/src/util/perforce.rs index c0cd5a08..32e3e9cd 100644 --- a/crates/shirabe/src/util/perforce.rs +++ b/crates/shirabe/src/util/perforce.rs @@ -6,11 +6,10 @@ use crate::util::Filesystem; use crate::util::Platform; use crate::util::ProcessExecutor; use indexmap::IndexMap; -use shirabe_pcre::Preg; use shirabe_php_shim::{ Exception, PHP_EOL, PhpMixed, PhpResource, chdir, date_local, explode, fclose, feof, fgets, - file_get_contents, fopen, fwrite, gethostname, json_decode_assoc, php_regex, str_replace_array, - strcmp, strlen, strpos, strrpos, substr, time, trim, + file_get_contents, fopen, fwrite, gethostname, json_decode_assoc, php_regex, preg_replace, + str_replace_array, strcmp, strlen, strpos, strrpos, substr, time, trim, }; use shirabe_symfony_process::ExecutableFinder; use shirabe_symfony_process::Process; @@ -660,7 +659,7 @@ impl Perforce { for line in &res_array { let res_bits = explode(" ", line); if res_bits.len() > 4 { - let branch = Preg::replace( + let branch = preg_replace( php_regex!(r"/[^A-Za-z0-9 ]/"), "", &res_bits.get(4).cloned().unwrap_or_default(), diff --git a/crates/shirabe/src/util/platform.rs b/crates/shirabe/src/util/platform.rs index 606ff43d..91039c17 100644 --- a/crates/shirabe/src/util/platform.rs +++ b/crates/shirabe/src/util/platform.rs @@ -2,12 +2,12 @@ use crate::util::ProcessExecutor; use crate::util::Silencer; -use shirabe_pcre::{Preg, PregMatches}; use shirabe_php_shim::{ - PHP_ENV, PHP_SERVER, PhpMixed, PhpResource, RuntimeException, defined, file_exists, - file_get_contents, fstat, function_exists, getcwd, getenv, ini_get, is_readable, mb_strlen, - php_os_family, php_regex, posix_geteuid, posix_getpwuid, posix_getuid, posix_isatty, putenv, - putenv_clear, realpath, stream_isatty, stripos, strlen, strtoupper, substr, usleep, + PHP_ENV, PHP_SERVER, PhpMixed, PhpResource, PregMatches, RuntimeException, defined, + file_exists, file_get_contents, fstat, function_exists, getcwd, getenv, ini_get, is_readable, + mb_strlen, php_os_family, php_regex, posix_geteuid, posix_getpwuid, posix_getuid, posix_isatty, + preg_match2, preg_replace_callback, putenv, putenv_clear, realpath, stream_isatty, stripos, + strlen, strtoupper, substr, usleep, }; use std::sync::Mutex; @@ -83,7 +83,7 @@ impl Platform { /// Parses tildes and environment variables in paths. pub fn expand_path(path: &str) -> String { - if Preg::is_match(php_regex!(r"#^~[\\/]#"), path) { + if preg_match2(php_regex!(r"#^~[\\/]#"), path, 0).is_some() { return format!( "{}{}", Self::get_user_directory().unwrap(), @@ -95,9 +95,9 @@ impl Platform { // The original pattern uses a conditional subpattern to make the trailing `%` required // only for the `%VAR%` form. The Rust regex crate does not support conditionals, so the // two forms are written as an explicit alternation: `$VAR` or `%VAR%`. - Preg::replace_callback( + preg_replace_callback( php_regex!(r"#^(?:\$(?P<dvar>\w+)|%(?P<pvar>\w+)%)(?P<path>.*)#"), - |matches: &PregMatches| -> String { + |matches: &PregMatches| -> anyhow::Result<String> { let var = matches .name("dvar") .or_else(|| matches.name("pvar")) @@ -108,24 +108,25 @@ impl Platform { let home = Platform::get_env("HOME").filter(|v| PhpMixed::String(v.clone()).to_bool()); if let Some(home) = home { - return format!("{}{}", home, path_part); + return Ok(format!("{}{}", home, path_part)); } - return format!( + return Ok(format!( "{}{}", Platform::get_env("USERPROFILE").unwrap_or_default(), path_part, - ); + )); } - format!( + Ok(format!( "{}{}", Platform::get_env(var).unwrap_or_default(), path_part, - ) + )) }, path, ) + .expect("the replacement callback cannot fail") } /// @throws \RuntimeException If the user home could not reliably be determined diff --git a/crates/shirabe/src/util/process_executor.rs b/crates/shirabe/src/util/process_executor.rs index 2bfaeb94..158729b4 100644 --- a/crates/shirabe/src/util/process_executor.rs +++ b/crates/shirabe/src/util/process_executor.rs @@ -7,13 +7,12 @@ use crate::signal::SignalSubscription; use crate::util::GitHub; use crate::util::Platform; use indexmap::IndexMap; -use shirabe_pcre::{Preg, PregMatches}; use shirabe_php_shim::Catch as _; use shirabe_php_shim::{ - LogicException, PHP_EOL, PhpMixed, RuntimeException, array_intersect, array_map, + LogicException, PHP_EOL, PhpMixed, PregMatches, RuntimeException, array_intersect, array_map, escapeshellarg, explode, implode, in_array_strict, is_array, is_dir, is_numeric, is_string, - php_regex, preg_split, rtrim, str_replace, strcspn, strlen, strpbrk, strtolower, strtr_array, - substr_replace, trim, + php_regex, preg_match2, preg_replace, preg_replace_callback, preg_replace2, preg_split, rtrim, + str_replace, strcspn, strlen, strpbrk, strtolower, strtr_array, substr_replace, trim, }; use shirabe_symfony_process::ExecutableFinder; use shirabe_symfony_process::Process; @@ -217,7 +216,7 @@ impl ProcessExecutor { if is_string(&command) { let mut command_str = command.as_string().unwrap_or("").to_string(); if Platform::is_windows() - && let Some(m) = Preg::is_match3(php_regex!(r"{^([^:/\\]++) }"), &command_str) + && let Some(m) = preg_match2(php_regex!(r"{^([^:/\\]++) }"), &command_str, 0) { let m1 = m.get(1).unwrap_or_default().to_string(); command_str = substr_replace( @@ -829,25 +828,31 @@ impl ProcessExecutor { } else { String::new() }; - let safe_command = Preg::replace_callback( + let safe_command = preg_replace_callback( php_regex!(r"{://(?P<user>[^:/\s]+):(?P<password>[^@\s/]+)@}i"), - |m: &PregMatches| -> String { + |m: &PregMatches| -> anyhow::Result<String> { // if the username looks like a long (12char+) hex string, or a modern github token (e.g. ghp_xxx, github_pat_xxx) we obfuscate that - if Preg::is_match( + if preg_match2( GitHub::GITHUB_TOKEN_REGEX, m.name("user").unwrap_or_default(), - ) { - return "://***:***@".to_string(); + 0, + ) + .is_some() + { + return Ok("://***:***@".to_string()); } - if Preg::is_match(r"{^[a-f0-9]{12,}$}", m.name("user").unwrap_or_default()) { - return "://***:***@".to_string(); + if preg_match2(r"{^[a-f0-9]{12,}$}", m.name("user").unwrap_or_default(), 0) + .is_some() + { + return Ok("://***:***@".to_string()); } - format!("://{}:***@", m.name("user").unwrap_or_default()) + Ok(format!("://{}:***@", m.name("user").unwrap_or_default())) }, &command_string, - ); - let safe_command = Preg::replace( + ) + .expect("the replacement callback cannot fail"); + let safe_command = preg_replace( php_regex!(r"{--password (.*[^\\]') }"), "--password '***' ", &safe_command, @@ -894,26 +899,27 @@ impl ProcessExecutor { let mut quote = strpbrk(&argument, " \t,").is_some(); let mut dquotes: usize = 0; // PHP: Preg::replace('/(\\\\*)"/', '$1$1\\"', $argument, -1, $dquotes) - argument = Preg::replace5( + argument = preg_replace2( php_regex!(r#"/(\\*)"/"#), r#"$1$1\""#, &argument, -1, - &mut dquotes, + Some(&mut dquotes), ); - let meta = dquotes > 0 || Preg::is_match(php_regex!(r"/%[^%]+%|![^!]+!/"), &argument); + let meta = + dquotes > 0 || preg_match2(php_regex!(r"/%[^%]+%|![^!]+!/"), &argument, 0).is_some(); if !meta && !quote { quote = strpbrk(&argument, "^&|<>()").is_some(); } if quote { - argument = format!("\"{}\"", Preg::replace(r"/(\\*)$/", "$1$1", &argument)); + argument = format!("\"{}\"", preg_replace(r"/(\\*)$/", "$1$1", &argument)); } if meta { - argument = Preg::replace(php_regex!(r#"/(["^&|<>()%])/"#), "^$1", &argument); - argument = Preg::replace(php_regex!(r"/(!)/"), "^^$1", &argument); + argument = preg_replace(php_regex!(r#"/(["^&|<>()%])/"#), "^$1", &argument); + argument = preg_replace(php_regex!(r"/(!)/"), "^^$1", &argument); } argument diff --git a/crates/shirabe/src/util/remote_filesystem.rs b/crates/shirabe/src/util/remote_filesystem.rs index e55e5200..7af5473a 100644 --- a/crates/shirabe/src/util/remote_filesystem.rs +++ b/crates/shirabe/src/util/remote_filesystem.rs @@ -13,14 +13,14 @@ use crate::util::Url; use crate::util::http::ProxyManager; use crate::util::http::Response; use indexmap::IndexMap; -use shirabe_pcre::Preg; use shirabe_php_shim::Catch as _; use shirabe_php_shim::{ PhpMixed, RuntimeException, STREAM_NOTIFY_FAILURE, STREAM_NOTIFY_FILE_SIZE_IS, STREAM_NOTIFY_PROGRESS, array_replace_recursive, base64_encode, explode, extension_loaded, file_get_contents, file_get_contents5, file_put_contents, filter_var_boolean, gethostbyname, http_clear_last_response_headers, http_get_last_response_headers, ini_get, json_decode_assoc, - parse_url, php_regex, preg_quote, strpos, strtolower, strtr, substr, trim, zlib_decode, + parse_url, php_regex, preg_match2, preg_quote, preg_replace, strpos, strtolower, strtr, substr, + trim, zlib_decode, }; /// Result of `RemoteFilesystem::get` — string content, `true` (for copy), or `false`. @@ -148,7 +148,7 @@ impl RemoteFilesystem { pub fn find_status_code(headers: &[String]) -> Option<i64> { let mut value: Option<i64> = None; for header in headers { - if let Some(m) = Preg::is_match3(php_regex!("{^HTTP/\\S+ (\\d+)}i"), header) { + if let Some(m) = preg_match2(php_regex!("{^HTTP/\\S+ (\\d+)}i"), header, 0) { value = m.get(1).and_then(|s| s.parse().ok()).or(Some(0)); } } @@ -159,7 +159,7 @@ impl RemoteFilesystem { pub fn find_status_message(&self, headers: &[String]) -> Option<String> { let mut value: Option<String> = None; for header in headers { - if Preg::is_match(php_regex!("{^HTTP/\\S+ \\d+}i"), header) { + if preg_match2(php_regex!("{^HTTP/\\S+ \\d+}i"), header, 0).is_some() { value = Some(header.clone()); } } @@ -285,10 +285,13 @@ impl RemoteFilesystem { crate::io::DEBUG, ); - if (!Preg::is_match( + if (preg_match2( php_regex!("{^http://(repo\\.)?packagist\\.org/p/}"), &file_url, - ) || (strpos(&file_url, "$").is_none() && strpos(&file_url, "%24").is_none())) + 0, + ) + .is_none() + || (strpos(&file_url, "$").is_none() && strpos(&file_url, "%24").is_none())) && !degraded_packagist { let _ = self.config.borrow_mut().prohibit_url_by_config( @@ -472,10 +475,12 @@ impl RemoteFilesystem { None, ) != ".zip") && content_type.is_some() - && Preg::is_match( + && preg_match2( php_regex!("{^text/html\\b}i"), content_type.as_deref().unwrap_or(""), - ); + 0, + ) + .is_some(); if bitbucket_login_match { result = None; if retry_auth_failure { @@ -941,7 +946,7 @@ impl RemoteFilesystem { .and_then(|parsed| parsed.host) .unwrap_or_default(); - target_url = Some(Preg::replace( + target_url = Some(preg_replace( format!( "{{^(.+(?://|@){}(?::\\d+)?)(?:[/\\?].*)?$}}", preg_quote(&url_host, None) @@ -950,7 +955,7 @@ impl RemoteFilesystem { &self.file_url, )); } else { - target_url = Some(Preg::replace( + target_url = Some(preg_replace( php_regex!("{^(.+/)[^/?]*(?:\\?.*)?$}"), &format!("\\1{}", location_header), &self.file_url, diff --git a/crates/shirabe/src/util/svn.rs b/crates/shirabe/src/util/svn.rs index 5ff6a025..38189d31 100644 --- a/crates/shirabe/src/util/svn.rs +++ b/crates/shirabe/src/util/svn.rs @@ -6,10 +6,9 @@ use crate::io::IOInterfaceImmutable; use crate::io::io_interface; use crate::util::Platform; use crate::util::ProcessExecutor; -use shirabe_pcre::Preg; use shirabe_php_shim::{ - LogicException, PhpMixed, RuntimeException, implode, parse_url, php_regex, stripos, strpos, - trim, + LogicException, PhpMixed, RuntimeException, implode, parse_url, php_regex, preg_match2, + stripos, strpos, trim, }; use std::sync::Mutex; @@ -405,7 +404,7 @@ impl Svn { &["svn".to_string(), "--version".to_string()], &mut output, None, - ) && let Some(matches) = Preg::is_match3(php_regex!(r"{(\d+(?:\.\d+)+)}"), &output) + ) && let Some(matches) = preg_match2(php_regex!(r"{(\d+(?:\.\d+)+)}"), &output, 0) { *cached = Some(matches.get(1).unwrap_or_default().to_string()); } diff --git a/crates/shirabe/src/util/url.rs b/crates/shirabe/src/util/url.rs index eb533a06..2754ef09 100644 --- a/crates/shirabe/src/util/url.rs +++ b/crates/shirabe/src/util/url.rs @@ -2,8 +2,10 @@ use crate::config::Config; use crate::util::GitHub; -use shirabe_pcre::Preg; -use shirabe_php_shim::{PhpMixed, in_array_strict, parse_url, php_regex}; +use shirabe_php_shim::{ + PhpMixed, in_array_strict, parse_url, php_regex, preg_match2, preg_replace, + preg_replace_callback, +}; pub struct Url; @@ -14,11 +16,12 @@ impl Url { .unwrap_or_default(); if host == "api.github.com" || host == "github.com" || host == "www.github.com" { - if let Some(m) = Preg::match3( + if let Some(m) = preg_match2( php_regex!( r"{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/(zip|tar)ball/(.+)$}i" ), &url, + 0, ) { url = format!( "https://api.github.com/repos/{}/{}/{}ball/{}", @@ -27,11 +30,12 @@ impl Url { m.get(3).unwrap_or_default(), r#ref ); - } else if let Some(m) = Preg::match3( + } else if let Some(m) = preg_match2( php_regex!( r"{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/archive/.+\.(zip|tar)(?:\.gz)?$}i" ), &url, + 0, ) { url = format!( "https://api.github.com/repos/{}/{}/{}ball/{}", @@ -40,11 +44,12 @@ impl Url { m.get(3).unwrap_or_default(), r#ref ); - } else if let Some(m) = Preg::match3( + } else if let Some(m) = preg_match2( php_regex!( r"{^https?://api\.github\.com/repos/([^/]+)/([^/]+)/(zip|tar)ball(?:/.+)?$}i" ), &url, + 0, ) { url = format!( "https://api.github.com/repos/{}/{}/{}ball/{}", @@ -55,11 +60,12 @@ impl Url { ); } } else if host == "bitbucket.org" || host == "www.bitbucket.org" { - if let Some(m) = Preg::match3( + if let Some(m) = preg_match2( php_regex!( r"{^https?://(?:www\.)?bitbucket\.org/([^/]+)/([^/]+)/get/(.+)\.(zip|tar\.gz|tar\.bz2)$}i" ), &url, + 0, ) { url = format!( "https://bitbucket.org/{}/{}/get/{}.{}", @@ -70,11 +76,12 @@ impl Url { ); } } else if host == "gitlab.com" || host == "www.gitlab.com" { - if let Some(m) = Preg::match3( + if let Some(m) = preg_match2( php_regex!( r"{^https?://(?:www\.)?gitlab\.com/api/v[34]/projects/([^/]+)/repository/archive\.(zip|tar\.gz|tar\.bz2|tar)\?sha=.+$}i" ), &url, + 0, ) { url = format!( "https://gitlab.com/api/v4/projects/{}/repository/archive.{}?sha={}", @@ -84,13 +91,13 @@ impl Url { ); } } else if in_array_strict(host.clone(), config.get("github-domains").values()) { - url = Preg::replace( + url = preg_replace( php_regex!(r"{(/repos/[^/]+/[^/]+/(zip|tar)ball)(?:/.+)?$}i"), &format!("$1/{}", r#ref), &url, ); } else if in_array_strict(host, config.get("gitlab-domains").values()) { - url = Preg::replace( + url = preg_replace( php_regex!( r"{(/api/v[34]/projects/[^/]+/repository/archive\.(?:zip|tar\.gz|tar\.bz2|tar)\?sha=).+$}i" ), @@ -158,21 +165,24 @@ impl Url { pub fn sanitize(url: String) -> String { // GitHub repository rename result in redirect locations containing the access_token as GET parameter // e.g. https://api.github.com/repositories/9999999999?access_token=github_token - let url = Preg::replace(php_regex!(r"{([&?]access_token=)[^&]+}"), "$1***", &url); + let url = preg_replace(php_regex!(r"{([&?]access_token=)[^&]+}"), "$1***", &url); - Preg::replace_callback( + preg_replace_callback( php_regex!(r"{^(?P<prefix>[a-z0-9]+://)?(?P<user>[^:/\s@]+):(?P<password>[^@\s/]+)@}i"), |m| { let user = m.name("user").unwrap_or_default().to_string(); let prefix = m.name("prefix").unwrap_or_default().to_string(); // if the username looks like a long (12char+) hex string, or a modern github token (e.g. ghp_xxx, github_pat_xxx) we obfuscate that - if Preg::is_match(GitHub::GITHUB_TOKEN_REGEX, &user) { - format!("{}***:***@", prefix) - } else { - format!("{}{}:***@", prefix, user) - } + Ok( + if preg_match2(GitHub::GITHUB_TOKEN_REGEX, &user, 0).is_some() { + format!("{}***:***@", prefix) + } else { + format!("{}{}:***@", prefix, user) + }, + ) }, &url, ) + .expect("the replacement callback cannot fail") } } |
