lixmaker.pl 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. #!/usr/bin/perl
  2. #
  3. # Copyright (C) 2011 Trizen <trizenx@gmail.com>.
  4. #
  5. # This program is free software: you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation, either version 3 of the License, or
  8. # (at your option) any later version.
  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, see <http://www.gnu.org/licenses/>.
  17. #
  18. # Experimental install maker.
  19. use Cwd;
  20. use MIME::Base64;
  21. use Gtk2 ('-init');
  22. my $cwd = getcwd();
  23. my $gui = 'Gtk2::Builder'->new;
  24. my $appname = 'lixmaker';
  25. my $version = '0.0.1';
  26. if (-e "$appname.glade") {
  27. $share_path = '';
  28. $interface_file = "$appname.glade";
  29. }
  30. else {
  31. $share_path = "/usr/share/$appname/";
  32. $interface_file = "$share_path$appname.glade";
  33. }
  34. $gui->add_from_file($interface_file);
  35. $gui->connect_signals(undef);
  36. my $mainw = $gui->get_object('window1');
  37. $mainw->set_title("$appname $version");
  38. $gui->get_object('entry3')->set_text($cwd);
  39. my $x_glade_interface = join('', <DATA>);
  40. 'Gtk2'->main;
  41. sub filechooser {
  42. $win = $gui->get_object('filechooserdialog1');
  43. $win->show;
  44. }
  45. sub about {
  46. $win = $gui->get_object('aboutdialog1');
  47. $win->set_logo('Gtk2::Gdk::Pixbuf'->new_from_file("$share_path$appname.png"));
  48. $win->show;
  49. }
  50. sub hide {
  51. $win->hide;
  52. }
  53. sub exit {
  54. exit;
  55. }
  56. sub get_filename {
  57. my $filename = $win->get_filename;
  58. $gui->get_object('entry1')->set_text($filename);
  59. if ($gui->get_object('appname')->get_text eq 'Application Name') {
  60. $gui->get_object('appname')->set_text($1) if $filename =~ m[([^/]+)$];
  61. }
  62. &hide;
  63. }
  64. sub create_installer {
  65. $tarball = $gui->get_object('entry1')->get_text;
  66. &error($!) unless -r -f $tarball;
  67. my $outname = $gui->get_object('appname')->get_text . '-' . $gui->get_object('appver')->get_text;
  68. &error('No output path specified!')
  69. unless $output_path = $gui->get_object('entry3')->get_text;
  70. &error($!) unless -d -w $output_path;
  71. my $output_name = "$output_path/$outname";
  72. my $n = 1;
  73. if (-e "$output_name.lix") {
  74. $final_name = "$output_name ($n).lix";
  75. while (-e $final_name) {
  76. $n += 1;
  77. $final_name = "$output_name ($n).lix";
  78. }
  79. }
  80. $output_name = $final_name if $final_name;
  81. print $output_name . "\n";
  82. $output_name .= '.lix' unless $output_name =~ /\.lix$/;
  83. my $textview = $gui->get_object('textview1');
  84. my $description =
  85. $textview->get_buffer->get_text($textview->get_buffer->get_start_iter, $textview->get_buffer->get_end_iter, 1);
  86. my $appname = $gui->get_object('appname')->get_text;
  87. $appname =~ s[/][ ]g;
  88. $appname =~ s/~/\\~/g;
  89. $outname =~ s/~/\\~/g;
  90. $description =~ s/~/\\~/g;
  91. my $untar_line = $gui->get_object('untar_line')->get_text;
  92. my $tmp_file = '/tmp/__temporary_file__.tmp';
  93. $untar_line =~ s/\$APPNAME/$tmp_file/g;
  94. &error(q['untar_line' must contain the '$APPNAME' variable!])
  95. unless $untar_line =~ /$tmp_file/;
  96. $untar_line = quotemeta $untar_line;
  97. &error($!) unless open IN, $tarball;
  98. &error($!) unless open OUT, '>', $output_name;
  99. print OUT "#!/usr/bin/perl\n";
  100. print OUT "use MIME::Base64;
  101. sub make_tar {
  102. open FILE, '>', '${tmp_file}' or &dialog('Unable to continue',\$!);
  103. while(<DATA>){
  104. print FILE &decode_base64(\$_);
  105. }
  106. close FILE;
  107. }
  108. ";
  109. if ($gui->get_object('cli')->get_active) {
  110. print OUT "print q~* Application name: '${outname}'\n~;\n";
  111. print OUT "print q~* Description\n> $description\n~;" if $description;
  112. print OUT qq[
  113. if (\$ENV{'USER'} eq 'root'){
  114. print "* Press <ENTER> to continue or insert 'q' to exit...\\n> ";
  115. chomp(my \$stdin = <STDIN>);
  116. exit if \$stdin =~ /^(?:q|quit|exit)\$/;
  117. &make_tar;
  118. system('${untar_line}');
  119. }else{
  120. if(-e '/usr/bin/sudo'){
  121. &make_tar;
  122. system('sudo ${untar_line}');
  123. }else{
  124. &make_tar;
  125. system('su -c ${untar_line}');
  126. }
  127. }
  128. ];
  129. }
  130. elsif (not $gui->get_object('silent')->get_active) {
  131. print OUT "\$interface = qq[$x_glade_interface];
  132. \nuse Gtk2 ('-init');
  133. \$gui = 'Gtk2::Builder'->new;
  134. \$gui->add_from_string(\$interface);
  135. \$gui->connect_signals(undef);
  136. \$mainw = \$gui->get_object('window1');
  137. \$mainw->set_title(q~'${outname}' installer - Created with lixmaker~);
  138. \$gui->get_object('title')->set_label(q~$outname~);
  139. \$gui->get_object('description')->set_label(q~$description~);
  140. 'Gtk2'->main;
  141. \nsub install {
  142. if(\$ENV{'USER'} eq 'root'){
  143. &make_tar;
  144. system(\"${untar_line}\");
  145. }else{
  146. if(not -e '/usr/bin/gksu' or not -e '/usr/local/bin/gksu'){
  147. &dialog('Error', 'Please install the \\'gksu\\' application to continue...');
  148. }
  149. &make_tar;
  150. system('gksu ${untar_line}');
  151. }
  152. &dialog('Congratulations!',q~'${appname}' was successfully installed.~);
  153. }
  154. sub dialog{
  155. \$gui->get_object('label1')->set_text(\$_[0]);
  156. \$gui->get_object('label2')->set_text(\$_[1]);
  157. \$win = \$gui->get_object('dialog1');
  158. \$win->show;
  159. }
  160. sub exit{
  161. unlink '${tmp_file}' if -e '${tmp_file}';
  162. exit;
  163. }
  164. ";
  165. }
  166. elsif ($gui->get_object('silent')->get_active) {
  167. print OUT "
  168. if (\$ENV{'USER'} eq 'root'){
  169. &make_tar;
  170. system(\"${untar_line}\");
  171. }else{
  172. if(-e '/usr/bin/gksu'){
  173. &make_tar;
  174. system('gksu ${untar_line}');
  175. }
  176. elsif(-e '/usr/bin/sudo'){
  177. &make_tar;
  178. system('sudo ${untar_line}');
  179. }else{
  180. &make_tar;
  181. system('su -c ${untar_line}');
  182. }
  183. }
  184. unlink '${tmp_file}' if -e '${tmp_file}';
  185. ";
  186. }
  187. print OUT "__DATA__\n";
  188. while (defined($_ = <IN>)) {
  189. print OUT &MIME::Base64::encode($_);
  190. }
  191. close OUT;
  192. $ok_text = "$outname was successfully created to\n$output_name";
  193. chmod 0755, $output_name;
  194. &ok($ok_text) if -e $output_name;
  195. }
  196. sub error {
  197. $gui->get_object('label7')->set_text($_[0]);
  198. $win = $gui->get_object('dialog1');
  199. $win->show;
  200. die;
  201. }
  202. sub ok {
  203. $gui->get_object('label9')->set_text($_[0]);
  204. $win = $gui->get_object('dialog2');
  205. $win->show;
  206. }
  207. __DATA__
  208. <?xml version="1.0" encoding="UTF-8"?>
  209. <interface>
  210. <requires lib="gtk+" version="2.16"/>
  211. <!-- interface-naming-policy project-wide -->
  212. <object class="GtkDialog" id="dialog1">
  213. <property name="can_focus">False</property>
  214. <property name="border_width">5</property>
  215. <property name="window_position">center-on-parent</property>
  216. <property name="type_hint">dialog</property>
  217. <property name="transient_for">window1</property>
  218. <signal name="close" handler="exit" swapped="no"/>
  219. <child internal-child="vbox">
  220. <object class="GtkVBox" id="dialog-vbox1">
  221. <property name="visible">True</property>
  222. <property name="can_focus">False</property>
  223. <property name="spacing">2</property>
  224. <child internal-child="action_area">
  225. <object class="GtkHButtonBox" id="dialog-action_area1">
  226. <property name="visible">True</property>
  227. <property name="can_focus">False</property>
  228. <property name="layout_style">end</property>
  229. <child>
  230. <object class="GtkButton" id="button4">
  231. <property name="label">gtk-ok</property>
  232. <property name="visible">True</property>
  233. <property name="can_focus">True</property>
  234. <property name="receives_default">True</property>
  235. <property name="use_action_appearance">False</property>
  236. <property name="use_stock">True</property>
  237. <signal name="clicked" handler="exit" swapped="no"/>
  238. </object>
  239. <packing>
  240. <property name="expand">False</property>
  241. <property name="fill">False</property>
  242. <property name="position">0</property>
  243. </packing>
  244. </child>
  245. <child>
  246. <object class="GtkButton" id="button3">
  247. <property name="label">gtk-close</property>
  248. <property name="visible">True</property>
  249. <property name="can_focus">True</property>
  250. <property name="receives_default">True</property>
  251. <property name="use_action_appearance">False</property>
  252. <property name="use_stock">True</property>
  253. <signal name="clicked" handler="exit" swapped="no"/>
  254. </object>
  255. <packing>
  256. <property name="expand">False</property>
  257. <property name="fill">False</property>
  258. <property name="position">1</property>
  259. </packing>
  260. </child>
  261. </object>
  262. <packing>
  263. <property name="expand">False</property>
  264. <property name="fill">True</property>
  265. <property name="pack_type">end</property>
  266. <property name="position">0</property>
  267. </packing>
  268. </child>
  269. <child>
  270. <object class="GtkLabel" id="label1">
  271. <property name="visible">True</property>
  272. <property name="can_focus">False</property>
  273. <property name="label" translatable="yes">Congratulations!</property>
  274. <attributes>
  275. <attribute name="scale" value="1.7"/>
  276. </attributes>
  277. </object>
  278. <packing>
  279. <property name="expand">True</property>
  280. <property name="fill">True</property>
  281. <property name="position">1</property>
  282. </packing>
  283. </child>
  284. <child>
  285. <object class="GtkLabel" id="label2">
  286. <property name="visible">True</property>
  287. <property name="can_focus">False</property>
  288. <property name="label" translatable="yes">label</property>
  289. </object>
  290. <packing>
  291. <property name="expand">True</property>
  292. <property name="fill">True</property>
  293. <property name="position">2</property>
  294. </packing>
  295. </child>
  296. </object>
  297. </child>
  298. <action-widgets>
  299. <action-widget response="0">button4</action-widget>
  300. <action-widget response="0">button3</action-widget>
  301. </action-widgets>
  302. </object>
  303. <object class="GtkImage" id="image2">
  304. <property name="visible">True</property>
  305. <property name="can_focus">False</property>
  306. <property name="icon_name">package-x-generic</property>
  307. </object>
  308. <object class="GtkWindow" id="window1">
  309. <property name="visible">True</property>
  310. <property name="can_focus">False</property>
  311. <property name="icon_name">package-x-generic</property>
  312. <signal name="destroy" handler="exit" swapped="no"/>
  313. <child>
  314. <object class="GtkVBox" id="vbox1">
  315. <property name="visible">True</property>
  316. <property name="can_focus">False</property>
  317. <child>
  318. <object class="GtkHBox" id="hbox1">
  319. <property name="visible">True</property>
  320. <property name="can_focus">False</property>
  321. <child>
  322. <object class="GtkVBox" id="vbox2">
  323. <property name="visible">True</property>
  324. <property name="can_focus">False</property>
  325. <child>
  326. <object class="GtkLabel" id="title">
  327. <property name="visible">True</property>
  328. <property name="can_focus">False</property>
  329. <property name="label" translatable="yes">label</property>
  330. <attributes>
  331. <attribute name="weight" value="bold"/>
  332. <attribute name="scale" value="1.5"/>
  333. </attributes>
  334. </object>
  335. <packing>
  336. <property name="expand">False</property>
  337. <property name="fill">False</property>
  338. <property name="position">0</property>
  339. </packing>
  340. </child>
  341. <child>
  342. <object class="GtkLabel" id="description">
  343. <property name="visible">True</property>
  344. <property name="can_focus">False</property>
  345. <property name="label" translatable="yes">label</property>
  346. </object>
  347. <packing>
  348. <property name="expand">True</property>
  349. <property name="fill">True</property>
  350. <property name="position">1</property>
  351. </packing>
  352. </child>
  353. </object>
  354. <packing>
  355. <property name="expand">True</property>
  356. <property name="fill">True</property>
  357. <property name="position">0</property>
  358. </packing>
  359. </child>
  360. </object>
  361. <packing>
  362. <property name="expand">True</property>
  363. <property name="fill">True</property>
  364. <property name="position">0</property>
  365. </packing>
  366. </child>
  367. <child>
  368. <object class="GtkHBox" id="hbox2">
  369. <property name="visible">True</property>
  370. <property name="can_focus">False</property>
  371. <child>
  372. <object class="GtkButton" id="button1">
  373. <property name="label" translatable="yes">Install</property>
  374. <property name="visible">True</property>
  375. <property name="can_focus">True</property>
  376. <property name="receives_default">True</property>
  377. <property name="use_action_appearance">False</property>
  378. <property name="image">image2</property>
  379. <signal name="clicked" handler="install" swapped="no"/>
  380. </object>
  381. <packing>
  382. <property name="expand">True</property>
  383. <property name="fill">True</property>
  384. <property name="position">0</property>
  385. </packing>
  386. </child>
  387. <child>
  388. <object class="GtkButton" id="button2">
  389. <property name="label">gtk-close</property>
  390. <property name="visible">True</property>
  391. <property name="can_focus">True</property>
  392. <property name="receives_default">True</property>
  393. <property name="use_action_appearance">False</property>
  394. <property name="use_stock">True</property>
  395. <signal name="clicked" handler="exit" swapped="no"/>
  396. </object>
  397. <packing>
  398. <property name="expand">True</property>
  399. <property name="fill">True</property>
  400. <property name="position">1</property>
  401. </packing>
  402. </child>
  403. </object>
  404. <packing>
  405. <property name="expand">False</property>
  406. <property name="fill">False</property>
  407. <property name="position">1</property>
  408. </packing>
  409. </child>
  410. </object>
  411. </child>
  412. </object>
  413. </interface>