Copy/Paste only to same application instance

Hi,
We want to control paste operation such a way that it only works if copy is done from same application instance. If I am running two instances 1 and 2 of an application, If I do copy from instance 1, I should not be able to past it on instance 2. This is done for stick IP protection reasons, not allowing user with access to two different systems, copy from one to another system.

Well, I’m not a security expert, but I can see at least two ways of doing this.

First, adding some tag to the clipboard (e.g. a GUID) on a Copy and only allowing a Paste if the application recognizes the GUID.

Second, doing some form of encryption on the data in the clipboard that only the source app can decode.

The first would prevent Paste as long as all the apps were being friendly. It wouldn’t prevent an app from ignoring the GUID and doing a paste.

The second would in theory even prevent malicious apps from stealing data.

Which are we talking about here?

We are talking about putting GUID type of approach here. We use _GoView.EditCopy(); and _GoView.EditCut(); _GoView.EditPaste();commands for copy/cut/paste.Can you suggest how I can overwrite these to say putting some identifier in the buffer in addition to what is being done by default EditCopy() command and extract that during paste command.

Can you please provide some example code on how I can overwrite EditCopy() and EditPaste() methods of goview to just add an additional guid during copy and check that during the paste() operation?

I suggest overriding GoView.CopyToClipboard and GoView.PasteFromClipboard so that they do not operate with the Windows Clipboard, but just with a global variable in memory.

Declare this global variable to act as the in-memory clipboard:

    private static Dictionary<String, GoDocument> myClipboard = new Dictionary<String, GoDocument>();  // simulate Clipboard

Override GoView.CopyToClipboard:

  public override void CopyToClipboard(IGoCollection coll) {
    if (coll == null || coll.IsEmpty) {
      myClipboard.Clear();
    } else {
      GoDocument thisdoc = this.Document;
      if (thisdoc != null) {
        Type doctype = thisdoc.GetType();
        GoDocument clipdoc = (GoDocument)Activator.CreateInstance(doctype);
        // don't need to worry about undo/redo
        clipdoc.UndoManager = null;
        // make sure the clipdoc has the same layers as the view's document,
        // but not the same document objects in those layers
        clipdoc.MergeLayersFrom(thisdoc);
        // now copy selected objects, making sure they go in Z-order
        GoCollection sorted = new GoCollection();
        sorted.InternalChecksForDuplicates = false;
        sorted.AddRange(coll);
        thisdoc.Layers.SortByZOrder(sorted);
        clipdoc.CopyFromCollection(sorted, true, true, new SizeF(), null);
        // and set up the clipboard
        myClipboard.Clear();
        myClipboard[clipdoc.DataFormat] = clipdoc;
      }
    }
  }

Override GoView.PasteFromClipboard:

    public override GoCopyDictionary PasteFromClipboard() {
      GoDocument thisdoc = this.Document;
      if (thisdoc == null)
        return null;
      GoDocument clipdoc = null;
      myClipboard.TryGetValue(thisdoc.DataFormat, out clipdoc);
      if (clipdoc != null) {
        return thisdoc.CopyFromCollection(clipdoc, false, false, new SizeF(1, 1), null);
      }
      return null;
    }

Oh, also:

    public override bool CanEditPaste() {
      if (!CanInsertObjects()) return false;
      GoDocument thisdoc = this.Document;
      if (thisdoc == null) return false;
      return myClipboard.ContainsKey(thisdoc.DataFormat);
    }

Hi,
We have implemented above suggestion, but it ran into an issue where original/source links are endsup getting same PartID. See attached picture where 1. two nodes and a link with PartID=6 is copied and pasted in same document, document ends up with two links with PartID=9. Once we reopen the doc, source link disappears and two links are drawn on top of eachother on the copied nodes as shown in the attached picture.

Only thing different from above code is following property is not set as InternalChecksForDuplicates is marked as internal property, so it's not accessible. This is Northwoods.Go version# 6.1.0.47
  //sorted.InternalChecksForDuplicates = false;	//Cannot set as it's marked as internal

Note: Copy/Paste of Nodes are working as expected. Issue is with Links only.

Let’s try another approach.

You would have to do some testing to prove this works in all cases, but I can’t break it. This clears the clipboard anytime the app loses focus or is minimized.

The little beep is just feedback to tell you it has cleared the clipboard. Probably want to remove that after testing.

Add this event handler to the main form:

private void MainForm_Deactivate(object sender, EventArgs e)
{
  Console.Beep(800, 200);
  Clipboard.Clear();
}

Jake

Jake,
Almost worked except the case where I open two RDP(Remote Desktop) sessions to two different machines and copy from one and paste to another. In this case app does not get deactivated in each RDP session as you are just switching tab in the RDP host program. It works perfectly fine on same machine.

image

Following approach worked where I ended up using default CopyToClipboard/PasteFromClipboard methods to let it do most of the work and then copy contents from global to local clipboard. This seems to avoid link duplicate ID issue and prevent copying between two instances of the app.

CopyToClipboard overwrite:

  1. Call base base.CopyToClipboard
  2. Copy the contents from global clipboard to local clipboard
  3. Clear global clipboard

PasteFromClipboard overwrite:

  1. Get data from local clipboard and set to global clipboard

  2. Call base.PasteFromClipboard()

  3. Clear global clipboard

    public override void CopyToClipboard(IGoCollection collection)
    {
            //Call default copy
            base.CopyToClipboard(collection);
    
            //Copy to local clipboard
            string dataFormatType = thisdoc.GetType().ToString();
            _LocalClipboard.Clear();
            _LocalClipboard.Add(dataFormatType, (GoDocument)Clipboard.GetData(dataFormatType));
    
            //clear global clipboard
            Clipboard.Clear();
    }
    
    public override GoCopyDictionary PasteFromClipboard()
    {
            //Custom Behavior
            GoDocument thisdoc = this.Document;
            if (thisdoc == null)
                 return null;
    
            GoDocument localClipDoc = null;
            _LocalClipboard.TryGetValue(thisdoc.DataFormat, out localClipDoc);
            if (localClipDoc != null)
            {
                            //Set data from local Clipboard to GlobalClipboard
                            Clipboard.Clear();
                            Clipboard.SetData(localClipDoc.DataFormat, localClipDoc);
    
                            //Call default paste         
                            GoCopyDictionary retDict = base.PasteFromClipboard();
                                                            
                            //Clear Global Clipboard
                            Clipboard.Clear();
                                                            
                            return retDict;
            } 
    
            return null;
    }
    
    public override bool CanEditPaste()
    {
            //Custom Behavior
            if (!CanInsertObjects())
                   return false;
    
            GoDocument thisdoc = this.Document;
            if (thisdoc == null)
                            return false;
    
            return _LocalClipboard.ContainsKey(thisdoc.DataFormat);
    }