gestion 1.9.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +48 -0
- data/.project +14 -0
- data/Binaries/adduser_to_buzz +15 -0
- data/Binaries/backup +7 -0
- data/Binaries/check_gestion +8 -0
- data/Binaries/gestion.gnumail +22 -0
- data/Binaries/gestion.logrotate +34 -0
- data/Binaries/gestion.service +12 -0
- data/Binaries/gestion_update.rb +183 -0
- data/Binaries/gestion_update.service +10 -0
- data/Binaries/get_compta +11 -0
- data/Binaries/kill_gestion +16 -0
- data/Binaries/ldap/add_indexes +51 -0
- data/Binaries/ldap/backup +2 -0
- data/Binaries/ldap/install_ldap +92 -0
- data/Binaries/ldap/restore +7 -0
- data/Binaries/lib_backup +5 -0
- data/Binaries/log_scan_errors +8 -0
- data/Binaries/loop_gestion +64 -0
- data/Binaries/onetimers/sync_courses_from_compta.rb +74 -0
- data/Binaries/onetimers/transfer_cash_from_ldap_to_csv +26 -0
- data/Binaries/reboot +5 -0
- data/Binaries/restore +3 -0
- data/Binaries/restore_do +22 -0
- data/Binaries/sort_events +31 -0
- data/Binaries/start_gestion +18 -0
- data/Binaries/swipe_gestion +18 -0
- data/Binaries/update_africompta +21 -0
- data/Binaries/update_users +3 -0
- data/Diplomas.src/accredited.odg +0 -0
- data/Diplomas.src/diploma.odg +0 -0
- data/Diplomas.src/label.odg +0 -0
- data/Diplomas.src/presence_sheet.ods +0 -0
- data/Diplomas.src/presence_sheet_small.ods +0 -0
- data/Diplomas.src/student_card.odg +0 -0
- data/Doc/130514-it-ideas.odt +0 -0
- data/Doc/Compta-cash.mm +179 -0
- data/Doc/General.odt +0 -0
- data/Entities/AccessGroups.rb +117 -0
- data/Entities/Activity.rb +178 -0
- data/Entities/ChatMsg.rb +142 -0
- data/Entities/Classroom.rb +11 -0
- data/Entities/Client.rb +19 -0
- data/Entities/Computer.rb +21 -0
- data/Entities/ConfigBase.rb +280 -0
- data/Entities/Course.rb +1588 -0
- data/Entities/CourseType.rb +171 -0
- data/Entities/DFiles.rb +466 -0
- data/Entities/FilesManage.rb +226 -0
- data/Entities/Grade.rb +186 -0
- data/Entities/Internet.rb +300 -0
- data/Entities/Netdev.rb +10 -0
- data/Entities/Person.rb +1175 -0
- data/Entities/Plug.rb +98 -0
- data/Entities/Quiz.rb +33 -0
- data/Entities/Recharges.rb +37 -0
- data/Entities/Report.rb +136 -0
- data/Entities/Room.rb +12 -0
- data/Entities/SMS.rb +30 -0
- data/Entities/ScheduleType.rb +33 -0
- data/Entities/Share.rb +120 -0
- data/Entities/Task.rb +51 -0
- data/Entities/Ticket.rb +72 -0
- data/Entities/Usage.rb +143 -0
- data/Entities/Worker.rb +29 -0
- data/Files/apache-profeda.conf +36 -0
- data/Files/label.erb +121 -0
- data/Files/label_notfound.erb +64 -0
- data/Files/label_notpassed.erb +84 -0
- data/Files/mobileinfo.erb +115 -0
- data/Files/smb.conf +333 -0
- data/Files/timetable.html +36 -0
- data/Files/timetable.js +239 -0
- data/Gemfile +12 -0
- data/Gemfile.dev +12 -0
- data/Gemfile.dev.lock +127 -0
- data/Gemfile.lock +127 -0
- data/Gemfile.prod +8 -0
- data/Gestion +35 -0
- data/Gestion.rb +220 -0
- data/INSTALL +40 -0
- data/Images/connection.xcf +0 -0
- data/Images/connection_no.png +0 -0
- data/Images/connection_wait.png +0 -0
- data/Images/connection_yes.png +0 -0
- data/Paths/Exas.rb +13 -0
- data/Paths/Files.rb +19 -0
- data/Paths/GetDiplomas.rb +20 -0
- data/Paths/Info.rb +114 -0
- data/Paths/Label.rb +187 -0
- data/Paths/MobileInfo.rb +19 -0
- data/Paths/internetCash.rb +34 -0
- data/Paths/internetWifi.rb +54 -0
- data/README.md +60 -0
- data/Rakefile +13 -0
- data/TODO +1391 -0
- data/Test/.gitignore +3 -0
- data/Test/Diplomas/base_gestion.odt +0 -0
- data/Test/Diplomas/base_report.odt +0 -0
- data/Test/Diplomas/carte_etudiant.odg +0 -0
- data/Test/Diplomas/exam_language.odt +0 -0
- data/Test/Diplomas/label.odg +0 -0
- data/Test/Diplomas/presence_sheet.ods +0 -0
- data/Test/Diplomas/presence_sheet_small.ods +0 -0
- data/Test/Diplomas/student_card.odg +0 -0
- data/Test/Manual/testMerge +18 -0
- data/Test/config_test.yaml +26 -0
- data/Test/db.testGestion +0 -0
- data/Test/dfiles/descs/avg-rescue.desc +10 -0
- data/Test/dfiles/descs/avg.desc +8 -0
- data/Test/dfiles/descs/driver.desc +8 -0
- data/Test/dfiles/descs/linuxmint.desc +7 -0
- data/Test/dfiles/files/avg-160203.exe +1 -0
- data/Test/dfiles/files/avg.iso +1 -0
- data/Test/dfiles/files/driver.exe +1 -0
- data/Test/dfiles/index_post.html +3 -0
- data/Test/dfiles/index_pre.html +8 -0
- data/Test/dfiles/priorities +5 -0
- data/Test/ge_activity.rb +124 -0
- data/Test/ge_chat.rb +106 -0
- data/Test/ge_compta.rb +67 -0
- data/Test/ge_configbase.rb +54 -0
- data/Test/ge_course.rb +1114 -0
- data/Test/ge_dfiles.rb +121 -0
- data/Test/ge_filesmanage.rb +180 -0
- data/Test/ge_info.rb +27 -0
- data/Test/ge_internet.rb +246 -0
- data/Test/ge_login.rb +55 -0
- data/Test/ge_person.rb +373 -0
- data/Test/ge_qvinfo.rb +28 -0
- data/Test/ge_report.rb +97 -0
- data/Test/ge_share.rb +27 -0
- data/Test/ge_sms.rb +34 -0
- data/Test/ge_tasks.rb +19 -0
- data/Test/ge_usage.rb +168 -0
- data/Test/ge_view.rb +46 -0
- data/Test/multiconf-captive +29 -0
- data/Test/test.conf +7 -0
- data/Test/test.rb +49 -0
- data/Test/test_bytes.png +0 -0
- data/VERSION +140 -0
- data/Views/Admin/Backup.rb +91 -0
- data/Views/Admin/Configuration.rb +44 -0
- data/Views/Admin/Credit.rb +32 -0
- data/Views/Admin/FilesManage.rb +219 -0
- data/Views/Admin/Function.rb +39 -0
- data/Views/Admin/Power.rb +49 -0
- data/Views/Admin/Printer.rb +37 -0
- data/Views/Admin/Server.rb +252 -0
- data/Views/Admin/Tabs.rb +5 -0
- data/Views/Admin/Update.rb +73 -0
- data/Views/Admin/UpdateSystem.rb +26 -0
- data/Views/Cashbox/Activity.rb +191 -0
- data/Views/Cashbox/Course.rb +141 -0
- data/Views/Cashbox/Credit.rb +79 -0
- data/Views/Cashbox/Report.rb +115 -0
- data/Views/Cashbox/Service.rb +105 -0
- data/Views/Cashbox/Tabs.rb +10 -0
- data/Views/Compta/Accounts.rb +36 -0
- data/Views/Compta/Course.rb +96 -0
- data/Views/Compta/Show.rb +6 -0
- data/Views/Compta/Transfer.rb +66 -0
- data/Views/Course/Diploma.rb +203 -0
- data/Views/Course/Grade.rb +401 -0
- data/Views/Course/Modify.rb +447 -0
- data/Views/Course/Print.rb +94 -0
- data/Views/Course/Responsible.rb +44 -0
- data/Views/Course/Stats.rb +76 -0
- data/Views/Course/Students.rb +92 -0
- data/Views/Course/Tabs.rb +220 -0
- data/Views/Internet/Access.rb +134 -0
- data/Views/Internet/ClassEdit.rb +24 -0
- data/Views/Internet/ClassUsers.rb +81 -0
- data/Views/Internet/Config.rb +32 -0
- data/Views/Internet/Mobile.rb +213 -0
- data/Views/Internet/Recharges.rb +49 -0
- data/Views/Internet/Tabs.rb +6 -0
- data/Views/Inventory/Computer.rb +24 -0
- data/Views/Inventory/Room.rb +18 -0
- data/Views/Inventory/Tabs.rb +9 -0
- data/Views/Inventory/TicketClosed.rb +7 -0
- data/Views/Inventory/TicketOpen.rb +23 -0
- data/Views/Library/Person.rb +36 -0
- data/Views/Library/Tabs.rb +7 -0
- data/Views/Network/Block.rb +87 -0
- data/Views/Network/Netdevs.rb +21 -0
- data/Views/Network/Restriction.rb +37 -0
- data/Views/Network/Share.rb +167 -0
- data/Views/Network/Tables.rb +28 -0
- data/Views/Network/Tabs.rb +6 -0
- data/Views/Person/Admin.rb +99 -0
- data/Views/Person/Center.rb +48 -0
- data/Views/Person/Course.rb +72 -0
- data/Views/Person/Modify.rb +153 -0
- data/Views/Person/Tabs.rb +162 -0
- data/Views/Report/ComptaExecutive.rb +221 -0
- data/Views/Report/ComptaFlat.rb +79 -0
- data/Views/Report/ReportCourse.rb +47 -0
- data/Views/Report/Tabs.rb +8 -0
- data/Views/Report/Usage.rb +52 -0
- data/Views/Report/UsageCases.rb +59 -0
- data/Views/Self/Cash.rb +67 -0
- data/Views/Self/Chat.rb +55 -0
- data/Views/Self/Concours.rb +109 -0
- data/Views/Self/Email.rb +34 -0
- data/Views/Self/Internet.rb +255 -0
- data/Views/Self/Results.rb +17 -0
- data/Views/Self/Services.rb +85 -0
- data/Views/Self/Show.rb +47 -0
- data/Views/Self/Tabs.rb +5 -0
- data/Views/Special/DFileEdit.rb +13 -0
- data/Views/Special/PlugEdit.rb +56 -0
- data/Views/Special/Tabs.rb +6 -0
- data/Views/Special/Vnc.rb +39 -0
- data/Views/Task/Client.rb +21 -0
- data/Views/Task/Edit.rb +33 -0
- data/Views/Task/List.rb +55 -0
- data/Views/Task/Tabs.rb +9 -0
- data/Views/Task/Worker.rb +30 -0
- data/Views/Template/Activity.rb +33 -0
- data/Views/Template/CourseType.rb +63 -0
- data/Views/Template/ScheduleType.rb +29 -0
- data/Views/Template/Tabs.rb +5 -0
- data/Views/Welcome.rb +121 -0
- data/config.yaml.default +36 -0
- data/po/Gestion-ar.po +2356 -0
- data/po/Gestion-en.mo +0 -0
- data/po/Gestion-en.po +4363 -0
- data/po/Gestion-fr.mo +0 -0
- data/po/Gestion-fr.po +4345 -0
- data/po/traduction-ar.rtf +76 -0
- metadata +381 -0
@@ -0,0 +1,171 @@
|
|
1
|
+
# To change this template, choose Tools | Templates
|
2
|
+
# and open the template in the editor.
|
3
|
+
|
4
|
+
class CourseTypes < Entities
|
5
|
+
def setup_data
|
6
|
+
value_str :file_diploma
|
7
|
+
value_str :file_exam
|
8
|
+
|
9
|
+
value_block :strings
|
10
|
+
value_str :name
|
11
|
+
value_str :duration
|
12
|
+
|
13
|
+
value_block :long
|
14
|
+
value_str :description
|
15
|
+
value_text :contents
|
16
|
+
|
17
|
+
value_block :central
|
18
|
+
value_list_drop :diploma_type, '%w( simple files accredited report )'
|
19
|
+
value_list_drop :output, '%w( certificate label )'
|
20
|
+
value_list_drop :diploma_lang, '%w( en fr )'
|
21
|
+
value_list_drop :page_format,
|
22
|
+
"[[1,'normal'],[2,'interchanged'],[3,'landscape'],[4,'seascape']]"
|
23
|
+
value_list_drop :remark, '%w(false true)'
|
24
|
+
|
25
|
+
value_block :lists
|
26
|
+
value_str :tests_str
|
27
|
+
value_int :tests_nbr
|
28
|
+
value_str :files_str
|
29
|
+
value_int :files_nbr
|
30
|
+
|
31
|
+
value_block :accounting
|
32
|
+
value_int :salary_teacher
|
33
|
+
value_int :cost_student
|
34
|
+
|
35
|
+
value_block :account
|
36
|
+
value_entity_account :account_base, :drop, :path
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.files
|
40
|
+
ddir = Courses.dir_diplomas
|
41
|
+
Dir.glob(ddir + '/*{odt,odg,ods}').
|
42
|
+
collect { |f| f.sub(/^.*\//, '') }
|
43
|
+
end
|
44
|
+
|
45
|
+
def set_entry(id, field, value)
|
46
|
+
case field.to_s
|
47
|
+
when 'name'
|
48
|
+
value.gsub!(/[^a-zA-Z0-9_-]/, '_')
|
49
|
+
end
|
50
|
+
super(id, field, value)
|
51
|
+
end
|
52
|
+
|
53
|
+
def listp_name
|
54
|
+
CourseTypes.listp_name
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.listp_name
|
58
|
+
self.search_all_.collect { |ct|
|
59
|
+
[ct.coursetype_id, ct.name]
|
60
|
+
}.sort { |a, b| a[1].downcase <=> b[1].downcase }
|
61
|
+
end
|
62
|
+
|
63
|
+
def migration_1(ct)
|
64
|
+
ct.tests = 1
|
65
|
+
ct.output = ['certificate']
|
66
|
+
end
|
67
|
+
|
68
|
+
def migration_2(ct)
|
69
|
+
ct.diploma_type = ['simple']
|
70
|
+
end
|
71
|
+
|
72
|
+
def migration_3(ct)
|
73
|
+
ct.page_format = [0]
|
74
|
+
end
|
75
|
+
|
76
|
+
def migration_4(ct)
|
77
|
+
ct.page_format[0] += 1
|
78
|
+
end
|
79
|
+
|
80
|
+
# Changed tests to tests_str and files_needed to files_str
|
81
|
+
def migration_5_raw(ct)
|
82
|
+
if (ct._tests_nbr = ct._tests.to_i) > 0
|
83
|
+
ct._tests_str = (1..ct._tests_nbr).collect { |t| "Test #{t}" }.join("\n")
|
84
|
+
end
|
85
|
+
if (ct._files_nbr = ct._files_needed.to_i) > 0
|
86
|
+
ct._files_str = (1..ct._files_nbr).collect { |f| "Files #{f}" }.join("\n")
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def migration_6(ct)
|
91
|
+
ct.diploma_lang = ['fr']
|
92
|
+
end
|
93
|
+
|
94
|
+
def icc_list(arg)
|
95
|
+
list_name
|
96
|
+
end
|
97
|
+
|
98
|
+
def icc_fetch(arg)
|
99
|
+
if ct_names = arg._course_type_names
|
100
|
+
ct_names.collect { |ct|
|
101
|
+
self.find_by_name(ct) or return "Error: CourseType #{ct} doesn't exist"
|
102
|
+
}
|
103
|
+
else
|
104
|
+
return 'Error: no course_type_name given'
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def icc_file(arg)
|
109
|
+
file = "#{ConfigBase.template_dir}/#{File.basename(arg._name.first)}"
|
110
|
+
if File.exists? file
|
111
|
+
log_msg :CourseTypes, "Sending file #{file}"
|
112
|
+
IO.binread(file)
|
113
|
+
else
|
114
|
+
log_msg :CourseTypes, "Didn't find #{file.inspect}"
|
115
|
+
return "Error: can't find file"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
class CourseType < Entity
|
121
|
+
def setup_instance
|
122
|
+
self.diploma_lang ||= ['fr']
|
123
|
+
self.files_nbr ||= 0
|
124
|
+
end
|
125
|
+
|
126
|
+
def get_unique
|
127
|
+
name
|
128
|
+
end
|
129
|
+
|
130
|
+
def clean_str(str)
|
131
|
+
s = str.to_s.split("\n").
|
132
|
+
collect { |s| s.sub(/^\s*/, '').sub(/\s*$/, '') }.
|
133
|
+
select { |s| s.length > 0 }
|
134
|
+
[s.join("\n"), s.length]
|
135
|
+
end
|
136
|
+
|
137
|
+
def tests_str=(str)
|
138
|
+
self._tests_str, self.tests_nbr = clean_str(str)
|
139
|
+
end
|
140
|
+
|
141
|
+
def tests_arr
|
142
|
+
tests_str.to_s.split("\n")
|
143
|
+
end
|
144
|
+
|
145
|
+
def files_str=(str)
|
146
|
+
self._files_str, self.files_nbr = clean_str(str)
|
147
|
+
end
|
148
|
+
|
149
|
+
def files_arr
|
150
|
+
files_str.to_s.split("\n")
|
151
|
+
end
|
152
|
+
|
153
|
+
def delete
|
154
|
+
if Courses.search_by_ctype(self).size > 0
|
155
|
+
log_msg :CourseType, "Tried to delete #{self.name} while courses still depend on it"
|
156
|
+
return false
|
157
|
+
else
|
158
|
+
super
|
159
|
+
return true
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def file_diploma=(f)
|
164
|
+
return if @loading
|
165
|
+
self._file_diploma = f
|
166
|
+
Courses.search_by_ctype(self).each{|c|
|
167
|
+
c.update_exam_file
|
168
|
+
}
|
169
|
+
f
|
170
|
+
end
|
171
|
+
end
|
data/Entities/DFiles.rb
ADDED
@@ -0,0 +1,466 @@
|
|
1
|
+
# DFiles is used to manage the updating of the files-repository on the
|
2
|
+
# Profeda-installations.
|
3
|
+
# - sync with a harddisk or over ssh
|
4
|
+
# - update the file-tree
|
5
|
+
|
6
|
+
class DFiles < Entities
|
7
|
+
attr_accessor :dir_base, :dir_files, :dir_descs, :url_html
|
8
|
+
|
9
|
+
def setup_data
|
10
|
+
value_int :dfile_id
|
11
|
+
value_str :name
|
12
|
+
value_str :desc_file
|
13
|
+
# url_file holds the url to the file. It can be preceded
|
14
|
+
# by a name held between two ":", which will be the
|
15
|
+
# save_file-name. Else the save_file-name is the 'basename' of the
|
16
|
+
# url_file
|
17
|
+
value_str :url_file
|
18
|
+
value_str :save_file
|
19
|
+
value_str :url_page
|
20
|
+
value_str :desc
|
21
|
+
# os and category are used to build the dokuwiki-pages
|
22
|
+
value_str :os
|
23
|
+
value_str :category
|
24
|
+
# tags are additional fields
|
25
|
+
value_str :tags
|
26
|
+
value_int :file_size
|
27
|
+
|
28
|
+
# Only used once a DFile is found - will not be stored, but represents
|
29
|
+
# the priority that will be used for pruning.
|
30
|
+
value_int :priority
|
31
|
+
|
32
|
+
set_dir_base('/opt/Files')
|
33
|
+
end
|
34
|
+
|
35
|
+
def set_dir_base(dir)
|
36
|
+
@dir_base = dir
|
37
|
+
@dir_files = File.join(@dir_base, 'files')
|
38
|
+
@dir_descs = File.join(@dir_base, 'descs')
|
39
|
+
@dir_html = File.join(@dir_base, 'html')
|
40
|
+
@url_html = 'http://files.ndjair.net/'
|
41
|
+
end
|
42
|
+
|
43
|
+
# searches for all descriptions in @dir_descs
|
44
|
+
def load(has_static = true)
|
45
|
+
#dputs_func
|
46
|
+
delete_all(true)
|
47
|
+
dputs(2) { "Loading descs from #{@dir_descs}" }
|
48
|
+
if Dir.exists?(@dir_descs)
|
49
|
+
dputs(4) { 'Directory exists' }
|
50
|
+
file_id = 1
|
51
|
+
Dir.glob("#{@dir_descs}/*.desc").each { |f|
|
52
|
+
dputs(4) { "Working on file #{f}" }
|
53
|
+
name = File.basename(f)
|
54
|
+
lines = IO.readlines(f).collect { |l| l.chomp }
|
55
|
+
if lines.size >= 7
|
56
|
+
file = {
|
57
|
+
dfile_id: file_id,
|
58
|
+
desc_file: name,
|
59
|
+
name: name.sub(/.desc$/, ''),
|
60
|
+
url_file: lines[0],
|
61
|
+
url_page: lines[1],
|
62
|
+
desc: lines[3],
|
63
|
+
os: lines[5],
|
64
|
+
category: lines[6],
|
65
|
+
tags: lines[5..-1].collect { |t|
|
66
|
+
t.split(' ')
|
67
|
+
}
|
68
|
+
}
|
69
|
+
if file[:url_file][0] == ':'
|
70
|
+
su = file[:url_file].match(/^:([^:]*):(.*)$/)
|
71
|
+
file[:save_file] = su[1]
|
72
|
+
file[:url_file] = su[2]
|
73
|
+
else
|
74
|
+
file[:save_file] = File.basename(file[:url_file])
|
75
|
+
end
|
76
|
+
dputs(3) { "Saving description #{file}" }
|
77
|
+
file_path = File.join(@dir_files, file[:save_file])
|
78
|
+
file[:file_size] = File.exists?(file_path) ? File.size(file_path) : 0
|
79
|
+
@data[file_id] = file
|
80
|
+
file_id += 1
|
81
|
+
else
|
82
|
+
dputs(2) { "Description #{f} has not enough lines, skipping" }
|
83
|
+
end
|
84
|
+
}
|
85
|
+
else
|
86
|
+
dputs(2) { "Didn't find directory #{@dir_descs}" }
|
87
|
+
end
|
88
|
+
dputs(3) { @data.inspect }
|
89
|
+
end
|
90
|
+
|
91
|
+
# saves back the descriptions to @dir_descs
|
92
|
+
def save()
|
93
|
+
return unless @changed
|
94
|
+
if Dir.exists?(@dir_descs)
|
95
|
+
FileUtils.rm(Dir.glob("#{@dir_descs}/*.desc"))
|
96
|
+
else
|
97
|
+
FileUtils.mkpath(@dir_descs)
|
98
|
+
end
|
99
|
+
@data.each { |k, v|
|
100
|
+
File.open("#{@dir_descs}/#{v[:desc_file]}", 'w') { |f|
|
101
|
+
if (file = v[:save_file]) != File.basename(v[:url_file])
|
102
|
+
v[:url_file] = ":#{file}:#{v[:url_file]}"
|
103
|
+
end
|
104
|
+
|
105
|
+
f.puts(v[:url_file], v[:url_page], '',
|
106
|
+
v[:desc], '',
|
107
|
+
v[:os], v[:category])
|
108
|
+
v[:tags].each { |t| f.puts(t.join(' ')) }
|
109
|
+
}
|
110
|
+
}
|
111
|
+
end
|
112
|
+
|
113
|
+
# updates the descriptions from a directory (probably a mount-point, has to
|
114
|
+
# be mounted before)
|
115
|
+
def update_desc_from_dir(update_dir)
|
116
|
+
return unless Dir.exists?(update_dir)
|
117
|
+
Dir.glob(File.join(update_dir, '*.desc')).each { |f|
|
118
|
+
name = File.basename(f)
|
119
|
+
local_name = File.join(@dir_descs, name)
|
120
|
+
if File.size(f) == 0
|
121
|
+
# This is a file that has to be removed
|
122
|
+
File.rm(local_name)
|
123
|
+
else
|
124
|
+
dputs(3) { "Copying #{f} to #{local_name}" }
|
125
|
+
FileUtils.cp(f, local_name)
|
126
|
+
end
|
127
|
+
}
|
128
|
+
load
|
129
|
+
end
|
130
|
+
|
131
|
+
# copies the files from a directory to @dir_files
|
132
|
+
def update_files_from_dir(update_dir)
|
133
|
+
#dputs_func
|
134
|
+
load
|
135
|
+
unless Dir.exists? @dir_files
|
136
|
+
FileUtils.mkpath @dir_files
|
137
|
+
end
|
138
|
+
# Update all sizes, delete if file is missing
|
139
|
+
search_all_.each { |df|
|
140
|
+
df.file_size = 0
|
141
|
+
[@dir_files, update_dir].each { |d|
|
142
|
+
file = File.join(d, df.save_file)
|
143
|
+
if File.exists?(file)
|
144
|
+
df.file_size = File.size(file)
|
145
|
+
dputs(3) { "Found file #{file} with size #{df.file_size}" }
|
146
|
+
else
|
147
|
+
df.file_size = 0
|
148
|
+
end
|
149
|
+
}
|
150
|
+
if df.file_size == 0
|
151
|
+
df.delete
|
152
|
+
end
|
153
|
+
}
|
154
|
+
|
155
|
+
files_wanted = get_limited_files(DFilePriorities.get_most_wanted,
|
156
|
+
DFileConfig.limit_size * 2**30).
|
157
|
+
collect { |f| f.save_file }
|
158
|
+
files_here = Dir.glob(File.join(@dir_files, '/*')).
|
159
|
+
collect { |f| File.basename(f) }
|
160
|
+
files_delete = files_here - files_wanted
|
161
|
+
files_copy = files_wanted - files_here
|
162
|
+
dputs(3) { "Files to delete are: #{files_delete}" }
|
163
|
+
dputs(3) { "Files to copy are: #{files_delete}" }
|
164
|
+
|
165
|
+
# Delete not used files
|
166
|
+
files_delete.each { |f|
|
167
|
+
file = File.join(@dir_files, f)
|
168
|
+
dputs(3) { "Deleting file #{file}" }
|
169
|
+
FileUtils.rm(file)
|
170
|
+
}
|
171
|
+
|
172
|
+
# Copy new files
|
173
|
+
files_copy.each { |f|
|
174
|
+
file = File.join(update_dir, f)
|
175
|
+
dputs(3) { "Copying file #{file}" }
|
176
|
+
FileUtils.cp(file, @dir_files)
|
177
|
+
}
|
178
|
+
save
|
179
|
+
end
|
180
|
+
|
181
|
+
# Returns the first files so that the total is not above the
|
182
|
+
# size_limit
|
183
|
+
def get_limited_files(files, size_limit)
|
184
|
+
ret = files.dup
|
185
|
+
if size_limit > 0
|
186
|
+
# Prioritize the files
|
187
|
+
while ret.inject(0) { |tot, f| tot + f.file_size } > size_limit
|
188
|
+
# We have too many files and need to prune some entries
|
189
|
+
ret.delete(ret.last)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
ret
|
193
|
+
end
|
194
|
+
|
195
|
+
def get_size(dir, files)
|
196
|
+
files.inject(0) { |tot, file|
|
197
|
+
tot += File.size(dir + "/#{file}")
|
198
|
+
}
|
199
|
+
end
|
200
|
+
|
201
|
+
# get_tags returns all tags with the most common tags at the beginning
|
202
|
+
def get_tags(tag)
|
203
|
+
# Get a list of all tags wihtout the priority
|
204
|
+
tags = search_by_tags(tag).collect { |df| df.tags.collect { |_, t| t } }.flatten.sort
|
205
|
+
# Count how many times each tag appears and sort inversely
|
206
|
+
tags_count = tags.uniq.collect { |t| [tags.count(t), t] }.sort { |a, b| b[0] <=> a[0] }
|
207
|
+
# Remove the counter
|
208
|
+
tags_count.collect { |_, t| t }
|
209
|
+
end
|
210
|
+
|
211
|
+
# creates html-files for downloading the files
|
212
|
+
def update_html
|
213
|
+
used_tags = %w(windows mac linux android media).select { |tag|
|
214
|
+
get_tags(tag).size > 0 }
|
215
|
+
|
216
|
+
# First create index.html
|
217
|
+
save_html('index.html',
|
218
|
+
"<ul>\n" +
|
219
|
+
used_tags.collect { |tag|
|
220
|
+
"<li><a href='#{@url_html}/html/#{tag}_all.html'>#{tag.capitalize}</a>"
|
221
|
+
}.join("\n") +
|
222
|
+
"</ul>\n")
|
223
|
+
|
224
|
+
unless File.exists?(@dir_html)
|
225
|
+
FileUtils.mkdir(@dir_html)
|
226
|
+
end
|
227
|
+
# Add each main tag that exists
|
228
|
+
used_tags.each { |tag|
|
229
|
+
save_html(File.join('html', "#{tag}_all.html"),
|
230
|
+
"<h1>#{tag.capitalize}</h1>\n" +
|
231
|
+
html_tag_links(tag) +
|
232
|
+
"<h3><a href='../index.html'>Home</a></h3>" +
|
233
|
+
html_tag_files(tag)
|
234
|
+
)
|
235
|
+
# Add tag-files
|
236
|
+
(get_tags(tag) - [tag]).each { |t|
|
237
|
+
save_html(File.join('html', "#{tag}_#{t}.html"),
|
238
|
+
"<h1><a href='#{tag}_all.html'>#{tag.capitalize}</a></h1>\n" +
|
239
|
+
"<h2 class='subtitle'>#{t.capitalize}</h2>" +
|
240
|
+
html_tag_links(tag) +
|
241
|
+
"<h4 class='back'><a href='../index.html'>Home</a></h4>" +
|
242
|
+
html_tag_files([tag, t]))
|
243
|
+
}
|
244
|
+
}
|
245
|
+
end
|
246
|
+
|
247
|
+
def save_html(file, text)
|
248
|
+
html = IO.read(File.join(@dir_base, 'index_pre.html')) +
|
249
|
+
text +
|
250
|
+
IO.read(File.join(@dir_base, 'index_post.html'))
|
251
|
+
IO.write(File.join(@dir_base, file), html)
|
252
|
+
end
|
253
|
+
|
254
|
+
def html_tag_links(tag)
|
255
|
+
"<h3>" + ([:all] + get_tags(tag) - [tag]).collect { |t|
|
256
|
+
"<a href='#{tag}_#{t}.html'>#{t.capitalize}</a>"
|
257
|
+
}.join(" - ") + '</h3>'
|
258
|
+
end
|
259
|
+
|
260
|
+
def html_tag_files(tags)
|
261
|
+
"<div class='files'><ul>\n" +
|
262
|
+
DFiles.search_by_all(:tags, tags.to_a).collect { |df|
|
263
|
+
"<li><a href='../files/#{df.save_file}'>" +
|
264
|
+
"#{df.name}</a> - #{df.desc} - " +
|
265
|
+
"<a href='#{df.url_page}'>#{df.url_page}</a>" +
|
266
|
+
"</li>"
|
267
|
+
}.join("\n") +
|
268
|
+
"</ul></div>"
|
269
|
+
end
|
270
|
+
|
271
|
+
# Returns a hash of the file-content
|
272
|
+
def self.hash(name)
|
273
|
+
if File.exists?(name)
|
274
|
+
return IO.read(name).bytes.inject { |a, b| a + a * b } % (2**64-1)
|
275
|
+
end
|
276
|
+
return 0
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
class DFile < Entity
|
281
|
+
def print
|
282
|
+
p self
|
283
|
+
end
|
284
|
+
|
285
|
+
def get_tag_prio(tag)
|
286
|
+
p, _ = tags.find { |_, t|
|
287
|
+
t == tag }
|
288
|
+
return p ? p.to_i : nil
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
# Singleton entity which holds the configuration
|
293
|
+
class DFileConfigs < Entities
|
294
|
+
def setup_data
|
295
|
+
# 0 for no limit, else limit in GBytes
|
296
|
+
value_int :limit_size
|
297
|
+
# at what time of the day the system should update
|
298
|
+
# -1 = no auto_update
|
299
|
+
value_int :auto_update
|
300
|
+
end
|
301
|
+
|
302
|
+
def migration_1(d)
|
303
|
+
d.limit_size = 10
|
304
|
+
d.auto_update = -1
|
305
|
+
end
|
306
|
+
|
307
|
+
def self.singleton
|
308
|
+
first or
|
309
|
+
self.create({limit_size: 10, auto_update: -1})
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
class DFileConfig < Entity
|
314
|
+
def self.method_missing(m, *args)
|
315
|
+
dputs(4) { "#{m} - #{args.inspect} - #{DFileConfigs.singleton.inspect}" }
|
316
|
+
if args.length > 0
|
317
|
+
DFileConfigs.singleton.send(m, *args)
|
318
|
+
else
|
319
|
+
DFileConfigs.singleton.send(m)
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
def self.respond_to?(cmd)
|
324
|
+
DFileConfigs.singleton.respond_to?(cmd)
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
class DFilePriorities < Entities
|
329
|
+
def setup_data
|
330
|
+
value_int :priority
|
331
|
+
value_str :tags_str
|
332
|
+
end
|
333
|
+
|
334
|
+
def load(has_static = true)
|
335
|
+
delete_all
|
336
|
+
config = File.join(DFiles.dir_base, 'priorities')
|
337
|
+
if File.exists?(config)
|
338
|
+
IO.readlines(config).each { |l|
|
339
|
+
case l[0]
|
340
|
+
when '#'
|
341
|
+
#comment
|
342
|
+
when /[0-9]/
|
343
|
+
# We have a priority
|
344
|
+
priority, tags = l.chomp.split(' ', 2)
|
345
|
+
DFilePriorities.create({priority: priority.to_i, tags_str: tags})
|
346
|
+
else
|
347
|
+
# Should be the space
|
348
|
+
DFileConfig.limit_size = l.sub(/.*=/, '').to_i
|
349
|
+
end
|
350
|
+
}
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
def save
|
355
|
+
|
356
|
+
end
|
357
|
+
|
358
|
+
# Uses DFilePriorities to decide which files are most important
|
359
|
+
def get_most_wanted
|
360
|
+
files = []
|
361
|
+
|
362
|
+
# First add all matching tags for every priority of 1-5
|
363
|
+
(1..5).to_a.each { |p|
|
364
|
+
search_all_.each { |fp|
|
365
|
+
if p == fp.priority
|
366
|
+
dputs(4) { "Adding files #{fp.get_files} for prio #{p}" }
|
367
|
+
files.push(*fp.get_files)
|
368
|
+
end
|
369
|
+
}
|
370
|
+
}
|
371
|
+
|
372
|
+
# Then add all other priorities for every line in DFilePriorities
|
373
|
+
search_all_.each { |fp|
|
374
|
+
if fp.priority >= 6
|
375
|
+
dputs(4) { "Adding files #{fp.get_files} for #{fp.inspect}" }
|
376
|
+
files.push(*fp.get_files)
|
377
|
+
end
|
378
|
+
}
|
379
|
+
|
380
|
+
files.uniq
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
|
385
|
+
class DFilePriority < Entity
|
386
|
+
def get_files
|
387
|
+
#dputs_func
|
388
|
+
# Search for all tags, then filter according to priorities
|
389
|
+
dputs(4) { "Searching tags #{tags.to_s} in #{self.inspect}" }
|
390
|
+
DFiles.search_by_all(:tags, tags).select { |df|
|
391
|
+
dputs(4) { "Searching DFile #{df.inspect}" }
|
392
|
+
prio_min = 10
|
393
|
+
df.tags.each { |prio, tag|
|
394
|
+
if tags.index(tag)
|
395
|
+
prio_min = [prio_min, prio.to_i].min
|
396
|
+
end
|
397
|
+
}
|
398
|
+
|
399
|
+
# This will return nil if the priority is not matched,
|
400
|
+
# else the priority found, which will be evaluated by
|
401
|
+
# the select above to be true.
|
402
|
+
if prio_min <= priority.to_i
|
403
|
+
dputs(3) { "Found tags #{tags} with priority #{prio_min}" }
|
404
|
+
df.priority = prio_min
|
405
|
+
end
|
406
|
+
}
|
407
|
+
end
|
408
|
+
|
409
|
+
def tags
|
410
|
+
tags_str.split(' ')
|
411
|
+
end
|
412
|
+
end
|
413
|
+
|
414
|
+
=begin
|
415
|
+
files.ndjair.net
|
416
|
+
|
417
|
+
- copy from profeda.org to markas-al-nour.org
|
418
|
+
- only serve completed copies
|
419
|
+
- copy Antivirus first, then other things
|
420
|
+
|
421
|
+
- copy from profeda.org to external hard-disk
|
422
|
+
|
423
|
+
- copy from external hard-disk to cubox
|
424
|
+
- only copy up to N GB of files
|
425
|
+
- separated into categories
|
426
|
+
- every category has it’s preference
|
427
|
+
|
428
|
+
- present as web-page
|
429
|
+
- first use dokuwiki
|
430
|
+
- then use static pages
|
431
|
+
|
432
|
+
-> move all .file in one directory
|
433
|
+
-> move all files in another directory
|
434
|
+
-> use hard links to re-create the ./update-files-structure
|
435
|
+
-> update .file-directory using rsync
|
436
|
+
-> update binary directory according to .file, priority
|
437
|
+
|
438
|
+
- priority
|
439
|
+
- each line contains the tags/directories and a priority
|
440
|
+
- first lines have highest priority, last lines are pruned first if too much space
|
441
|
+
- 1-5 are pruned in order of importance
|
442
|
+
- 6-9 are more important at the beginning
|
443
|
+
- 1 is pruned last
|
444
|
+
- if more than one tag is given, the lowest priority in the description is taken for
|
445
|
+
comparison. So a "3 windows\n1 antivirus"-description would not fit the 1st line, but
|
446
|
+
it would fit the 2nd line as priority of 1
|
447
|
+
|
448
|
+
SPACE=10G
|
449
|
+
1 windows
|
450
|
+
2 windows antivirus
|
451
|
+
9 medias
|
452
|
+
|
453
|
+
- .file
|
454
|
+
add a priority-field: 1 is most important, 9 is least important, for each category
|
455
|
+
|
456
|
+
- decision which files to include
|
457
|
+
1. make list of all files with sizes according to ‘priority’
|
458
|
+
2. if total > SPACE
|
459
|
+
2.1. starting from the last line in ‘priority’, remove 9 through 6, repeat up the list until SPACE is met
|
460
|
+
2.2 if total > SPACE
|
461
|
+
2.2.1 prune ‘priority’ 5 to 1, one priority at the time, from end to beginning, starting with biggest files first
|
462
|
+
|
463
|
+
-> make list and delete from end till space-requirement is met:
|
464
|
+
- from priority 1 to priority 5 for all lines, collect files, starting with smallest
|
465
|
+
- from first to last line in list do priorities 6 to 9 from smallest to tallest
|
466
|
+
=end
|