Esempio n. 1
0
def build_updatedetail_page(identifier):
    '''Build detail page for a non-optional update'''
    items = MunkiItems.getUpdateList()
    page_name = u'updatedetail-%s.html' % identifier
    name, sep, version = identifier.partition('--version-')
    for item in items:
        if item['name'] == name and item['version_to_install'] == version:
            page = MunkiItems.UpdateItem(item)
            addDetailSidebarLabels(page)
            force_install_after_date = item.get('force_install_after_date')
            if force_install_after_date:
                local_date = munki.discardTimeZoneFromDate(
                    force_install_after_date)
                date_str = munki.shortRelativeStringFromDate(local_date)
                page['dueLabel'] += u' '
                page['short_due_date'] = date_str
            else:
                page['dueLabel'] = u''
                page['short_due_date'] = u''

            footer = get_template('footer_template.html', raw=True)
            generate_page(page_name,
                          'updatedetail_template.html',
                          page,
                          footer=footer)
            return
    # if we get here we didn't find any item matching identifier
    msclog.debug_log('No update detail found for %s' % item_name)
    build_item_not_found_page(page_name)
Esempio n. 2
0
 def kickOffInstallSession(self):
     '''start an update install/removal session'''
     # check for need to logout, restart, firmware warnings
     # warn about blocking applications, etc...
     # then start an update session
     if MunkiItems.updatesRequireRestart() or MunkiItems.updatesRequireLogout():
         # switch to updates view
         self.loadUpdatesPage_(self)
         # warn about need to logout or restart
         self.alert_controller.confirmUpdatesAndInstall()
     else:
         if self.alert_controller.alertedToBlockingAppsRunning():
             self.loadUpdatesPage_(self)
             return
         if self.alert_controller.alertedToRunningOnBatteryAndCancelled():
             self.loadUpdatesPage_(self)
             return
         self.managedsoftwareupdate_task = None
         msclog.log("user", "install_without_logout")
         self._update_in_progress = True
         self.displayUpdateCount()
         self.setStatusViewTitle_(NSLocalizedString(u"Updating...", u"Updating message"))
         result = munki.justUpdate()
         if result:
             msclog.debug_log("Error starting install session: %s" % result)
             self.munkiStatusSessionEnded_(2)
         else:
             self.managedsoftwareupdate_task = "installwithnologout"
             NSApp.delegate().statusController.startMunkiStatusSession()
             self.markPendingItemsAsInstalling()
Esempio n. 3
0
 def confirmUpdatesAndInstall(self):
     '''Make sure it's OK to proceed with installing if logout or restart is required'''
     if self.alertedToMultipleUsers():
         return
     elif MunkiItems.updatesRequireRestart():
         alert = NSAlert.alertWithMessageText_defaultButton_alternateButton_otherButton_informativeTextWithFormat_(
             NSLocalizedString(u"Restart Required", u"Restart Required title"),
             NSLocalizedString(u"Log out and update", u"Log out and Update button text"),
             NSLocalizedString(u"Cancel", u"Cancel button title/short action text"),
             nil,
             u"%@", NSLocalizedString(
                 (u"A restart is required after updating. Please be patient "
                 "as there may be a short delay at the login window. Log "
                 "out and update now?"), u"Restart Required detail"))
         alert.beginSheetModalForWindow_modalDelegate_didEndSelector_contextInfo_(
             self.window, self,
             self.logoutAlertDidEnd_returnCode_contextInfo_, nil)
     elif MunkiItems.updatesRequireLogout() or munki.installRequiresLogout():
         alert = NSAlert.alertWithMessageText_defaultButton_alternateButton_otherButton_informativeTextWithFormat_(
             NSLocalizedString(u"Logout Required", u"Logout Required title"),
             NSLocalizedString(u"Log out and update", u"Log out and Update button text"),
             NSLocalizedString(u"Cancel", u"Cancel button title/short action text"),
             nil,
             u"%@", NSLocalizedString(
                 (u"A logout is required before updating. Please be patient "
                 "as there may be a short delay at the login window. Log "
                 "out and update now?"), u"Logout Required detail"))
         alert.beginSheetModalForWindow_modalDelegate_didEndSelector_contextInfo_(
             self.window, self,
                 self.logoutAlertDidEnd_returnCode_contextInfo_, nil)
     else:
         # we shouldn't have been invoked if neither a restart or logout was required
         msclog.debug_log(
                     'confirmUpdatesAndInstall was called but no restart or logout was needed')
Esempio n. 4
0
def build_updatedetail_page(identifier):
    '''Build detail page for a non-optional update'''
    items = MunkiItems.getUpdateList() + MunkiItems.getProblemItems()
    page_name = u'updatedetail-%s.html' % identifier
    name, sep, version = identifier.partition('--version-')
    for item in items:
        if item['name'] == name and item.get('version_to_install', '') == version:
            page = MunkiItems.UpdateItem(item)
            escapeAndQuoteCommonFields(page)
            addDetailSidebarLabels(page)
            force_install_after_date = item.get('force_install_after_date')
            if force_install_after_date:
                try:
                    local_date = munki.discardTimeZoneFromDate(
                                                force_install_after_date)
                    date_str = munki.shortRelativeStringFromDate(
                                                local_date)
                    page['dueLabel'] += u' '
                    page['short_due_date'] = date_str
                except munki.BadDateError:
                    # some issue with the stored date
                    msclog.debug_log('Problem with force_install_after_date for %s' % identifier)
                    page['dueLabel'] = u''
                    page['short_due_date'] = u''
            else:
                page['dueLabel'] = u''
                page['short_due_date'] = u''

            footer = get_template('footer_template.html', raw=True)
            generate_page(page_name, 'updatedetail_template.html', page, footer=footer)
            return
    # if we get here we didn't find any item matching identifier
    msclog.debug_log('No update detail found for %s' % identifier)
    build_item_not_found_page(page_name)
Esempio n. 5
0
def build_updates_page():
    '''available/pending updates'''
    page_name = u'updates.html'

    # need to consolidate/centralize this flag. Accessing it this way is ugly.
    if NSApp.delegate().mainWindowController._update_in_progress:
        return build_update_status_page()

    item_list = MunkiItems.getEffectiveUpdateList()

    other_updates = [
        item for item in MunkiItems.getOptionalInstallItems()
        if item['status'] == 'update-available'
    ]

    page = {}
    page['update_rows'] = u''
    page['hide_progress_spinner'] = u'hidden'
    page['hide_other_updates'] = u'hidden'
    page['install_all_button_classes'] = u''

    item_template = get_template('update_row_template.html')

    if item_list:
        for item in item_list:
            escapeAndQuoteCommonFields(item)
            page['update_rows'] += item_template.safe_substitute(item)
    elif not other_updates:
        status_results_template = get_template('status_results_template.html')
        alert = {}
        alert['primary_status_text'] = NSLocalizedString(
            u"Your software is up to date.",
            u"No Pending Updates primary text")
        alert['secondary_status_text'] = NSLocalizedString(
            u"There is no new software for your computer at this time.",
            u"No Pending Updates secondary text")
        alert['hide_progress_bar'] = u'hidden'
        alert['progress_bar_value'] = u''
        page['update_rows'] = status_results_template.safe_substitute(alert)

    count = len(item_list)
    page['update_count'] = msclib.updateCountMessage(count)
    page['install_btn_label'] = msclib.getInstallAllButtonTextForCount(count)
    page['warning_text'] = get_warning_text()

    page['other_updates_header_message'] = NSLocalizedString(
        u"Other available updates", u"Other Available Updates label")
    page['other_update_rows'] = u''

    if other_updates:
        page['hide_other_updates'] = u''
        for item in other_updates:
            escapeAndQuoteCommonFields(item)
            page['other_update_rows'] += item_template.safe_substitute(item)

    footer = get_template('footer_template.html', raw=True)
    generate_page(page_name, 'updates_template.html', page, footer=footer)
Esempio n. 6
0
def build_updates_page():
    '''available/pending updates'''
    page_name = u'updates.html'
    
    # need to consolidate/centralize this flag. Accessing it this way is ugly.
    if NSApp.delegate().mainWindowController._update_in_progress:
        return build_update_status_page()

    item_list = MunkiItems.getEffectiveUpdateList()

    other_updates = [
        item for item in MunkiItems.getOptionalInstallItems()
        if item['status'] == 'update-available']

    page = {}
    page['update_rows'] = u''
    page['hide_progress_spinner'] = u'hidden'
    page['hide_other_updates'] = u'hidden'
    page['install_all_button_classes'] = u''
    
    item_template = get_template('update_row_template.html')

    if item_list:
        for item in item_list:
            escapeAndQuoteCommonFields(item)
            page['update_rows'] += item_template.safe_substitute(item)
    elif not other_updates:
        status_results_template = get_template('status_results_template.html')
        alert = {}
        alert['primary_status_text'] = NSLocalizedString(
             u"Your software is up to date.", u"No Pending Updates primary text")
        alert['secondary_status_text'] = NSLocalizedString(
             u"There is no new software for your computer at this time.",
             u"No Pending Updates secondary text")
        alert['hide_progress_bar'] = u'hidden'
        alert['progress_bar_value'] = u''
        page['update_rows'] = status_results_template.safe_substitute(alert)

    count = len(item_list)
    page['update_count'] = msclib.updateCountMessage(count)
    page['install_btn_label'] = msclib.getInstallAllButtonTextForCount(count)
    page['warning_text'] = get_warning_text()

    page['other_updates_header_message'] = NSLocalizedString(
        u"Other available updates",
        u"Other Available Updates label")
    page['other_update_rows'] = u''

    if other_updates:
        page['hide_other_updates'] = u''
        for item in other_updates:
            escapeAndQuoteCommonFields(item)
            page['other_update_rows'] += item_template.safe_substitute(item)
    
    footer = get_template('footer_template.html', raw=True)
    generate_page(page_name, 'updates_template.html', page, footer=footer)
Esempio n. 7
0
    def myItemsActionButtonClicked_(self, item_name):
        '''this method is called from JavaScript when the user clicks
        the Install/Remove/Cancel button in the My Items view'''
        document = self.webView.mainFrameDocument()
        item = MunkiItems.optionalItemForName_(item_name)
        status_line = document.getElementById_('%s_status_text' % item_name)
        btn = document.getElementById_('%s_action_button_text' % item_name)
        if not item or not btn or not status_line:
            msclog.debug_log('User clicked MyItems action button for %s' % item_name)
            msclog.debug_log('Unexpected error finding HTML elements')
            return
        prior_status = item['status']
        item.update_status()
        
        self.displayUpdateCount()
        if item['status'] == 'not-installed':
            # we removed item from list of things to install
            # now remove from display
            table_row = document.getElementById_('%s_myitems_table_row' % item_name)
            if table_row:
                node = table_row.parentNode().removeChild_(table_row)
        else:
            btn.setInnerText_(item['myitem_action_text'])
            status_line.setInnerText_(item['status_text'])
            status_line.setClassName_('status %s' % item['status'])

        if item['status'] in ['install-requested', 'removal-requested']:
            self._alertedUserToOutstandingUpdates = False
            if not self._update_in_progress:
                self.updateNow()
        elif prior_status in ['will-be-installed', 'update-will-be-installed',
                              'will-be-removed']:
            # cancelled a pending install or removal; should run an updatecheck
            self.checkForUpdates(suppress_apple_update_check=True)
Esempio n. 8
0
 def markPendingItemsAsInstalling(self):
     '''While an install/removal session is happening, mark optional items
     that are being installed/removed with the appropriate status'''
     msclog.debug_log('marking pendingItems as installing')
     install_info = munki.getInstallInfo()
     items_to_be_installed_names = [item['name']
                                    for item in install_info.get('managed_installs', [])]
     items_to_be_removed_names = [item['name']
                                  for item in install_info.get('removals', [])]
                                  
     for name in items_to_be_installed_names:
         # remove names for user selections since we are installing
         MunkiItems.user_install_selections.discard(name)
     
     for name in items_to_be_removed_names:
         # remove names for user selections since we are removing
         MunkiItems.user_removal_selections.discard(name)
     
     for item in MunkiItems.getOptionalInstallItems():
         new_status = None
         if item['name'] in items_to_be_installed_names:
             msclog.debug_log('Setting status for %s to "installing"' % item['name'])
             new_status = u'installing'
         elif item['name'] in items_to_be_removed_names:
             msclog.debug_log('Setting status for %s to "removing"' % item['name'])
             new_status = u'removing'
         if new_status:
             item['status'] = new_status
             self.updateDOMforOptionalItem(item)
Esempio n. 9
0
def build_categories_page():
    '''Build page showing available categories and some items in each one'''
    all_items = MunkiItems.getOptionalInstallItems()
    header = NSLocalizedString(u"Categories", u"Categories label")
    page_name = u'categories.html'
    category_list = []
    for item in all_items:
        if 'category' in item and item['category'] not in category_list:
            category_list.append(item['category'])

    item_html = build_category_items_html()

    all_categories_label = NSLocalizedString(u"All Categories",
                                             u"AllCategoriesLabel")
    categories_html = u'<option selected>%s</option>\n' % all_categories_label
    for item in sorted(category_list):
        categories_html += u'<option>%s</option>\n' % item

    page = {}
    page['list_items'] = item_html
    page['category_items'] = categories_html
    page['header_text'] = header

    footer = get_template('footer_template.html', raw=True)
    generate_page(page_name,
                  'list_template.html',
                  page,
                  showcase=u'',
                  sidebar=u'',
                  footer=footer)
Esempio n. 10
0
    def alertedToBlockingAppsRunning(self):
        '''Returns True if blocking_apps are running; alerts as a side-effect'''
        apps_to_check = []
        for update_item in MunkiItems.getUpdateList():
            if 'blocking_applications' in update_item:
                apps_to_check.extend(update_item['blocking_applications'])
            else:
                apps_to_check.extend(
                    [os.path.basename(item.get('path'))
                     for item in update_item.get('installs', [])
                     if item['type'] == 'application']
                )

        running_apps = munki.getRunningBlockingApps(apps_to_check)
        if running_apps:
            current_user = munki.getconsoleuser()
            other_users_apps = [item['display_name'] for item in running_apps
                                if item['user'] != current_user]
            my_apps = [item['display_name'] for item in running_apps
                       if item['user'] == current_user]
            msclog.log(
                "MSC", "conflicting_apps", ','.join(other_users_apps + my_apps))
            if other_users_apps:
                detailText = NSLocalizedString(
                    u"Other logged in users are using the following "
                    "applications. Try updating later when they are no longer "
                    "in use:\n\n%s",
                    u"Other Users Blocking Apps Running detail")
                alert = NSAlert.alertWithMessageText_defaultButton_alternateButton_otherButton_informativeTextWithFormat_(
                    NSLocalizedString(
                        u"Applications in use by others",
                        u"Other Users Blocking Apps Running title"),
                    NSLocalizedString(u"OK", u'OKButtonText'),
                    nil,
                    nil,
                    u"%@", detailText % u'\n'.join(set(other_users_apps))
                    )
            else:
                detailText = NSLocalizedString(
                    u"You must quit the following applications before "
                    "proceeding with installation or removal:\n\n%s",
                    u"Blocking Apps Running detail")
                alert = NSAlert.alertWithMessageText_defaultButton_alternateButton_otherButton_informativeTextWithFormat_(
                    NSLocalizedString(
                        u"Conflicting applications running",
                        u"Blocking Apps Running title"),
                    NSLocalizedString(u"OK", u"OK button title"),
                    nil,
                    nil,
                    u"%@", detailText % u'\n'.join(set(my_apps))
                    )
            alert.beginSheetModalForWindow_modalDelegate_didEndSelector_contextInfo_(
                self.window, self,
                self.blockingAppsRunningAlertDidEnd_returnCode_contextInfo_,
                nil)
            return True
        else:
            return False
Esempio n. 11
0
    def alertedToBlockingAppsRunning(self):
        '''Returns True if blocking_apps are running; alerts as a side-effect'''
        apps_to_check = []
        for update_item in MunkiItems.getUpdateList():
            if 'blocking_applications' in update_item:
                apps_to_check.extend(update_item['blocking_applications'])
            else:
                apps_to_check.extend(
                    [os.path.basename(item.get('path'))
                     for item in update_item.get('installs', [])
                     if item['type'] == 'application']
                )

        running_apps = munki.getRunningBlockingApps(apps_to_check)
        if running_apps:
            current_user = munki.getconsoleuser()
            other_users_apps = [item['display_name'] for item in running_apps
                                if item['user'] != current_user]
            my_apps = [item['display_name'] for item in running_apps
                       if item['user'] == current_user]
            msclog.log(
                "MSC", "conflicting_apps", ','.join(other_users_apps + my_apps))
            if other_users_apps:
                detailText = NSLocalizedString(
                    u"Other logged in users are using the following "
                    "applications. Try updating later when they are no longer "
                    "in use:\n\n%s",
                    u"Other Users Blocking Apps Running detail")
                alert = NSAlert.alertWithMessageText_defaultButton_alternateButton_otherButton_informativeTextWithFormat_(
                    NSLocalizedString(
                        u"Applications in use by others",
                        u"Other Users Blocking Apps Running title"),
                    NSLocalizedString(u"OK", u'OKButtonText'),
                    nil,
                    nil,
                    u"%@", detailText % u'\n'.join(set(other_users_apps))
                    )
            else:
                detailText = NSLocalizedString(
                    u"You must quit the following applications before "
                    "proceeding with installation or removal:\n\n%s",
                    u"Blocking Apps Running detail")
                alert = NSAlert.alertWithMessageText_defaultButton_alternateButton_otherButton_informativeTextWithFormat_(
                    NSLocalizedString(
                        u"Conflicting applications running",
                        u"Blocking Apps Running title"),
                    NSLocalizedString(u"OK", u"OK button title"),
                    nil,
                    nil,
                    u"%@", detailText % u'\n'.join(set(my_apps))
                    )
            alert.beginSheetModalForWindow_modalDelegate_didEndSelector_contextInfo_(
                self.window, self,
                self.blockingAppsRunningAlertDidEnd_returnCode_contextInfo_,
                nil)
            return True
        else:
            return False
Esempio n. 12
0
def build_list_page(category=None, developer=None, filter=None):
    '''Build page listing available optional items'''
    items = MunkiItems.getOptionalInstallItems()

    header = NSLocalizedString(u"All items", u"AllItemsHeaderText")
    page_name = u'category-all.html'
    if category == 'all':
        category = None
    if category:
        header = category
        page_name = u'category-%s.html' % category
    if developer:
        header = developer
        page_name = u'developer-%s.html' % developer
    if filter:
        header = u'Search results for %s' % filter
        page_name = u'filter-%s.html' % filter

    category_list = []
    for item in items:
        if 'category' in item and item['category'] not in category_list:
            category_list.append(item['category'])

    item_html = build_list_page_items_html(
                            category=category, developer=developer, filter=filter)

    # make HTML for Categories pop-up menu
    all_categories_label = NSLocalizedString(u"All Categories", u"AllCategoriesLabel")
    if category:
        categories_html = u'<option>%s</option>\n' % all_categories_label
    else:
        categories_html = u'<option selected>%s</option>\n' % all_categories_label

    for item in sorted(category_list):
        if item == category:
            categories_html += u'<option selected>%s</option>\n' % item
        else:
            categories_html += u'<option>%s</option>\n' % item

    categories_html_list = ''
    # make HTML for list of categories
    for item in sorted(category_list):
        categories_html_list += (u'<li class="link"><a href="category-%s.html">%s</a></li>\n'
                                 % (quote(item), item))

    page = {}
    page['list_items'] = item_html
    page['category_items'] = categories_html
    page['category_list'] = categories_html_list
    page['header_text'] = header
    if category or filter or developer:
        showcase = ''
    else:
        showcase = get_template('showcase_template.html', raw=True)
    sidebar = get_template('sidebar_template.html', raw=True)
    footer = get_template('footer_template.html', raw=True)
    generate_page(page_name, 'list_template.html', page,
                  showcase=showcase, sidebar=sidebar, footer=footer)
Esempio n. 13
0
def build_detail_page(item_name):
    '''Build page showing detail for a single optional item'''
    msclog.debug_log('build_detail_page for %s' % item_name)
    items = MunkiItems.getOptionalInstallItems()
    page_name = u'detail-%s.html' % item_name
    for item in items:
        if item['name'] == item_name:
            page = MunkiItems.OptionalItem(item)
            addDetailSidebarLabels(page)
            # make "More in CategoryFoo" list
            page['hide_more_in_category'] = u'hidden'
            more_in_category_html = u''
            more_in_category = []
            if item.get('category'):
                category = item['category']
                page['category_link'] = u'category-%s.html' % quote(category)
                more_in_category = [a for a in items
                                    if a.get('category') == category
                                    and a != item
                                    and a.get('status') != 'installed']
                if more_in_category:
                    page['hide_more_in_category'] = u''
                    page['moreInCategoryLabel'] = page['moreInCategoryLabel'] % page['category']
                    shuffle(more_in_category)
                    more_template = get_template('detail_more_items_template.html')
                    for more_item in more_in_category[:4]:
                        more_item['second_line'] = more_item.get('developer', '')
                        more_in_category_html += more_template.safe_substitute(more_item)
            page['more_in_category'] = more_in_category_html
            # make "More by DeveloperFoo" list
            page['hide_more_by_developer'] = u'hidden'
            more_by_developer_html = u''
            more_by_developer = []
            if item.get('developer'):
                developer = item['developer']
                page['developer_link'] = u'developer-%s.html' % quote(developer)
                more_by_developer = [a for a in items
                                     if a.get('developer') == developer
                                     and a != item
                                     and a not in more_in_category
                                     and a.get('status') != 'installed']
                if more_by_developer:
                    page['hide_more_by_developer'] = u''
                    page['moreByDeveloperLabel'] = (
                        page['moreByDeveloperLabel'] % developer)
                    shuffle(more_by_developer)
                    more_template = get_template(
                                        'detail_more_items_template.html')
                    for more_item in more_by_developer[:4]:
                        more_item['second_line'] = more_item.get('category', '')
                        more_by_developer_html += more_template.safe_substitute(more_item)
            page['more_by_developer'] = more_by_developer_html
            footer = get_template('footer_template.html', raw=True)
            generate_page(page_name, 'detail_template.html', page, footer=footer)
            return
    msclog.debug_log('No detail found for %s' % item_name)
    build_item_not_found_page(page_name)
Esempio n. 14
0
def build_category_items_html():
    '''Returns HTML for the items on the Categories page'''
    all_items = MunkiItems.getOptionalInstallItems()
    if all_items:
        category_list = []
        for item in all_items:
            if 'category' in item and item['category'] not in category_list:
                category_list.append(item['category'])

        item_template = get_template('category_item_template.html')
        item_html = u''
        for category in sorted(category_list):
            category_data = {}
            category_data['category_name_escaped'] = escape_html(category)
            category_data['category_link'] = u'category-%s.html' % quote(category)
            category_items = [item for item in all_items if item.get('category') == category]
            shuffle(category_items)
            category_data['item1_icon'] = category_items[0]['icon']
            category_data['item1_display_name_escaped'] = escape_html(
                 category_items[0]['display_name'])
            category_data['item1_detail_link'] = category_items[0]['detail_link']
            if len(category_items) > 1:
                category_data['item2_display_name_escaped'] = escape_html(
                    category_items[1]['display_name'])
                category_data['item2_detail_link'] = category_items[1]['detail_link']
            else:
                category_data['item2_display_name_escaped'] = u''
                category_data['item2_detail_link'] = u'#'
            if len(category_items) > 2:
                category_data['item3_display_name_escaped'] = escape_html(
                    category_items[2]['display_name'])
                category_data['item3_detail_link'] = category_items[2]['detail_link']
            else:
                category_data['item3_display_name_escaped'] = u''
                category_data['item3_detail_link'] = u'#'

            item_html += item_template.safe_substitute(category_data)

        # pad with extra empty items so we have a multiple of 3
        if len(category_list) % 3:
            for x in range(3 - (len(category_list) % 3)):
                item_html += u'<div class="lockup"></div>\n'

    else:
        # no items
        status_results_template = get_template('status_results_template.html')
        alert = {}
        alert['primary_status_text'] = NSLocalizedString(
            u"There are no available software items.",
            u"No Items primary text")
        alert['secondary_status_text'] = NSLocalizedString(
            u"Try again later.",
            u"No Items secondary text")
        alert['hide_progress_bar'] = u'hidden'
        alert['progress_bar_value'] = u''
        item_html = status_results_template.safe_substitute(alert)
    return item_html
Esempio n. 15
0
def build_category_items_html():
    '''Returns HTML for the items on the Categories page'''
    all_items = MunkiItems.getOptionalInstallItems()
    if all_items:
        category_list = []
        for item in all_items:
            if 'category' in item and item['category'] not in category_list:
                category_list.append(item['category'])

        item_template = get_template('category_item_template.html')
        item_html = u''
        for category in sorted(category_list):
            category_data = {}
            category_data['category_name_escaped'] = escape_html(category)
            category_data['category_link'] = u'category-%s.html' % quote(category)
            category_items = [item for item in all_items if item.get('category') == category]
            shuffle(category_items)
            category_data['item1_icon'] = category_items[0]['icon']
            category_data['item1_display_name_escaped'] = escape_html(
                 category_items[0]['display_name'])
            category_data['item1_detail_link'] = category_items[0]['detail_link']
            if len(category_items) > 1:
                category_data['item2_display_name_escaped'] = escape_html(
                    category_items[1]['display_name'])
                category_data['item2_detail_link'] = category_items[1]['detail_link']
            else:
                category_data['item2_display_name_escaped'] = u''
                category_data['item2_detail_link'] = u'#'
            if len(category_items) > 2:
                category_data['item3_display_name_escaped'] = escape_html(
                    category_items[2]['display_name'])
                category_data['item3_detail_link'] = category_items[2]['detail_link']
            else:
                category_data['item3_display_name_escaped'] = u''
                category_data['item3_detail_link'] = u'#'

            item_html += item_template.safe_substitute(category_data)

        # pad with extra empty items so we have a multiple of 3
        if len(category_list) % 3:
            for x in range(3 - (len(category_list) % 3)):
                item_html += u'<div class="lockup"></div>\n'

    else:
        # no items
        status_results_template = get_template('status_results_template.html')
        alert = {}
        alert['primary_status_text'] = NSLocalizedString(
            u"There are no available software items.",
            u"No Items primary text")
        alert['secondary_status_text'] = NSLocalizedString(
            u"Try again later.",
            u"No Items secondary text")
        alert['hide_progress_bar'] = u'hidden'
        alert['progress_bar_value'] = u''
        item_html = status_results_template.safe_substitute(alert)
    return item_html
Esempio n. 16
0
 def confirmUpdatesAndInstall(self):
     '''Make sure it's OK to proceed with installing if logout or restart is
     required'''
     if self.alertedToMultipleUsers():
         return
     elif MunkiItems.updatesRequireRestart():
         alert = NSAlert.alertWithMessageText_defaultButton_alternateButton_otherButton_informativeTextWithFormat_(
             NSLocalizedString(u"Restart Required",
                               u"Restart Required title"),
             NSLocalizedString(u"Log out and update",
                               u"Log out and Update button text"),
             NSLocalizedString(u"Cancel",
                               u"Cancel button title/short action text"),
             nil, u"%@",
             NSLocalizedString(
                 u"A restart is required after updating. Please be patient "
                 "as there may be a short delay at the login window. Log "
                 "out and update now?", u"Restart Required detail"))
         alert.beginSheetModalForWindow_modalDelegate_didEndSelector_contextInfo_(
             self.window, self,
             self.logoutAlertDidEnd_returnCode_contextInfo_, nil)
     elif MunkiItems.updatesRequireLogout() or munki.installRequiresLogout(
     ):
         alert = NSAlert.alertWithMessageText_defaultButton_alternateButton_otherButton_informativeTextWithFormat_(
             NSLocalizedString(u"Logout Required",
                               u"Logout Required title"),
             NSLocalizedString(u"Log out and update",
                               u"Log out and Update button text"),
             NSLocalizedString(u"Cancel",
                               u"Cancel button title/short action text"),
             nil, u"%@",
             NSLocalizedString(
                 u"A logout is required before updating. Please be patient "
                 "as there may be a short delay at the login window. Log "
                 "out and update now?", u"Logout Required detail"))
         alert.beginSheetModalForWindow_modalDelegate_didEndSelector_contextInfo_(
             self.window, self,
             self.logoutAlertDidEnd_returnCode_contextInfo_, nil)
     else:
         # we shouldn't have been invoked if neither a restart or logout was
         # required
         msclog.debug_log(
             'confirmUpdatesAndInstall was called but no restart or logout '
             'was needed')
Esempio n. 17
0
 def loadInitialView(self):
     '''Called by app delegate from applicationDidFinishLaunching:'''
     self.enableOrDisableSoftwareViewControls()
     optional_items = MunkiItems.getOptionalInstallItems()
     if not optional_items or self.getUpdateCount():
         self.loadUpdatesPage_(self)
     else:
         self.loadAllSoftwarePage_(self)
     self.displayUpdateCount()
     self.cached_self_service = MunkiItems.SelfService()
Esempio n. 18
0
 def enableOrDisableSoftwareViewControls(self):
     '''Disable or enable the controls that let us view optional items'''
     optional_items = MunkiItems.getOptionalInstallItems()
     enabled_state = (len(optional_items) > 0)
     self.enableOrDisableToolbarButtons_(enabled_state)
     self.searchField.setEnabled_(enabled_state)
     self.findMenuItem.setEnabled_(enabled_state)
     self.softwareMenuItem.setEnabled_(enabled_state)
     self.softwareMenuItem.setEnabled_(enabled_state)
     self.categoriesMenuItem.setEnabled_(enabled_state)
     self.myItemsMenuItem.setEnabled_(enabled_state)
Esempio n. 19
0
 def handlePossibleAuthRestart(self):
     '''Ask for and store a password for auth restart if needed/possible'''
     username = NSUserName()
     if (MunkiItems.updatesRequireRestart()
             and authrestart.verify_user(username)
             and not authrestart.verify_recovery_key_present()):
         # FV is on and user is in list of FV users, so they can
         # authrestart, and we do not have a stored FV recovery
         # key/password. So we should prompt the user for a password
         # we can use for fdesetup authrestart
         NSApp.delegate(
         ).passwordAlertController.promptForPasswordForAuthRestart()
Esempio n. 20
0
 def handlePossibleAuthRestart(self):
     '''Ask for and store a password for auth restart if needed/possible'''
     username = NSUserName()
     if (MunkiItems.updatesRequireRestart() and
             authrestart.verify_user(username) and
             not authrestart.verify_recovery_key_present()):
         # FV is on and user is in list of FV users, so they can
         # authrestart, and we do not have a stored FV recovery
         # key/password. So we should prompt the user for a password
         # we can use for fdesetup authrestart
         NSApp.delegate(
             ).passwordAlertController.promptForPasswordForAuthRestart()
Esempio n. 21
0
 def resetAndReload(self):
     '''Clear cached values, reload from disk. Display any changes.
     Typically called soon after a Munki session completes'''
     msclog.debug_log('resetAndReload method called')
     # need to clear out cached data
     MunkiItems.reset()
     # recache SelfService choices
     self.cached_self_service = MunkiItems.SelfService()
     # copy any new custom client resources
     msclib.get_custom_resources()
     # pending updates may have changed
     self._alertedUserToOutstandingUpdates = False
     # enable/disable controls as needed
     self.enableOrDisableSoftwareViewControls()
     # what page are we currently viewing?
     page_url = self.webView.mainFrameURL()
     filename = NSURL.URLWithString_(page_url).lastPathComponent()
     name = os.path.splitext(filename)[0]
     key, p, value = name.partition('-')
     if key == 'detail':
         # optional item detail page
         self.webView.reload_(self)
     if key in ['category', 'filter', 'developer']:
         # optional item list page
         self.updateListPage()
     if key == 'categories':
         # categories page
         self.updateCategoriesPage()
     if key == 'myitems':
         # my items page
         self.updateMyItemsPage()
     if key == 'updates':
         # updates page
         self.webView.reload_(self)
         self._alertedUserToOutstandingUpdates = True
     if key == 'updatedetail':
         # update detail page
         self.webView.reload_(self)
     # update count might have changed
     self.displayUpdateCount()
Esempio n. 22
0
 def updateNow(self):
     '''If user has added to/removed from the list of things to be updated,
     run a check session. If there are no more changes, proceed to an update
     installation session if items to be installed/removed are exclusively
     those selected by the user in this session'''
     if self.stop_requested:
         # reset the flag
         self.stop_requested = False
         self.resetAndReload()
         return
     if MunkiItems.updateCheckNeeded():
         # any item status changes that require an update check?
         msclog.debug_log('updateCheck needed')
         msclog.log("user", "check_then_install_without_logout")
         # since we are just checking for changed self-service items
         # we can suppress the Apple update check
         suppress_apple_update_check = True
         self._update_in_progress = True
         self.displayUpdateCount()
         result = munki.startUpdateCheck(suppress_apple_update_check)
         if result:
             msclog.debug_log("Error starting check-then-install session: %s" % result)
             self.munkiStatusSessionEnded_(2)
         else:
             self.managedsoftwareupdate_task = "checktheninstall"
             NSApp.delegate().statusController.startMunkiStatusSession()
             self.markRequestedItemsAsProcessing()
     elif (not self._alertedUserToOutstandingUpdates
           and MunkiItems.updatesContainNonUserSelectedItems()):
         # current list of updates contains some not explicitly chosen by the user
         msclog.debug_log('updateCheck not needed, items require user approval')
         self._update_in_progress = False
         self.displayUpdateCount()
         self.loadUpdatesPage_(self)
         self.alert_controller.alertToExtraUpdates()
     else:
         msclog.debug_log('updateCheck not needed')
         self._alertedUserToOutstandingUpdates = False
         self.kickOffInstallSession()
Esempio n. 23
0
    def applicationDidFinishLaunching_(self, sender):
        '''NSApplication delegate method called at launch'''
        # Prevent automatic relaunching at login on Lion+
        if NSApp.respondsToSelector_('disableRelaunchOnLogin'):
            NSApp.disableRelaunchOnLogin()

        ver = NSBundle.mainBundle().infoDictionary().get(
            'CFBundleShortVersionString')
        msclog.log("MSC", "launched", "VER=%s" % ver)

        # if we're running under Snow Leopard, swap out the Dock icon for one
        # without the Retina assets to avoid an appearance issue when the
        # icon has a badge in the Dock (and App Switcher)
        # Darwin major version 10 is Snow Leopard (10.6)
        if os.uname()[2].split('.')[0] == '10':
            myImage = NSImage.imageNamed_("Managed Software Center 10_6")
            NSApp.setApplicationIconImage_(myImage)

        # setup client logging
        msclog.setup_logging()

        # have the statuscontroller register for its own notifications
        self.statusController.registerForNotifications()

        # user may have launched the app manually, or it may have
        # been launched by /usr/local/munki/managedsoftwareupdate
        # to display available updates
        if munki.thereAreUpdatesToBeForcedSoon(hours=2):
            # skip the check and just display the updates
            # by pretending the lastcheck is now
            lastcheck = NSDate.date()
        else:
            lastcheck = munki.pref('LastCheckDate')
        max_cache_age = munki.pref('CheckResultsCacheSeconds')
        # if there is no lastcheck timestamp, check for updates.
        if not lastcheck:
            self.mainWindowController.checkForUpdates()
        elif lastcheck.timeIntervalSinceNow() * -1 > int(max_cache_age):
            # check for updates if the last check is over the
            # configured manualcheck cache age max.
            self.mainWindowController.checkForUpdates()
        elif MunkiItems.updateCheckNeeded():
            # check for updates if we have optional items selected for install
            # or removal that have not yet been processed
            self.mainWindowController.checkForUpdates()

        # load the initial view only if we are not already loading something else.
        # enables launching the app to a specific panel, eg. from URL handler
        if not self.mainWindowController.webView.isLoading():
            self.mainWindowController.loadInitialView()
Esempio n. 24
0
    def applicationDidFinishLaunching_(self, sender):
        '''NSApplication delegate method called at launch'''
        # Prevent automatic relaunching at login on Lion+
        if NSApp.respondsToSelector_('disableRelaunchOnLogin'):
            NSApp.disableRelaunchOnLogin()

        ver = NSBundle.mainBundle().infoDictionary().get('CFBundleShortVersionString')
        msclog.log("MSC", "launched", "VER=%s" % ver)
        
        # if we're running under Snow Leopard, swap out the Dock icon for one
        # without the Retina assets to avoid an appearance issue when the
        # icon has a badge in the Dock (and App Switcher)
        # Darwin major version 10 is Snow Leopard (10.6)
        if os.uname()[2].split('.')[0] == '10':
            myImage = NSImage.imageNamed_("Managed Software Center 10_6")
            NSApp.setApplicationIconImage_(myImage)

        # setup client logging
        msclog.setup_logging()

        # have the statuscontroller register for its own notifications
        self.statusController.registerForNotifications()

        # user may have launched the app manually, or it may have
        # been launched by /usr/local/munki/managedsoftwareupdate
        # to display available updates
        if munki.thereAreUpdatesToBeForcedSoon(hours=2):
            # skip the check and just display the updates
            # by pretending the lastcheck is now
            lastcheck = NSDate.date()
        else:
            lastcheck = munki.pref('LastCheckDate')
        max_cache_age = munki.pref('CheckResultsCacheSeconds')
        # if there is no lastcheck timestamp, check for updates.
        if not lastcheck:
            self.mainWindowController.checkForUpdates()
        elif lastcheck.timeIntervalSinceNow() * -1 > int(max_cache_age):
            # check for updates if the last check is over the
            # configured manualcheck cache age max.
            self.mainWindowController.checkForUpdates()
        elif MunkiItems.updateCheckNeeded():
            # check for updates if we have optional items selected for install
            # or removal that have not yet been processed
            self.mainWindowController.checkForUpdates()
        
        # load the initial view only if we are not already loading something else.
        # enables launching the app to a specific panel, eg. from URL handler
        if not self.mainWindowController.webView.isLoading():
            self.mainWindowController.loadInitialView()
Esempio n. 25
0
 def markRequestedItemsAsProcessing(self):
     '''When an update check session is happening, mark optional items
        that have been requested as processing'''
     msclog.debug_log('marking requested items as processing')
     for item in MunkiItems.getOptionalInstallItems():
         new_status = None
         if item['status'] == 'install-requested':
             msclog.debug_log('Setting status for %s to "downloading"' % item['name'])
             new_status = u'downloading'
         elif item['status'] == 'removal-requested':
             msclog.debug_log('Setting status for %s to "preparing-removal"' % item['name'])
             new_status = u'preparing-removal'
         if new_status:
             item['status'] = new_status
             self.updateDOMforOptionalItem(item)
Esempio n. 26
0
def get_warning_text():
    '''Return localized text warning about forced installs and/or
        logouts and/or restarts'''
    item_list = MunkiItems.getEffectiveUpdateList()
    warning_text = u''
    forced_install_date = munki.earliestForceInstallDate(item_list)
    if forced_install_date:
        date_str = munki.stringFromDate(forced_install_date)
        forced_date_text = NSLocalizedString(
            u"One or more items must be installed by %s",
            u"Forced Install Date summary")
        warning_text = forced_date_text % date_str
    restart_text = getRestartActionForUpdateList(item_list)
    if restart_text:
        if warning_text:
            warning_text += u' &bull; ' + restart_text
        else:
            warning_text = restart_text
    return warning_text
Esempio n. 27
0
def get_warning_text():
    '''Return localized text warning about forced installs and/or
        logouts and/or restarts'''
    item_list = MunkiItems.getEffectiveUpdateList()
    warning_text = u''
    forced_install_date = munki.earliestForceInstallDate(item_list)
    if forced_install_date:
        date_str = munki.stringFromDate(forced_install_date)
        forced_date_text = NSLocalizedString(
                            u"One or more items must be installed by %s",
                            u"Forced Install Date summary")
        warning_text = forced_date_text % date_str
    restart_text = getRestartActionForUpdateList(item_list)
    if restart_text:
        if warning_text:
            warning_text += u' &bull; ' + restart_text
        else:
            warning_text = restart_text
    return warning_text
Esempio n. 28
0
def build_myitems_rows():
    '''Returns HTML for the items on the 'My Items' page'''
    item_list = MunkiItems.getMyItemsList()
    if item_list:
        item_template = get_template('myitems_row_template.html')
        myitems_rows = u''
        for item in sorted(item_list, key=itemgetter('display_name_lower')):
            myitems_rows += item_template.safe_substitute(item)
    else:
        status_results_template = get_template('status_results_template.html')
        alert = {}
        alert['primary_status_text'] = NSLocalizedString(
            u"You have no selected software.",
            u"No Installed Software primary text")
        alert['secondary_status_text'] = (
            u'<a href="category-all.html">%s</a>' % NSLocalizedString(
                                                        u"Select software to install.",
                                                        u"No Installed Software secondary text"))
        alert['hide_progress_bar'] = u'hidden'
        myitems_rows = status_results_template.safe_substitute(alert)
    return myitems_rows
Esempio n. 29
0
 def getFirmwareAlertInfo(self):
     '''Get detail about a firmware update'''
     info = []
     for update_item in MunkiItems.getUpdateList():
         if 'firmware_alert_text' in update_item:
             info_item = {}
             info_item['name'] = update_item.get('display_name', 'name')
             alert_text = update_item['firmware_alert_text']
             if alert_text == u'_DEFAULT_FIRMWARE_ALERT_TEXT_':
                 # substitute localized default alert text
                 alert_text = NSLocalizedString(
                     (u"Firmware will be updated on your computer. "
                      "Your computer's power cord must be connected "
                      "and plugged into a working power source. "
                      "It may take several minutes for the update to "
                      "complete. Do not disturb or shut off the power "
                      "on your computer during this update."),
                     u"Firmware Alert Default detail")
             info_item['alert_text'] = alert_text
             info.append(info_item)
     return info
Esempio n. 30
0
def build_myitems_rows():
    '''Returns HTML for the items on the 'My Items' page'''
    item_list = MunkiItems.getMyItemsList()
    if item_list:
        item_template = get_template('myitems_row_template.html')
        myitems_rows = u''
        for item in sorted(item_list, key=itemgetter('display_name_lower')):
            myitems_rows += item_template.safe_substitute(item)
    else:
        status_results_template = get_template('status_results_template.html')
        alert = {}
        alert['primary_status_text'] = NSLocalizedString(
            u"You have no selected software.",
            u"No Installed Software primary text")
        alert['secondary_status_text'] = (
            u'<a href="category-all.html">%s</a>' %
            NSLocalizedString(u"Select software to install.",
                              u"No Installed Software secondary text"))
        alert['hide_progress_bar'] = u'hidden'
        myitems_rows = status_results_template.safe_substitute(alert)
    return myitems_rows
Esempio n. 31
0
 def getFirmwareAlertInfo(self):
     '''Get detail about a firmware update'''
     info = []
     for update_item in MunkiItems.getUpdateList():
         if 'firmware_alert_text' in update_item:
             info_item = {}
             info_item['name'] = update_item.get('display_name', 'name')
             alert_text = update_item['firmware_alert_text']
             if alert_text == u'_DEFAULT_FIRMWARE_ALERT_TEXT_':
                 # substitute localized default alert text
                 alert_text = NSLocalizedString(
                     (u"Firmware will be updated on your computer. "
                      "Your computer's power cord must be connected "
                      "and plugged into a working power source. "
                      "It may take several minutes for the update to "
                      "complete. Do not disturb or shut off the power "
                      "on your computer during this update."),
                     u"Firmware Alert Default detail")
             info_item['alert_text'] = alert_text
             info.append(info_item)
     return info
Esempio n. 32
0
 def actionButtonClicked_(self, item_name):
     '''this method is called from JavaScript when the user clicks
     the Install/Removel/Cancel button in the list or detail view'''
     item = MunkiItems.optionalItemForName_(item_name)
     if not item:
         msclog.debug_log(
             'User clicked Install/Removel/Cancel button in the list or detail view')
         msclog.debug_log('Can\'t find item: %s' % item_name)
         return
     
     prior_status = item['status']
     item.update_status()
     self.displayUpdateCount()
     self.updateDOMforOptionalItem(item)
     
     if item['status'] in ['install-requested', 'removal-requested']:
         self._alertedUserToOutstandingUpdates = False
         if not self._update_in_progress:
             self.updateNow()
     elif prior_status in ['will-be-installed', 'update-will-be-installed',
                             'will-be-removed']:
         # cancelled a pending install or removal; should run an updatecheck
         self.checkForUpdates(suppress_apple_update_check=True)
Esempio n. 33
0
def build_categories_page():
    '''Build page showing available categories and some items in each one'''
    all_items = MunkiItems.getOptionalInstallItems()
    header = NSLocalizedString(u"Categories", u"Categories label")
    page_name = u'categories.html'
    category_list = []
    for item in all_items:
        if 'category' in item and item['category'] not in category_list:
            category_list.append(item['category'])

    item_html = build_category_items_html()
    
    all_categories_label = NSLocalizedString(u"All Categories", u"AllCategoriesLabel")
    categories_html = u'<option selected>%s</option>\n' % all_categories_label
    for item in sorted(category_list):
        categories_html += u'<option>%s</option>\n' % item

    page = {}
    page['list_items'] = item_html
    page['category_items'] = categories_html
    page['header_text'] = header
    
    footer = get_template('footer_template.html', raw=True)
    generate_page(page_name, 'list_template.html', page, showcase=u'', sidebar=u'', footer=footer)
Esempio n. 34
0
def build_updates_page():
    '''available/pending updates'''
    page_name = u'updates.html'
    
    # need to consolidate/centralize this flag. Accessing it this way is ugly.
    if NSApp.delegate().mainWindowController._update_in_progress:
        return build_update_status_page()

    item_list = MunkiItems.getEffectiveUpdateList()

    problem_updates = MunkiItems.getProblemItems()
    for item in problem_updates:
        item['hide_cancel_button'] = u'hidden'

    # find any optional installs with update available
    other_updates = [
        item for item in MunkiItems.getOptionalInstallItems()
        if item['status'] == 'update-available']

    # find any listed optional install updates that require a higher OS
    # or have insufficient disk space or other blockers (because they have a
    # note)
    blocked_optional_updates = [
        item for item in MunkiItems.getOptionalInstallItems()
        if item['status'] == 'installed' and item.get('note')]
    for item in blocked_optional_updates:
        item['hide_cancel_button'] = u'hidden'

    other_updates.extend(blocked_optional_updates)

    page = {}
    page['update_rows'] = u''
    page['hide_progress_spinner'] = u'hidden'
    page['hide_problem_updates'] = u'hidden'
    page['hide_other_updates'] = u'hidden'
    page['install_all_button_classes'] = u''
    
    item_template = get_template('update_row_template.html')

    # build pending updates table
    if item_list:
        for item in item_list:
            escapeAndQuoteCommonFields(item)
            page['update_rows'] += item_template.safe_substitute(item)
    elif not other_updates and not problem_updates:
        status_results_template = get_template('status_results_template.html')
        alert = {}
        alert['primary_status_text'] = NSLocalizedString(
             u"Your software is up to date.", u"No Pending Updates primary text")
        alert['secondary_status_text'] = NSLocalizedString(
             u"There is no new software for your computer at this time.",
             u"No Pending Updates secondary text")
        alert['hide_progress_bar'] = u'hidden'
        alert['progress_bar_value'] = u''
        page['update_rows'] = status_results_template.safe_substitute(alert)

    count = len([item for item in item_list if item['status'] != 'problem-item'])
    page['update_count'] = msclib.updateCountMessage(count)
    page['install_btn_label'] = msclib.getInstallAllButtonTextForCount(count)
    page['warning_text'] = get_warning_text()

    # build problem updates table
    page['problem_updates_header_message'] = NSLocalizedString(
        u"Problem updates",
        u"Problem Updates label")
    page['problem_update_rows'] = u''

    if problem_updates:
        page['hide_problem_updates'] = u''
        for item in problem_updates:
            escapeAndQuoteCommonFields(item)
            page['problem_update_rows'] += item_template.safe_substitute(item)

    # build other available updates table
    page['other_updates_header_message'] = NSLocalizedString(
        u"Other available updates",
        u"Other Available Updates label")
    page['other_update_rows'] = u''

    if other_updates:
        page['hide_other_updates'] = u''
        for item in other_updates:
            escapeAndQuoteCommonFields(item)
            page['other_update_rows'] += item_template.safe_substitute(item)
    
    footer = get_template('footer_template.html', raw=True)
    generate_page(page_name, 'updates_template.html', page, footer=footer)
Esempio n. 35
0
    def munkiStatusSessionEnded_(self, sessionResult):
        '''Called by StatusController when a Munki session ends'''
        msclog.debug_log(u"MunkiStatus session ended: %s" % sessionResult)
        msclog.debug_log(u"MunkiStatus session type: %s" % self.managedsoftwareupdate_task)
        tasktype = self.managedsoftwareupdate_task
        self.managedsoftwareupdate_task = None
        self._update_in_progress = False
        
        # The managedsoftwareupdate run will have changed state preferences
        # in ManagedInstalls.plist. Load the new values.
        munki.reload_prefs()
        lastCheckResult = munki.pref("LastCheckResult")
        if sessionResult != 0 or lastCheckResult < 0:
            OKButtonTitle = NSLocalizedString(u"OK", u"OK button title")
            alertMessageText = NSLocalizedString(
                                    u"Update check failed", u"Update Check Failed title")
            if tasktype == "installwithnologout":
                alertMessageText = NSLocalizedString(
                                        u"Install session failed", u"Install Session Failed title")

            if sessionResult == -1:
                # connection was dropped unexpectedly
                msclog.log("MSC", "cant_update", "unexpected process end")
                detailText = NSLocalizedString(
                    (u"There is a configuration problem with the managed software installer. "
                      "The process ended unexpectedly. Contact your systems administrator."),
                     u"Unexpected Session End message")
            elif sessionResult == -2:
                # session never started
                msclog.log("MSC", "cant_update", "process did not start")
                detailText = NSLocalizedString(
                    (u"There is a configuration problem with the managed software installer. "
                      "Could not start the process. Contact your systems administrator."),
                     u"Could Not Start Session message")
            elif lastCheckResult == -1:
                # server not reachable
                msclog.log("MSC", "cant_update", "cannot contact server")
                detailText = NSLocalizedString(
                    (u"Managed Software Center cannot contact the update server at this time.\n"
                      "Try again later. If this situation continues, "
                      "contact your systems administrator."), u"Cannot Contact Server detail")
            elif lastCheckResult == -2:
                # preflight failed
                msclog.log("MSU", "cant_update", "failed preflight")
                detailText = NSLocalizedString(
                    (u"Managed Software Center cannot check for updates now.\n"
                      "Try again later. If this situation continues, "
                      "contact your systems administrator."), u"Failed Preflight Check detail")
            # show the alert sheet
            self.window().makeKeyAndOrderFront_(self)
            alert = NSAlert.alertWithMessageText_defaultButton_alternateButton_otherButton_informativeTextWithFormat_(
                alertMessageText, OKButtonTitle, nil, nil, u"%@", detailText)
            alert.beginSheetModalForWindow_modalDelegate_didEndSelector_contextInfo_(
                self.window(), self,
                self.munkiSessionErrorAlertDidEnd_returnCode_contextInfo_, nil)
            return
        
        if tasktype == 'checktheninstall':
            MunkiItems.reset()
            # possibly check again if choices have changed
            self.updateNow()
            return

        # all done checking and/or installing: display results
        self.resetAndReload()
        
        if MunkiItems.updateCheckNeeded():
            # more stuff pending? Let's do it...
            self.updateNow()
Esempio n. 36
0
 def windowDidBecomeMain_(self, notification):
     '''Our window was activated, make sure controls enabled as needed'''
     optional_items = MunkiItems.getOptionalInstallItems()
     enabled_state = (len(optional_items) > 0)
     self.enableOrDisableToolbarButtons_(enabled_state)
Esempio n. 37
0
 def getUpdateCount(self):
     '''Get the count of effective updates'''
     if self._update_in_progress:
         return 0
     return len(MunkiItems.getEffectiveUpdateList())
Esempio n. 38
0
def build_updates_page():
    '''available/pending updates'''
    page_name = u'updates.html'

    # need to consolidate/centralize this flag. Accessing it this way is ugly.
    if NSApp.delegate().mainWindowController._update_in_progress:
        return build_update_status_page()

    item_list = MunkiItems.getEffectiveUpdateList()

    problem_updates = MunkiItems.getProblemItems()
    for item in problem_updates:
        item['hide_cancel_button'] = u'hidden'

    # find any optional installs with update available
    other_updates = [
        item for item in MunkiItems.getOptionalInstallItems()
        if item['status'] == 'update-available'
    ]

    # find any listed optional install updates that require a higher OS
    # or have insufficient disk space or other blockers (because they have a
    # note)
    blocked_optional_updates = [
        item for item in MunkiItems.getOptionalInstallItems()
        if item['status'] == 'installed' and item.get('note')
    ]
    for item in blocked_optional_updates:
        item['hide_cancel_button'] = u'hidden'

    other_updates.extend(blocked_optional_updates)

    page = {}
    page['update_rows'] = u''
    page['hide_progress_spinner'] = u'hidden'
    page['hide_problem_updates'] = u'hidden'
    page['hide_other_updates'] = u'hidden'
    page['install_all_button_classes'] = u''

    item_template = get_template('update_row_template.html')

    # build pending updates table
    if item_list:
        for item in item_list:
            escapeAndQuoteCommonFields(item)
            page['update_rows'] += item_template.safe_substitute(item)
    elif not other_updates and not problem_updates:
        status_results_template = get_template('status_results_template.html')
        alert = {}
        alert['primary_status_text'] = NSLocalizedString(
            u"Your software is up to date.",
            u"No Pending Updates primary text")
        alert['secondary_status_text'] = NSLocalizedString(
            u"There is no new software for your computer at this time.",
            u"No Pending Updates secondary text")
        alert['hide_progress_bar'] = u'hidden'
        alert['progress_bar_value'] = u''
        page['update_rows'] = status_results_template.safe_substitute(alert)

    count = len(
        [item for item in item_list if item['status'] != 'problem-item'])
    page['update_count'] = msclib.updateCountMessage(count)
    page['install_btn_label'] = msclib.getInstallAllButtonTextForCount(count)
    page['warning_text'] = get_warning_text()

    # build problem updates table
    page['problem_updates_header_message'] = NSLocalizedString(
        u"Problem updates", u"Problem Updates label")
    page['problem_update_rows'] = u''

    if problem_updates:
        page['hide_problem_updates'] = u''
        for item in problem_updates:
            escapeAndQuoteCommonFields(item)
            page['problem_update_rows'] += item_template.safe_substitute(item)

    # build other available updates table
    page['other_updates_header_message'] = NSLocalizedString(
        u"Other available updates", u"Other Available Updates label")
    page['other_update_rows'] = u''

    if other_updates:
        page['hide_other_updates'] = u''
        for item in other_updates:
            escapeAndQuoteCommonFields(item)
            page['other_update_rows'] += item_template.safe_substitute(item)

    footer = get_template('footer_template.html', raw=True)
    generate_page(page_name, 'updates_template.html', page, footer=footer)
Esempio n. 39
0
    def updateOptionalInstallButtonClicked_(self, item_name):
        '''this method is called from JavaScript when a user clicks
        the cancel or add button in the updates list'''
        # TO-DO: better handling of all the possible "unexpected error"s
        document = self.webView.mainFrameDocument()
        item = MunkiItems.optionalItemForName_(item_name)
        if not item:
            msclog.debug_log('Unexpected error: Can\'t find item for %s' % item_name)
            return
        update_table_row = document.getElementById_('%s_update_table_row' % item_name)
        if not update_table_row:
            msclog.debug_log('Unexpected error: Can\'t find table row for %s' % item_name)
            return
        # remove this row from its current table
        node = update_table_row.parentNode().removeChild_(update_table_row)

        previous_status = item['status']
        # update item status
        item.update_status()
        
        # do we need to add a new node to the other list?
        if item.get('needs_update'):
            # make some new HTML for the updated item
            managed_update_names = MunkiItems.getInstallInfo().get('managed_updates', [])
            item_template = mschtml.get_template('update_row_template.html')
            item_html = item_template.safe_substitute(item)

            if item['status'] in ['install-requested', 'update-will-be-installed', 'installed']:
                # add the node to the updates-to-install table
                table = document.getElementById_('updates-to-install-table')
            if item['status'] == 'update-available':
                # add the node to the other-updates table
                table = document.getElementById_('other-updates-table')
            if not table:
                msclog.debug_log('Unexpected error: could not find other-updates-table')
                return
            # this isn't the greatest way to add something to the DOM
            # but it works...
            table.setInnerHTML_(table.innerHTML() + item_html)

        # might need to toggle visibility of other updates div
        other_updates_div = document.getElementById_('other-updates')
        other_updates_div_classes = other_updates_div.className().split(' ')
        other_updates_table = document.getElementById_('other-updates-table')
        if other_updates_table.innerHTML().strip():
            if 'hidden' in other_updates_div_classes:
                other_updates_div_classes.remove('hidden')
                other_updates_div.setClassName_(' '.join(other_updates_div_classes))
        else:
            if not 'hidden' in other_updates_div_classes:
                other_updates_div_classes.append('hidden')
                other_updates_div.setClassName_(' '.join(other_updates_div_classes))

        # update the updates-to-install header to reflect the new list of updates to install
        updateCount = self.getUpdateCount()
        update_count_message = msclib.updateCountMessage(updateCount)
        update_count_element = document.getElementById_('update-count-string')
        if update_count_element:
            update_count_element.setInnerText_(update_count_message)

        warning_text = mschtml.get_warning_text()
        warning_text_element = document.getElementById_('update-warning-text')
        if warning_text_element:
            warning_text_element.setInnerHTML_(warning_text)

        # update text of Install All button
        install_all_button_element = document.getElementById_('install-all-button-text')
        if install_all_button_element:
            install_all_button_element.setInnerText_(
                msclib.getInstallAllButtonTextForCount(updateCount))

        # update count badges
        self.displayUpdateCount()
        
        if MunkiItems.updateCheckNeeded():
            # check for updates after a short delay so UI changes visually complete first
            self.performSelector_withObject_afterDelay_(self.checkForUpdates, True, 1.0)
Esempio n. 40
0
def build_list_page_items_html(category=None, developer=None, filter=None):
    '''Returns HTML for the items on the list page'''
    items = MunkiItems.getOptionalInstallItems()
    item_html = u''
    if filter:
        # since the filter term came through the filesystem,
        # HFS+ does some unicode character decomposition which can cause issue
        # with comparisons
        # so before we do our comparison, we normalize the unicode string
        # using unicodedata.normalize
        filter = normalize('NFC', filter)
        msclog.debug_log(u'Filtering on %s' % filter)
        items = [
            item for item in items if filter in item['display_name'].lower()
            or filter in item['description'].lower() or filter in
            item['developer'].lower() or filter in item['category'].lower()
        ]
    if category:
        items = [
            item for item in items
            if category.lower() == item.get('category', '').lower()
        ]
    if developer:
        items = [
            item for item in items
            if developer.lower() == item.get('developer', '').lower()
        ]

    if category is None and developer is None and filter is None:
        # this is the default (formerly) "all items" view
        # look for featured items and display those if we have them
        featured_items = [item for item in items if item.get('featured')]
        if featured_items:
            items = featured_items

    if items:
        item_template = get_template('list_item_template.html')
        for item in sorted(items, key=itemgetter('display_name_lower')):
            escapeAndQuoteCommonFields(item)
            item['category_and_developer_escaped'] = escape_html(
                item['category_and_developer'])
            item_html += item_template.safe_substitute(item)
        # pad with extra empty items so we have a multiple of 3
        if len(items) % 3:
            for x in range(3 - (len(items) % 3)):
                item_html += u'<div class="lockup"></div>\n'
    else:
        # no items; build appropriate alert messages
        status_results_template = get_template('status_results_template.html')
        alert = {}
        if filter:
            alert['primary_status_text'] = NSLocalizedString(
                u"Your search had no results.",
                u"No Search Results primary text")
            alert['secondary_status_text'] = NSLocalizedString(
                u"Try searching again.", u"No Search Results secondary text")
        elif category:
            alert['primary_status_text'] = NSLocalizedString(
                u"There are no items in this category.",
                u"No Category Results primary text")
            alert['secondary_status_text'] = NSLocalizedString(
                u"Try selecting another category.",
                u"No Category Results secondary text")
        elif developer:
            alert['primary_status_text'] = NSLocalizedString(
                u"There are no items from this developer.",
                u"No Developer Results primary text")
            alert['secondary_status_text'] = NSLocalizedString(
                u"Try selecting another developer.",
                u"No Developer Results secondary text")
        else:
            alert['primary_status_text'] = NSLocalizedString(
                u"There are no available software items.",
                u"No Items primary text")
            alert['secondary_status_text'] = NSLocalizedString(
                u"Try again later.", u"No Items secondary text")
        alert['hide_progress_bar'] = u'hidden'
        alert['progress_bar_value'] = u''
        item_html = status_results_template.safe_substitute(alert)
    return item_html
Esempio n. 41
0
def build_list_page(category=None, developer=None, filter=None):
    '''Build page listing available optional items'''
    items = MunkiItems.getOptionalInstallItems()

    header = NSLocalizedString(u"All items", u"AllItemsHeaderText")
    page_name = u'category-all.html'
    if category == 'all':
        category = None
    if category:
        header = category
        page_name = u'category-%s.html' % category
    if developer:
        header = developer
        page_name = u'developer-%s.html' % developer
    if filter:
        header = u'Search results for %s' % filter
        page_name = u'filter-%s.html' % filter

    featured_items = [item for item in items if item.get('featured')]
    if (featured_items and category is None and developer is None
            and filter is None):
        header = NSLocalizedString(u"Featured items",
                                   u"FeaturedItemsHeaderText")

    category_list = []
    for item in items:
        if 'category' in item and item['category'] not in category_list:
            category_list.append(item['category'])

    item_html = build_list_page_items_html(category=category,
                                           developer=developer,
                                           filter=filter)

    # make HTML for Categories pop-up menu
    if featured_items:
        all_categories_label = NSLocalizedString(u"Featured", u"FeaturedLabel")
    else:
        all_categories_label = NSLocalizedString(u"All Categories",
                                                 u"AllCategoriesLabel")
    if category:
        categories_html = u'<option>%s</option>\n' % all_categories_label
    else:
        categories_html = u'<option selected>%s</option>\n' % all_categories_label

    for item in sorted(category_list):
        if item == category:
            categories_html += u'<option selected>%s</option>\n' % item
        else:
            categories_html += u'<option>%s</option>\n' % item

    categories_html_list = ''
    # make HTML for list of categories
    for item in sorted(category_list):
        categories_html_list += (
            u'<li class="link"><a href="category-%s.html">%s</a></li>\n' %
            (quote(item), item))

    page = {}
    page['list_items'] = item_html
    page['category_items'] = categories_html
    page['category_list'] = categories_html_list
    page['header_text'] = header
    if category or filter or developer:
        showcase = ''
    else:
        showcase = get_template('showcase_template.html', raw=True)
    sidebar = get_template('sidebar_template.html', raw=True)
    footer = get_template('footer_template.html', raw=True)
    generate_page(page_name,
                  'list_template.html',
                  page,
                  showcase=showcase,
                  sidebar=sidebar,
                  footer=footer)
Esempio n. 42
0
def build_detail_page(item_name):
    '''Build page showing detail for a single optional item'''
    msclog.debug_log('build_detail_page for %s' % item_name)
    items = MunkiItems.getOptionalInstallItems()
    page_name = u'detail-%s.html' % item_name
    for item in items:
        if item['name'] == item_name:
            # make a copy of the item to use to build our page
            page = MunkiItems.OptionalItem(item)
            escapeAndQuoteCommonFields(page)
            addDetailSidebarLabels(page)
            # make "More in CategoryFoo" list
            page['hide_more_in_category'] = u'hidden'
            more_in_category_html = u''
            more_in_category = []
            if item.get('category'):
                category = item['category']
                page['category_link'] = u'category-%s.html' % quote(category)
                more_in_category = [
                    a for a in items if a.get('category') == category
                    and a != item and a.get('status') != 'installed'
                ]
                if more_in_category:
                    page['hide_more_in_category'] = u''
                    page['moreInCategoryLabel'] = page[
                        'moreInCategoryLabel'] % page['category']
                    shuffle(more_in_category)
                    more_template = get_template(
                        'detail_more_items_template.html')
                    for more_item in more_in_category[:4]:
                        more_item['display_name_escaped'] = escape_html(
                            more_item['display_name'])
                        more_item['second_line'] = more_item.get(
                            'developer', '')
                        more_in_category_html += more_template.safe_substitute(
                            more_item)
            page['more_in_category'] = more_in_category_html
            # make "More by DeveloperFoo" list
            page['hide_more_by_developer'] = u'hidden'
            more_by_developer_html = u''
            more_by_developer = []
            if item.get('developer'):
                developer = item['developer']
                page['developer_link'] = u'developer-%s.html' % quote(
                    developer)
                more_by_developer = [
                    a for a in items
                    if a.get('developer') == developer and a != item and a
                    not in more_in_category and a.get('status') != 'installed'
                ]
                if more_by_developer:
                    page['hide_more_by_developer'] = u''
                    page['moreByDeveloperLabel'] = (
                        page['moreByDeveloperLabel'] % developer)
                    shuffle(more_by_developer)
                    more_template = get_template(
                        'detail_more_items_template.html')
                    for more_item in more_by_developer[:4]:
                        escapeAndQuoteCommonFields(more_item)
                        more_item['second_line'] = more_item.get(
                            'category', '')
                        more_by_developer_html += more_template.safe_substitute(
                            more_item)
            page['more_by_developer'] = more_by_developer_html
            footer = get_template('footer_template.html', raw=True)
            generate_page(page_name,
                          'detail_template.html',
                          page,
                          footer=footer)
            return
    msclog.debug_log('No detail found for %s' % item_name)
    build_item_not_found_page(page_name)
Esempio n. 43
0
def build_list_page_items_html(category=None, developer=None, filter=None):
    '''Returns HTML for the items on the list page'''
    items = MunkiItems.getOptionalInstallItems()
    item_html = u''
    if filter:
        # since the filter term came through the filesystem,
        # HFS+ does some unicode character decomposition which can cause issues with comparisons
        # so before we do our comparison, we normalize the unicode string
        # using unicodedata.normalize
        filter = normalize('NFC', filter)
        msclog.debug_log(u'Filtering on %s' % filter)
        items = [item for item in items
                 if filter in item['display_name'].lower()
                 or filter in item['description'].lower()
                 or filter in item['developer'].lower()
                 or filter in item['category'].lower()]
    if category:
        items = [item for item in items
                 if category.lower() in item.get('category', '').lower()]
    if developer:
        items = [item for item in items
                 if developer.lower() in item.get('developer', '').lower()]

    if items:
        item_template = get_template('list_item_template.html')
        for item in sorted(items, key=itemgetter('display_name_lower')):
            escapeAndQuoteCommonFields(item)
            item['category_and_developer_escaped'] = escape_html(item['category_and_developer'])
            item_html += item_template.safe_substitute(item)
        # pad with extra empty items so we have a multiple of 3
        if len(items) % 3:
            for x in range(3 - (len(items) % 3)):
                item_html += u'<div class="lockup"></div>\n'
    else:
        # no items; build appropriate alert messages
        status_results_template = get_template('status_results_template.html')
        alert = {}
        if filter:
            alert['primary_status_text'] = NSLocalizedString(
                u"Your search had no results.",
                u"No Search Results primary text")
            alert['secondary_status_text'] = NSLocalizedString(
                u"Try searching again.", u"No Search Results secondary text")
        elif category:
            alert['primary_status_text'] = NSLocalizedString(
                u"There are no items in this category.",
                u"No Category Results primary text")
            alert['secondary_status_text'] = NSLocalizedString(
                u"Try selecting another category.",
                u"No Category Results secondary text")
        elif developer:
            alert['primary_status_text'] = NSLocalizedString(
                u"There are no items from this developer.",
                u"No Developer Results primary text")
            alert['secondary_status_text'] = NSLocalizedString(
                u"Try selecting another developer.",
                u"No Developer Results secondary text")
        else:
            alert['primary_status_text'] = NSLocalizedString(
               u"There are no available software items.",
               u"No Items primary text")
            alert['secondary_status_text'] = NSLocalizedString(
               u"Try again later.",
               u"No Items secondary text")
        alert['hide_progress_bar'] = u'hidden'
        alert['progress_bar_value'] = u''
        item_html = status_results_template.safe_substitute(alert)
    return item_html