add function to toggle config file status
[webos-internals:applications.git] / org.webosinternals.ipkgservice / org / webosinternals / ipkgservice / IPKGService.java
1 package org.webosinternals.ipkgservice;
2
3 import java.io.BufferedInputStream;
4 import java.io.BufferedReader;
5 import java.io.File;
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.io.InputStreamReader;
9 import java.util.ArrayList;
10 import java.util.Iterator;
11
12 import com.palm.luna.LSException;
13 import com.palm.luna.service.LunaServiceThread;
14 import com.palm.luna.service.ServiceMessage;
15 import com.palm.luna.message.ErrorMessage;
16
17 import org.json.JSONException;
18 import org.json.JSONObject;
19
20 public class IPKGService extends LunaServiceThread {
21
22         /* ============================== Variables ==============================*/
23         private static final String ipkgBaseCommand = "/usr/bin/ipkg -o /var ";
24         private static final String ipkgConfigDirPath = "/var/etc/ipkg";
25         private Runtime runtime;
26         File ipkgconfdir;
27         boolean ipkgReady = false;
28
29         /**
30          * An object to hold the return value and stdout of the executed command.
31          */
32         private class ReturnResult {
33                 int returnValue;
34                 ArrayList<String> stdOut;
35                 public ReturnResult(int returnValue, ArrayList<String> stdOut) {
36                         this.returnValue = returnValue;
37                         this.stdOut = stdOut;
38                 }
39         }
40
41         /**
42          * Create a new IPKGService
43          */
44         public IPKGService() {
45                 ipkgconfdir = new File(ipkgConfigDirPath);
46                 if (ipkgconfdir.exists()) {
47                         if (ipkgconfdir.isDirectory())
48                                 ipkgReady = true;
49                 } else
50                         ipkgReady = ipkgconfdir.mkdirs();
51                 if (ipkgReady)
52                         runtime = Runtime.getRuntime();
53         }
54
55         private void ipkgDirNotReady(ServiceMessage msg) throws LSException {
56                 msg.respondError(ErrorMessage.ERROR_CODE_METHOD_EXCEPTION, "You fail!");
57         }
58
59         /**
60          * A function to make sure package names are safe
61          * 
62          * @param arg A package name to be passed to ipkg binary
63          * @return True if package name is safe, false if not
64          */
65         private boolean checkArg(String arg) {
66                 String cleaned = arg.replaceAll("/[^A-Za-z0-9.-]/","");
67                 if (cleaned.equals(arg))
68                         return true;
69                 else
70                         return false;
71         }
72
73         /**
74          * Compare version strings
75          * 
76          * @param version1
77          * @param version2
78          * @return 1 is version1 is larger, -1 if version1 is smaller, 0 if equal
79          */
80         private int compareVersions(String[] version1, String[] version2) {
81                 int ret = 0;
82                 int val1 = Integer.valueOf(version1[0]);
83                 int val2 = Integer.valueOf(version2[0]);
84                 if ( val1 > val2 ) {
85                         ret = 1;
86                 } else if ( val1 < val2 ) {             
87                         ret = -1;
88                 } else if ( val1 == val2 ) {
89                         val1 = Integer.valueOf(version1[1]);
90                         val2 = Integer.valueOf(version2[1]);
91                         if ( val1 > val2 ) {
92                                 ret = 1;
93                         } else if ( val1 < val2 ) {
94                                 ret = -1;
95                         } else if ( val1 == val2 ) {
96                                 val1 = Integer.valueOf(version1[2]);
97                                 val2 = Integer.valueOf(version2[2]);
98                                 if ( val1 > val2 ) {
99                                         ret = 1;
100                                 } else if ( val1 < val2 ) {
101                                         ret = -1;
102                                 }
103                         }
104                 }
105                 return ret;
106         }
107
108         /**
109          * A function to execute system commands.
110          * 
111          * @param command The system command to execute
112          * @return A ReturnResult object containing the return value and stdout of
113          * of the executed command.
114          */
115         private ReturnResult executeCMD(String command) {
116                 int ret = 1;
117                 ArrayList<String> output = new ArrayList<String>();
118                 if (checkArg(command)) {
119                         try {
120                                 Process p = runtime.exec(command);
121                                 InputStream in = p.getInputStream();
122                                 BufferedInputStream buf = new BufferedInputStream(in);
123                                 InputStreamReader inread = new InputStreamReader(buf);
124                                 BufferedReader bufferedreader = new BufferedReader(inread);
125
126                                 String line;
127                                 while ((line = bufferedreader.readLine()) != null) {
128                                         output.add(line);
129                                 }
130
131                                 try {
132                                         if (p.waitFor() != 0)
133                                                 System.err.println("exit value = " + p.exitValue());
134                                         else
135                                                 ret = 0;
136                                 } catch (InterruptedException e) {
137                                         System.err.println(e);
138                                 } finally {
139                                         bufferedreader.close();
140                                         inread.close();
141                                         buf.close();
142                                         in.close();
143                                 }
144                         } catch (IOException e) {
145                                 System.err.println(e.getMessage());
146                         }
147                 }
148                 return new ReturnResult(ret, output);
149         }
150         
151         private JSONObject getConfigs() {
152                 ArrayList<String> configNames = new ArrayList<String>();
153                 File[] configs = ipkgconfdir.listFiles();
154                 for (File file : configs) {
155                         if (!file.getName().equals("arch.conf"))
156                                 configNames.add(file.getName());
157                 }
158                 if (configNames.size()>0)
159                         return new JSONObject("configs",(String[])configNames.toArray());
160                 else
161                         return null;
162         }
163         
164         private JSONObject toggleConfigState(String configName)
165         throws JSONException {
166                 JSONObject result = new JSONObject();
167                 File config = new File(ipkgConfigDirPath+"/"+configName);
168                 Boolean status;
169                 if (configName.endsWith(".disabled"))
170                         status = config.renameTo(new File(configName.replace(".disabled", "")));
171                 else
172                         status = config.renameTo(new File(configName+".disabled"));
173                 result.put("returnVal", status);
174                 return result;
175         }
176
177         private JSONObject getList(String listType)
178         throws JSONException, LSException {
179                 ReturnResult ret = executeCMD(ipkgBaseCommand + listType);
180                 if (ret.returnValue==0) {
181                         JSONObject list = new JSONObject();
182                         for (int i=0; i<ret.stdOut.size()-1;i++) {
183                                 String[] item = ret.stdOut.get(i).split(" - ");
184                                 JSONObject info = new JSONObject();
185                                 String name = item[0].trim();
186                                 String version = item[1].trim();
187                                 String description = null;
188                                 if (item.length==3)
189                                         description = item[2].trim();
190                                 info.put("version", version);
191                                 info.put("description", description);
192                                 if (!list.has(name))
193                                         list.put(name, info);
194                                 else {
195                                         JSONObject dupeInfo = list.getJSONObject(name);
196                                         int comparison = compareVersions(version.split("\\."), dupeInfo.get("version").toString().split("\\."));
197                                         if (comparison==1)
198                                                 list.put(name, info);
199                                 }
200                         }
201                         return list;
202                 }
203                 return null;
204         }
205
206         private JSONObject getUpgrades()
207         throws JSONException, LSException {
208                 JSONObject upgrades = new JSONObject();
209                 JSONObject allList = getList("list");
210                 JSONObject installedList = getList("list_installed");
211                 Iterator<String> installedListIter = installedList.keys();
212                 while (installedListIter.hasNext()) {
213                         String packageKey = installedListIter.next();
214                         JSONObject item = installedList.getJSONObject(packageKey);
215                         JSONObject potentialUpgrade = allList.getJSONObject(packageKey);
216                         String[] installedVersionString = item.get("version").toString().split("\\.");
217                         String[] potentialUpgradeVersionString = potentialUpgrade.get("version").toString().split("\\.");
218                         int comparison = compareVersions(installedVersionString, potentialUpgradeVersionString);
219                         if (comparison==-1)
220                                 upgrades.put(packageKey,potentialUpgrade.get("version").toString());
221                 }
222                 if (upgrades.length()>0)
223                         return upgrades;
224                 else
225                         return null;
226         }
227
228         private JSONObject update()
229         throws JSONException, LSException {
230                 ReturnResult ret = executeCMD(ipkgBaseCommand + "update");
231                 if (ret.returnValue==0) {
232                         JSONObject reply = new JSONObject();
233                         reply.put("returnVal",ret.returnValue);
234                         return reply;
235                 } else {
236                         return null;
237                 }
238         }
239
240         private JSONObject install(String packageName)
241         throws JSONException, LSException {
242                 ReturnResult ret = executeCMD(ipkgBaseCommand + "install " + packageName);
243                 if (ret.returnValue==0) {
244                         JSONObject reply = new JSONObject();
245                         reply.put("returnVal",ret.returnValue);
246                         return reply;
247                 } else
248                         return null;
249         }
250
251         private JSONObject remove(String packageName)
252         throws JSONException, LSException {
253                 ReturnResult ret = executeCMD(ipkgBaseCommand + "remove " + packageName);
254                 if (ret.returnValue==0) {
255                         JSONObject reply = new JSONObject();
256                         reply.put("returnVal",ret.returnValue);
257                         return reply;
258                 } else
259                         return null;
260         }
261
262         private JSONObject remove_recursive(String packageName)
263         throws JSONException, LSException {
264                 ReturnResult ret = executeCMD(ipkgBaseCommand + "-recursive remove " + packageName);
265                 if (ret.returnValue==0) {
266                         JSONObject reply = new JSONObject();
267                         reply.put("returnVal",ret.returnValue);
268                         return reply;
269                 } else
270                         return null;
271         }
272
273         /* ============================ DBUS Methods =============================*/
274
275         @LunaServiceThread.PublicMethod
276         public void list(ServiceMessage msg)
277         throws JSONException, LSException {
278                 if (ipkgReady) {
279                 JSONObject reply = getList("list");
280                 if (reply!=null)
281                         msg.respond(reply.toString());
282                 else
283                         msg.respondError(ErrorMessage.ERROR_CODE_METHOD_EXCEPTION, "You fail!");
284                 } else
285                         ipkgDirNotReady(msg);
286         }
287
288         @LunaServiceThread.PublicMethod
289         public void list_installed(ServiceMessage msg)
290         throws JSONException, LSException {
291                 if (ipkgReady) {
292                 JSONObject reply = getList("list_installed");
293                 if (reply!=null)
294                         msg.respond(reply.toString());
295                 else
296                         msg.respondError(ErrorMessage.ERROR_CODE_METHOD_EXCEPTION, "You fail!");
297                 } else
298                         ipkgDirNotReady(msg);
299         }
300
301         @LunaServiceThread.PublicMethod
302         public void list_upgrades(ServiceMessage msg)
303         throws JSONException, LSException {
304                 if (ipkgReady) {
305                 JSONObject reply = getUpgrades();
306                 if (reply!=null)
307                         msg.respond(reply.toString());
308                 else
309                         msg.respondError(ErrorMessage.ERROR_CODE_METHOD_EXCEPTION, "You fail!");
310                 } else
311                         ipkgDirNotReady(msg);
312         }
313
314         @LunaServiceThread.PublicMethod
315         public void install(ServiceMessage msg)
316         throws JSONException, LSException {
317                 if (ipkgReady) {
318                 if (msg.getJSONPayload().has("package")) {
319                         String pkg = msg.getJSONPayload().getString("package").trim();
320                         if (checkArg(pkg)) {
321                                 JSONObject reply = install(pkg);
322                                 if (reply!=null)
323                                         msg.respond(reply.toString());
324                                 else
325                                         msg.respondError(ErrorMessage.ERROR_CODE_METHOD_EXCEPTION, "You fail!");
326                         }
327                 } else
328                         msg.respondError(ErrorMessage.ERROR_CODE_METHOD_EXCEPTION, "You fail!");
329                 } else
330                         ipkgDirNotReady(msg);
331         }
332
333         @LunaServiceThread.PublicMethod
334         public void remove(ServiceMessage msg)
335         throws JSONException, LSException {
336                 if (ipkgReady) {
337                 if (msg.getJSONPayload().has("package")) {
338                         String pkg = msg.getJSONPayload().getString("package").trim();
339                         if (checkArg(pkg)) {
340                                 JSONObject reply = remove(pkg);
341                                 if (reply!=null)
342                                         msg.respond(reply.toString());
343                                 else
344                                         msg.respondError(ErrorMessage.ERROR_CODE_METHOD_EXCEPTION, "You fail!");
345                         }
346                 } else
347                         msg.respondError(ErrorMessage.ERROR_CODE_METHOD_EXCEPTION, "You fail!");
348                 } else
349                         ipkgDirNotReady(msg);
350         }
351
352         @LunaServiceThread.PublicMethod
353         public void remove_recursive(ServiceMessage msg)
354         throws JSONException, LSException {
355                 if (ipkgReady) {
356                         if (msg.getJSONPayload().has("package")) {
357                                 String pkg = msg.getJSONPayload().getString("package").trim();
358                                 if (checkArg(pkg)) {
359                                         JSONObject reply = remove_recursive(pkg);
360                                         if (reply!=null)
361                                                 msg.respond(reply.toString());
362                                         else
363                                                 msg.respondError(ErrorMessage.ERROR_CODE_METHOD_EXCEPTION, "You fail!");
364                                 }
365                         } else
366                                 msg.respondError(ErrorMessage.ERROR_CODE_METHOD_EXCEPTION, "You fail!");
367                 } else
368                         ipkgDirNotReady(msg);
369         }
370
371         @LunaServiceThread.PublicMethod
372         public void update(ServiceMessage msg)
373         throws JSONException, LSException {
374                 if (ipkgReady) {
375                         JSONObject reply = update();
376                         if (reply!=null)
377                                 msg.respond(reply.toString());
378                         else
379                                 msg.respondError(ErrorMessage.ERROR_CODE_METHOD_EXCEPTION, "You fail!");
380                 } else
381                         ipkgDirNotReady(msg);
382         }
383         
384         @LunaServiceThread.PublicMethod
385         public void get_configs(ServiceMessage msg)
386         throws JSONException, LSException {
387                 if (ipkgReady) {
388                         JSONObject reply = getConfigs();
389                         if (reply!=null)
390                                 msg.respond(reply.toString());
391                         else
392                                 msg.respondError(ErrorMessage.ERROR_CODE_METHOD_EXCEPTION, "You fail!");
393                 } else
394                         ipkgDirNotReady(msg);
395         }
396
397 }