diff --git a/FileSystemIDandChk/ImagePlugins/CDRWin.cs b/FileSystemIDandChk/ImagePlugins/CDRWin.cs index 155e8b57..6dbc5613 100644 --- a/FileSystemIDandChk/ImagePlugins/CDRWin.cs +++ b/FileSystemIDandChk/ImagePlugins/CDRWin.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Text; +using System.Text.RegularExpressions; using System.Collections.Generic; using FileSystemIDandChk; @@ -9,28 +10,133 @@ namespace FileSystemIDandChk.ImagePlugins class CDRWin : ImagePlugin { #region Internal structures - private struct TrackFile + private struct CDRWinTrackFile { public UInt32 sequence; // Track # public string datafile; // Path of file containing track public UInt64 offset; // Offset of track start in file + public string filetype; // Type of file + } + + private struct CDRWinTrack + { + public UInt32 sequence; // Track # + public string title; // Track title (from CD-Text) + public string genre; // Track genre (from CD-Text) + public string arranger; // Track arranger (from CD-Text) + public string composer; // Track composer (from CD-Text) + public string performer; // Track performer (from CD-Text) + public string songwriter; // Track song writer (from CD-Text) + public string isrc; // Track ISRC + public CDRWinTrackFile trackfile; // File struct for this track + public List indexes; // Indexes on this track + public UInt32 pregap; // Track pre-gap in sectors + public UInt32 postgap; // Track post-gap in sectors + public bool flag_dcp; // Digical Copy Permitted + public bool flag_4ch; // Track is quadraphonic + public bool flag_pre; // Track has preemphasis + public bool flag_scms; // Track has SCMS } #endregion + private struct CDRWinDisc + { + public string title; // Disk title (from CD-Text) + public string genre; // Disk genre (from CD-Text) + public string arranger; // Disk arranger (from CD-Text) + public string composer; // Disk composer (from CD-Text) + public string performer; // Disk performer (from CD-Text) + public string songwriter; // Disk song writer (from CD-Text) + public string mcn; // Media catalog number + public DiskType disktype; // Disk type + public string disktypestr; // Disk type string + public string disk_id; // Disk CDDB ID + public string barcode; // Disk UPC/EAN + public List sessions; // Sessions + public List tracks; // Tracks + public string comment; // Disk comment + public string cdtextfile; // File containing CD-Text + } + +#region Internal consts + // Type for FILE entity + private const string CDRWinDiskTypeLittleEndian = "BINARY"; // Data as-is in little-endian + private const string CDRWinDiskTypeBigEndian = "MOTOROLA"; // Data as-is in big-endian + private const string CDRWinDiskTypeAIFF = "AIFF"; // Audio in Apple AIF file + private const string CDRWinDiskTypeRIFF = "WAVE"; // Audio in Microsoft WAV file + private const string CDRWinDiskTypeMP3 = "MP3"; // Audio in MP3 file + + // Type for TRACK entity + private const string CDRWinTrackTypeAudio = "AUDIO"; // Audio track, 2352 bytes/sector + private const string CDRWinTrackTypeCDG = "CDG"; // CD+G track, 2448 bytes/sector (audio+subchannel) + private const string CDRWinTrackTypeMode1 = "MODE1/2048"; // Mode 1 track, cooked, 2048 bytes/sector + private const string CDRWinTrackTypeMode1Raw = "MODE1/2352"; // Mode 1 track, raw, 2352 bytes/sector + private const string CDRWinTrackTypeMode2Form1 = "MODE2/2048"; // Mode 2 form 1 track, cooked, 2048 bytes/sector + private const string CDRWinTrackTypeMode2Form2 = "MODE2/2324"; // Mode 2 form 2 track, cooked, 2324 bytes/sector + private const string CDRWinTrackTypeMode2Formless = "MODE2/2336"; // Mode 2 formless track, cooked, 2336 bytes/sector + private const string CDRWinTrackTypeMode2Raw = "MODE2/2352"; // Mode 2 track, raw, 2352 bytes/sector + private const string CDRWinTrackTypeCDI = "CDI/2336"; // CD-i track, cooked, 2336 bytes/sector + private const string CDRWinTrackTypeCDIRaw = "CDI/2352"; // CD-i track, raw, 2352 bytes/sector + + // Type for REM ORIGINAL MEDIA-TYPE entity + private const string CDRWinDiskTypeCD = "CD"; // DiskType.CD + private const string CDRWinDiskTypeCDRW = "CD-RW"; // DiskType.CDRW + private const string CDRWinDiskTypeCDMRW = "CD-MRW"; // DiskType.CDMRW + private const string CDRWinDiskTypeCDMRW2 = "CD-(MRW)"; // DiskType.CDMRW + private const string CDRWinDiskTypeDVD = "DVD"; // DiskType.DVDROM + private const string CDRWinDiskTypeDVDPMRW = "DVD+MRW"; // DiskType.DVDPRW + private const string CDRWinDiskTypeDVDPMRW2 = "DVD+(MRW)"; // DiskType.DVDPRW + private const string CDRWinDiskTypeDVDPMRWDL = "DVD+MRW DL"; // DiskType.DVDPRWDL + private const string CDRWinDiskTypeDVDPMRWDL2 = "DVD+(MRW) DL"; // DiskType.DVDPRWDL + private const string CDRWinDiskTypeDVDPR = "DVD+R"; // DiskType.DVDPR + private const string CDRWinDiskTypeDVDPRDL = "DVD+R DL"; // DiskType.DVDPRDL + private const string CDRWinDiskTypeDVDPRW = "DVD+RW"; // DiskType.DVDPRW + private const string CDRWinDiskTypeDVDPRWDL = "DVD+RW DL"; // DiskType.DVDPRWDL + private const string CDRWinDiskTypeDVDPVR = "DVD+VR"; // DiskType.DVDPR + private const string CDRWinDiskTypeDVDRAM = "DVD-RAM"; // DiskType.DVDRAM + private const string CDRWinDiskTypeDVDR = "DVD-R"; // DiskType.DVDR + private const string CDRWinDiskTypeDVDRDL = "DVD-R DL"; // DiskType.DVDRDL + private const string CDRWinDiskTypeDVDRW = "DVD-RW"; // DiskType.DVDRW + private const string CDRWinDiskTypeDVDRWDL = "DVD-RW DL"; // DiskType.DVDRWDL + private const string CDRWinDiskTypeDVDVR = "DVD-VR"; // DiskType.DVDR + private const string CDRWinDiskTypeDVDRW2 = "DVDRW"; // DiskType.DVDRW + private const string CDRWinDiskTypeHDDVD = "HD DVD"; // DiskType.HDDVDROM + private const string CDRWinDiskTypeHDDVDRAM = "HD DVD-RAM"; // DiskType.HDDVDRAM + private const string CDRWinDiskTypeHDDVDR = "HD DVD-R"; // DiskType.HDDVDR + private const string CDRWinDiskTypeHDDVDRDL = "HD DVD-R DL"; // DiskType.HDDVDR + private const string CDRWinDiskTypeHDDVDRW = "HD DVD-RW"; // DiskType.HDDVDRW + private const string CDRWinDiskTypeHDDVDRWDL = "HD DVD-RW DL"; // DiskType.HDDVDRW + private const string CDRWinDiskTypeBD = "BD"; // DiskType.BDROM + private const string CDRWinDiskTypeBDR = "BD-R"; // DiskType.BDR + private const string CDRWinDiskTypeBDRE = "BD-RE"; // DiskType.BDRE + private const string CDRWinDiskTypeBDRDL = "BD-R DL"; // DiskType.BDR + private const string CDRWinDiskTypeBDREDL = "BD-RE DL"; // DiskType.BDRE + +#endregion + #region Internal variables + private bool initialized; private string imagePath; + private StreamReader cueStream; private FileStream imageStream; - private List sessions; - private List tracks; - private Dictionary trackFiles; // Dictionary, index is track #, value is TrackFile -#region + private Dictionary trackFiles; // Dictionary, index is track #, value is TrackFile + private CDRWinDisc discimage; +#endregion #region Parsing regexs private const string SessionRegEx = "REM\\s+SESSION\\s+(?\\d+)$"; + private const string DiskTypeRegEx = "REM\\s+ORIGINAL MEDIA-TYPE:\\s+(?.+)$"; + private const string LeadOutRegEx = "REM\\s+LEAD-OUT\\s+(?[\\d]+:[\\d]+:[\\d]+)$"; + private const string LBARegEx = "REM MSF:\\s+(?[\\d]+:[\\d]+:[\\d]+)\\s+=\\s+LBA:\\s+(?[\\d]+)$"; // Not checked + private const string DiskIDRegEx = "DISC_ID\\s+(?[\\da-f]{8})$"; + private const string BarCodeRegEx = "UPC_EAN\\s+(?[\\d]{12,13})$"; private const string CommentRegEx = "REM\\s+(?.+)$"; - private const string CDTextRegEx = "CDTEXMAIN\\s+(?.+)$"; + private const string CDTextRegEx = "CDTEXTFILE\\s+(?.+)$"; private const string MCNRegEx = "CATALOG\\s+(?\\d{13})$"; private const string TitleRegEx = "TITLE\\s+(?.+)$"; + private const string GenreRegEx = "GENRE\\s+(?<genre>.+)$"; + private const string ArrangerRegEx = "ARRANGER\\s+(?<arranger>.+)$"; + private const string ComposerRegEx = "COMPOSER\\s+(?<composer>.+)$"; private const string PerformerRegEx = "PERFORMER\\s+(?<performer>.+)$"; private const string SongWriterRegEx = "SONGWRITER\\s+(?<songwriter>.+)$"; private const string FileRegEx = "FILE\\s+(?<filename>.+)\\s+(?<type>\\S+)$"; @@ -39,7 +145,7 @@ namespace FileSystemIDandChk.ImagePlugins private const string IndexRegEx = "INDEX\\s+(?<index>\\d+)\\s+(?<msf>[\\d]+:[\\d]+:[\\d]+)$"; private const string PregapRegEx = "PREGAP\\s+(?<msf>[\\d]+:[\\d]+:[\\d]+)$"; private const string PostgapRegex = "POSTGAP\\s+(?<msf>[\\d]+:[\\d]+:[\\d]+)$"; - private const string FlagsRegEx = "FLAGS\\+(((?<dcp>DCP)|(?<4ch>4CH)|(?<pre>PRE)|(?<scms>SCMS))\\s*)+$"; + private const string FlagsRegEx = "FLAGS\\s+(((?<dcp>DCP)|(?<quad>4CH)|(?<pre>PRE)|(?<scms>SCMS))\\s*)+$"; #endregion #region Methods @@ -50,23 +156,356 @@ namespace FileSystemIDandChk.ImagePlugins this.imagePath = ""; } - public CDRWin (PluginBase Core, string imagePath) + // Due to .cue format, this method must parse whole file, ignoring errors (those will be thrown by OpenImage()). + public override bool IdentifyImage(string imagePath) { this.imagePath = imagePath; + + try + { + this.cueStream = new StreamReader(this.imagePath); + int line = 0; + + while (this.cueStream.Peek() >= 0) + { + line++; + string _line = this.cueStream.ReadLine(); + + Regex Sr = new Regex(SessionRegEx); + Regex Rr = new Regex(CommentRegEx); + Regex Cr = new Regex(MCNRegEx); + Regex Fr = new Regex(FileRegEx); + + Match Sm; + Match Rm; + Match Cm; + Match Fm; + + // First line must be SESSION, REM, CATALOG or FILE. + Sm = Sr.Match(_line); + Rm = Rr.Match(_line); + Cm = Cr.Match(_line); + Fm = Fr.Match(_line); + + if(!Sm.Success && !Rm.Success && !Cm.Success && !Fm.Success) + return false; + else + return true; + } + + return false; + } + catch(Exception ex) + { + Console.WriteLine("Exception trying to identify image file {0}", this.imagePath); + Console.WriteLine("Exception: {0}", ex.Message); + Console.WriteLine("Stack trace: {0}", ex.StackTrace); + return false; + } } - // Due to .cue format, this method must parse whole file, ignoring errors (those will be thrown by OpenImage()). - public override bool IdentifyImage() + public override bool OpenImage(string filename) { - throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented"); - } - public override bool OpenImage() - { - throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented"); + if (filename == "") + return false; + + this.imagePath = imagePath; + + try + { + this.cueStream = new StreamReader(this.imagePath); + int line = 0; + bool intrack = false; + string currentfile = ""; + string currentfileformat = ""; + byte currentsession = 1; + + // Initialize all RegExs + Regex RegexSession = new Regex(SessionRegEx); + Regex RegexDiskType = new Regex(DiskTypeRegEx); + Regex RegexLeadOut = new Regex(LeadOutRegEx); + Regex RegexLBA = new Regex(LBARegEx); + Regex RegexDiskID = new Regex(DiskIDRegEx); + Regex RegexBarCode = new Regex(BarCodeRegEx); + Regex RegexComment = new Regex(CommentRegEx); + Regex RegexCDText = new Regex(CDTextRegEx); + Regex RegexMCN = new Regex(MCNRegEx); + Regex RegexTitle = new Regex(TitleRegEx); + Regex RegexGenre = new Regex(GenreRegEx); + Regex RegexArranger = new Regex(ArrangerRegEx); + Regex RegexComposer = new Regex(ComposerRegEx); + Regex RegexPerformer = new Regex(PerformerRegEx); + Regex RegexSongWriter = new Regex(SongWriterRegEx); + Regex RegexFile = new Regex(FileRegEx); + Regex RegexTrack = new Regex(TrackRegEx); + Regex RegexISRC = new Regex(ISRCRegEx); + Regex RegexIndex = new Regex(IndexRegEx); + Regex RegexPregap = new Regex(PregapRegEx); + Regex RegexPostgap = new Regex(PostgapRegex); + Regex RegexFlags = new Regex(FlagsRegEx); + + // Initialize all RegEx matches + Match MatchSession; + Match MatchDiskType; + Match MatchLeadOut; + Match MatchLBA; + Match MatchDiskID; + Match MatchBarCode; + Match MatchComment; + Match MatchCDText; + Match MatchMCN; + Match MatchTitle; + Match MatchGenre; + Match MatchArranger; + Match MatchComposer; + Match MatchPerformer; + Match MatchSongWriter; + Match MatchFile; + Match MatchTrack; + Match MatchISRC; + Match MatchIndex; + Match MatchPregap; + Match MatchPostgap; + Match MatchFlags; + + // Initialize disc + this.discimage = new CDRWinDisc(); + this.discimage.sessions = new List<Session>(); + this.discimage.tracks = new List<CDRWinTrack>(); + + CDRWinTrack currenttrack = new CDRWinTrack(); + + while (this.cueStream.Peek() >= 0) + { + line++; + string _line = this.cueStream.ReadLine(); + + MatchSession = RegexSession.Match(_line); + MatchDiskType = RegexDiskType.Match(_line); + MatchComment = RegexComment.Match(_line); + MatchLBA = RegexLBA.Match(_line); // Unhandled, just ignored + MatchLeadOut = RegexLeadOut.Match(_line); // Unhandled, just ignored + + if(MatchDiskType.Success && intrack == false) + { + Console.WriteLine("DEBUG (CDRWin plugin): Found REM ORIGINAL MEDIA TYPE at line {0}", line); + this.discimage.disktypestr = MatchDiskType.Groups[1].Value; + } + else if(MatchSession.Success && intrack == false) + { + Console.WriteLine("DEBUG (CDRWin plugin): Found REM SESSION at line {0}", line); + currentsession = Byte.Parse(MatchSession.Groups[1].Value); + + // What happens between sessions + } + else if(MatchLBA.Success) + { + Console.WriteLine("DEBUG (CDRWin plugin): Found REM MSF at line {0}", line); + // Just ignored + } + else if(MatchLeadOut.Success) + { + Console.WriteLine("DEBUG (CDRWin plugin): Found REM LEAD-OUT at line {0}", line); + // Just ignored + } + else if(MatchComment.Success && intrack == false) + { + Console.WriteLine("DEBUG (CDRWin plugin): Found REM at line {0}", line); + this.discimage.comment = MatchComment.Groups[1].Value; + } + else if((MatchComment.Success || MatchSession.Success || MatchDiskType.Success) && intrack == true) + { + throw new FeatureUnsupportedImageException(String.Format("Found comment/session/disktype field after a track in line {0}", line)); + } + else + { + MatchTrack = RegexTrack.Match(_line); + MatchTitle = RegexTitle.Match(_line); + MatchSongWriter = RegexSongWriter.Match(_line); + MatchPregap = RegexPregap.Match(_line); + MatchPostgap = RegexPostgap.Match(_line); + MatchPerformer = RegexPerformer.Match(_line); + MatchMCN = RegexMCN.Match(_line); + MatchISRC = RegexISRC.Match(_line); + MatchIndex = RegexIndex.Match(_line); + MatchGenre = RegexGenre.Match(_line); + MatchFlags = RegexFlags.Match(_line); + MatchFile = RegexFile.Match(_line); + MatchDiskID = RegexDiskID.Match(_line); + MatchComposer = RegexComposer.Match(_line); + MatchCDText = RegexCDText.Match(_line); + MatchBarCode = RegexBarCode.Match(_line); + MatchArranger = RegexArranger.Match(_line); + + if(MatchArranger.Success) + { + Console.WriteLine("DEBUG (CDRWin plugin): Found ARRANGER at line {0}", line); + if(intrack == true) + currenttrack.arranger = MatchArranger.Groups[1].Value; + else + this.discimage.arranger = MatchArranger.Groups[1].Value; + } + else if(MatchBarCode.Success) + { + Console.WriteLine("DEBUG (CDRWin plugin): Found CATALOG at line {0}", line); + if(intrack == false) + this.discimage.barcode = MatchBarCode.Groups[1].Value; + else + throw new FeatureUnsupportedImageException(String.Format("Found barcode field in incorrect place at line {0}", line)); + } + else if(MatchCDText.Success) + { + Console.WriteLine("DEBUG (CDRWin plugin): Found CDTEXTFILE at line {0}", line); + if(intrack == false) + this.discimage.cdtextfile = MatchCDText.Groups[1].Value; + else + throw new FeatureUnsupportedImageException(String.Format("Found CD-Text file field in incorrect place at line {0}", line)); + } + else if(MatchComposer.Success) + { + Console.WriteLine("DEBUG (CDRWin plugin): Found COMPOSER at line {0}", line); + if(intrack == true) + currenttrack.arranger = MatchComposer.Groups[1].Value; + else + this.discimage.arranger = MatchComposer.Groups[1].Value; + } + else if(MatchDiskID.Success) + { + Console.WriteLine("DEBUG (CDRWin plugin): Found DISC_ID at line {0}", line); + if(intrack == false) + this.discimage.disk_id = MatchDiskID.Groups[1].Value; + else + throw new FeatureUnsupportedImageException(String.Format("Found CDDB ID field in incorrect place at line {0}", line)); + } + else if(MatchFile.Success) + { + Console.WriteLine("DEBUG (CDRWin plugin): Found FILE at line {0}", line); + currentfile = MatchFile.Groups[1].Value; + currentfileformat = MatchFile.Groups[2].Value; + } + else if(MatchFlags.Success) + { + Console.WriteLine("DEBUG (CDRWin plugin): Found FLAGS at line {0}", line); + if(intrack == false) + throw new FeatureUnsupportedImageException(String.Format("Found FLAGS field in incorrect place at line {0}", line)); + else + { + // Not yet implemented + } + } + else if(MatchGenre.Success) + { + Console.WriteLine("DEBUG (CDRWin plugin): Found GENRE at line {0}", line); + if(intrack == true) + currenttrack.genre = MatchGenre.Groups[1].Value; + else + this.discimage.genre = MatchGenre.Groups[1].Value; + } + else if(MatchIndex.Success) + { + Console.WriteLine("DEBUG (CDRWin plugin): Found INDEX at line {0}", line); + if(intrack == false) + throw new FeatureUnsupportedImageException(String.Format("Found INDEX before a track {0}", line)); + else + { + // Not yet implemented + } + } + else if(MatchISRC.Success) + { + Console.WriteLine("DEBUG (CDRWin plugin): Found ISRC at line {0}", line); + if(intrack == false) + throw new FeatureUnsupportedImageException(String.Format("Found ISRC before a track {0}", line)); + else + currenttrack.isrc = MatchISRC.Groups[1].Value; + } + else if(MatchMCN.Success) + { + Console.WriteLine("DEBUG (CDRWin plugin): Found CATALOG at line {0}", line); + if(intrack == false) + this.discimage.mcn = MatchMCN.Groups[1].Value; + else + throw new FeatureUnsupportedImageException(String.Format("Found CATALOG field in incorrect place at line {0}", line)); + } + else if(MatchPerformer.Success) + { + Console.WriteLine("DEBUG (CDRWin plugin): Found PERFORMER at line {0}", line); + if(intrack == true) + currenttrack.performer = MatchPerformer.Groups[1].Value; + else + this.discimage.performer = MatchPerformer.Groups[1].Value; + } + else if(MatchPostgap.Success) + { + Console.WriteLine("DEBUG (CDRWin plugin): Found POSTGAP at line {0}", line); + if(intrack == true) + { + // Not yet implemented + } + else + throw new FeatureUnsupportedImageException(String.Format("Found POSTGAP field before a track at line {0}", line)); + } + else if(MatchPregap.Success) + { + Console.WriteLine("DEBUG (CDRWin plugin): Found PREGAP at line {0}", line); + if(intrack == true) + { + // Not yet implemented + } + else + throw new FeatureUnsupportedImageException(String.Format("Found PREGAP field before a track at line {0}", line)); + } + else if(MatchSongWriter.Success) + { + Console.WriteLine("DEBUG (CDRWin plugin): Found SONGWRITER at line {0}", line); + if(intrack == true) + currenttrack.songwriter = MatchSongWriter.Groups[1].Value; + else + this.discimage.songwriter = MatchSongWriter.Groups[1].Value; + } + else if(MatchTitle.Success) + { + Console.WriteLine("DEBUG (CDRWin plugin): Found TITLE at line {0}", line); + if(intrack == true) + currenttrack.title = MatchTitle.Groups[1].Value; + else + this.discimage.title = MatchTitle.Groups[1].Value; + } + else if(MatchTrack.Success) + { + Console.WriteLine("DEBUG (CDRWin plugin): Found TRACK at line {0}", line); + if(currentfile == "") + throw new FeatureUnsupportedImageException(String.Format("Found TRACK field before a file is defined at line {0}", line)); + else + { + if(intrack == true) + { + this.discimage.tracks.Add(currenttrack); + } + currenttrack = new CDRWinTrack(); + intrack = true; + + // TODO + } + } + } + } + + return false; + } + catch(Exception ex) + { + Console.WriteLine("Exception trying to identify image file {0}", this.imagePath); + Console.WriteLine("Exception: {0}", ex.Message); + Console.WriteLine("Stack trace: {0}", ex.StackTrace); + return false; + } } + public override bool ImageHasPartitions() { - throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented"); + // Even if they only have 1 track, there is a partition (track 1) + return true; } public override UInt64 GetImageSize() diff --git a/FileSystemIDandChk/ImagePlugins/ImagePlugin.cs b/FileSystemIDandChk/ImagePlugins/ImagePlugin.cs index f6a3e2a1..5dddb187 100644 --- a/FileSystemIDandChk/ImagePlugins/ImagePlugin.cs +++ b/FileSystemIDandChk/ImagePlugins/ImagePlugin.cs @@ -13,13 +13,9 @@ namespace FileSystemIDandChk.ImagePlugins { } - protected ImagePlugin (string ImagePath) - { - } - // Basic image handling functions - public abstract bool IdentifyImage(); // Returns true if the plugin can handle the given image file - public abstract bool OpenImage(); // Initialize internal plugin structures to handle image + public abstract bool IdentifyImage(string imagepath); // Returns true if the plugin can handle the given image file + public abstract bool OpenImage(string imagepath); // Initialize internal plugin structures to handle image public abstract bool ImageHasPartitions(); // Image has different partitions (sessions, tracks) // Image size functions @@ -74,12 +70,92 @@ namespace FileSystemIDandChk.ImagePlugins public abstract List<Track> GetSessionTracks(Session Session); // Returns disc track extensts for a session public abstract List<Track> GetSessionTracks(UInt16 Session); // Returns disc track extensts for a session public abstract List<Session> GetSessions(); // Returns disc sessions + + // CD flags bitmask + public const byte CDFlagsFourChannel = 0x20; + public const byte CDFlagsDataTrack = 0x10; + public const byte CDFlagsCopyPrevent = 0x08; + public const byte CDFlagsPreEmphasis = 0x04; } // Disk types public enum DiskType { - Unknown + Unknown, + // Somewhat standard Compact Disc formats + CDDA, // CD Digital Audio (Red Book) + CDG, // CD+G (Red Book) + CDEG, // CD+EG (Red Book) + CDI, // CD-i (Green Book) + CDROM, // CD-ROM (Yellow Book) + CDROMXA, // CD-ROM XA (Yellow Book) + CDPLUS, // CD+ (Blue Book) + CDMO, // CD-MO (Orange Book) + CDR, // CD-Recordable (Orange Book) + CDRW, // CD-ReWritable (Orange Book) + CDMRW, // Mount-Rainier CD-RW + VCD, // Video CD (White Book) + SVCD, // Super Video CD (White Book) + PCD, // Photo CD (Beige Book) + SACD, // Super Audio CD (Scarlet Book) + DDCD, // Double-Density CD-ROM (Purple Book) + DDCDR, // DD CD-R (Purple Book) + DDCDRW, // DD CD-RW (Purple Book) + DTSCD, // DTS audio CD (non-standard) + CDMIDI, // CD-MIDI (Red Book) + CD, // Any unknown or standard violating CD + // Standard DVD formats + DVDROM, // DVD-ROM (applies to DVD Video and DVD Audio) + DVDR, // DVD-R + DVDRW, // DVD-RW + DVDPR, // DVD+R + DVDPRW, // DVD+RW + DVDPRWDL, // DVD+RW DL + DVDRDL, // DVD-R DL + DVDPRDL, // DVD+R DL + DVDRAM, // DVD-RAM + // Standard HD-DVD formats + HDDVDROM, // HD DVD-ROM (applies to HD DVD Video) + HDDVDRAM, // HD DVD-RAM + HDDVDR, // HD DVD-R + HDDVDRW, // HD DVD-RW + // Standard Blu-ray formats + BDROM, // BD-ROM (and BD Video) + BDR, // BD-R + BDRE, // BD-RE + // Rare or uncommon standards + EVD, // Enhanced Versatile Disc + FVD, // Forward Versatile Disc + HVD, // Holographic Versatile Disc + CBHD, // China Blue High Definition + HDVMD, // High Definition Versatile Multilayer Disc + VCDHD, // Versatile Compact Disc High Density + LD, // Pioneer LaserDisc + LDROM, // Pioneer LaserDisc data + MD, // Sony MiniDisc + HiMD, // Sony Hi-MD + UDO, // Ultra Density Optical + SVOD, // Stacked Volumetric Optical Disc + FDDVD, // Five Dimensional disc + // Propietary game discs + PS1CD, // Sony PlayStation game CD + PS2CD, // Sony PlayStation 2 game CD + PS2DVD, // Sony PlayStation 2 game DVD + PS3DVD, // Sony PlayStation 3 game DVD + PS3BD, // Sony PlayStation 3 game Blu-ray + PS4BD, // Sony PlayStation 4 game Blu-ray + UMD, // Sony PlayStation Portable Universal Media Disc (ECMA-365) + GOD, // Nintendo GameCube Optical Disc + WOD, // Nintendo Wii Optical Disc + WUOD, // Nintendo Wii U Optical Disc + XGD, // Microsoft X-box Game Disc + XGD2, // Microsoft X-box 360 Game Disc + XGD3, // Microsoft X-box 360 Game Disc + XGD4, // Microsoft X-box One Game Disc + MEGACD, // Sega MegaCD + SATURNCD, // Sega Saturn disc + GDROM, // Sega/Yamaha Gigabyte Disc + GDR // Sega/Yamaha recordable Gigabyte Disc }; // Track (as partitioning element) types @@ -125,17 +201,18 @@ namespace FileSystemIDandChk.ImagePlugins // Metadata present for each sector (aka, "tag") public enum SectorTagType { - AppleSectorTag, // Apple's GCR sector tags - CDSectorSync, // Sync frame from CD sector - CDSectorHeader, // CD sector header + AppleSectorTag, // Apple's GCR sector tags, 20 bytes + CDSectorSync, // Sync frame from CD sector, 12 bytes + CDSectorHeader, // CD sector header, 4 bytes CDSectorSubHeader, // CD mode 2 sector subheader - CDSectorEDC, // CD sector EDC - CDSectorECC_P, // CD sector ECC P - CDSectorECC_Q, // CD sector ECC Q - CDSectorECC, // CD sector ECC (P and Q) - CDSectorSubchannel, // CD sector subchannel - CDTrackISRC, // CD track ISRC - CDTrackText, // CD track text + CDSectorEDC, // CD sector EDC, 4 bytes + CDSectorECC_P, // CD sector ECC P, 172 bytes + CDSectorECC_Q, // CD sector ECC Q, 104 bytes + CDSectorECC, // CD sector ECC (P and Q), 276 bytes + CDSectorSubchannel, // CD sector subchannel, 96 bytes + CDTrackISRC, // CD track ISRC, string, 12 bytes + CDTrackText, // CD track text, string, 13 bytes + CDTrackFlags, // CD track flags, 1 byte DVD_CMI // DVD sector copyright information }; @@ -200,4 +277,15 @@ namespace FileSystemIDandChk.ImagePlugins System.Runtime.Serialization.StreamingContext context) { } } + // Corrupt, incorrect or unhandled feature found on image + [Serializable()] + public class ImageNotSupportedException : System.Exception + { + public ImageNotSupportedException() : base() { } + public ImageNotSupportedException(string message) : base(message) { } + public ImageNotSupportedException(string message, System.Exception inner) : base(message, inner) { } + + protected ImageNotSupportedException(System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) { } + } } \ No newline at end of file diff --git a/FileSystemIDandChk/Main.cs b/FileSystemIDandChk/Main.cs index 7f79957a..aea737fe 100644 --- a/FileSystemIDandChk/Main.cs +++ b/FileSystemIDandChk/Main.cs @@ -3,6 +3,7 @@ using System.IO; using System.Collections.Generic; using FileSystemIDandChk.Plugins; using FileSystemIDandChk.PartPlugins; +using FileSystemIDandChk.ImagePlugins; namespace FileSystemIDandChk { @@ -24,6 +25,11 @@ namespace FileSystemIDandChk Console.WriteLine ("Filesystem Identifier and Checker"); Console.WriteLine ("Copyright (C) Natalia Portillo, All Rights Reserved"); + // For debug + plugins.RegisterAllPlugins(); + Runner(""); + + /* if(args.Length==0) { Usage(); @@ -34,6 +40,10 @@ namespace FileSystemIDandChk if(args[0]=="--formats") { + Console.WriteLine("Supported images:"); + foreach(KeyValuePair<string, ImagePlugin> kvp in plugins.ImagePluginsList) + Console.WriteLine(kvp.Value.Name); + Console.WriteLine(); Console.WriteLine("Supported filesystems:"); foreach(KeyValuePair<string, Plugin> kvp in plugins.PluginsList) Console.WriteLine(kvp.Value.Name); @@ -73,6 +83,7 @@ namespace FileSystemIDandChk Runner(args[args.Length-1]); } + */ } private static void Runner (string filename) @@ -82,9 +93,54 @@ namespace FileSystemIDandChk Plugin _plugin; string information; bool checkraw = false; + ImagePlugin _imageFormat; try { + _imageFormat = null; + + foreach(ImagePlugin _imageplugin in plugins.ImagePluginsList.Values) + { + // DEBUG + filename = "/Users/claunia/Desktop/disk_images/cdrom.cue"; + + if(_imageplugin.IdentifyImage(filename)) + { + _imageFormat = _imageplugin; + Console.WriteLine("Image format identified by {0}.", _imageplugin.Name); + break; + } + } + + if(_imageFormat == null) + { + Console.WriteLine("Image format not identified, not proceeding."); + return; + } + + try + { + if(_imageFormat.OpenImage(filename)) + { + Console.WriteLine("DEBUG: Correctly opened image file."); + return; + } + else + { + Console.WriteLine("Unable to open image format"); + Console.WriteLine("No error given"); + return; + } + } + catch(Exception ex) + { + Console.WriteLine("Unable to open image format"); + Console.WriteLine("Error: {0}", ex.Message); + return; + } + + // All commented until image formats are implemented correctly. + /* stream = File.OpenRead(filename); if(chkPartitions) @@ -190,6 +246,7 @@ namespace FileSystemIDandChk Console.Write(information); } } + */ } catch(Exception ex) { diff --git a/FileSystemIDandChk/Plugins.cs b/FileSystemIDandChk/Plugins.cs index f9c76a87..f3bb7cee 100644 --- a/FileSystemIDandChk/Plugins.cs +++ b/FileSystemIDandChk/Plugins.cs @@ -3,6 +3,7 @@ using System.Reflection; using System.Collections.Generic; using FileSystemIDandChk.Plugins; using FileSystemIDandChk.PartPlugins; +using FileSystemIDandChk.ImagePlugins; namespace FileSystemIDandChk { @@ -10,11 +11,13 @@ namespace FileSystemIDandChk { public Dictionary<string, Plugin> PluginsList; public Dictionary<string, PartPlugin> PartPluginsList; + public Dictionary<string, ImagePlugin> ImagePluginsList; public PluginBase () { this.PluginsList = new Dictionary<string, Plugin>(); this.PartPluginsList = new Dictionary<string, PartPlugin>(); + this.ImagePluginsList = new Dictionary<string, ImagePlugin>(); } public void RegisterAllPlugins() @@ -25,6 +28,11 @@ namespace FileSystemIDandChk { try { + if (type.IsSubclassOf(typeof(ImagePlugin))) + { + ImagePlugin plugin = (ImagePlugin)type.GetConstructor(new Type[] { typeof(PluginBase) }).Invoke(new object[] { this }); + this.RegisterImagePlugin(plugin); + } if (type.IsSubclassOf(typeof(Plugin))) { Plugin plugin = (Plugin)type.GetConstructor(new Type[] { typeof(PluginBase) }).Invoke(new object[] { this }); @@ -44,6 +52,14 @@ namespace FileSystemIDandChk } } + private void RegisterImagePlugin(ImagePlugin plugin) + { + if (!this.ImagePluginsList.ContainsKey(plugin.Name.ToLower())) + { + this.ImagePluginsList.Add(plugin.Name.ToLower(), plugin); + } + } + private void RegisterPlugin(Plugin plugin) { if (!this.PluginsList.ContainsKey(plugin.Name.ToLower()))