~ifolder-dev/simias/trunk-packaging

« back to all changes in this revision

Viewing changes to src/core/Sync/.svn/text-base/SyncFile.cs.svn-base

  • Committer: Jorge O. Castro
  • Date: 2007-12-03 06:56:46 UTC
  • Revision ID: jorge@ubuntu.com-20071203065646-mupcnjcwgm5mnhyt
* Remove a bunch of .svn directories we no longer need.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/****************************************************************************
2
 
 |
3
 
 | Copyright (c) 2007 Novell, Inc.
4
 
 | All Rights Reserved.
5
 
 |
6
 
 | This program is free software; you can redistribute it and/or
7
 
 | modify it under the terms of version 2 of the GNU General Public License as
8
 
 | published by the Free Software Foundation.
9
 
 |
10
 
 | This program is distributed in the hope that it will be useful,
11
 
 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 | GNU General Public License for more details.
14
 
 |
15
 
 | You should have received a copy of the GNU General Public License
16
 
 | along with this program; if not, contact Novell, Inc.
17
 
 |
18
 
 | To contact Novell about this file by physical or electronic mail,
19
 
 | you may find current contact information at www.novell.com 
20
 
 |
21
 
 | Author: Russ Young
22
 
 |***************************************************************************/
23
 
 
24
 
 
25
 
using System;
26
 
using System.IO;
27
 
using System.Text;
28
 
using System.Threading;
29
 
using System.Collections;
30
 
using System.Security.Cryptography;
31
 
using Simias.Storage;
32
 
using Simias.Event;
33
 
using Simias.Sync.Delta;
34
 
using Simias.Client;
35
 
 
36
 
#if MONO
37
 
#if MONONATIVE
38
 
        // This is used if configure.in detected mono 1.1.13 or newer
39
 
        using Mono.Unix.Native;
40
 
#else
41
 
        using Mono.Unix;
42
 
#endif
43
 
#endif
44
 
 
45
 
namespace Simias.Sync
46
 
{
47
 
        #region OutFile
48
 
 
49
 
        /// <summary>
50
 
        /// Class to handle file operations for a file to be synced out.
51
 
        /// </summary>
52
 
        public abstract class OutFile : SyncFile
53
 
        {
54
 
                #region fields
55
 
 
56
 
                StreamStream    workStream;
57
 
 
58
 
                /// <summary>
59
 
                /// Gets the output stream.
60
 
                /// </summary>
61
 
                protected StreamStream OutStream
62
 
                {
63
 
                        get { return workStream; }
64
 
                }
65
 
 
66
 
                #endregion
67
 
                
68
 
                #region Constructor / Finalizer
69
 
 
70
 
                /// <summary>
71
 
                /// Constructs an OutFile object.
72
 
                /// </summary>
73
 
                /// <param name="collection">The collection that the node belongs to.</param>
74
 
                protected OutFile(Collection collection) :
75
 
                        base(collection)
76
 
                {
77
 
                }
78
 
 
79
 
                /// <summary>
80
 
                /// Finalizer.
81
 
                /// </summary>
82
 
                ~OutFile()
83
 
                {
84
 
                        Close (true);
85
 
                }
86
 
 
87
 
                #endregion
88
 
 
89
 
                #region public methods.
90
 
 
91
 
                /// <summary>
92
 
                /// Reads data into the buffer.
93
 
                /// </summary>
94
 
                /// <param name="stream">The stream to read into.</param>
95
 
                /// <param name="count">The number of bytes to read.</param>
96
 
                /// <returns></returns>
97
 
                public int Read(Stream stream, int count)
98
 
                {
99
 
                        try
100
 
                        {
101
 
                                //Log.log.Debug("Reading File {0} : offset = {1}", file, ReadPosition);
102
 
                                return workStream.Read(stream, count);
103
 
                        }
104
 
                        catch (Exception ex)
105
 
                        {
106
 
                                Log.log.Debug(ex, "Failed Reading {0}", file);
107
 
                                throw ex;
108
 
                        }
109
 
                }
110
 
 
111
 
                /// <summary>
112
 
                /// Get the platform file handle.
113
 
                /// </summary>
114
 
                public StreamStream outStream
115
 
                {
116
 
                        get {return workStream;}
117
 
                }
118
 
 
119
 
 
120
 
                /// <summary>
121
 
                /// Gets or Sets the file position.
122
 
                /// </summary>
123
 
                public long ReadPosition
124
 
                {
125
 
                        get { return workStream.Position; }
126
 
                        set { workStream.Position = value; }
127
 
                }
128
 
 
129
 
                /// <summary>
130
 
                /// Gets the length of the stream.
131
 
                /// </summary>
132
 
                public long Length
133
 
                {
134
 
                        get { return workStream.Length; }
135
 
                }
136
 
 
137
 
                #endregion
138
 
 
139
 
                #region protected methods.
140
 
 
141
 
                /// <summary>
142
 
                /// Called to open the file.
143
 
                /// </summary>
144
 
                /// <param name="node">The node that represents the file.</param>
145
 
                /// <param name="sessionID">The unique session ID.</param>
146
 
                protected void Open(BaseFileNode node, string sessionID)
147
 
                {
148
 
                        SetupFileNames(node, sessionID);
149
 
                        Log.log.Debug("Opening File {0}", file);
150
 
                        FileInfo fi = new FileInfo(file);
151
 
                        if (Store.IsEnterpriseServer || fi.Length > (1024 * 100000))
152
 
                        {
153
 
                                workStream = new StreamStream(File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read));
154
 
                                workFile = null;
155
 
                        }
156
 
                        else
157
 
                        {
158
 
                                // This file is being pushed make a copy to work from.
159
 
                                File.Copy(file, workFile, true);
160
 
                                File.SetAttributes(workFile, FileAttributes.Normal);
161
 
                                workStream = new StreamStream(File.Open(workFile, FileMode.Open, FileAccess.Read));
162
 
                        }
163
 
                }
164
 
 
165
 
                /// <summary>
166
 
                /// Called to create the hash map for the uploaded file.
167
 
                /// </summary>
168
 
                public void CreateHashMap()
169
 
                {
170
 
                        map.CreateHashMapFile();
171
 
                }
172
 
 
173
 
                /// <summary>
174
 
                /// Called to delete the hash map since it is not stored in the simias client
175
 
                /// </summary>
176
 
                public void DeleteHashMap()
177
 
                {
178
 
                        map.Delete();
179
 
                }
180
 
 
181
 
                /// <summary>
182
 
                /// Called to get the hash map stream for the uploaded file.
183
 
                /// </summary>
184
 
                public FileStream GetHashMap(out int entryCount, out int blockSize)
185
 
                {
186
 
                        //TBD find out why old node was used in server 
187
 
                        //arg. false, here the create hash map is obtained
188
 
                        return map.GetHashMapStream(out entryCount, out blockSize, false, node.LocalIncarnation);
189
 
                }
190
 
 
191
 
                /// <summary>
192
 
                /// Called to close the file and cleanup resources.
193
 
                /// </summary>
194
 
                protected void Close()
195
 
                {
196
 
                        Log.log.Debug("Closing File {0}", file);
197
 
                        Close (false);
198
 
                }
199
 
                
200
 
                #endregion
201
 
 
202
 
                #region private methods.
203
 
 
204
 
                /// <summary>
205
 
                /// Called to close the file and cleanup.
206
 
                /// </summary>
207
 
                /// <param name="InFinalizer">true if called from the finalizer.</param>
208
 
                private void Close(bool InFinalizer)
209
 
                {
210
 
                        if (!InFinalizer)
211
 
                                GC.SuppressFinalize(this);
212
 
 
213
 
                        if (workStream != null)
214
 
                        {
215
 
                                workStream.Close();
216
 
                                workStream = null;
217
 
                        }
218
 
                        // We need to delete the temp file.
219
 
                        if (workFile != null)
220
 
                                File.Delete(workFile);
221
 
                }
222
 
 
223
 
                #endregion
224
 
        }
225
 
 
226
 
        #endregion
227
 
 
228
 
        #region InFile
229
 
 
230
 
        /// <summary>
231
 
        /// Class to handle files that are being imported.
232
 
        /// </summary>
233
 
        public abstract class InFile : SyncFile
234
 
        {
235
 
                #region fields
236
 
 
237
 
                /// <summary>Stream to the Incoming file.</summary>
238
 
                StreamStream    workStream;
239
 
                /// <summary>Stream to the Original file.</summary>
240
 
                FileStream              stream;
241
 
                /// <summary>The partially downloaded file.</summary>
242
 
                string                  partialFile;
243
 
                /// <summary>The Old Node if it exists.</summary>
244
 
                protected BaseFileNode  oldNode;
245
 
                                
246
 
                #endregion
247
 
                
248
 
                #region Constructor / Finalizer.
249
 
 
250
 
                /// <summary>
251
 
                /// Constructs an InFile object.
252
 
                /// </summary>
253
 
                /// <param name="collection">The collection that the node belongs to.</param>
254
 
                protected InFile(Collection collection) :
255
 
                        base(collection)
256
 
                {
257
 
                }
258
 
 
259
 
                /// <summary>
260
 
                /// Finalizer.
261
 
                /// </summary>
262
 
                ~InFile()
263
 
                {
264
 
                        Close (true, false);
265
 
                }
266
 
 
267
 
                #endregion
268
 
 
269
 
                #region public methods.
270
 
 
271
 
                /// <summary>
272
 
                /// Reads data into the buffer.
273
 
                /// </summary>
274
 
                /// <param name="buffer">The buffer to read into.</param>
275
 
                /// <param name="offset">The offset in the buffer to read into.</param>
276
 
                /// <param name="count">The number of bytes to read.</param>
277
 
                /// <returns></returns>
278
 
                public int Read(byte[] buffer, int offset, int count)
279
 
                {
280
 
                        if (stream != null)     return stream.Read(buffer, offset, count);
281
 
                        else return 0;
282
 
                }
283
 
 
284
 
                /// <summary>
285
 
                /// Writes data from buffer into file.
286
 
                /// </summary>
287
 
                /// <param name="stream">The stream to write.</param>
288
 
                /// <param name="count">The number of bytes to write.</param>
289
 
                public void Write(Stream stream, int count)
290
 
                {
291
 
                        //Log.log.Debug("Writing File {0} : offset = {1}", file, WritePosition);
292
 
                        workStream.Write(stream, count);
293
 
                }
294
 
                
295
 
                // BUGBUG Encryption Here.
296
 
                // Add decryption here.
297
 
                /// <summary>
298
 
                /// Writes data from buffer into file.
299
 
                /// </summary>
300
 
                /// <param name="stream">The stream to write.</param>
301
 
                /// <param name="count">The number of bytes to write.</param>
302
 
                /// <param name="count">The encryption Key.</param>
303
 
                public int Write(Stream stream, int count,  int actualCount, string encryptionAlgorithm, string encryptionKey)
304
 
                {
305
 
                        workStream.Write(stream, count, actualCount, encryptionAlgorithm, encryptionKey);
306
 
                        return -1;
307
 
                }
308
 
                
309
 
 
310
 
                /// <summary>
311
 
                /// Copyt the data from the original file into the new file.
312
 
                /// </summary>
313
 
                /// <param name="originalOffset">The offset in the original file to copy from.</param>
314
 
                /// <param name="offset">The offset in the file where the data is to be written.</param>
315
 
                /// <param name="count">The number of bytes to write.</param>
316
 
                public void Copy(long originalOffset, long offset, int count)
317
 
                {
318
 
                        lock (this)
319
 
                        {
320
 
                                ReadPosition = originalOffset;
321
 
                                WritePosition = offset;
322
 
                                workStream.Write(stream, count);
323
 
                        }
324
 
                }
325
 
 
326
 
                /// <summary>
327
 
                /// Set the Length of the file.
328
 
                /// </summary>
329
 
                /// <param name="length">The size to set.</param>
330
 
                public void SetLength(long length)
331
 
                {
332
 
                        workStream.SetLength(length);
333
 
                }
334
 
                
335
 
                /// <summary>
336
 
                /// Get the stream.
337
 
                /// </summary>
338
 
                public StreamStream inStream
339
 
                {
340
 
                        get {return workStream;}
341
 
                }
342
 
 
343
 
                /// <summary>
344
 
                /// Gets the original stream.
345
 
                /// </summary>
346
 
                public FileStream ReadStream
347
 
                {
348
 
                        get {return stream;}
349
 
                }
350
 
 
351
 
 
352
 
                /// <summary>
353
 
                /// Gets or Sets the file position.
354
 
                /// </summary>
355
 
                public long ReadPosition
356
 
                {
357
 
                        get { return (stream == null ? 0 : stream.Position); }
358
 
                        set { if (stream != null) stream.Position = value; }
359
 
                }
360
 
 
361
 
                /// <summary>
362
 
                /// Gets or Sets the file position.
363
 
                /// </summary>
364
 
                public long WritePosition
365
 
                {
366
 
                        get { return workStream.Position; }
367
 
                        set { workStream.Position = value; }
368
 
                }
369
 
 
370
 
                /// <summary>
371
 
                /// Gets the length of the stream.
372
 
                /// </summary>
373
 
                public long Length
374
 
                {
375
 
                        get { return node.Length; }
376
 
                }
377
 
                
378
 
                #endregion
379
 
 
380
 
                #region protected methods.
381
 
 
382
 
                /// <summary>
383
 
                /// Called to open the file.
384
 
                /// </summary>
385
 
                /// <param name="node">The node that represents the file.</param>
386
 
                protected void Open(BaseFileNode node)
387
 
                {
388
 
                        SetupFileNames(node, "");
389
 
                        CheckForNameConflict();
390
 
                        Log.log.Debug("Opening File {0}", file);
391
 
                        // Open the file so that it cannot be modified.
392
 
                        oldNode = collection.GetNodeByID(node.ID) as BaseFileNode;
393
 
                        try
394
 
                        {
395
 
                                if (!NameConflict)
396
 
                                {
397
 
                                        stream = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.None);
398
 
                                }
399
 
                        }
400
 
                        catch (FileNotFoundException)
401
 
                        {
402
 
                                // Check to see if we have a partially downloaded file to delta sync with.
403
 
                                if (collection.Role == SyncRoles.Slave && File.Exists(workFile))
404
 
                                {
405
 
                                        if (File.Exists(partialFile))
406
 
                                                File.Delete(partialFile);
407
 
                                        partialFile = workFile + ".part";
408
 
                                        File.Move(workFile, partialFile);
409
 
                                        stream = File.Open(partialFile, FileMode.Open, FileAccess.Read, FileShare.None);
410
 
                                }
411
 
                                else if (oldNode != null)
412
 
                                {
413
 
                                        // The file may have been renamed.
414
 
                                        string oldPath = oldNode.GetFullPath(collection);
415
 
                                        if (oldPath != file)
416
 
                                                stream = File.Open(oldPath, FileMode.Open, FileAccess.Read, FileShare.None);
417
 
                                }
418
 
                        }
419
 
                        // Create the file in the parent directory and then move to the work area.
420
 
                        // This will insure that the proper attributes are set.
421
 
                        // This was added to support EFS (Encrypted File System).
422
 
                        string createName = Path.Combine(Path.GetDirectoryName(file), Path.GetFileName(workFile));
423
 
                        FileStream tmpStream = File.Open(createName, FileMode.Create, FileAccess.ReadWrite, FileShare.None);
424
 
                        if (File.Exists(workFile))
425
 
                        {
426
 
                                File.Delete(workFile);
427
 
                        }
428
 
                        // Make sure we have enough space for the file.
429
 
                        try
430
 
                        {
431
 
                                tmpStream.SetLength(node.Length);
432
 
                                tmpStream.Close();
433
 
                                tmpStream = null;
434
 
#if MONO
435
 
                                if (MyEnvironment.Unix)
436
 
                                {
437
 
                                        if (node.Properties.GetSingleProperty(SyncFile.ModeProperty) != null)
438
 
                                        {
439
 
                                                // Get the posix mode flags for the file.
440
 
                                                Stat sStat;
441
 
                                                if (Syscall.stat(createName, out sStat) == 0)
442
 
                                                {
443
 
                                                        // Now or in the execute bit and set it on the file.
444
 
                                                        FilePermissions fp = sStat.st_mode | FilePermissions.S_IXUSR;
445
 
                                                        Syscall.chmod(createName, fp);
446
 
                                                }
447
 
                                        }
448
 
                                }
449
 
#endif 
450
 
 
451
 
                                File.Move(createName, workFile);
452
 
                        }
453
 
                        catch (IOException)
454
 
                        {
455
 
                                if (tmpStream != null)
456
 
                                        tmpStream.Close();
457
 
                                throw new InsufficientStorageException();
458
 
                        }
459
 
                        workStream = new StreamStream(File.Open(workFile, FileMode.Truncate, FileAccess.ReadWrite, FileShare.None));
460
 
                }
461
 
 
462
 
                /// <summary>
463
 
                /// Called to close the file and cleanup resources.
464
 
                /// </summary>
465
 
                protected void Close(bool commit)
466
 
                {
467
 
                        Log.log.Debug("Closing File {0}", file);
468
 
                        Close (false, commit);
469
 
                }
470
 
 
471
 
                #endregion
472
 
 
473
 
                #region private methods.
474
 
 
475
 
                /// <summary>
476
 
                /// Called to cleanup any resources and close the file.
477
 
                /// </summary>
478
 
                /// <param name="InFinalizer"></param>
479
 
                /// <param name="commit"></param>
480
 
                private void Close(bool InFinalizer, bool commit)
481
 
                {
482
 
                        if (!InFinalizer)
483
 
                        {
484
 
                                GC.SuppressFinalize(this);
485
 
                        }
486
 
                        if (stream != null)
487
 
                        {
488
 
                                stream.Close();
489
 
                                stream = null;
490
 
                        }
491
 
                        if (workStream != null)
492
 
                        {
493
 
                                workStream.Close();
494
 
                                workStream = null;
495
 
                        }
496
 
                        if (commit)
497
 
                        {
498
 
                                if (File.Exists(file))
499
 
                                {
500
 
                                        string tmpFile = file + ".~stmp";
501
 
                                        File.Move(file, tmpFile);
502
 
                                        try
503
 
                                        {
504
 
                                                File.Move(workFile, file);
505
 
                                                File.Delete(tmpFile);
506
 
                                                workFile = null;        
507
 
                                        }
508
 
                                        catch
509
 
                                        {
510
 
                                                File.Move(tmpFile, file);
511
 
                                                throw;
512
 
                                        }
513
 
                                }
514
 
                                else
515
 
                                {
516
 
                                        File.Move(workFile, file);
517
 
                                        workFile = null;
518
 
                                }
519
 
                                FileInfo fi = new FileInfo(file);
520
 
                                fi.LastWriteTime = node.LastWriteTime;
521
 
                                fi.CreationTime = node.CreationTime;
522
 
                                if (oldNode != null)
523
 
                                {
524
 
                                        // Check if this was a rename.
525
 
                                        // If the old path does not equal the new path
526
 
                                        // Delete the old file.
527
 
                                        string oldPath = oldNode.GetFullPath(collection);
528
 
                                        try
529
 
                                        {
530
 
                                                if (MyEnvironment.Windows)
531
 
                                                {
532
 
                                                        if (string.Compare(oldPath, file, true) != 0)
533
 
                                                                File.Delete(oldPath);
534
 
                                                }
535
 
                                                else
536
 
                                                {
537
 
                                                        if (oldPath != file)
538
 
                                                                File.Delete(oldPath);
539
 
                                                }
540
 
                                        }
541
 
                                        catch {};
542
 
                                }
543
 
                        }
544
 
 
545
 
                        // We need to delete the temp file if we are the master.
546
 
                        // On the client leave for a delta sync.
547
 
                        if (workFile != null)
548
 
                        {
549
 
                                if (collection.Role == SyncRoles.Master || (collection.Role == SyncRoles.Slave && File.Exists(file)))
550
 
                                {
551
 
                                        File.Delete(workFile);
552
 
                                }
553
 
                        }
554
 
 
555
 
                        if (partialFile != null)
556
 
                                File.Delete(partialFile);
557
 
                }
558
 
 
559
 
                #endregion
560
 
        }
561
 
 
562
 
        #endregion
563
 
 
564
 
        #region SyncFile
565
 
 
566
 
        /// <summary>
567
 
        /// Class used to determine the common data between two files.
568
 
        /// This is done from a copy of the local file and a map of hash code for the server file.
569
 
        /// </summary>
570
 
        public abstract class SyncFile
571
 
        {
572
 
                #region fields
573
 
 
574
 
                bool                                    nameConflict = false;
575
 
                bool                                    dateConflict = false;
576
 
                protected Node                  conflictingNode = null;
577
 
                /// <summary>Used to signal to stop upload or downloading the file.</summary>
578
 
                protected bool                  stopping = false;
579
 
                /// <summary>The Collection the file belongs to.</summary>
580
 
                protected Collection    collection;
581
 
                /// <summary> The node that represents the file.</summary>
582
 
                protected BaseFileNode  node;
583
 
                /// <summary>The ID of the node.</summary>
584
 
                protected string                nodeID;
585
 
                /// <summary>The maximun size of a transfer.</summary>
586
 
                protected const int             MaxXFerSize = 1024 * 256;
587
 
                /// <summary>The name of the actual file.</summary>
588
 
                protected string                file;
589
 
                /// <summary>The name of the working file.</summary>
590
 
                protected string                workFile;
591
 
                /// <summary>
592
 
                /// The HashMap for this file.
593
 
                /// </summary>
594
 
                protected HashMap               map;
595
 
                /// <summary>The Prefix of the working file.</summary>
596
 
                const string                    WorkFilePrefix = ".simias.wf.";
597
 
                static string                   workBinDir = "WorkArea";
598
 
                static string                   workBin;
599
 
                // '/' is left out on purpose because all systems disallow this char.
600
 
                public static char[] InvalidChars = {'\\', ':', '*', '?', '\"', '<', '>', '|'};
601
 
 
602
 
                /// <summary>Used to publish Sync events.</summary>
603
 
                static public                   EventPublisher  eventPublisher = new EventPublisher();
604
 
                static internal string  ModeProperty = "FAMode";
605
 
                [Flags]
606
 
                public enum FAMode
607
 
                {
608
 
                        None = 0,
609
 
                        Execute = 1,
610
 
                };
611
 
                
612
 
                #endregion
613
 
 
614
 
                #region protected methods.
615
 
 
616
 
                /// <summary>
617
 
                /// 
618
 
                /// </summary>
619
 
                /// <param name="collection">The collection that the node belongs to.</param>
620
 
                protected SyncFile(Collection collection)
621
 
                {
622
 
                        this.collection = collection;
623
 
                }
624
 
 
625
 
                /// <summary>
626
 
                /// Called to get the name of the file and workFile;
627
 
                /// </summary>
628
 
                /// <param name="node">The node that represents the file.</param>
629
 
                /// <param name="sessionID">The unique session ID.</param>
630
 
                protected void SetupFileNames(BaseFileNode node, string sessionID)
631
 
                {
632
 
                        this.node = node;
633
 
                        this.nodeID = node.ID;
634
 
                        try
635
 
                        {
636
 
                                this.file = node.GetFullPath(collection);
637
 
                        }
638
 
                        catch
639
 
                        {
640
 
                                // If this failed the file name has illegal characters.
641
 
                                nameConflict = true;
642
 
                        }
643
 
                        if (workBin == null)
644
 
                        {
645
 
                                workBin = Path.Combine(collection.StorePath, workBinDir);
646
 
                                if (!Directory.Exists(workBin))
647
 
                                        Directory.CreateDirectory(workBin);
648
 
                        }
649
 
                        this.workFile = Path.Combine(workBin, WorkFilePrefix + node.ID + sessionID);
650
 
                }
651
 
 
652
 
                /// <summary>
653
 
                /// Checks for a name conflict.
654
 
                /// </summary>
655
 
                /// <returns>True if conflict.</returns>
656
 
                protected bool CheckForNameConflict()
657
 
                {
658
 
                        if (!NameConflict)
659
 
                        {
660
 
                                // Look up the FsPath property (StoreFileNodes don't have this property set).
661
 
                                Property property = node.Properties.GetSingleProperty(PropertyTags.FileSystemPath);
662
 
                                if (property != null)
663
 
                                {
664
 
                                        string path = property.Value.ToString();
665
 
                                        ICSList nodeList;
666
 
                                        nodeList = collection.Search(PropertyTags.FileSystemPath, path, SearchOp.Equal);
667
 
                                        foreach (ShallowNode sn in nodeList)
668
 
                                        {
669
 
                                                if (sn.ID != node.ID)
670
 
                                                {
671
 
                                                        conflictingNode = collection.GetNodeByID(sn.ID);
672
 
                                                        nameConflict = true;
673
 
                                                        break;
674
 
                                                }
675
 
                                        }
676
 
                                        // Now make sure we don't have any illegal characters.
677
 
                                        if (!IsNameValid(path))
678
 
                                                nameConflict = true;
679
 
 
680
 
                                        if (nameConflict)
681
 
                                        {
682
 
                                                node = Conflict.CreateNameConflict(collection, node) as BaseFileNode;
683
 
                                                file = Conflict.GetFileConflictPath(collection, node);
684
 
                                                if (conflictingNode != null)
685
 
                                                {
686
 
                                                        string cnPath;
687
 
                                                        FileNode tmpFn = conflictingNode as FileNode;
688
 
                                                        DirNode tmpDn = conflictingNode as DirNode;
689
 
                                                        if (tmpFn != null)
690
 
                                                        {
691
 
                                                                cnPath = tmpFn.GetFullPath(collection);
692
 
                                                        }
693
 
                                                        else
694
 
                                                        {
695
 
                                                                cnPath = tmpDn.GetFullPath(collection);
696
 
                                                        }
697
 
                                                        conflictingNode = Conflict.CreateNameConflict(collection, conflictingNode, cnPath);
698
 
                                                        Conflict.LinkConflictingNodes(conflictingNode, node);
699
 
                                                }
700
 
                                        }
701
 
                                }
702
 
                        }
703
 
                        return nameConflict;
704
 
                }
705
 
 
706
 
                /// <summary>
707
 
                /// Called to see if a node with the same name exists.
708
 
                /// </summary>
709
 
                /// <param name="collection">The collection that contains the node.</param>
710
 
                /// <param name="parent">The parent node</param>
711
 
                /// <param name="name">The leaf name of the file.</param>
712
 
                /// <returns>true if allowed.</returns>
713
 
                public static bool DoesNodeExist(Collection collection, DirNode parent, string name)
714
 
                {
715
 
                        string path = parent.Properties.GetSingleProperty(PropertyTags.FileSystemPath).Value.ToString() + "/" + name;
716
 
                        ICSList nodeList;
717
 
                        nodeList = collection.Search(PropertyTags.FileSystemPath, path, SearchOp.Equal);
718
 
                        if (nodeList.Count > 0)
719
 
                        {
720
 
                                return true;
721
 
                        }
722
 
                        return false;
723
 
                }
724
 
 
725
 
 
726
 
                /// <summary>
727
 
                /// Gets or Sets a NameConflict.
728
 
                /// </summary>
729
 
                protected bool NameConflict
730
 
                {
731
 
                        get {return nameConflict;}
732
 
                        set {nameConflict = value;}
733
 
                }
734
 
 
735
 
                /// <summary>
736
 
                /// Gets or Sets a NameConflict.
737
 
                /// </summary>
738
 
                protected bool DateConflict
739
 
                {
740
 
                        get {return dateConflict;}
741
 
                        set {dateConflict = value;}
742
 
                }
743
 
 
744
 
                #endregion
745
 
 
746
 
                #region public methods.
747
 
 
748
 
                /// <summary>
749
 
                /// Delete ther file and map file.
750
 
                /// </summary>
751
 
                /// <param name="collection">The collection that the node belongs to.</param>
752
 
                /// <param name="node">The node that represents the file.</param>
753
 
                /// <param name="path">The full path to the file.</param>
754
 
                public static void DeleteFile(Collection collection, BaseFileNode node, string path)
755
 
                {
756
 
                        if (File.Exists(path))
757
 
                                File.Delete(path);
758
 
                        try
759
 
                        {
760
 
                                // Now delete the map file.
761
 
                                HashMap.Delete(collection, node);
762
 
                        }
763
 
                        catch {}
764
 
                }
765
 
 
766
 
                /// <summary>
767
 
                /// Get the file name.
768
 
                /// </summary>
769
 
                public string Name
770
 
                {
771
 
                        get { return Path.GetFileName(file); }
772
 
                }
773
 
 
774
 
                /// <summary>
775
 
                /// Tells the file to stop and return.
776
 
                /// </summary>
777
 
                public bool Stop
778
 
                {
779
 
                        set { stopping = value; }
780
 
                }
781
 
 
782
 
                /// <summary>
783
 
                /// Tests if the file name is valid.
784
 
                /// </summary>
785
 
                /// <param name="name">The file name.</param>
786
 
                /// <returns>true if valid.</returns>
787
 
                public static bool IsNameValid(string name)
788
 
                {
789
 
                        return name.IndexOfAny(InvalidChars) == -1 ? true : false;
790
 
                }
791
 
 
792
 
                /// <summary>
793
 
                /// Tests if the relative path is valid.
794
 
                /// </summary>
795
 
                /// <param name="path">The path.</param>
796
 
                /// <returns>true if valid</returns>
797
 
                public static bool IsRelativePathValid(string path)
798
 
                {
799
 
                        return path.IndexOfAny(InvalidChars) == -1 ? true : false;
800
 
                }
801
 
 
802
 
                /// <summary>
803
 
                /// Test if encryption is enabled
804
 
                /// </summary>
805
 
                public bool IsEncryptionEnabled()
806
 
                {
807
 
                        string EncryptionAlgorithm="";
808
 
                        Property p = collection.Properties.FindSingleValue(PropertyTags.EncryptionType);
809
 
                        EncryptionAlgorithm = (p!=null) ? (string) p.Value as string : "";
810
 
                        if(EncryptionAlgorithm =="")
811
 
                                return false;
812
 
                        else
813
 
                                return true;
814
 
                }
815
 
 
816
 
                /// <summary>
817
 
                /// Gets the crypto key
818
 
                /// </summary>
819
 
                public bool GetCryptoKey(out string EncryptionKey)
820
 
                {
821
 
                        try
822
 
                        {
823
 
                                string EncryptionAlgorithm="";
824
 
                                Property p = collection.Properties.FindSingleValue(PropertyTags.EncryptionType);
825
 
                                EncryptionAlgorithm = (p!=null) ? (string) p.Value as string : "";
826
 
                                if(EncryptionAlgorithm != "")
827
 
                                {
828
 
                                        p = collection.Properties.FindSingleValue(PropertyTags.EncryptionKey);
829
 
                                        string EncryptedKey = (p!=null) ? (string) p.Value as string : null;
830
 
                                        
831
 
                                        Store store = Store.GetStore();
832
 
                                        string Passphrase =  store.GetPassPhrase(collection.Domain);
833
 
                                        if(Passphrase ==null)
834
 
                                                throw new CollectionStoreException("Passphrase not provided");
835
 
 
836
 
                                        //Hash the passphrase and use it for encryption and decryption
837
 
                                        PassphraseHash hash = new PassphraseHash();
838
 
                                        byte[] passphrase = hash.HashPassPhrase(Passphrase);                                    
839
 
                        
840
 
                                        Key key = new Key(EncryptedKey);//send the key size and algorithm
841
 
                                        key.DecrypytKey(passphrase, out EncryptionKey);//send the passphrase to decrypt the key
842
 
                                
843
 
                                        p = collection.Properties.FindSingleValue(PropertyTags.EncryptionBlob);
844
 
                                        string EncryptionBlob = (p!=null) ? (string) p.Value as string : null;
845
 
                                        if(EncryptionBlob == null)
846
 
                                                throw new CollectionStoreException("The specified cryptographic key not found");
847
 
                                        
848
 
                                        Key hashKey = new Key(EncryptionKey);
849
 
                                        if(hashKey.HashKey() != EncryptionBlob)
850
 
                                                throw new CollectionStoreException("The specified cryptographic key does not match");
851
 
 
852
 
                                        return true;
853
 
                                }
854
 
 
855
 
                                else
856
 
                                {
857
 
                                        EncryptionKey = "";
858
 
                                        return false;
859
 
                                }
860
 
                        }
861
 
                        catch (Exception ex)
862
 
                        {
863
 
                                throw ex;       
864
 
                        }
865
 
                }
866
 
                #endregion
867
 
        }
868
 
 
869
 
        #endregion
870
 
 
871
 
        #region SyncSize
872
 
 
873
 
        /// <summary>
874
 
        /// class to approximate amount of data that is out of sync with master
875
 
        /// Note that this is worst-case of data that may need to be sent from
876
 
        /// this collection to the master. It does not include data that may need
877
 
        /// to be retrieved from the master. It also does not account for
878
 
        /// delta-sync algorithms that may reduce what needs to be sent
879
 
        /// </summary>
880
 
        public class SyncSize
881
 
        {
882
 
                /// <summary>
883
 
                /// 
884
 
                /// </summary>
885
 
                /// <param name="col"></param>
886
 
                /// <param name="nodeCount"></param>
887
 
                /// <param name="maxBytesToSend"></param>
888
 
                public static void CalculateSendSize(Collection col, out uint nodeCount, out ulong maxBytesToSend)
889
 
                {
890
 
                        Log.log.Debug("starting to calculate size to send to master for collection {0}", col.Name);
891
 
 
892
 
                        maxBytesToSend = 0;
893
 
                        nodeCount = 0;
894
 
                        SyncClient.GetCountToSync(col.ID, out nodeCount);
895
 
                }
896
 
        }
897
 
 
898
 
        #endregion
899
 
}