Exemple #1
0
        /// <summary>
        /// The newline string for a particular input stream.
        /// </summary>
        /// <param name="stream">
        /// A <see cref="GLib.DataInputStream"/>
        /// </param>
        /// <returns>
        /// A <see cref="System.String"/>
        /// </returns>
        public static string NewLineString(this GLib.DataInputStream stream)
        {
            switch (stream.NewlineType)
            {
            case DataStreamNewlineType.Cr:
                return("\r");

            case DataStreamNewlineType.Lf:
                return("\n");

            case DataStreamNewlineType.CrLf:
                return("\r\n");

            // this is a safe default because \n is the common line ending on *nix
            default:
                return("\n");
            }
        }
		void DataRead (GLib.Object obj, GLib.AsyncResult res) 
		{
			File file = FileAdapter.GetObject (obj);
			
			Regex keyValueRegex = new Regex (
				@"(^(\s)*(?<Key>([^\=^\n]+))[\s^\n]*\=(\s)*(?<Value>([^\n]+(\n){0,1})))",
				RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled | 
				RegexOptions.CultureInvariant
			);

			using (DataInputStream stream = new DataInputStream (file.ReadFinish (res))) {
				ulong len;
				string line;
				while ((line = stream.ReadLine (out len, null)) != null) {
					line = line.Trim ();
					
					Match match = keyValueRegex.Match (line);
					if (match.Success) {
						string key = match.Groups["Key"].Value;
						string val = match.Groups["Value"].Value;
						
						if (key.Equals (NameTag)) {
							Name = val;
						} else if (key.Equals (DescTag)) {
							Description = val;
						} else if (key.Equals (AppUriTag)) {
							AppUri = val;
						} else if (key.Equals (IconTag)) {
							if (val.StartsWith ("./") && val.Length > 2) {
								IconFile = file.Parent.GetChild (val.Substring (2));
								if (IconFile.Exists)
									Icon = DockServices.Drawing.LoadIcon (IconFile.Path + ";;extension");
							} else {
								Icon = DockServices.Drawing.LoadIcon (val + ";;extension", 128);
							}
						}
					}
				}
			}
			OnDataReady ();
		}
		void BuildExecStrings ()
		{
			ItemsByExec = new Dictionary<string, List<DesktopItem>> ();
			
			foreach (DesktopItem item in DesktopItems) {
				if (item == null || item.Ignored || !item.HasAttribute ("Exec"))
					continue;
				
				string exec = item.GetString ("Exec").Trim ();
				string vexec = null;
				
				// for openoffice
				if (exec.Contains (' ') &&
				   (exec.StartsWith ("ooffice") || exec.StartsWith ("openoffice") || exec.StartsWith ("soffice") ||
				    exec.Contains ("/ooffice ") || exec.Contains ("/openoffice.org ") || exec.Contains ("/soffice "))) {
					vexec = "ooffice" + exec.Split (' ')[1];
					vexec = vexec.Replace ("--", "-");
				
				// for libreoffice
				} else if (exec.Contains (' ') &&
				   (exec.StartsWith ("libreoffice"))) {
					vexec = "libreoffice" + exec.Split (' ')[1];
					vexec = vexec.Replace ("--", "-");
				
				// for wine apps
				} else if ((exec.Contains ("env WINEPREFIX=") && exec.Contains (" wine ")) ||
						exec.Contains ("wine ")) {
					int startIndex = exec.IndexOf ("wine ") + 5;
					// length of 'wine '
					// CommandLineForPid already splits based on \\ and takes the last entry, so do the same here
					vexec = exec.Substring (startIndex).Split (new[] { @"\\" }, StringSplitOptions.RemoveEmptyEntries).Last ();
					// remove the trailing " and anything after it
					if (vexec.Contains ("\""))
						vexec = vexec.Substring (0, vexec.IndexOf ("\""));

				// for crossover apps
				} else if (exec.Contains (".cxoffice") || (item.HasAttribute ("X-Created-By") && item.GetString ("X-Created-By").Contains ("cxoffice"))) {
					// The exec is actually another file that uses exec to launch the actual app.
					exec = exec.Replace ("\"", "");
					
					GLib.File launcher = GLib.FileFactory.NewForPath (exec);
					if (!launcher.Exists) {
						Log<DesktopItemService>.Warn ("Crossover launcher decoded as: {0}, but does not exist.", launcher.Path);
						continue;
					}
					
					string execLine = "";
					using (GLib.DataInputStream stream = new GLib.DataInputStream (launcher.Read (null))) {
						ulong len;
						string line;
						try {
							while ((line = stream.ReadLine (out len, null)) != null) {
								if (line.StartsWith ("exec")) {
									execLine = line;
									break;
								}
							}
						} catch (Exception e) {
							Log<DesktopItemService>.Error ("Error reading crossover launher: {0}", e.Message);
							Log<DesktopItemService>.Error (e.StackTrace);
							continue;
						}
					}
	
					// if no exec line was found, bail
					if (string.IsNullOrEmpty (execLine))
						continue;
					
					// get the relevant part from the execLine
					string[] parts = execLine.Split (new[] { '\"' });
					// find the part that contains C:/path/to/app.lnk
					if (parts.Any (part => part.StartsWith ("C:"))) {
						vexec = parts.First (part => part.StartsWith ("C:"));
						// and take only app.lnk (this is what is exposed to ps -ef)
						vexec = ExecForPath (vexec);
					} else {
						continue;
					}
					
				// other apps
				} else {
					string[] parts = exec.Split (' ');
					
					vexec = parts
						.DefaultIfEmpty (null)
						.Select (part => ExecForPath (part))
						.Where (part => !DockServices.WindowMatcher.PrefixFilters.Any (f => f.IsMatch (part)))
						.FirstOrDefault ();
					
					// for AIR apps
					if (vexec != null && vexec.Contains ('\'')) {
						vexec = vexec.Replace ("'", "");
					}
				}
				
				if (vexec == null)
					continue;
				
				if (!ItemsByExec.ContainsKey (vexec))
					ItemsByExec [vexec] = new List<DesktopItem> ();
				
				ItemsByExec [vexec].Add (item);
				foreach (Regex f in DockServices.WindowMatcher.SuffixFilters) {
					if (f.IsMatch (vexec)) {
						string vexecStripped = f.Replace (vexec, "");
						if (!ItemsByExec.ContainsKey (vexecStripped))
							ItemsByExec [vexecStripped] = new List<DesktopItem> ();
						ItemsByExec [vexecStripped].Add (item);
					}
				}
			}
		}
        void BuildExecStrings()
        {
            ItemsByExec = new Dictionary <string, List <DesktopItem> > ();

            foreach (DesktopItem item in DesktopItems)
            {
                if (item == null || item.Ignored || !item.HasAttribute("Exec"))
                {
                    continue;
                }

                string exec  = item.GetString("Exec").Trim();
                string vexec = null;

                // for openoffice
                if (exec.Contains(' ') &&
                    (exec.StartsWith("ooffice") || exec.StartsWith("openoffice") || exec.StartsWith("soffice") ||
                     exec.Contains("/ooffice ") || exec.Contains("/openoffice.org ") || exec.Contains("/soffice ")))
                {
                    vexec = "ooffice" + exec.Split(' ')[1];
                    vexec = vexec.Replace("--", "-");

                    // for libreoffice
                }
                else if (exec.Contains(' ') &&
                         (exec.StartsWith("libreoffice")))
                {
                    vexec = "libreoffice" + exec.Split(' ')[1];
                    vexec = vexec.Replace("--", "-");

                    // for wine apps
                }
                else if ((exec.Contains("env WINEPREFIX=") && exec.Contains(" wine ")) ||
                         exec.Contains("wine "))
                {
                    int startIndex = exec.IndexOf("wine ") + 5;
                    // length of 'wine '
                    // CommandLineForPid already splits based on \\ and takes the last entry, so do the same here
                    vexec = exec.Substring(startIndex).Split(new[] { @"\\" }, StringSplitOptions.RemoveEmptyEntries).Last();
                    // remove the trailing " and anything after it
                    if (vexec.Contains("\""))
                    {
                        vexec = vexec.Substring(0, vexec.IndexOf("\""));
                    }

                    // for crossover apps
                }
                else if (exec.Contains(".cxoffice") || (item.HasAttribute("X-Created-By") && item.GetString("X-Created-By").Contains("cxoffice")))
                {
                    // The exec is actually another file that uses exec to launch the actual app.
                    exec = exec.Replace("\"", "");

                    GLib.File launcher = GLib.FileFactory.NewForPath(exec);
                    if (!launcher.Exists)
                    {
                        Log <DesktopItemService> .Warn("Crossover launcher decoded as: {0}, but does not exist.", launcher.Path);

                        continue;
                    }

                    string execLine = "";
                    using (GLib.DataInputStream stream = new GLib.DataInputStream(launcher.Read(null))) {
                        ulong  len;
                        string line;
                        try {
                            while ((line = stream.ReadLine(out len, null)) != null)
                            {
                                if (line.StartsWith("exec"))
                                {
                                    execLine = line;
                                    break;
                                }
                            }
                        } catch (Exception e) {
                            Log <DesktopItemService> .Error("Error reading crossover launher: {0}", e.Message);

                            Log <DesktopItemService> .Error(e.StackTrace);

                            continue;
                        }
                    }

                    // if no exec line was found, bail
                    if (string.IsNullOrEmpty(execLine))
                    {
                        continue;
                    }

                    // get the relevant part from the execLine
                    string[] parts = execLine.Split(new[] { '\"' });
                    // find the part that contains C:/path/to/app.lnk
                    if (parts.Any(part => part.StartsWith("C:")))
                    {
                        vexec = parts.First(part => part.StartsWith("C:"));
                        // and take only app.lnk (this is what is exposed to ps -ef)
                        vexec = ExecForPath(vexec);
                    }
                    else
                    {
                        continue;
                    }

                    // other apps
                }
                else
                {
                    string[] parts = exec.Split(' ');

                    vexec = parts
                            .DefaultIfEmpty(null)
                            .Select(part => ExecForPath(part))
                            .Where(part => !DockServices.WindowMatcher.PrefixFilters.Any(f => f.IsMatch(part)))
                            .FirstOrDefault();

                    // for AIR apps
                    if (vexec != null && vexec.Contains('\''))
                    {
                        vexec = vexec.Replace("'", "");
                    }
                }

                if (vexec == null)
                {
                    continue;
                }

                if (!ItemsByExec.ContainsKey(vexec))
                {
                    ItemsByExec [vexec] = new List <DesktopItem> ();
                }

                ItemsByExec [vexec].Add(item);
                foreach (Regex f in DockServices.WindowMatcher.SuffixFilters)
                {
                    if (f.IsMatch(vexec))
                    {
                        string vexecStripped = f.Replace(vexec, "");
                        if (!ItemsByExec.ContainsKey(vexecStripped))
                        {
                            ItemsByExec [vexecStripped] = new List <DesktopItem> ();
                        }
                        ItemsByExec [vexecStripped].Add(item);
                    }
                }
            }
        }
		public override bool RemoveItem (AbstractDockItem item)
		{
			if (!ItemCanBeRemoved (item))
				return false;
			
			FileDockItem bookmark = item as FileDockItem;
			
			if (!bookmark.OwnedFile.Exists)
				return false;
			
			File tempFile = FileFactory.NewForPath (System.IO.Path.GetTempFileName ());
			
			using (DataInputStream reader = new DataInputStream (BookmarksFile.Read (null))) {
				using (DataOutputStream writer = new DataOutputStream (tempFile.AppendTo (FileCreateFlags.None, null))) {
					string line;
					ulong length;
					while ((line = reader.ReadLine (out length, null)) != null) {
						if (line.Split (' ')[0] != bookmark.Uri) {
							writer.PutString (string.Format ("{0}{1}", line, reader.NewLineString ()), null);
						} else {
							items.Remove (bookmark);
							Items = InnerItems;
							Log<BookmarksItemProvider>.Debug ("Removing '{0}'", bookmark.HoverText);
						}
					}
				}
			}
			
			if (tempFile.Exists)
				tempFile.Move (BookmarksFile, FileCopyFlags.Overwrite, null, null);

			return true;
		}
		protected override AbstractDockItem OnAcceptDrop (string uri)
		{
			File tempFile = FileFactory.NewForPath (System.IO.Path.GetTempFileName ());
			FileDockItem bookmark = FileDockItem.NewFromUri (uri);
			
			// make sure the bookmarked location actually exists
			if (!bookmark.OwnedFile.Exists)
				return null;
			
			using (DataInputStream reader = new DataInputStream (BookmarksFile.Read (null))) {
				using (DataOutputStream writer = new DataOutputStream (tempFile.AppendTo (FileCreateFlags.None, null))) {
					string line;
					ulong length;
					while ((line = reader.ReadLine (out length, null)) != null)
						writer.PutString (string.Format ("{0}{1}", line, reader.NewLineString ()), null);
					
					writer.PutString (string.Format ("{0}{1}", bookmark.Uri, reader.NewLineString ()), null);
				}
			}
			
			items.Add (bookmark);
			Items = InnerItems;
			
			if (tempFile.Exists)
				tempFile.Move (BookmarksFile, FileCopyFlags.Overwrite, null, null);
			
			return bookmark;
		}
		void UpdateItems ()
		{
			List<AbstractDockItem> old = items;
			items = new List<AbstractDockItem> ();
			
			Log<BookmarksItemProvider>.Debug ("Updating bookmarks.");
			
			if (!BookmarksFile.QueryExists (null)) {
				Log<BookmarksItemProvider>.Error ("File '{0} does not exist.", BookmarksFile);
				return;
			}
			
			using (DataInputStream stream = new DataInputStream (BookmarksFile.Read (null))) {
				ulong length;
				string line, name, uri;
				while ((line = stream.ReadLine (out length, null)) != null) {
					uri = line.Split (' ').First ();
					File bookmark = FileFactory.NewForUri (uri);
					name = line.Substring (uri.Length).Trim ();
					if (old.Cast<FileDockItem> ().Any (fdi => fdi.Uri == uri)) {
						FileDockItem item = old.Cast<FileDockItem> ().First (fdi => fdi.Uri == uri);
						old.Remove (item);
						items.Add (item);
						item.ForcedHoverText = name;
					} else if (bookmark.StringUri ().StartsWith ("file://") && !bookmark.Exists) {
						Log<BookmarksItemProvider>.Warn ("Bookmark path '{0}' does not exist, please fix the bookmarks file", bookmark.StringUri ());
						continue;
					} else {
						FileDockItem item = FileDockItem.NewFromUri (bookmark.StringUri (), name, "folder");
						if (item != null)
							items.Add (item);
					}
				}
			}
			
			Items = InnerItems;
			
			foreach (AbstractDockItem item in old)
				item.Dispose ();
		}