Revision 31c97141
b/trunk/Pithos.Client.WPF/Pithos.Client.WPF.csproj | ||
---|---|---|
262 | 262 |
</Compile> |
263 | 263 |
<Compile Include="FileProperties\NewContainerViewModel.cs" /> |
264 | 264 |
<Compile Include="PithosException.cs" /> |
265 |
<Compile Include="Preferences\AccountViewModel.cs" /> |
|
265 | 266 |
<Compile Include="Preferences\AddAccountView.xaml.cs"> |
266 | 267 |
<DependentUpon>AddAccountView.xaml</DependentUpon> |
267 | 268 |
</Compile> |
b/trunk/Pithos.Client.WPF/Preferences/AccountViewModel.cs | ||
---|---|---|
1 |
#region |
|
2 |
/* ----------------------------------------------------------------------- |
|
3 |
* <copyright file="AccountViewModel.cs" company="GRNet"> |
|
4 |
* |
|
5 |
* Copyright 2011-2012 GRNET S.A. All rights reserved. |
|
6 |
* |
|
7 |
* Redistribution and use in source and binary forms, with or |
|
8 |
* without modification, are permitted provided that the following |
|
9 |
* conditions are met: |
|
10 |
* |
|
11 |
* 1. Redistributions of source code must retain the above |
|
12 |
* copyright notice, this list of conditions and the following |
|
13 |
* disclaimer. |
|
14 |
* |
|
15 |
* 2. Redistributions in binary form must reproduce the above |
|
16 |
* copyright notice, this list of conditions and the following |
|
17 |
* disclaimer in the documentation and/or other materials |
|
18 |
* provided with the distribution. |
|
19 |
* |
|
20 |
* |
|
21 |
* THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
|
22 |
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
23 |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
24 |
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
|
25 |
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
26 |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
27 |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
|
28 |
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
|
29 |
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
30 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
|
31 |
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
32 |
* POSSIBILITY OF SUCH DAMAGE. |
|
33 |
* |
|
34 |
* The views and conclusions contained in the software and |
|
35 |
* documentation are those of the authors and should not be |
|
36 |
* interpreted as representing official policies, either expressed |
|
37 |
* or implied, of GRNET S.A. |
|
38 |
* </copyright> |
|
39 |
* ----------------------------------------------------------------------- |
|
40 |
*/ |
|
41 |
#endregion |
|
42 |
using Caliburn.Micro; |
|
43 |
using Pithos.Interfaces; |
|
44 |
|
|
45 |
namespace Pithos.Client.WPF.Preferences |
|
46 |
{ |
|
47 |
/// <summary> |
|
48 |
/// ViewModel wrapper for an account |
|
49 |
/// </summary> |
|
50 |
public class AccountViewModel:PropertyChangedBase |
|
51 |
{ |
|
52 |
|
|
53 |
private readonly AccountSettings _account; |
|
54 |
|
|
55 |
public AccountSettings Account |
|
56 |
{ |
|
57 |
get { return _account; } |
|
58 |
} |
|
59 |
|
|
60 |
public AccountViewModel(AccountSettings account) |
|
61 |
{ |
|
62 |
_account = account; |
|
63 |
} |
|
64 |
|
|
65 |
|
|
66 |
public string AccountName |
|
67 |
{ |
|
68 |
get { |
|
69 |
return _account.AccountName; |
|
70 |
} |
|
71 |
set { |
|
72 |
_account.AccountName = value; |
|
73 |
NotifyOfPropertyChange(()=>AccountName); |
|
74 |
} |
|
75 |
} |
|
76 |
|
|
77 |
public string RootPath |
|
78 |
{ |
|
79 |
get { return _account.RootPath; } |
|
80 |
set |
|
81 |
{ |
|
82 |
_account.RootPath = value; |
|
83 |
NotifyOfPropertyChange(()=>RootPath); |
|
84 |
} |
|
85 |
} |
|
86 |
|
|
87 |
public bool IsActive |
|
88 |
{ |
|
89 |
get { return _account.IsActive; } |
|
90 |
set |
|
91 |
{ |
|
92 |
_account.IsActive = value; |
|
93 |
NotifyOfPropertyChange(()=>IsActive); |
|
94 |
} |
|
95 |
} |
|
96 |
|
|
97 |
public bool IsExpired |
|
98 |
{ |
|
99 |
get { return _account.IsExpired; } |
|
100 |
set |
|
101 |
{ |
|
102 |
_account.IsExpired = value; |
|
103 |
NotifyOfPropertyChange(()=>IsExpired); |
|
104 |
} |
|
105 |
} |
|
106 |
|
|
107 |
public string ServerUrl |
|
108 |
{ |
|
109 |
get { return _account.ServerUrl; } |
|
110 |
set |
|
111 |
{ |
|
112 |
_account.ServerUrl = value; |
|
113 |
NotifyOfPropertyChange(()=>ServerUrl); |
|
114 |
} |
|
115 |
} |
|
116 |
|
|
117 |
public string ApiKey |
|
118 |
{ |
|
119 |
get { return _account.ApiKey; } |
|
120 |
set |
|
121 |
{ |
|
122 |
_account.ApiKey = value; |
|
123 |
NotifyOfPropertyChange(() => ApiKey); |
|
124 |
} |
|
125 |
} |
|
126 |
|
|
127 |
|
|
128 |
} |
|
129 |
} |
b/trunk/Pithos.Client.WPF/Preferences/PreferencesView.xaml | ||
---|---|---|
72 | 72 |
<ListBox.ItemTemplate> |
73 | 73 |
<DataTemplate> |
74 | 74 |
<StackPanel Orientation="Horizontal"> |
75 |
<Image Visibility="{Binding Converter={StaticResource BoolToVisible}, Path=IsExpired}" Source="/Pithos.Client.WPF;component/Images/SmallWarning.png" Margin="2,0"/> |
|
75 |
<Image Visibility="{Binding Converter={StaticResource BoolToVisible}, Path=IsExpired,Mode=OneWay}" Source="/Pithos.Client.WPF;component/Images/SmallWarning.png" Margin="2,0"/>
|
|
76 | 76 |
<TextBlock Text="{Binding AccountName}" /> |
77 | 77 |
</StackPanel> |
78 | 78 |
</DataTemplate> |
b/trunk/Pithos.Client.WPF/Preferences/PreferencesViewModel.cs | ||
---|---|---|
45 | 45 |
|
46 | 46 |
using System.Collections.Concurrent; |
47 | 47 |
using System.ComponentModel.Composition; |
48 |
using System.Diagnostics; |
|
48 | 49 |
using System.IO; |
49 | 50 |
using System.Net; |
50 | 51 |
using System.Threading.Tasks; |
... | ... | |
69 | 70 |
{ |
70 | 71 |
private IEventAggregator _events; |
71 | 72 |
|
73 |
//Logging in the Pithos client is provided by log4net |
|
74 |
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger("Pithos"); |
|
72 | 75 |
|
73 | 76 |
private PithosSettings _settings; |
74 | 77 |
public PithosSettings Settings |
... | ... | |
81 | 84 |
} |
82 | 85 |
} |
83 | 86 |
|
84 |
private ObservableConcurrentCollection<AccountSettings> _accounts;
|
|
85 |
public ObservableConcurrentCollection<AccountSettings> Accounts
|
|
87 |
private ObservableConcurrentCollection<AccountViewModel> _accounts;
|
|
88 |
public ObservableConcurrentCollection<AccountViewModel> Accounts
|
|
86 | 89 |
{ |
87 | 90 |
get { return _accounts; } |
88 | 91 |
set |
... | ... | |
106 | 109 |
Shell = shell; |
107 | 110 |
|
108 | 111 |
Settings=settings; |
109 |
Accounts = new ObservableConcurrentCollection<AccountSettings>();
|
|
112 |
Accounts = new ObservableConcurrentCollection<AccountViewModel>();
|
|
110 | 113 |
if (settings.Accounts == null) |
111 | 114 |
{ |
112 | 115 |
settings.Accounts=new AccountsCollection(); |
113 | 116 |
settings.Save(); |
114 | 117 |
} |
115 |
Accounts.AddFromEnumerable(settings.Accounts); |
|
118 |
var accountVMs = from account in settings.Accounts |
|
119 |
select new AccountViewModel(account); |
|
120 |
|
|
121 |
Accounts.AddFromEnumerable(accountVMs); |
|
116 | 122 |
|
117 | 123 |
var startupPath = Environment.GetFolderPath(Environment.SpecialFolder.Startup); |
118 | 124 |
_shortcutPath = Path.Combine(startupPath, "Pithos.lnk"); |
... | ... | |
205 | 211 |
var monitor = Shell.Monitors[CurrentAccount.AccountName]; |
206 | 212 |
|
207 | 213 |
|
208 |
var model = new SelectiveSynchViewModel(monitor,_events,CurrentAccount); |
|
214 |
var model = new SelectiveSynchViewModel(monitor,_events,CurrentAccount.Account);
|
|
209 | 215 |
if (_windowManager.ShowDialog(model) == true) |
210 | 216 |
{ |
211 | 217 |
|
... | ... | |
213 | 219 |
} |
214 | 220 |
|
215 | 221 |
public async Task RefreshApiKey() |
216 |
{ |
|
217 |
await Shell.TryAuthorize(CurrentAccount.AccountName, 3); |
|
218 |
NotifyOfPropertyChange(()=>CurrentAccount); |
|
222 |
{ |
|
223 |
_events.Publish(new Notification { Title = "Authorization failed", Message = "Your API Key has probably expired. You will be directed to a page where you can renew it", Level = TraceLevel.Error }); |
|
224 |
|
|
225 |
//var userName = CurrentAccount.AccountName; |
|
226 |
try |
|
227 |
{ |
|
228 |
|
|
229 |
var credentials = await PithosAccount.RetrieveCredentials(Settings.PithosLoginUrl); |
|
230 |
|
|
231 |
var account = Accounts.First(act => act.AccountName == credentials.UserName); |
|
232 |
//The server may return credentials for a different account |
|
233 |
var monitor = Shell.Monitors[account.AccountName]; |
|
234 |
account.ApiKey = credentials.Password; |
|
235 |
monitor.ApiKey = credentials.Password; |
|
236 |
account.IsExpired = false; |
|
237 |
Settings.Save(); |
|
238 |
TaskEx.Delay(10000).ContinueWith(_ =>Shell.MonitorAccount(account.Account)); |
|
239 |
NotifyOfPropertyChange(() => Accounts); |
|
240 |
} |
|
241 |
catch (AggregateException exc) |
|
242 |
{ |
|
243 |
string message = String.Format("API Key retrieval failed"); |
|
244 |
Log.Error(message, exc.InnerException); |
|
245 |
_events.Publish(new Notification { Title = "Authorization failed", Message = message, Level = TraceLevel.Error }); |
|
246 |
} |
|
247 |
catch (Exception exc) |
|
248 |
{ |
|
249 |
string message = String.Format("API Key retrieval failed"); |
|
250 |
Log.Error(message, exc); |
|
251 |
_events.Publish(new Notification { Title = "Authorization failed", Message = message, Level = TraceLevel.Error }); |
|
252 |
} |
|
253 |
|
|
219 | 254 |
} |
255 |
|
|
220 | 256 |
|
221 | 257 |
public void SaveChanges() |
222 | 258 |
{ |
... | ... | |
298 | 334 |
IsActive=wizard.IsAccountActive |
299 | 335 |
}; |
300 | 336 |
Settings.Accounts.Add(newAccount); |
301 |
(Accounts as IProducerConsumerCollection<AccountSettings>).TryAdd(newAccount); |
|
302 |
CurrentAccount = newAccount; |
|
337 |
var accountVM = new AccountViewModel(newAccount); |
|
338 |
(Accounts as IProducerConsumerCollection<AccountViewModel>).TryAdd(accountVM); |
|
339 |
CurrentAccount = accountVM; |
|
303 | 340 |
NotifyOfPropertyChange(() => Accounts); |
304 | 341 |
NotifyOfPropertyChange(() => Settings); |
305 | 342 |
} |
... | ... | |
312 | 349 |
{ |
313 | 350 |
var credentials=await PithosAccount.RetrieveCredentials(Settings.PithosLoginUrl); |
314 | 351 |
var account = Settings.Accounts.FirstOrDefault(act => act.AccountName == credentials.UserName); |
352 |
var accountVM = new AccountViewModel(account); |
|
315 | 353 |
if (account == null) |
316 | 354 |
{ |
317 | 355 |
account=new AccountSettings{ |
... | ... | |
319 | 357 |
ApiKey=credentials.Password |
320 | 358 |
}; |
321 | 359 |
Settings.Accounts.Add(account); |
322 |
(Accounts as IProducerConsumerCollection<AccountSettings>).TryAdd(account); |
|
360 |
accountVM = new AccountViewModel(account); |
|
361 |
(Accounts as IProducerConsumerCollection<AccountViewModel>).TryAdd(accountVM); |
|
323 | 362 |
} |
324 | 363 |
else |
325 | 364 |
{ |
326 | 365 |
account.ApiKey=credentials.Password; |
327 | 366 |
} |
328 | 367 |
//SelectedAccountIndex= Settings.Accounts.IndexOf(account); |
329 |
CurrentAccount = account; |
|
368 |
CurrentAccount = accountVM;
|
|
330 | 369 |
NotifyOfPropertyChange(() => Accounts); |
331 | 370 |
NotifyOfPropertyChange(()=>Settings); |
332 | 371 |
} |
... | ... | |
334 | 373 |
public void RemoveAccount() |
335 | 374 |
{ |
336 | 375 |
var accountName = CurrentAccount.AccountName; |
337 |
Settings.Accounts.Remove(CurrentAccount); |
|
376 |
Settings.Accounts.Remove(CurrentAccount.Account);
|
|
338 | 377 |
|
339 | 378 |
Accounts.TryRemove(CurrentAccount); |
340 | 379 |
|
... | ... | |
401 | 440 |
} |
402 | 441 |
}*/ |
403 | 442 |
|
404 |
private AccountSettings _currentAccount;
|
|
443 |
private AccountViewModel _currentAccount;
|
|
405 | 444 |
private IWindowManager _windowManager; |
406 | 445 |
private string _shortcutPath; |
407 | 446 |
|
408 | 447 |
|
409 | 448 |
|
410 |
public AccountSettings CurrentAccount
|
|
449 |
public AccountViewModel CurrentAccount
|
|
411 | 450 |
{ |
412 | 451 |
get { return _currentAccount; } |
413 | 452 |
set |
... | ... | |
494 | 533 |
monitor.Start(); |
495 | 534 |
} |
496 | 535 |
else |
497 |
Shell.MonitorAccount(CurrentAccount); |
|
536 |
Shell.MonitorAccount(CurrentAccount.Account);
|
|
498 | 537 |
//Finally, notify that the Settings, CurrentAccount have changed |
499 | 538 |
NotifyOfPropertyChange(() => CurrentAccount); |
500 | 539 |
NotifyOfPropertyChange(() => Settings); |
b/trunk/Pithos.Client.WPF/Properties/AssemblyInfo.cs | ||
---|---|---|
94 | 94 |
// by using the '*' as shown below: |
95 | 95 |
// [assembly: AssemblyVersion("1.0.*")] |
96 | 96 |
[assembly: AssemblyVersion("0.7.0.0")] |
97 |
[assembly: AssemblyFileVersionAttribute("0.7.20228.1899")] |
|
97 |
[assembly: AssemblyFileVersionAttribute("0.7.20229.2112")] |
b/trunk/Pithos.Client.WPF/Shell/ShellViewModel.cs | ||
---|---|---|
124 | 124 |
//Lazily initialized File Version info. This is done once and lazily to avoid blocking the UI |
125 | 125 |
private Lazy<FileVersionInfo> _fileVersion; |
126 | 126 |
|
127 |
private PollAgent _pollAgent; |
|
128 |
|
|
127 | 129 |
///<summary> |
128 | 130 |
/// The Shell depends on MEF to provide implementations for windowManager, events, the status checker service and the settings |
129 | 131 |
///</summary> |
... | ... | |
131 | 133 |
/// The PithosSettings class encapsulates the app's settings to abstract their storage mechanism (App settings, a database or registry) |
132 | 134 |
///</remarks> |
133 | 135 |
[ImportingConstructor] |
134 |
public ShellViewModel(IWindowManager windowManager, IEventAggregator events, IStatusChecker statusChecker, PithosSettings settings) |
|
136 |
public ShellViewModel(IWindowManager windowManager, IEventAggregator events, IStatusChecker statusChecker, PithosSettings settings,PollAgent pollAgent)
|
|
135 | 137 |
{ |
136 | 138 |
try |
137 | 139 |
{ |
... | ... | |
144 | 146 |
_events = events; |
145 | 147 |
_events.Subscribe(this); |
146 | 148 |
|
149 |
_pollAgent = pollAgent; |
|
147 | 150 |
Settings = settings; |
148 | 151 |
|
149 | 152 |
Proxy.SetFromSettings(settings); |
... | ... | |
471 | 474 |
|
472 | 475 |
public void SynchNow() |
473 | 476 |
{ |
474 |
var agent = IoC.Get<PollAgent>(); |
|
475 |
agent.SynchNow(); |
|
477 |
_pollAgent.SynchNow(); |
|
476 | 478 |
} |
477 | 479 |
|
478 | 480 |
public ObjectInfo RefreshObjectInfo(ObjectInfo currentInfo) |
... | ... | |
637 | 639 |
} |
638 | 640 |
|
639 | 641 |
|
640 |
public async Task TryAuthorize(string userName, int retries) |
|
641 |
{ |
|
642 |
_events.Publish(new Notification { Title = "Authorization failed", Message = "Your API Key has probably expired. You will be directed to a page where you can renew it", Level = TraceLevel.Error }); |
|
643 |
|
|
644 |
try |
|
645 |
{ |
|
646 |
|
|
647 |
var credentials = await PithosAccount.RetrieveCredentials(Settings.PithosLoginUrl); |
|
648 |
|
|
649 |
var account = Settings.Accounts.First(act => act.AccountName == credentials.UserName); |
|
650 |
//The server may return credentials for a different account |
|
651 |
var monitor = _monitors[account.AccountName]; |
|
652 |
account.ApiKey = credentials.Password; |
|
653 |
monitor.ApiKey = credentials.Password; |
|
654 |
account.IsExpired = false; |
|
655 |
Settings.Save(); |
|
656 |
TaskEx.Delay(10000).ContinueWith(_=> |
|
657 |
StartMonitor(monitor, retries + 1)); |
|
658 |
NotifyOfPropertyChange(()=>Accounts); |
|
659 |
} |
|
660 |
catch (AggregateException exc) |
|
661 |
{ |
|
662 |
string message = String.Format("API Key retrieval for {0} failed", userName); |
|
663 |
Log.Error(message, exc.InnerException); |
|
664 |
_events.Publish(new Notification { Title = "Authorization failed", Message = message, Level = TraceLevel.Error }); |
|
665 |
} |
|
666 |
catch (Exception exc) |
|
667 |
{ |
|
668 |
string message = String.Format("API Key retrieval for {0} failed", userName); |
|
669 |
Log.Error(message, exc); |
|
670 |
_events.Publish(new Notification { Title = "Authorization failed", Message = message, Level = TraceLevel.Error }); |
|
671 |
} |
|
672 |
|
|
673 |
} |
|
674 | 642 |
|
675 | 643 |
private static bool IsUnauthorized(WebException exc) |
676 | 644 |
{ |
b/trunk/Pithos.Interfaces/ObjectInfo.cs | ||
---|---|---|
53 | 53 |
namespace Pithos.Interfaces |
54 | 54 |
{ |
55 | 55 |
[DebuggerDisplay("Name {Name}")] |
56 |
public class ObjectInfo:DynamicObject |
|
56 |
public class ObjectInfo//:DynamicObject
|
|
57 | 57 |
{ |
58 | 58 |
private readonly List<string> _knownContainers= new List<string>{"trash"}; |
59 | 59 |
public string Name { get; set; } |
... | ... | |
234 | 234 |
Hash = String.Empty, |
235 | 235 |
Bytes = 0, |
236 | 236 |
Content_Type = String.Empty, |
237 |
Last_Modified = DateTime.MinValue |
|
237 |
Last_Modified = DateTime.MinValue, |
|
238 |
Exists=false |
|
238 | 239 |
}; |
239 | 240 |
|
240 |
|
|
241 |
private bool _exists=true; |
|
242 |
|
|
243 |
public bool Exists |
|
244 |
{ |
|
245 |
get { |
|
246 |
return _exists; |
|
247 |
} |
|
248 |
set { |
|
249 |
_exists = value; |
|
250 |
} |
|
251 |
} |
|
252 |
|
|
241 | 253 |
|
242 | 254 |
public string RelativeUrlToFilePath(string currentAccount) |
243 | 255 |
{ |
... | ... | |
268 | 280 |
return finalPath; |
269 | 281 |
} |
270 | 282 |
|
283 |
/* |
|
271 | 284 |
public override bool TrySetMember(SetMemberBinder binder, object value) |
272 | 285 |
{ |
273 | 286 |
if (binder.Name.StartsWith("x_object_meta")) |
... | ... | |
276 | 289 |
} |
277 | 290 |
return false; |
278 | 291 |
} |
292 |
*/ |
|
279 | 293 |
|
280 | 294 |
public string GetPermissionString() |
281 | 295 |
{ |
b/trunk/Pithos.Setup.x64/Pithos.Setup.x64.vdproj | ||
---|---|---|
1310 | 1310 |
{ |
1311 | 1311 |
"Name" = "8:Microsoft Visual Studio" |
1312 | 1312 |
"ProductName" = "8:Pithos" |
1313 |
"ProductCode" = "8:{E88F0F45-5BE6-4616-A86B-D595712A5663}"
|
|
1314 |
"PackageCode" = "8:{8314D97A-C981-4184-8444-4DB962DC3240}"
|
|
1313 |
"ProductCode" = "8:{013ABFEC-E6FB-4C5E-930F-736A4730268A}"
|
|
1314 |
"PackageCode" = "8:{C7D65245-240C-42FA-9E46-2AAFB3351131}"
|
|
1315 | 1315 |
"UpgradeCode" = "8:{205365D1-28AA-4322-A46C-FCB37502C6EF}" |
1316 | 1316 |
"AspNetVersion" = "8:4.0.30319.0" |
1317 | 1317 |
"RestartWWWService" = "11:FALSE" |
1318 | 1318 |
"RemovePreviousVersions" = "11:TRUE" |
1319 | 1319 |
"DetectNewerInstalledVersion" = "11:TRUE" |
1320 | 1320 |
"InstallAllUsers" = "11:FALSE" |
1321 |
"ProductVersion" = "8:0.7.20228"
|
|
1321 |
"ProductVersion" = "8:0.7.20229"
|
|
1322 | 1322 |
"Manufacturer" = "8:GRNET" |
1323 | 1323 |
"ARPHELPTELEPHONE" = "8:" |
1324 | 1324 |
"ARPHELPLINK" = "8:http://code.grnet.gr/projects/pithos-ms-client" |
b/trunk/Pithos.Setup.x86/Pithos.Setup.x86.vdproj | ||
---|---|---|
1310 | 1310 |
{ |
1311 | 1311 |
"Name" = "8:Microsoft Visual Studio" |
1312 | 1312 |
"ProductName" = "8:Pithos" |
1313 |
"ProductCode" = "8:{F70830AB-AE3C-4721-9FBD-2EF0CD415B7D}"
|
|
1314 |
"PackageCode" = "8:{78D43546-C115-43DE-AAE2-6C262F691990}"
|
|
1313 |
"ProductCode" = "8:{CDF5C181-8F2F-4135-9861-89F031E4B435}"
|
|
1314 |
"PackageCode" = "8:{CD80CD47-92C9-4445-A777-4110130323B8}"
|
|
1315 | 1315 |
"UpgradeCode" = "8:{205365D1-28AA-4322-A46C-FCB37502C6EF}" |
1316 | 1316 |
"AspNetVersion" = "8:4.0.30319.0" |
1317 | 1317 |
"RestartWWWService" = "11:FALSE" |
1318 | 1318 |
"RemovePreviousVersions" = "11:TRUE" |
1319 | 1319 |
"DetectNewerInstalledVersion" = "11:TRUE" |
1320 | 1320 |
"InstallAllUsers" = "11:FALSE" |
1321 |
"ProductVersion" = "8:0.7.20228"
|
|
1321 |
"ProductVersion" = "8:0.7.20229"
|
|
1322 | 1322 |
"Manufacturer" = "8:GRNET" |
1323 | 1323 |
"ARPHELPTELEPHONE" = "8:" |
1324 | 1324 |
"ARPHELPLINK" = "8:http://code.grnet.gr/projects/pithos-ms-client" |
Also available in: Unified diff