Added
Link Here
|
1 |
/* |
2 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
3 |
* |
4 |
* Copyright 2010 Sun Microsystems, Inc. All rights reserved. |
5 |
* |
6 |
* The contents of this file are subject to the terms of either the GNU |
7 |
* General Public License Version 2 only ("GPL") or the Common |
8 |
* Development and Distribution License("CDDL") (collectively, the |
9 |
* "License"). You may not use this file except in compliance with the |
10 |
* License. You can obtain a copy of the License at |
11 |
* http://www.netbeans.org/cddl-gplv2.html |
12 |
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the |
13 |
* specific language governing permissions and limitations under the |
14 |
* License. When distributing the software, include this License Header |
15 |
* Notice in each file and include the License file at |
16 |
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this |
17 |
* particular file as subject to the "Classpath" exception as provided |
18 |
* by Sun in the GPL Version 2 section of the License file that |
19 |
* accompanied this code. If applicable, add the following below the |
20 |
* License Header, with the fields enclosed by brackets [] replaced by |
21 |
* your own identifying information: |
22 |
* "Portions Copyrighted [year] [name of copyright owner]" |
23 |
* |
24 |
* If you wish your version of this file to be governed by only the CDDL |
25 |
* or only the GPL Version 2, indicate your decision by adding |
26 |
* "[Contributor] elects to include this software in this distribution |
27 |
* under the [CDDL or GPL Version 2] license." If you do not indicate a |
28 |
* single choice of license, a recipient has the option to distribute |
29 |
* your version of this file under either the CDDL, the GPL Version 2 or |
30 |
* to extend the choice of license to its licensees as provided above. |
31 |
* However, if you add GPL Version 2 code and therefore, elected the GPL |
32 |
* Version 2 license, then the option applies only if the new code is |
33 |
* made subject to such option by the copyright holder. |
34 |
* |
35 |
* Contributor(s): |
36 |
* |
37 |
* Portions Copyrighted 2010 Sun Microsystems, Inc. |
38 |
*/ |
39 |
|
40 |
package org.netbeans.modules.keyring.kde; |
41 |
|
42 |
import java.io.BufferedReader; |
43 |
import java.io.IOException; |
44 |
import java.io.InputStreamReader; |
45 |
import java.text.MessageFormat; |
46 |
import java.util.MissingResourceException; |
47 |
import java.util.logging.Level; |
48 |
import java.util.logging.Logger; |
49 |
import org.netbeans.spi.keyring.KeyringProvider; |
50 |
import org.openide.util.NbBundle; |
51 |
import org.openide.util.lookup.ServiceProvider; |
52 |
|
53 |
/** |
54 |
* |
55 |
* @author psychollek |
56 |
*/ |
57 |
@ServiceProvider(service=KeyringProvider.class, position=99) |
58 |
public class KWalletProvider implements KeyringProvider{ |
59 |
|
60 |
private static final Logger logger = Logger.getLogger(KWalletProvider.class.getName()); |
61 |
private char[] handler = "0".toCharArray(); |
62 |
|
63 |
@Override |
64 |
public boolean enabled(){ |
65 |
if (Boolean.getBoolean("netbeans.keyring.no.native")) { |
66 |
logger.fine("native keyring integration disabled"); |
67 |
return false; |
68 |
} |
69 |
if (new String(runCommand("isEnabled")).equals("true")){ |
70 |
return updateHandler(); |
71 |
} |
72 |
return false; |
73 |
}; |
74 |
|
75 |
@Override |
76 |
public char[] read(String key){ |
77 |
runCommand("close", runCommand("localWallet"), "true".toCharArray() ); |
78 |
if (updateHandler()){ |
79 |
char[] runCommand = runCommand("readPassword", handler, getApplicationName(), key.toCharArray(), getApplicationNameWithVersion()); |
80 |
runCommand("close", runCommand("localWallet"), "true".toCharArray() ); |
81 |
return runCommand; |
82 |
} |
83 |
throw new KwalletException("read"); |
84 |
}; |
85 |
|
86 |
@Override |
87 |
public void save(String key, char[] password, String description){ |
88 |
//description is forgoten ! kdewallet dosen't have any facility to store |
89 |
//it by default and I don't want to do it by adding new fields to kwallet |
90 |
runCommand("close", runCommand("localWallet"), "true".toCharArray() ); |
91 |
if (updateHandler()){ |
92 |
if (new String(runCommand("writePassword", handler , getApplicationName() |
93 |
, key.toCharArray(), password , getApplicationNameWithVersion()) |
94 |
).equals("-1")){ |
95 |
throw new KwalletException("save"); |
96 |
} |
97 |
runCommand("close", runCommand("localWallet"), "true".toCharArray() ); |
98 |
return; |
99 |
} |
100 |
throw new KwalletException("save"); |
101 |
}; |
102 |
|
103 |
@Override |
104 |
public void delete(String key){ |
105 |
runCommand("close", runCommand("localWallet"), "true".toCharArray() ); |
106 |
if (updateHandler()){ |
107 |
if (new String(runCommand("removeEntry" ,handler, |
108 |
getApplicationName() , key.toCharArray() , getApplicationNameWithVersion() |
109 |
)).equals("-1")){ |
110 |
throw new KwalletException("delete"); |
111 |
} |
112 |
runCommand("close", runCommand("localWallet"), "true".toCharArray() ); |
113 |
return; |
114 |
} |
115 |
throw new KwalletException("delete"); |
116 |
}; |
117 |
|
118 |
private boolean updateHandler(){ |
119 |
handler = new String(handler).equals("")? "0".toCharArray() : handler; |
120 |
if(new String(runCommand("isOpen",handler)).equals("true")){ |
121 |
return true; |
122 |
} |
123 |
char[] localWallet = runCommand("localWallet"); |
124 |
handler = runCommand("open", localWallet , "0".toCharArray() , getApplicationNameWithVersion()); |
125 |
if(!(new String(handler)).equals("-1")){ |
126 |
return true; |
127 |
} |
128 |
return false; |
129 |
} |
130 |
|
131 |
private char[] runCommand(String command,char[]... commandArgs){ |
132 |
String commandString = "qdbus org.kde.kwalletd /modules/kwalletd org.kde.KWallet."+command; |
133 |
String[] argv = new String[commandArgs.length+4]; |
134 |
argv[0] = "qdbus"; |
135 |
argv[1] = "org.kde.kwalletd"; |
136 |
argv[2] = "/modules/kwalletd"; |
137 |
argv[3] = "org.kde.KWallet."+command; |
138 |
for (int i = 0; i < commandArgs.length; i++) { |
139 |
//unfortunatelly I cannot pass char[] to the exec in any way - so this poses a security issue with passwords in String() ! |
140 |
//TODO: find a way to avoid changing char[] into String |
141 |
argv[i+4] = new String(commandArgs[i]); |
142 |
char[] arg = commandArgs[i]; |
143 |
String string = new String(arg); |
144 |
commandString = commandString+" "+string; |
145 |
} |
146 |
|
147 |
Runtime rt = Runtime.getRuntime(); |
148 |
String retVal = ""; |
149 |
try { |
150 |
|
151 |
Process pr = rt.exec(argv); |
152 |
|
153 |
BufferedReader input = new BufferedReader(new InputStreamReader(pr.getInputStream())); |
154 |
|
155 |
String line; |
156 |
while((line = input.readLine()) != null) { |
157 |
if (!retVal.equals("")){ |
158 |
retVal = retVal.concat("\n"); |
159 |
} |
160 |
retVal = retVal.concat(line); |
161 |
} |
162 |
input.close(); |
163 |
input = new BufferedReader(new InputStreamReader(pr.getErrorStream())); |
164 |
|
165 |
while((line = input.readLine()) != null) { |
166 |
if (!retVal.equals("")){ |
167 |
retVal = retVal.concat("\n"); |
168 |
} |
169 |
retVal = retVal.concat(line); |
170 |
} |
171 |
input.close(); |
172 |
|
173 |
|
174 |
int exitVal = pr.waitFor(); |
175 |
if(exitVal!=0){ |
176 |
logger.log(Level.SEVERE,"application exit with code "+exitVal+" for commandString: "+commandString); |
177 |
} |
178 |
|
179 |
} catch (InterruptedException ex) { |
180 |
logger.log(Level.SEVERE, |
181 |
"exception thrown while invoking the command \""+commandString+"\"", |
182 |
ex); |
183 |
} catch (IOException ex) { |
184 |
logger.log(Level.SEVERE, |
185 |
"exception thrown while invoking the command \""+commandString+"\"", |
186 |
ex); |
187 |
} |
188 |
return (!retVal.equals("")) ? retVal.trim().toCharArray() : null; |
189 |
} |
190 |
|
191 |
private char[] getApplicationName(){ |
192 |
String appName; |
193 |
try { |
194 |
appName = MessageFormat.format(NbBundle.getBundle("org.netbeans.core.windows.view.ui.Bundle").getString("CTL_MainWindow_Title_No_Project"),"…"); |
195 |
} catch (MissingResourceException x) { |
196 |
appName = "NetBeans"; |
197 |
} |
198 |
return appName.toCharArray(); |
199 |
} |
200 |
|
201 |
private char[] getApplicationNameWithVersion(){ |
202 |
return (new String(getApplicationName())+" "+System.getProperty("netbeans.buildnumber")).toCharArray(); |
203 |
} |
204 |
|
205 |
public class KwalletException extends RuntimeException{ |
206 |
|
207 |
public KwalletException(String desc) { |
208 |
super("error while trying to access KWallet, during "+desc); |
209 |
} |
210 |
|
211 |
} |
212 |
|
213 |
} |