1717using Microsoft . PowerShell . Commands ;
1818using Microsoft . Win32 ;
1919using System . Security ;
20-
2120#if CORECLR
21+ using System . IO . Compression ;
2222using System . Net . Http ;
2323using System . Threading . Tasks ;
2424// Use stub for SerializableAttribute, SerializationInfo and ISerializable related types. WebClient.
@@ -1209,9 +1209,9 @@ internal void InstallHelpContent(UpdatableHelpCommandType commandType, Execution
12091209 OnProgressChanged ( this , new UpdatableHelpProgressEventArgs ( CurrentModule , commandType , StringUtil . Format (
12101210 HelpDisplayStrings . UpdateProgressInstalling ) , 0 ) ) ;
12111211
1212- string combinedSourcePath = Path . Combine ( sourcePath , fileName ) ;
1212+ string combinedSourcePath = GetFilePath ( Path . Combine ( sourcePath , fileName ) ) ;
12131213
1214- if ( ! File . Exists ( combinedSourcePath ) )
1214+ if ( string . IsNullOrEmpty ( combinedSourcePath ) )
12151215 {
12161216 throw new UpdatableHelpSystemException ( "HelpContentNotFound" , StringUtil . Format ( HelpDisplayStrings . HelpContentNotFound ) ,
12171217 ErrorCategory . ResourceUnavailable , null , null ) ;
@@ -1249,6 +1249,37 @@ internal void InstallHelpContent(UpdatableHelpCommandType commandType, Execution
12491249 }
12501250 }
12511251
1252+ #if UNIX
1253+ private bool ExpandArchive ( string source , string destination )
1254+ {
1255+ bool sucessfulDecompression = false ;
1256+
1257+ try
1258+ {
1259+ using ( FileStream archiveFileStream = new FileStream ( source , IO . FileMode . Open , FileAccess . Read ) )
1260+ using ( ZipArchive zipArchive = new ZipArchive ( archiveFileStream , ZipArchiveMode . Read , false ) )
1261+ {
1262+ foreach ( ZipArchiveEntry entry in zipArchive . Entries )
1263+ {
1264+ string extractPath = Path . Combine ( destination , entry . FullName ) ;
1265+ entry . ExtractToFile ( extractPath ) ;
1266+ }
1267+ sucessfulDecompression = true ;
1268+ }
1269+ }
1270+ catch ( ArgumentException ) { }
1271+ catch ( InvalidDataException ) { }
1272+ catch ( NotSupportedException ) { }
1273+ catch ( FileNotFoundException ) { }
1274+ catch ( IOException ) { }
1275+ catch ( SecurityException ) { }
1276+ catch ( UnauthorizedAccessException ) { }
1277+ catch ( ObjectDisposedException ) { }
1278+
1279+ return sucessfulDecompression ;
1280+ }
1281+ #endif
1282+
12521283 /// <summary>
12531284 /// Unzips to help content to a given location
12541285 /// </summary>
@@ -1265,20 +1296,25 @@ private void UnzipHelpContent(ExecutionContext context, string srcPath, string d
12651296 Directory . CreateDirectory ( destPath ) ;
12661297 }
12671298
1268- string cabDir = Path . GetDirectoryName ( srcPath ) ;
1269-
1299+ string sourceDirectory = Path . GetDirectoryName ( srcPath ) ;
1300+ bool sucessfulDecompression = false ;
1301+ #if UNIX
1302+ sucessfulDecompression = ExpandArchive ( Path . Combine ( sourceDirectory , Path . GetFileName ( srcPath ) ) , destPath ) ;
1303+ #else
12701304 // Cabinet API doesn't handle the trailing back slash
1271- if ( ! cabDir . EndsWith ( "\\ " , StringComparison . Ordinal ) )
1305+ if ( ! sourceDirectory . EndsWith ( "\\ " , StringComparison . Ordinal ) )
12721306 {
1273- cabDir += "\\ " ;
1307+ sourceDirectory += "\\ " ;
12741308 }
12751309
12761310 if ( ! destPath . EndsWith ( "\\ " , StringComparison . Ordinal ) )
12771311 {
12781312 destPath += "\\ " ;
12791313 }
1280-
1281- if ( ! CabinetExtractorFactory . GetCabinetExtractor ( ) . Extract ( Path . GetFileName ( srcPath ) , cabDir , destPath ) )
1314+
1315+ sucessfulDecompression = CabinetExtractorFactory . GetCabinetExtractor ( ) . Extract ( Path . GetFileName ( srcPath ) , sourceDirectory , destPath ) ;
1316+ #endif
1317+ if ( ! sucessfulDecompression )
12821318 {
12831319 throw new UpdatableHelpSystemException ( "UnableToExtract" , StringUtil . Format ( HelpDisplayStrings . UnzipFailure ) ,
12841320 ErrorCategory . InvalidOperation , null , null ) ;
@@ -1574,9 +1610,10 @@ internal static string LoadStringFromPath(PSCmdlet cmdlet, string path, PSCreden
15741610 }
15751611 }
15761612
1577- if ( File . Exists ( path ) )
1613+ string filePath = GetFilePath ( path ) ;
1614+ if ( ! string . IsNullOrEmpty ( filePath ) )
15781615 {
1579- using ( FileStream currentHelpInfoFile = new FileStream ( path , FileMode . Open , FileAccess . Read ) )
1616+ using ( FileStream currentHelpInfoFile = new FileStream ( filePath , FileMode . Open , FileAccess . Read ) )
15801617 {
15811618 StreamReader reader = new StreamReader ( currentHelpInfoFile ) ;
15821619
@@ -1587,6 +1624,43 @@ internal static string LoadStringFromPath(PSCmdlet cmdlet, string path, PSCreden
15871624 return null ;
15881625 }
15891626
1627+ /// <summary>
1628+ /// Validate the given path. If it exists, return the full path to the file.
1629+ /// </summary>
1630+ /// <param name="path"></param>
1631+ /// <returns></returns>
1632+ internal static string GetFilePath ( string path )
1633+ {
1634+ #if UNIX
1635+ // On Linux, file paths are case sensitive.
1636+ // The user does not have control over the files (HelpInfo.xml, .zip, and cab) that are generated by the Publishing team.
1637+ // The logic below is to support updating help content via sourcepath parameter for case insensitive files.
1638+ FileInfo item = new FileInfo ( path ) ;
1639+ string directoryPath = item . Directory . FullName ;
1640+ string fileName = item . Name ;
1641+
1642+ // Prerequisite: The directory in the given path must exist and it is case sensitive.
1643+ if ( Utils . NativeDirectoryExists ( directoryPath ) )
1644+ {
1645+ // Get the list of files in the directory.
1646+ string [ ] fileList = Directory . GetFiles ( directoryPath ) ;
1647+ foreach ( string filePath in fileList )
1648+ {
1649+ if ( filePath . EndsWith ( fileName , StringComparison . OrdinalIgnoreCase ) )
1650+ {
1651+ return filePath ;
1652+ }
1653+ }
1654+ }
1655+ #else
1656+ if ( Utils . NativeFileExists ( path ) )
1657+ {
1658+ return path ;
1659+ }
1660+ #endif
1661+ return null ;
1662+ }
1663+
15901664 /// <summary>
15911665 /// Gets the default source path from GP
15921666 /// </summary>
0 commit comments